diff --git a/build-data/dev-imports.txt b/build-data/dev-imports.txt index 585b551..b818b96 100644 --- a/build-data/dev-imports.txt +++ b/build-data/dev-imports.txt @@ -8,6 +8,3 @@ # To import classes from the vanilla Minecraft jar use `minecraft` as the artifactId: # minecraft net.minecraft.world.level.entity.LevelEntityGetterAdapter # minecraft net/minecraft/world/level/entity/LevelEntityGetter.java -minecraft net.minecraft.world.TickRateManager -minecraft net.minecraft.server.ServerTickRateManager -minecraft net.minecraft.server.commands.TickCommand \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3ef73fe..04a164b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ repositories { } dependencies { - remapper("net.fabricmc:tiny-remapper:0.10.2:fat") + remapper("net.fabricmc:tiny-remapper:0.10.3:fat") decompiler("org.vineflower:vineflower:1.10.1") paperclip("io.papermc:paperclip:3.0.3") } diff --git a/gradle.properties b/gradle.properties index f58b040..ffa4202 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ group=dev.folia -version=1.20.6-R0.1-SNAPSHOT -mcVersion=1.20.6 +version=1.21-R0.1-SNAPSHOT +mcVersion=1.21 -paperRef=e41d44fa873466064879ebed476d280932379a9c +paperRef=0a1be9ae87416ffca38cf20412e248c78a9d6a3c org.gradle.caching=true org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23..a441313 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a4..b740cf1 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/patches/api/0001-Force-disable-timings.patch b/patches/api/0001-Force-disable-timings.patch index 79d236b..50d619a 100644 --- a/patches/api/0001-Force-disable-timings.patch +++ b/patches/api/0001-Force-disable-timings.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Force disable timings Need a new profiler system with region threading diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java -index 9812d668ad945aba486fbf6d5bf83c4292cb5d03..34386d6ce702de9a58f2892045563dd57ef46bbf 100644 +index e81d0bc309de877ed2b5da6122f55c162e9b5f10..7760c779e97a0e95d5c3d255b25d949ac20df235 100644 --- a/src/main/java/co/aikar/timings/Timings.java +++ b/src/main/java/co/aikar/timings/Timings.java @@ -145,13 +145,14 @@ public final class Timings { @@ -29,18 +29,18 @@ index 9812d668ad945aba486fbf6d5bf83c4292cb5d03..34386d6ce702de9a58f2892045563dd5 public static Component deprecationMessage() { return Component.text() -- .color(TextColor.color(0xf3ef91)) +- .color(TextColor.color(0xffc93a)) - .append(Component.text("[!] The timings profiler has been enabled but has been scheduled for removal from Paper in the future.")) + .color(TextColor.color(0xf39195)) // Folia + .append(Component.text("[!] The timings system cannot be enabled on Folia, and has been scheduled for removal from Paper in the future.")) // Folia .append(Component.newline()) - .append( - Component.text(" We recommend installing the spark profiler as a replacement: ") + .append(Component.text(" We recommend migrating to the spark profiler.")) + .append(Component.newline()) diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java -index e801e79fa57c44b2e5d359647c920f88064826f1..d897b92311da36b21561e95f1530016d1579facc 100644 +index 95d87c9dbf2b237787294dfbe7fed87a36e6dedf..b83e5ff7ada8771fdf27ba9807c77ba6a4ce12da 100644 --- a/src/main/java/co/aikar/timings/TimingsCommand.java +++ b/src/main/java/co/aikar/timings/TimingsCommand.java -@@ -54,8 +54,9 @@ public class TimingsCommand extends BukkitCommand { +@@ -56,8 +56,9 @@ public class TimingsCommand extends BukkitCommand { if (!testPermission(sender)) { return true; } diff --git a/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch b/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch index f1e88b3..f39bfa9 100644 --- a/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch +++ b/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch @@ -11,10 +11,10 @@ the schedulers depending on the result of the ownership check. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 47039514503d99e84cb99f4941707a7726286516..15049641b8123abf03edcbb49257fb4f3db0a5ec 100644 +index 4705c1d91e39fcc3c608b1f1a38a30d063ccf06e..886920b33b37bdefc301f898ad0003e40eff6443 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2908,6 +2908,14 @@ public final class Bukkit { +@@ -2905,6 +2905,14 @@ public final class Bukkit { return server.isOwnedByCurrentRegion(entity); } // Paper end - Folia region threading API @@ -30,10 +30,10 @@ index 47039514503d99e84cb99f4941707a7726286516..15049641b8123abf03edcbb49257fb4f @NotNull public static Server.Spigot spigot() { diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 0614bd7e2d658172a7765925adf81b75b5620f11..1f51f80e8516cfac7ed4078ed96e535389a31f25 100644 +index c043d239c449bf4bb13a24467f2f6c67b4d28d2d..d6f72cb1e2380bd1a18d695c7d26ae3834f6eb52 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2546,4 +2546,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2543,4 +2543,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ boolean isOwnedByCurrentRegion(@NotNull Entity entity); // Paper end - Folia region threading API diff --git a/patches/server/0001-Build-changes.patch b/patches/server/0001-Build-changes.patch index 1a5591c..715aae0 100644 --- a/patches/server/0001-Build-changes.patch +++ b/patches/server/0001-Build-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Build changes diff --git a/build.gradle.kts b/build.gradle.kts -index 4998aff0b7cb084dcda15c6a18bbe45e99b6000a..eb2f9941b24af591f1e56339b97f5284a765cf81 100644 +index 421f6b3dc8890d63d2e7aa774d0bf8f7e15890ab..f0a90d13a17160cd363d54d494add4f6433b4758 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { @@ -17,7 +17,7 @@ index 4998aff0b7cb084dcda15c6a18bbe45e99b6000a..eb2f9941b24af591f1e56339b97f5284 // Paper start implementation("org.jline:jline-terminal-jansi:3.21.0") implementation("net.minecrell:terminalconsoleappender:1.3.0") -@@ -80,14 +80,14 @@ tasks.jar { +@@ -84,14 +84,14 @@ tasks.jar { val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", @@ -36,7 +36,7 @@ index 4998aff0b7cb084dcda15c6a18bbe45e99b6000a..eb2f9941b24af591f1e56339b97f5284 "Build-Number" to (build ?: ""), "Build-Time" to Instant.now().toString(), "Git-Branch" to gitBranch, // Paper -@@ -144,7 +144,7 @@ fun TaskContainer.registerRunTask( +@@ -148,7 +148,7 @@ fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { diff --git a/patches/server/0003-Threaded-Regions.patch b/patches/server/0003-Threaded-Regions.patch index f85dbce..734e745 100644 --- a/patches/server/0003-Threaded-Regions.patch +++ b/patches/server/0003-Threaded-Regions.patch @@ -6,1351 +6,896 @@ Subject: [PATCH] Threaded Regions See https://docs.papermc.io/folia/reference/overview and https://docs.papermc.io/folia/reference/region-logic -diff --git a/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRInt2IntHashTable.java b/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRInt2IntHashTable.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7869cc177c95e26dd9e1d3db5b50e996956edb24 ---- /dev/null -+++ b/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRInt2IntHashTable.java -@@ -0,0 +1,664 @@ -+package ca.spottedleaf.concurrentutil.map; +diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java +index 0abba00741b39b69a7f167e5d2670f2565c9a752..f1cb1ecedf0e183cbf6acf12e2034907a8aa9cdd 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java ++++ b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java +@@ -72,11 +72,15 @@ public final class ChunkSystem { + } + + public static void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder) { +- ++ // Folia start - threaded regions ++ level.regioniser.addChunk(holder.getPos().x, holder.getPos().z); ++ // Folia end - threaded regions + } + + public static void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder) { +- ++ // Folia start - threaded regions ++ level.regioniser.removeChunk(holder.getPos().x, holder.getPos().z); ++ // Folia end - threaded regions + } + + public static void onChunkPreBorder(final LevelChunk chunk, final ChunkHolder holder) { +diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java +index 11b7f15755dde766140c29bedca456c80d53293f..7d626bec6f0a4497026de6c0311e27cf95cfd757 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java ++++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java +@@ -1,5 +1,11 @@ + package ca.spottedleaf.moonrise.common.util; + ++import io.papermc.paper.threadedregions.RegionShutdownThread; ++import io.papermc.paper.threadedregions.RegionizedServer; ++import io.papermc.paper.threadedregions.RegionizedWorldData; ++import io.papermc.paper.threadedregions.ThreadedRegionizer; ++import io.papermc.paper.threadedregions.TickRegionScheduler; ++import io.papermc.paper.threadedregions.TickRegions; + import net.minecraft.core.BlockPos; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.level.ChunkPos; +@@ -94,46 +100,149 @@ public class TickThread extends Thread { + } + + public static boolean isShutdownThread() { +- return false; ++ return Thread.currentThread().getClass() == RegionShutdownThread.class; + } + + public static boolean isTickThreadFor(final Level world, final BlockPos pos) { +- return isTickThread(); ++ return isTickThreadFor(world, pos.getX() >> 4, pos.getZ() >> 4); + } + + public static boolean isTickThreadFor(final Level world, final ChunkPos pos) { +- return isTickThread(); ++ return isTickThreadFor(world, pos.x, pos.z); + } + + public static boolean isTickThreadFor(final Level world, final Vec3 pos) { +- return isTickThread(); ++ return isTickThreadFor(world, net.minecraft.util.Mth.floor(pos.x) >> 4, net.minecraft.util.Mth.floor(pos.z) >> 4); + } + + public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ) { +- return isTickThread(); ++ final ThreadedRegionizer.ThreadedRegion region = ++ TickRegionScheduler.getCurrentRegion(); ++ if (region == null) { ++ return isShutdownThread(); ++ } ++ return ((net.minecraft.server.level.ServerLevel)world).regioniser.getRegionAtUnsynchronised(chunkX, chunkZ) == region; + } + + public static boolean isTickThreadFor(final Level world, final AABB aabb) { +- return isTickThread(); ++ return isTickThreadFor( ++ world, ++ CoordinateUtils.getChunkCoordinate(aabb.minX), CoordinateUtils.getChunkCoordinate(aabb.minZ), ++ CoordinateUtils.getChunkCoordinate(aabb.maxX), CoordinateUtils.getChunkCoordinate(aabb.maxZ) ++ ); + } + + public static boolean isTickThreadFor(final Level world, final double blockX, final double blockZ) { +- return isTickThread(); ++ return isTickThreadFor(world, CoordinateUtils.getChunkCoordinate(blockX), CoordinateUtils.getChunkCoordinate(blockZ)); + } + + public static boolean isTickThreadFor(final Level world, final Vec3 position, final Vec3 deltaMovement, final int buffer) { +- return isTickThread(); ++ final int fromChunkX = CoordinateUtils.getChunkX(position); ++ final int fromChunkZ = CoordinateUtils.getChunkZ(position); + -+import ca.spottedleaf.concurrentutil.util.ArrayUtil; -+import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; -+import ca.spottedleaf.concurrentutil.util.Validate; -+import io.papermc.paper.util.IntegerUtil; -+import java.lang.invoke.VarHandle; -+import java.util.Arrays; -+import java.util.function.Consumer; -+import java.util.function.IntConsumer; ++ final int toChunkX = CoordinateUtils.getChunkCoordinate(position.x + deltaMovement.x); ++ final int toChunkZ = CoordinateUtils.getChunkCoordinate(position.z + deltaMovement.z); + -+public class SWMRInt2IntHashTable { -+ -+ protected int size; -+ -+ protected TableEntry[] table; -+ -+ protected final float loadFactor; -+ -+ protected static final VarHandle SIZE_HANDLE = ConcurrentUtil.getVarHandle(SWMRInt2IntHashTable.class, "size", int.class); -+ protected static final VarHandle TABLE_HANDLE = ConcurrentUtil.getVarHandle(SWMRInt2IntHashTable.class, "table", TableEntry[].class); -+ -+ /* size */ -+ -+ protected final int getSizePlain() { -+ return (int)SIZE_HANDLE.get(this); -+ } -+ -+ protected final int getSizeOpaque() { -+ return (int)SIZE_HANDLE.getOpaque(this); -+ } -+ -+ protected final int getSizeAcquire() { -+ return (int)SIZE_HANDLE.getAcquire(this); -+ } -+ -+ protected final void setSizePlain(final int value) { -+ SIZE_HANDLE.set(this, value); -+ } -+ -+ protected final void setSizeOpaque(final int value) { -+ SIZE_HANDLE.setOpaque(this, value); -+ } -+ -+ protected final void setSizeRelease(final int value) { -+ SIZE_HANDLE.setRelease(this, value); -+ } -+ -+ /* table */ -+ -+ protected final TableEntry[] getTablePlain() { -+ //noinspection unchecked -+ return (TableEntry[])TABLE_HANDLE.get(this); -+ } -+ -+ protected final TableEntry[] getTableAcquire() { -+ //noinspection unchecked -+ return (TableEntry[])TABLE_HANDLE.getAcquire(this); -+ } -+ -+ protected final void setTablePlain(final TableEntry[] table) { -+ TABLE_HANDLE.set(this, table); -+ } -+ -+ protected final void setTableRelease(final TableEntry[] table) { -+ TABLE_HANDLE.setRelease(this, table); -+ } -+ -+ protected static final int DEFAULT_CAPACITY = 16; -+ protected static final float DEFAULT_LOAD_FACTOR = 0.75f; -+ protected static final int MAXIMUM_CAPACITY = Integer.MIN_VALUE >>> 1; -+ -+ /** -+ * Constructs this map with a capacity of {@code 16} and load factor of {@code 0.75f}. -+ */ -+ public SWMRInt2IntHashTable() { -+ this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); -+ } -+ -+ /** -+ * Constructs this map with the specified capacity and load factor of {@code 0.75f}. -+ * @param capacity specified initial capacity, > 0 -+ */ -+ public SWMRInt2IntHashTable(final int capacity) { -+ this(capacity, DEFAULT_LOAD_FACTOR); -+ } -+ -+ /** -+ * Constructs this map with the specified capacity and load factor. -+ * @param capacity specified capacity, > 0 -+ * @param loadFactor specified load factor, > 0 && finite -+ */ -+ public SWMRInt2IntHashTable(final int capacity, final float loadFactor) { -+ final int tableSize = getCapacityFor(capacity); -+ -+ if (loadFactor <= 0.0 || !Float.isFinite(loadFactor)) { -+ throw new IllegalArgumentException("Invalid load factor: " + loadFactor); ++ // expect from < to, but that may not be the case ++ return isTickThreadFor( ++ world, ++ Math.min(fromChunkX, toChunkX) - buffer, ++ Math.min(fromChunkZ, toChunkZ) - buffer, ++ Math.max(fromChunkX, toChunkX) + buffer, ++ Math.max(fromChunkZ, toChunkZ) + buffer ++ ); + } + + public static boolean isTickThreadFor(final Level world, final int fromChunkX, final int fromChunkZ, final int toChunkX, final int toChunkZ) { +- return isTickThread(); ++ final ThreadedRegionizer.ThreadedRegion region = ++ TickRegionScheduler.getCurrentRegion(); ++ if (region == null) { ++ return isShutdownThread(); + } + -+ //noinspection unchecked -+ final TableEntry[] table = new TableEntry[tableSize]; -+ this.setTablePlain(table); ++ final int shift = ((net.minecraft.server.level.ServerLevel)world).regioniser.sectionChunkShift; + -+ if (tableSize == MAXIMUM_CAPACITY) { -+ this.threshold = -1; -+ } else { -+ this.threshold = getTargetCapacity(tableSize, loadFactor); -+ } ++ final int minSectionX = fromChunkX >> shift; ++ final int maxSectionX = toChunkX >> shift; ++ final int minSectionZ = fromChunkZ >> shift; ++ final int maxSectionZ = toChunkZ >> shift; + -+ this.loadFactor = loadFactor; -+ } -+ -+ /** -+ * Constructs this map with a capacity of {@code 16} or the specified map's size, whichever is larger, and -+ * with a load factor of {@code 0.75f}. -+ * All of the specified map's entries are copied into this map. -+ * @param other The specified map. -+ */ -+ public SWMRInt2IntHashTable(final SWMRInt2IntHashTable other) { -+ this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, other); -+ } -+ -+ /** -+ * Constructs this map with a minimum capacity of the specified capacity or the specified map's size, whichever is larger, and -+ * with a load factor of {@code 0.75f}. -+ * All of the specified map's entries are copied into this map. -+ * @param capacity specified capacity, > 0 -+ * @param other The specified map. -+ */ -+ public SWMRInt2IntHashTable(final int capacity, final SWMRInt2IntHashTable other) { -+ this(capacity, DEFAULT_LOAD_FACTOR, other); -+ } -+ -+ /** -+ * Constructs this map with a min capacity of the specified capacity or the specified map's size, whichever is larger, and -+ * with the specified load factor. -+ * All of the specified map's entries are copied into this map. -+ * @param capacity specified capacity, > 0 -+ * @param loadFactor specified load factor, > 0 && finite -+ * @param other The specified map. -+ */ -+ public SWMRInt2IntHashTable(final int capacity, final float loadFactor, final SWMRInt2IntHashTable other) { -+ this(Math.max(Validate.notNull(other, "Null map").size(), capacity), loadFactor); -+ this.putAll(other); -+ } -+ -+ public final float getLoadFactor() { -+ return this.loadFactor; -+ } -+ -+ protected static int getCapacityFor(final int capacity) { -+ if (capacity <= 0) { -+ throw new IllegalArgumentException("Invalid capacity: " + capacity); -+ } -+ if (capacity >= MAXIMUM_CAPACITY) { -+ return MAXIMUM_CAPACITY; -+ } -+ return IntegerUtil.roundCeilLog2(capacity); -+ } -+ -+ /** Callers must still use acquire when reading the value of the entry. */ -+ protected final TableEntry getEntryForOpaque(final int key) { -+ final int hash = SWMRInt2IntHashTable.getHash(key); -+ final TableEntry[] table = this.getTableAcquire(); -+ -+ for (TableEntry curr = ArrayUtil.getOpaque(table, hash & (table.length - 1)); curr != null; curr = curr.getNextOpaque()) { -+ if (key == curr.key) { -+ return curr; -+ } -+ } -+ -+ return null; -+ } -+ -+ protected final TableEntry getEntryForPlain(final int key) { -+ final int hash = SWMRInt2IntHashTable.getHash(key); -+ final TableEntry[] table = this.getTablePlain(); -+ -+ for (TableEntry curr = table[hash & (table.length - 1)]; curr != null; curr = curr.getNextPlain()) { -+ if (key == curr.key) { -+ return curr; -+ } -+ } -+ -+ return null; -+ } -+ -+ /* MT-Safe */ -+ -+ /** must be deterministic given a key */ -+ protected static int getHash(final int key) { -+ return it.unimi.dsi.fastutil.HashCommon.mix(key); -+ } -+ -+ // rets -1 if capacity*loadFactor is too large -+ protected static int getTargetCapacity(final int capacity, final float loadFactor) { -+ final double ret = (double)capacity * (double)loadFactor; -+ if (Double.isInfinite(ret) || ret >= ((double)Integer.MAX_VALUE)) { -+ return -1; -+ } -+ -+ return (int)ret; -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ @Override -+ public boolean equals(final Object obj) { -+ if (this == obj) { -+ return true; -+ } -+ /* Make no attempt to deal with concurrent modifications */ -+ if (!(obj instanceof SWMRInt2IntHashTable)) { -+ return false; -+ } -+ final SWMRInt2IntHashTable other = (SWMRInt2IntHashTable)obj; -+ -+ if (this.size() != other.size()) { -+ return false; -+ } -+ -+ final TableEntry[] table = this.getTableAcquire(); -+ -+ for (int i = 0, len = table.length; i < len; ++i) { -+ for (TableEntry curr = ArrayUtil.getOpaque(table, i); curr != null; curr = curr.getNextOpaque()) { -+ final int value = curr.getValueAcquire(); -+ -+ final int otherValue = other.get(curr.key); -+ if (value != otherValue) { ++ for (int secZ = minSectionZ; secZ <= maxSectionZ; ++secZ) { ++ for (int secX = minSectionX; secX <= maxSectionX; ++secX) { ++ final int lowerLeftCX = secX << shift; ++ final int lowerLeftCZ = secZ << shift; ++ if (((net.minecraft.server.level.ServerLevel)world).regioniser.getRegionAtUnsynchronised(lowerLeftCX, lowerLeftCZ) != region) { + return false; + } + } + } + + return true; -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ @Override -+ public int hashCode() { -+ /* Make no attempt to deal with concurrent modifications */ -+ int hash = 0; -+ final TableEntry[] table = this.getTableAcquire(); -+ -+ for (int i = 0, len = table.length; i < len; ++i) { -+ for (TableEntry curr = ArrayUtil.getOpaque(table, i); curr != null; curr = curr.getNextOpaque()) { -+ hash += curr.hashCode(); -+ } + } + + public static boolean isTickThreadFor(final Level world, final int chunkX, final int chunkZ, final int radius) { +- return isTickThread(); ++ return isTickThreadFor(world, chunkX - radius, chunkZ - radius, chunkX + radius, chunkZ + radius); + } + + public static boolean isTickThreadFor(final Entity entity) { +- return isTickThread(); ++ if (entity == null) { ++ return true; + } ++ final ThreadedRegionizer.ThreadedRegion region = ++ TickRegionScheduler.getCurrentRegion(); ++ if (region == null) { ++ if (RegionizedServer.isGlobalTickThread()) { ++ if (entity instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { ++ final net.minecraft.server.network.ServerGamePacketListenerImpl possibleBad = serverPlayer.connection; ++ if (possibleBad == null) { ++ return true; ++ } + -+ return hash; -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ @Override -+ public String toString() { -+ final StringBuilder builder = new StringBuilder(64); -+ builder.append("SingleWriterMultiReaderHashMap:{"); -+ -+ this.forEach((final int key, final int value) -> { -+ builder.append("{key: \"").append(key).append("\", value: \"").append(value).append("\"}"); -+ }); -+ -+ return builder.append('}').toString(); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ @Override -+ public SWMRInt2IntHashTable clone() { -+ return new SWMRInt2IntHashTable(this.getTableAcquire().length, this.loadFactor, this); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public void forEach(final Consumer action) { -+ Validate.notNull(action, "Null action"); -+ -+ final TableEntry[] table = this.getTableAcquire(); -+ for (int i = 0, len = table.length; i < len; ++i) { -+ for (TableEntry curr = ArrayUtil.getOpaque(table, i); curr != null; curr = curr.getNextOpaque()) { -+ action.accept(curr); -+ } -+ } -+ } -+ -+ @FunctionalInterface -+ public static interface BiIntIntConsumer { -+ public void accept(final int key, final int value); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public void forEach(final BiIntIntConsumer action) { -+ Validate.notNull(action, "Null action"); -+ -+ final TableEntry[] table = this.getTableAcquire(); -+ for (int i = 0, len = table.length; i < len; ++i) { -+ for (TableEntry curr = ArrayUtil.getOpaque(table, i); curr != null; curr = curr.getNextOpaque()) { -+ final int value = curr.getValueAcquire(); -+ -+ action.accept(curr.key, value); -+ } -+ } -+ } -+ -+ /** -+ * Provides the specified consumer with all keys contained within this map. -+ * @param action The specified consumer. -+ */ -+ public void forEachKey(final IntConsumer action) { -+ Validate.notNull(action, "Null action"); -+ -+ final TableEntry[] table = this.getTableAcquire(); -+ for (int i = 0, len = table.length; i < len; ++i) { -+ for (TableEntry curr = ArrayUtil.getOpaque(table, i); curr != null; curr = curr.getNextOpaque()) { -+ action.accept(curr.key); -+ } -+ } -+ } -+ -+ /** -+ * Provides the specified consumer with all values contained within this map. Equivalent to {@code map.values().forEach(Consumer)}. -+ * @param action The specified consumer. -+ */ -+ public void forEachValue(final IntConsumer action) { -+ Validate.notNull(action, "Null action"); -+ -+ final TableEntry[] table = this.getTableAcquire(); -+ for (int i = 0, len = table.length; i < len; ++i) { -+ for (TableEntry curr = ArrayUtil.getOpaque(table, i); curr != null; curr = curr.getNextOpaque()) { -+ final int value = curr.getValueAcquire(); -+ -+ action.accept(value); -+ } -+ } -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public int get(final int key) { -+ final TableEntry entry = this.getEntryForOpaque(key); -+ return entry == null ? 0 : entry.getValueAcquire(); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public boolean containsKey(final int key) { -+ final TableEntry entry = this.getEntryForOpaque(key); -+ return entry != null; -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public int getOrDefault(final int key, final int defaultValue) { -+ final TableEntry entry = this.getEntryForOpaque(key); -+ -+ return entry == null ? defaultValue : entry.getValueAcquire(); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public int size() { -+ return this.getSizeAcquire(); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public boolean isEmpty() { -+ return this.getSizeAcquire() == 0; -+ } -+ -+ /* Non-MT-Safe */ -+ -+ protected int threshold; -+ -+ protected final void checkResize(final int minCapacity) { -+ if (minCapacity <= this.threshold || this.threshold < 0) { -+ return; -+ } -+ -+ final TableEntry[] table = this.getTablePlain(); -+ int newCapacity = minCapacity >= MAXIMUM_CAPACITY ? MAXIMUM_CAPACITY : IntegerUtil.roundCeilLog2(minCapacity); -+ if (newCapacity < 0) { -+ newCapacity = MAXIMUM_CAPACITY; -+ } -+ if (newCapacity <= table.length) { -+ if (newCapacity == MAXIMUM_CAPACITY) { -+ return; -+ } -+ newCapacity = table.length << 1; -+ } -+ -+ //noinspection unchecked -+ final TableEntry[] newTable = new TableEntry[newCapacity]; -+ final int indexMask = newCapacity - 1; -+ -+ for (int i = 0, len = table.length; i < len; ++i) { -+ for (TableEntry entry = table[i]; entry != null; entry = entry.getNextPlain()) { -+ final int key = entry.key; -+ final int hash = SWMRInt2IntHashTable.getHash(key); -+ final int index = hash & indexMask; -+ -+ /* we need to create a new entry since there could be reading threads */ -+ final TableEntry insert = new TableEntry(key, entry.getValuePlain()); -+ -+ final TableEntry prev = newTable[index]; -+ -+ newTable[index] = insert; -+ insert.setNextPlain(prev); -+ } -+ } -+ -+ if (newCapacity == MAXIMUM_CAPACITY) { -+ this.threshold = -1; /* No more resizing */ -+ } else { -+ this.threshold = getTargetCapacity(newCapacity, this.loadFactor); -+ } -+ this.setTableRelease(newTable); /* use release to publish entries in table */ -+ } -+ -+ protected final int addToSize(final int num) { -+ final int newSize = this.getSizePlain() + num; -+ -+ this.setSizeOpaque(newSize); -+ this.checkResize(newSize); -+ -+ return newSize; -+ } -+ -+ protected final int removeFromSize(final int num) { -+ final int newSize = this.getSizePlain() - num; -+ -+ this.setSizeOpaque(newSize); -+ -+ return newSize; -+ } -+ -+ protected final int put(final int key, final int value, final boolean onlyIfAbsent) { -+ final TableEntry[] table = this.getTablePlain(); -+ final int hash = SWMRInt2IntHashTable.getHash(key); -+ final int index = hash & (table.length - 1); -+ -+ final TableEntry head = table[index]; -+ if (head == null) { -+ final TableEntry insert = new TableEntry(key, value); -+ ArrayUtil.setRelease(table, index, insert); -+ this.addToSize(1); -+ return 0; -+ } -+ -+ for (TableEntry curr = head;;) { -+ if (key == curr.key) { -+ if (onlyIfAbsent) { -+ return curr.getValuePlain(); ++ final net.minecraft.network.PacketListener packetListener = possibleBad.connection.getPacketListener(); ++ if (packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) { ++ return gamePacketListener.waitingForSwitchToConfig; ++ } ++ if (packetListener instanceof net.minecraft.server.network.ServerConfigurationPacketListenerImpl configurationPacketListener) { ++ return !configurationPacketListener.switchToMain; ++ } ++ return true; ++ } else { ++ return false; + } -+ -+ final int currVal = curr.getValuePlain(); -+ curr.setValueRelease(value); -+ return currVal; + } ++ if (isShutdownThread()) { ++ return true; ++ } ++ if (entity instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { ++ // off-main access to server player is never ok, server player is owned by one of global context or region context always ++ return false; ++ } ++ // only own entities that have not yet been added to the world + -+ final TableEntry next = curr.getNextPlain(); -+ if (next != null) { -+ curr = next; ++ // if the entity is removed, then it was in the world previously - which means that a region containing its location ++ // owns it ++ // if the entity has a callback, then it is contained in a world ++ return entity.hasNullCallback() && !entity.isRemoved(); ++ } ++ ++ final Level world = entity.level(); ++ if (world != region.regioniser.world) { ++ // world mismatch ++ return false; ++ } ++ ++ final RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); ++ ++ // pass through the check if the entity is removed and we own its chunk ++ if (worldData.hasEntity(entity)) { ++ return true; ++ } ++ ++ if (entity instanceof net.minecraft.server.level.ServerPlayer serverPlayer) { ++ net.minecraft.server.network.ServerGamePacketListenerImpl conn = serverPlayer.connection; ++ return conn != null && worldData.connections.contains(conn.connection); ++ } else { ++ return ((entity.hasNullCallback() || entity.isRemoved())) && isTickThreadFor((net.minecraft.server.level.ServerLevel)world, entity.chunkPosition()); ++ } + } + } +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java +index efc0c1acc8239dd7b00211a1d3bfd3fc3b2c810c..d13902e58c9bf6b25469a432bb87230da98b9d12 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java +@@ -460,6 +460,19 @@ public abstract class EntityLookup implements LevelEntityGetter { + return slices == null || !slices.isPreventingStatusUpdates(); + } + ++ // Folia start - region threading ++ // only appropriate to use when in shutdown, as this performs no logic hooks to properly add to world ++ public boolean addEntityForShutdownTeleportComplete(final Entity entity) { ++ final BlockPos pos = entity.blockPosition(); ++ final int sectionX = pos.getX() >> 4; ++ final int sectionY = Mth.clamp(pos.getY() >> 4, this.minSection, this.maxSection); ++ final int sectionZ = pos.getZ() >> 4; ++ final ChunkEntitySlices slices = this.getOrCreateChunk(sectionX, sectionZ); ++ ++ return slices.addEntity(entity, sectionY); ++ } ++ // Folia end - region threading ++ + protected void removeEntity(final Entity entity) { + final int sectionX = ((ChunkSystemEntity)entity).moonrise$getSectionX(); + final int sectionY = ((ChunkSystemEntity)entity).moonrise$getSectionY(); +@@ -1067,6 +1080,9 @@ public abstract class EntityLookup implements LevelEntityGetter { + EntityLookup.this.removeEntityCallback(entity); + + this.entity.setLevelCallback(NoOpCallback.INSTANCE); ++ ++ // only AFTER full removal callbacks, so that thread checking will work. // Folia - region threading ++ EntityLookup.this.world.getCurrentWorldData().removeEntity(entity); // Folia - region threading + } + } + +@@ -1080,4 +1096,4 @@ public abstract class EntityLookup implements LevelEntityGetter { + @Override + public void onRemove(final Entity.RemovalReason reason) {} + } +-} +\ No newline at end of file ++} +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java +index dacf2b2988ce603879fe525a3418ac77f8a663f7..e479cea245b0a345c46c9bb5fd9d86afba6fd77e 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java +@@ -16,8 +16,7 @@ public final class ServerEntityLookup extends EntityLookup { + private static final Entity[] EMPTY_ENTITY_ARRAY = new Entity[0]; + + private final ServerLevel serverWorld; +- public final ReferenceList trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker +- public final ReferenceList trackerUnloadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker ++ // Folia - move to regionized world data + + public ServerEntityLookup(final ServerLevel world, final LevelCallback worldCallback) { + super(world, worldCallback); +@@ -70,6 +69,7 @@ public final class ServerEntityLookup extends EntityLookup { + if (entity instanceof ServerPlayer player) { + ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().addPlayer(player); + } ++ this.world.getCurrentWorldData().addEntity(entity); // Folia - region threading + } + + @Override +@@ -77,22 +77,22 @@ public final class ServerEntityLookup extends EntityLookup { + if (entity instanceof ServerPlayer player) { + ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().removePlayer(player); + } +- this.trackerUnloadedEntities.remove(entity); // Moonrise - entity tracker ++ this.world.getCurrentWorldData().trackerUnloadedEntities.remove(entity); // Moonrise - entity tracker // Folia - region threading + } + + @Override + protected void entityStartLoaded(final Entity entity) { + // Moonrise start - entity tracker +- this.trackerEntities.add(entity); +- this.trackerUnloadedEntities.remove(entity); ++ this.world.getCurrentWorldData().trackerEntities.add(entity); // Folia - region threading ++ this.world.getCurrentWorldData().trackerUnloadedEntities.remove(entity); // Folia - region threading + // Moonrise end - entity tracker + } + + @Override + protected void entityEndLoaded(final Entity entity) { + // Moonrise start - entity tracker +- this.trackerEntities.remove(entity); +- this.trackerUnloadedEntities.add(entity); ++ this.world.getCurrentWorldData().trackerEntities.remove(entity); // Folia - region threading ++ this.world.getCurrentWorldData().trackerUnloadedEntities.add(entity); // Folia - region threading + // Moonrise end - entity tracker + } + +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +index ab18bbf87dfc1455ed185a5152dad6d236565ecc..d246389333749b55822f985597edfe761d89caf9 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +@@ -213,7 +213,7 @@ public final class RegionizedPlayerChunkLoader { + final PlayerChunkLoaderData loader = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader(); + + if (loader == null) { +- return; ++ throw new IllegalStateException("Player is already removed from player chunk loader"); // Folia - region threading + } + + loader.remove(); +@@ -301,7 +301,7 @@ public final class RegionizedPlayerChunkLoader { + public void tick() { + TickThread.ensureTickThread("Cannot tick player chunk loader async"); + long currTime = System.nanoTime(); +- for (final ServerPlayer player : new java.util.ArrayList<>(this.world.players())) { ++ for (final ServerPlayer player : new java.util.ArrayList<>(this.world.getLocalPlayers())) { // Folia - region threding + final PlayerChunkLoaderData loader = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader(); + if (loader == null || loader.removed || loader.world != this.world) { + // not our problem anymore +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/queue/ChunkUnloadQueue.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/queue/ChunkUnloadQueue.java +index 7eafc5b7cba23d8dec92ecc1050afe3fd8c9e309..4bfcae47ed76346e6200514ebce5b04f907c5026 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/queue/ChunkUnloadQueue.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/queue/ChunkUnloadQueue.java +@@ -29,6 +29,39 @@ public final class ChunkUnloadQueue { + + public static record SectionToUnload(int sectionX, int sectionZ, long order, int count) {} + ++ // Folia start - threaded regions ++ public List retrieveForCurrentRegion() { ++ final io.papermc.paper.threadedregions.ThreadedRegionizer.ThreadedRegion region = ++ io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion(); ++ final io.papermc.paper.threadedregions.ThreadedRegionizer regionizer = region.regioniser; ++ final int shift = this.coordinateShift; ++ ++ final List ret = new ArrayList<>(); ++ ++ for (final Iterator> iterator = this.unloadSections.entryIterator(); iterator.hasNext();) { ++ final ConcurrentLong2ReferenceChainedHashTable.TableEntry entry = iterator.next(); ++ final long key = entry.getKey(); ++ final UnloadSection section = entry.getValue(); ++ final int sectionX = CoordinateUtils.getChunkX(key); ++ final int sectionZ = CoordinateUtils.getChunkZ(key); ++ final int chunkX = sectionX << shift; ++ final int chunkZ = sectionZ << shift; ++ ++ if (regionizer.getRegionAtUnsynchronised(chunkX, chunkZ) != region) { + continue; + } + -+ final TableEntry insert = new TableEntry(key, value); -+ -+ curr.setNextRelease(insert); -+ this.addToSize(1); -+ return 0; -+ } -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public int put(final int key, final int value) { -+ return this.put(key, value, false); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public int putIfAbsent(final int key, final int value) { -+ return this.put(key, value, true); -+ } -+ -+ protected final int remove(final int key, final int hash) { -+ final TableEntry[] table = this.getTablePlain(); -+ final int index = (table.length - 1) & hash; -+ -+ final TableEntry head = table[index]; -+ if (head == null) { -+ return 0; ++ ret.add(new SectionToUnload(sectionX, sectionZ, section.order, section.chunks.size())); + } + -+ if (head.key == key) { -+ ArrayUtil.setRelease(table, index, head.getNextPlain()); -+ this.removeFromSize(1); -+ -+ return head.getValuePlain(); -+ } -+ -+ for (TableEntry curr = head.getNextPlain(), prev = head; curr != null; prev = curr, curr = curr.getNextPlain()) { -+ if (key == curr.key) { -+ prev.setNextRelease(curr.getNextPlain()); -+ this.removeFromSize(1); -+ -+ return curr.getValuePlain(); -+ } -+ } -+ -+ return 0; -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public int remove(final int key) { -+ return this.remove(key, SWMRInt2IntHashTable.getHash(key)); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public void putAll(final SWMRInt2IntHashTable map) { -+ Validate.notNull(map, "Null map"); -+ -+ final int size = map.size(); -+ this.checkResize(Math.max(this.getSizePlain() + size/2, size)); /* preemptively resize */ -+ map.forEach(this::put); -+ } -+ -+ /** -+ * {@inheritDoc} -+ *

-+ * This call is non-atomic and the order that which entries are removed is undefined. The clear operation itself -+ * is release ordered, that is, after the clear operation is performed a release fence is performed. -+ *

-+ */ -+ public void clear() { -+ Arrays.fill(this.getTablePlain(), null); -+ this.setSizeRelease(0); -+ } -+ -+ public static final class TableEntry { -+ -+ protected final int key; -+ protected int value; -+ -+ protected TableEntry next; -+ -+ protected static final VarHandle VALUE_HANDLE = ConcurrentUtil.getVarHandle(TableEntry.class, "value", Object.class); -+ protected static final VarHandle NEXT_HANDLE = ConcurrentUtil.getVarHandle(TableEntry.class, "next", TableEntry.class); -+ -+ /* value */ -+ -+ protected final int getValuePlain() { -+ //noinspection unchecked -+ return (int)VALUE_HANDLE.get(this); -+ } -+ -+ protected final int getValueAcquire() { -+ //noinspection unchecked -+ return (int)VALUE_HANDLE.getAcquire(this); -+ } -+ -+ protected final void setValueRelease(final int to) { -+ VALUE_HANDLE.setRelease(this, to); -+ } -+ -+ /* next */ -+ -+ protected final TableEntry getNextPlain() { -+ //noinspection unchecked -+ return (TableEntry)NEXT_HANDLE.get(this); -+ } -+ -+ protected final TableEntry getNextOpaque() { -+ //noinspection unchecked -+ return (TableEntry)NEXT_HANDLE.getOpaque(this); -+ } -+ -+ protected final void setNextPlain(final TableEntry next) { -+ NEXT_HANDLE.set(this, next); -+ } -+ -+ protected final void setNextRelease(final TableEntry next) { -+ NEXT_HANDLE.setRelease(this, next); -+ } -+ -+ protected TableEntry(final int key, final int value) { -+ this.key = key; -+ this.value = value; -+ } -+ -+ public int getKey() { -+ return this.key; -+ } -+ -+ public int getValue() { -+ return this.getValueAcquire(); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ public int setValue(final int value) { -+ final int curr = this.getValuePlain(); -+ -+ this.setValueRelease(value); -+ return curr; -+ } -+ -+ protected static int hash(final int key, final int value) { -+ return SWMRInt2IntHashTable.getHash(key) ^ SWMRInt2IntHashTable.getHash(value); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ @Override -+ public int hashCode() { -+ return hash(this.key, this.getValueAcquire()); -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ -+ @Override -+ public boolean equals(final Object obj) { -+ if (this == obj) { -+ return true; -+ } -+ -+ if (!(obj instanceof TableEntry)) { -+ return false; -+ } -+ final TableEntry other = (TableEntry)obj; -+ final int otherKey = other.getKey(); -+ final int thisKey = this.getKey(); -+ final int otherValue = other.getValueAcquire(); -+ final int thisVal = this.getValueAcquire(); -+ return (thisKey == otherKey) && (thisVal == otherValue); -+ } -+ } -+ -+} -diff --git a/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java b/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java -index 94fca3c9b31ca4e40688209e419e93320b0f7c34..fea1244ee156e0f562f295f31e3da288774d2f5c 100644 ---- a/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java -+++ b/src/main/java/ca/spottedleaf/concurrentutil/map/SWMRLong2ObjectHashTable.java -@@ -534,6 +534,44 @@ public class SWMRLong2ObjectHashTable { - return null; - } - -+ protected final V remove(final long key, final int hash, final V expect) { -+ final TableEntry[] table = this.getTablePlain(); -+ final int index = (table.length - 1) & hash; -+ -+ final TableEntry head = table[index]; -+ if (head == null) { -+ return null; -+ } -+ -+ if (head.key == key) { -+ final V val = head.value; -+ if (val == expect || val.equals(expect)) { -+ ArrayUtil.setRelease(table, index, head.getNextPlain()); -+ this.removeFromSize(1); -+ -+ return head.getValuePlain(); -+ } else { -+ return null; -+ } -+ } -+ -+ for (TableEntry curr = head.getNextPlain(), prev = head; curr != null; prev = curr, curr = curr.getNextPlain()) { -+ if (key == curr.key) { -+ final V val = curr.value; -+ if (val == expect || val.equals(expect)) { -+ prev.setNextRelease(curr.getNextPlain()); -+ this.removeFromSize(1); -+ -+ return curr.getValuePlain(); -+ } else { -+ return null; -+ } -+ } -+ } -+ -+ return null; -+ } -+ - /** - * {@inheritDoc} - */ -@@ -541,6 +579,10 @@ public class SWMRLong2ObjectHashTable { - return this.remove(key, SWMRLong2ObjectHashTable.getHash(key)); - } - -+ public boolean remove(final long key, final V expect) { -+ return this.remove(key, SWMRLong2ObjectHashTable.getHash(key), expect) != null; -+ } -+ - /** - * {@inheritDoc} - */ -diff --git a/src/main/java/ca/spottedleaf/concurrentutil/scheduler/SchedulerThreadPool.java b/src/main/java/ca/spottedleaf/concurrentutil/scheduler/SchedulerThreadPool.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0ce825d7af2a1dbeac5c22640534ee1901edce20 ---- /dev/null -+++ b/src/main/java/ca/spottedleaf/concurrentutil/scheduler/SchedulerThreadPool.java -@@ -0,0 +1,543 @@ -+package ca.spottedleaf.concurrentutil.scheduler; -+ -+import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; -+import ca.spottedleaf.concurrentutil.util.TimeUtil; -+import com.mojang.logging.LogUtils; -+import io.papermc.paper.util.TraceUtil; -+import io.papermc.paper.util.set.LinkedSortedSet; -+import org.slf4j.Logger; -+import java.lang.invoke.VarHandle; -+import java.util.BitSet; -+import java.util.Comparator; -+import java.util.PriorityQueue; -+import java.util.concurrent.ThreadFactory; -+import java.util.concurrent.atomic.AtomicInteger; -+import java.util.concurrent.atomic.AtomicLong; -+import java.util.concurrent.locks.LockSupport; -+import java.util.function.BooleanSupplier; -+ -+public class SchedulerThreadPool { -+ -+ private static final Logger LOGGER = LogUtils.getLogger(); -+ -+ public static final long DEADLINE_NOT_SET = Long.MIN_VALUE; -+ -+ private static final Comparator TICK_COMPARATOR_BY_TIME = (final SchedulableTick t1, final SchedulableTick t2) -> { -+ final int timeCompare = TimeUtil.compareTimes(t1.scheduledStart, t2.scheduledStart); -+ if (timeCompare != 0) { -+ return timeCompare; -+ } -+ -+ return Long.compare(t1.id, t2.id); -+ }; -+ -+ private final TickThreadRunner[] runners; -+ private final Thread[] threads; -+ private final LinkedSortedSet awaiting = new LinkedSortedSet<>(TICK_COMPARATOR_BY_TIME); -+ private final PriorityQueue queued = new PriorityQueue<>(TICK_COMPARATOR_BY_TIME); -+ private final BitSet idleThreads; -+ -+ private final Object scheduleLock = new Object(); -+ -+ private volatile boolean halted; -+ -+ public SchedulerThreadPool(final int threads, final ThreadFactory threadFactory) { -+ final BitSet idleThreads = new BitSet(threads); -+ for (int i = 0; i < threads; ++i) { -+ idleThreads.set(i); -+ } -+ this.idleThreads = idleThreads; -+ -+ final TickThreadRunner[] runners = new TickThreadRunner[threads]; -+ final Thread[] t = new Thread[threads]; -+ for (int i = 0; i < threads; ++i) { -+ runners[i] = new TickThreadRunner(i, this); -+ t[i] = threadFactory.newThread(runners[i]); -+ } -+ -+ this.threads = t; -+ this.runners = runners; -+ } -+ -+ /** -+ * Starts the threads in this pool. -+ */ -+ public void start() { -+ for (final Thread thread : this.threads) { -+ thread.start(); -+ } -+ } -+ -+ /** -+ * Attempts to prevent further execution of tasks, optionally waiting for the scheduler threads to die. -+ * -+ * @param sync Whether to wait for the scheduler threads to die. -+ * @param maxWaitNS The maximum time, in ns, to wait for the scheduler threads to die. -+ * @return {@code true} if sync was false, or if sync was true and the scheduler threads died before the timeout. -+ * Otherwise, returns {@code false} if the time elapsed exceeded the maximum wait time. -+ */ -+ public boolean halt(final boolean sync, final long maxWaitNS) { -+ this.halted = true; -+ for (final Thread thread : this.threads) { -+ // force response to halt -+ LockSupport.unpark(thread); -+ } -+ final long time = System.nanoTime(); -+ if (sync) { -+ // start at 10 * 0.5ms -> 5ms -+ for (long failures = 9L;; failures = ConcurrentUtil.linearLongBackoff(failures, 500_000L, 50_000_000L)) { -+ boolean allDead = true; -+ for (final Thread thread : this.threads) { -+ if (thread.isAlive()) { -+ allDead = false; -+ break; -+ } -+ } -+ if (allDead) { -+ return true; -+ } -+ if ((System.nanoTime() - time) >= maxWaitNS) { -+ return false; -+ } -+ } -+ } -+ -+ return true; -+ } -+ -+ public void dumpAliveThreadTraces(final String reason) { -+ for (final Thread thread : this.threads) { -+ if (thread.isAlive()) { -+ TraceUtil.dumpTraceForThread(thread, reason); -+ } -+ } -+ } -+ -+ /** -+ * Returns an array of the underlying scheduling threads. -+ */ -+ public Thread[] getThreads() { -+ return this.threads.clone(); -+ } -+ -+ private void insertFresh(final SchedulableTick task) { -+ final TickThreadRunner[] runners = this.runners; -+ -+ final int firstIdleThread = this.idleThreads.nextSetBit(0); -+ -+ if (firstIdleThread != -1) { -+ // push to idle thread -+ this.idleThreads.clear(firstIdleThread); -+ final TickThreadRunner runner = runners[firstIdleThread]; -+ task.awaitingLink = this.awaiting.addLast(task); -+ runner.acceptTask(task); -+ return; -+ } -+ -+ // try to replace the last awaiting task -+ final SchedulableTick last = this.awaiting.last(); -+ -+ if (last != null && TICK_COMPARATOR_BY_TIME.compare(task, last) < 0) { -+ // need to replace the last task -+ this.awaiting.pollLast(); -+ last.awaitingLink = null; -+ task.awaitingLink = this.awaiting.addLast(task); -+ // need to add task to queue to be picked up later -+ this.queued.add(last); -+ -+ final TickThreadRunner runner = last.ownedBy; -+ runner.replaceTask(task); -+ -+ return; -+ } -+ -+ // add to queue, will be picked up later -+ this.queued.add(task); -+ } -+ -+ private void takeTask(final TickThreadRunner runner, final SchedulableTick tick) { -+ if (!this.awaiting.remove(tick.awaitingLink)) { -+ throw new IllegalStateException("Task is not in awaiting"); -+ } -+ tick.awaitingLink = null; -+ } -+ -+ private SchedulableTick returnTask(final TickThreadRunner runner, final SchedulableTick reschedule) { -+ if (reschedule != null) { -+ this.queued.add(reschedule); -+ } -+ final SchedulableTick ret = this.queued.poll(); -+ if (ret == null) { -+ this.idleThreads.set(runner.id); -+ } else { -+ ret.awaitingLink = this.awaiting.addLast(ret); -+ } ++ ret.sort((final SectionToUnload s1, final SectionToUnload s2) -> { ++ return Long.compare(s1.order, s2.order); ++ }); + + return ret; + } ++ // Folia end - threaded regions + -+ public void schedule(final SchedulableTick task) { -+ synchronized (this.scheduleLock) { -+ if (!task.tryMarkScheduled()) { -+ throw new IllegalStateException("Task " + task + " is already scheduled or cancelled"); + public List retrieveForAllRegions() { + final List ret = new ArrayList<>(); + +@@ -141,4 +174,4 @@ public final class ChunkUnloadQueue { + this.order = order; + } + } +-} +\ No newline at end of file ++} +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd677cd937 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +@@ -56,6 +56,14 @@ import java.util.concurrent.atomic.AtomicReference; + import java.util.concurrent.locks.LockSupport; + import java.util.function.Predicate; + ++// Folia start - region threading ++import io.papermc.paper.threadedregions.RegionizedServer; ++import io.papermc.paper.threadedregions.ThreadedRegionizer; ++import io.papermc.paper.threadedregions.TickRegionScheduler; ++import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; ++// Folia end - region threading ++ + public final class ChunkHolderManager { + + private static final Logger LOGGER = LogUtils.getClassLogger(); +@@ -78,29 +86,83 @@ public final class ChunkHolderManager { + private final ConcurrentLong2ReferenceChainedHashTable chunkHolders = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(16384, 0.25f); + private final ServerLevel world; + private final ChunkTaskScheduler taskScheduler; +- private long currentTick; ++ // Folia start - region threading ++ public static final class HolderManagerRegionData { ++ private final ArrayDeque pendingFullLoadUpdate = new ArrayDeque<>(); ++ private final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> { ++ if (c1 == c2) { ++ return 0; + } + -+ task.schedulerOwnedBy = this; ++ final int saveTickCompare = Long.compare(c1.lastAutoSave, c2.lastAutoSave); + -+ this.insertFresh(task); -+ } ++ if (saveTickCompare != 0) { ++ return saveTickCompare; ++ } ++ ++ final long coord1 = CoordinateUtils.getChunkKey(c1.chunkX, c1.chunkZ); ++ final long coord2 = CoordinateUtils.getChunkKey(c2.chunkX, c2.chunkZ); + +- private final ArrayDeque pendingFullLoadUpdate = new ArrayDeque<>(); +- private final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> { +- if (c1 == c2) { +- return 0; ++ if (coord1 == coord2) { ++ throw new IllegalStateException("Duplicate chunkholder in auto save queue"); ++ } ++ ++ return Long.compare(coord1, coord2); ++ }); ++ ++ public void merge(final HolderManagerRegionData into, final long tickOffset) { ++ // Order doesn't really matter for the pending full update... ++ into.pendingFullLoadUpdate.addAll(this.pendingFullLoadUpdate); ++ ++ // We need to copy the set to iterate over, because modifying the field used in compareTo while iterating ++ // will destroy the result from compareTo (However, the set is not destroyed _after_ iteration because a constant ++ // addition to every entry will not affect compareTo). ++ for (final NewChunkHolder holder : new ArrayList<>(this.autoSaveQueue)) { ++ holder.lastAutoSave += tickOffset; ++ into.autoSaveQueue.add(holder); ++ } + } + +- final int saveTickCompare = Long.compare(c1.lastAutoSave, c2.lastAutoSave); ++ public void split(final int chunkToRegionShift, final Long2ReferenceOpenHashMap regionToData, ++ final ReferenceOpenHashSet dataSet) { ++ for (final NewChunkHolder fullLoadUpdate : this.pendingFullLoadUpdate) { ++ final int regionCoordinateX = fullLoadUpdate.chunkX >> chunkToRegionShift; ++ final int regionCoordinateZ = fullLoadUpdate.chunkZ >> chunkToRegionShift; ++ ++ final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ)); ++ if (data != null) { ++ data.pendingFullLoadUpdate.add(fullLoadUpdate); ++ } // else: fullLoadUpdate is an unloaded chunk holder ++ } ++ ++ for (final NewChunkHolder autoSave : this.autoSaveQueue) { ++ final int regionCoordinateX = autoSave.chunkX >> chunkToRegionShift; ++ final int regionCoordinateZ = autoSave.chunkZ >> chunkToRegionShift; + +- if (saveTickCompare != 0) { +- return saveTickCompare; ++ final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ)); ++ if (data != null) { ++ data.autoSaveQueue.add(autoSave); ++ } // else: autoSave is an unloaded chunk holder ++ } + } + } + +- final long coord1 = CoordinateUtils.getChunkKey(c1.chunkX, c1.chunkZ); +- final long coord2 = CoordinateUtils.getChunkKey(c2.chunkX, c2.chunkZ); ++ private ChunkHolderManager.HolderManagerRegionData getCurrentRegionData() { ++ final ThreadedRegionizer.ThreadedRegion region = ++ TickRegionScheduler.getCurrentRegion(); + +- if (coord1 == coord2) { +- throw new IllegalStateException("Duplicate chunkholder in auto save queue"); ++ if (region == null) { ++ return null; + } + +- return Long.compare(coord1, coord2); +- }); ++ if (this.world != null && this.world != region.getData().world) { ++ throw new IllegalStateException("World check failed: expected world: " + this.world.getWorld().getKey() + ", region world: " + region.getData().world.getWorld().getKey()); ++ } + -+ public boolean updateTickStartToMax(final SchedulableTick task, final long newStart) { -+ synchronized (this.scheduleLock) { -+ if (TimeUtil.compareTimes(newStart, task.getScheduledStart()) <= 0) { -+ return false; -+ } -+ if (this.queued.remove(task)) { -+ task.setScheduledStart(newStart); -+ this.queued.add(task); -+ return true; -+ } -+ if (task.awaitingLink != null) { -+ this.awaiting.remove(task.awaitingLink); -+ task.awaitingLink = null; ++ return region.getData().getHolderManagerRegionData(); ++ } ++ // Folia end - region threading + -+ // re-queue task -+ task.setScheduledStart(newStart); -+ this.queued.add(task); + + public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) { + this.world = world; +@@ -185,8 +247,13 @@ public final class ChunkHolderManager { + } + + public void close(final boolean save, final boolean halt) { ++ // Folia start - region threading ++ this.close(save, halt, true, true, true); ++ } ++ public void close(final boolean save, final boolean halt, final boolean first, final boolean last, final boolean checkRegions) { ++ // Folia end - region threading + TickThread.ensureTickThread("Closing world off-main"); +- if (halt) { ++ if (halt && halt) { // Folia - region threading + LOGGER.info("Waiting 60s for chunk system to halt for world '" + WorldUtil.getWorldName(this.world) + "'"); + if (!this.taskScheduler.halt(true, TimeUnit.SECONDS.toNanos(60L))) { + LOGGER.warn("Failed to halt world generation/loading tasks for world '" + WorldUtil.getWorldName(this.world) + "'"); +@@ -196,9 +263,10 @@ public final class ChunkHolderManager { + } + + if (save) { +- this.saveAllChunks(true, true, true); ++ this.saveAllChunksRegionised(true, true, true, first, last, checkRegions); // Folia - region threading + } + ++ if (last) { // Folia - region threading + boolean hasTasks = false; + for (final RegionFileIOThread.RegionFileType type : RegionFileIOThread.RegionFileType.values()) { + if (RegionFileIOThread.getControllerFor(this.world, type).hasTasks()) { +@@ -218,28 +286,35 @@ public final class ChunkHolderManager { + LOGGER.error("Failed to close '" + type.name() + "' regionfile cache for world '" + WorldUtil.getWorldName(this.world) + "'", ex); + } + } ++ } // Folia - region threading + } + + void ensureInAutosave(final NewChunkHolder holder) { +- if (!this.autoSaveQueue.contains(holder)) { +- holder.lastAutoSave = this.currentTick; +- this.autoSaveQueue.add(holder); ++ // Folia start - region threading ++ final HolderManagerRegionData regionData = this.getCurrentRegionData(); ++ if (!regionData.autoSaveQueue.contains(holder)) { ++ holder.lastAutoSave = RegionizedServer.getCurrentTick(); ++ regionData.autoSaveQueue.add(holder); ++ // Folia end - region threading + } + } + + public void autoSave() { + final List reschedule = new ArrayList<>(); +- final long currentTick = this.currentTick; ++ final long currentTick = RegionizedServer.getCurrentTick(); // Folia - region threading + final long maxSaveTime = currentTick - Math.max(1L, this.world.paperConfig().chunks.autoSaveInterval.value()); + final int maxToSave = this.world.paperConfig().chunks.maxAutoSaveChunksPerTick; +- for (int autoSaved = 0; autoSaved < maxToSave && !this.autoSaveQueue.isEmpty();) { +- final NewChunkHolder holder = this.autoSaveQueue.first(); ++ // Folia start - region threading ++ final HolderManagerRegionData regionData = this.getCurrentRegionData(); ++ for (int autoSaved = 0; autoSaved < maxToSave && !regionData.autoSaveQueue.isEmpty();) { ++ final NewChunkHolder holder = regionData.autoSaveQueue.first(); ++ // Folia end - region threading + + if (holder.lastAutoSave > maxSaveTime) { + break; + } + +- this.autoSaveQueue.remove(holder); ++ regionData.autoSaveQueue.remove(holder); // Folia - region threading + + holder.lastAutoSave = currentTick; + if (holder.save(false) != null) { +@@ -253,15 +328,38 @@ public final class ChunkHolderManager { + + for (final NewChunkHolder holder : reschedule) { + if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) { +- this.autoSaveQueue.add(holder); ++ regionData.autoSaveQueue.add(holder); // Folia start - region threading + } + } + } + + public void saveAllChunks(final boolean flush, final boolean shutdown, final boolean logProgress) { +- final List holders = this.getChunkHolders(); ++ // Folia start - region threading ++ this.saveAllChunksRegionised(flush, shutdown, logProgress, true, true, true); ++ } ++ public void saveAllChunksRegionised(final boolean flush, final boolean shutdown, final boolean logProgress, final boolean first, final boolean last, final boolean checkRegion) { ++ final List holders = new java.util.ArrayList<>(this.chunkHolders.size() / 10); ++ // we could iterate through all chunk holders with thread checks, however for many regions the iteration cost alone ++ // will multiply. to avoid this, we can simply iterate through all owned sections ++ final int regionShift = this.world.moonrise$getRegionChunkShift(); ++ for (final LongIterator iterator = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion().getOwnedSectionsUnsynchronised(); iterator.hasNext();) { ++ final long sectionKey = iterator.nextLong(); ++ final int width = 1 << regionShift; ++ final int offsetX = CoordinateUtils.getChunkX(sectionKey) << regionShift; ++ final int offsetZ = CoordinateUtils.getChunkZ(sectionKey) << regionShift; + -+ // now we need to replace the task the runner was waiting for -+ final TickThreadRunner runner = task.ownedBy; -+ final SchedulableTick replace = this.queued.poll(); -+ -+ // replace cannot be null, since we have added a task to queued -+ if (replace != task) { -+ runner.replaceTask(replace); ++ for (int dz = 0; dz < width; ++dz) { ++ for (int dx = 0; dx < width; ++dx) { ++ final NewChunkHolder holder = this.getChunkHolder(offsetX | dx, offsetZ | dz); ++ if (holder != null) { ++ holders.add(holder); ++ } + } -+ -+ return true; + } ++ } ++ // Folia end - region threading + +- if (logProgress) { ++ if (first && logProgress) { // Folia - region threading + LOGGER.info("Saving all chunkholders for world '" + WorldUtil.getWorldName(this.world) + "'"); + } + +@@ -280,6 +378,12 @@ public final class ChunkHolderManager { + + for (int i = 0, len = holders.size(); i < len; ++i) { + final NewChunkHolder holder = holders.get(i); ++ // Folia start - region threading ++ if (!checkRegion && !TickThread.isTickThreadFor(this.world, holder.chunkX, holder.chunkZ)) { ++ // skip holders that would fail the thread check ++ continue; ++ } ++ // Folia end - region threading + try { + final NewChunkHolder.SaveStat saveStat = holder.save(shutdown); + if (saveStat != null) { +@@ -310,7 +414,7 @@ public final class ChunkHolderManager { + } + } + } +- if (flush) { ++ if (last && flush) { // Folia - region threading + RegionFileIOThread.flush(); + try { + RegionFileIOThread.flushRegionStorages(this.world); +@@ -711,7 +815,13 @@ public final class ChunkHolderManager { + } + + public void tick() { +- ++this.currentTick; ++ // Folia start - region threading ++ final ThreadedRegionizer.ThreadedRegion region = ++ TickRegionScheduler.getCurrentRegion(); ++ if (region == null) { ++ throw new IllegalStateException("Not running tick() while on a region"); ++ } ++ // Folia end - region threading + + final int sectionShift = ((ChunkSystemServerLevel)this.world).moonrise$getRegionChunkShift(); + +@@ -725,7 +835,7 @@ public final class ChunkHolderManager { + return removeDelay <= 0L; + }; + +- for (final PrimitiveIterator.OfLong iterator = this.sectionToChunkToExpireCount.keyIterator(); iterator.hasNext();) { ++ for (final LongIterator iterator = region.getOwnedSectionsUnsynchronised(); iterator.hasNext();) { + final long sectionKey = iterator.nextLong(); + + if (!this.sectionToChunkToExpireCount.containsKey(sectionKey)) { +@@ -1010,26 +1120,58 @@ public final class ChunkHolderManager { + if (changedFullStatus.isEmpty()) { + return; + } +- if (!TickThread.isTickThread()) { +- this.taskScheduler.scheduleChunkTask(() -> { +- final ArrayDeque pendingFullLoadUpdate = ChunkHolderManager.this.pendingFullLoadUpdate; +- for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { +- pendingFullLoadUpdate.add(changedFullStatus.get(i)); +- } + +- ChunkHolderManager.this.processPendingFullUpdate(); +- }, PrioritisedExecutor.Priority.HIGHEST); +- } else { +- final ArrayDeque pendingFullLoadUpdate = this.pendingFullLoadUpdate; +- for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { +- pendingFullLoadUpdate.add(changedFullStatus.get(i)); ++ // Folia start - region threading ++ final Long2ObjectOpenHashMap> sectionToUpdates = new Long2ObjectOpenHashMap<>(); ++ final List thisRegionHolders = new ArrayList<>(); + ++ final int regionShift = this.world.moonrise$getRegionChunkShift(); ++ final ThreadedRegionizer.ThreadedRegion thisRegion ++ = TickRegionScheduler.getCurrentRegion(); ++ ++ for (final NewChunkHolder holder : changedFullStatus) { ++ final int regionX = holder.chunkX >> regionShift; ++ final int regionZ = holder.chunkZ >> regionShift; ++ final long holderSectionKey = CoordinateUtils.getChunkKey(regionX, regionZ); ++ ++ // region may be null ++ if (thisRegion != null && this.world.regioniser.getRegionAtUnsynchronised(holder.chunkX, holder.chunkZ) == thisRegion) { ++ thisRegionHolders.add(holder); ++ } else { ++ sectionToUpdates.computeIfAbsent(holderSectionKey, (final long keyInMap) -> { ++ return new ArrayList<>(); ++ }).add(holder); ++ } ++ } ++ // Folia end - region threading ++ ++ // Folia start - region threading ++ if (!thisRegionHolders.isEmpty()) { ++ thisRegion.getData().getHolderManagerRegionData().pendingFullLoadUpdate.addAll(thisRegionHolders); ++ } ++ ++ if (!sectionToUpdates.isEmpty()) { ++ for (final Iterator>> iterator = sectionToUpdates.long2ObjectEntrySet().fastIterator(); ++ iterator.hasNext();) { ++ final Long2ObjectMap.Entry> entry = iterator.next(); ++ final long sectionKey = entry.getLongKey(); ++ ++ final int chunkX = CoordinateUtils.getChunkX(sectionKey) << regionShift; ++ final int chunkZ = CoordinateUtils.getChunkZ(sectionKey) << regionShift; ++ ++ final List regionHolders = entry.getValue(); ++ this.taskScheduler.scheduleChunkTaskEventually(chunkX, chunkZ, () -> { // Folia - region threading ++ ChunkHolderManager.this.getCurrentRegionData().pendingFullLoadUpdate.addAll(regionHolders); ++ ChunkHolderManager.this.processPendingFullUpdate(); ++ }, PrioritisedExecutor.Priority.HIGHEST); ++ // Folia end - region threading + } + } + } + + private void removeChunkHolder(final NewChunkHolder holder) { + holder.markUnloaded(); +- this.autoSaveQueue.remove(holder); ++ this.getCurrentRegionData().autoSaveQueue.remove(holder); // Folia - region threading + ChunkSystem.onChunkHolderDelete(this.world, holder.vanillaChunkHolder); + this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ)); + +@@ -1043,7 +1185,7 @@ public final class ChunkHolderManager { + throw new IllegalStateException("Cannot unload chunks recursively"); + } + final int sectionShift = this.unloadQueue.coordinateShift; // sectionShift <= lock shift +- final List unloadSectionsForRegion = this.unloadQueue.retrieveForAllRegions(); ++ final List unloadSectionsForRegion = this.unloadQueue.retrieveForCurrentRegion(); // Folia - threaded regions + int unloadCountTentative = 0; + for (final ChunkUnloadQueue.SectionToUnload sectionRef : unloadSectionsForRegion) { + final ChunkUnloadQueue.UnloadSection section +@@ -1353,7 +1495,13 @@ public final class ChunkHolderManager { + + // only call on tick thread + private boolean processPendingFullUpdate() { +- final ArrayDeque pendingFullLoadUpdate = this.pendingFullLoadUpdate; ++ // Folia start - region threading ++ final HolderManagerRegionData data = this.getCurrentRegionData(); ++ if (data == null) { + return false; + } -+ } -+ -+ /** -+ * Returns {@code null} if the task is not scheduled, returns {@code TRUE} if the task was cancelled -+ * and was queued to execute, returns {@code FALSE} if the task was cancelled but was executing. -+ */ -+ public Boolean tryRetire(final SchedulableTick task) { -+ if (task.schedulerOwnedBy != this) { -+ return null; -+ } -+ -+ synchronized (this.scheduleLock) { -+ if (this.queued.remove(task)) { -+ // cancelled, and no runner owns it - so return -+ return Boolean.TRUE; -+ } -+ if (task.awaitingLink != null) { -+ this.awaiting.remove(task.awaitingLink); -+ task.awaitingLink = null; -+ // here we need to replace the task the runner was waiting for -+ final TickThreadRunner runner = task.ownedBy; -+ final SchedulableTick replace = this.queued.poll(); -+ -+ if (replace == null) { -+ // nothing to replace with, set to idle -+ this.idleThreads.set(runner.id); -+ runner.forceIdle(); -+ } else { -+ runner.replaceTask(replace); -+ } -+ -+ return Boolean.TRUE; -+ } -+ -+ // could not find it in queue -+ return task.tryMarkCancelled() ? Boolean.FALSE : null; -+ } -+ } -+ -+ public void notifyTasks(final SchedulableTick task) { -+ // Not implemented -+ } -+ -+ /** -+ * Represents a tickable task that can be scheduled into a {@link SchedulerThreadPool}. -+ *

-+ * A tickable task is expected to run on a fixed interval, which is determined by -+ * the {@link SchedulerThreadPool}. -+ *

-+ *

-+ * A tickable task can have intermediate tasks that can be executed before its tick method is ran. Instead of -+ * the {@link SchedulerThreadPool} parking in-between ticks, the scheduler will instead drain -+ * intermediate tasks from scheduled tasks. The parsing of intermediate tasks allows the scheduler to take -+ * advantage of downtime to reduce the intermediate task load from tasks once they begin ticking. -+ *

-+ *

-+ * It is guaranteed that {@link #runTick()} and {@link #runTasks(BooleanSupplier)} are never -+ * invoked in parallel. -+ * It is required that when intermediate tasks are scheduled, that {@link SchedulerThreadPool#notifyTasks(SchedulableTick)} -+ * is invoked for any scheduled task - otherwise, {@link #runTasks(BooleanSupplier)} may not be invoked to -+ * parse intermediate tasks. -+ *

-+ */ -+ public static abstract class SchedulableTick { -+ private static final AtomicLong ID_GENERATOR = new AtomicLong(); -+ public final long id = ID_GENERATOR.getAndIncrement(); -+ -+ private static final int SCHEDULE_STATE_NOT_SCHEDULED = 0; -+ private static final int SCHEDULE_STATE_SCHEDULED = 1; -+ private static final int SCHEDULE_STATE_CANCELLED = 2; -+ -+ private final AtomicInteger scheduled = new AtomicInteger(); -+ private SchedulerThreadPool schedulerOwnedBy; -+ private long scheduledStart = DEADLINE_NOT_SET; -+ private TickThreadRunner ownedBy; -+ -+ private LinkedSortedSet.Link awaitingLink; -+ -+ private boolean tryMarkScheduled() { -+ return this.scheduled.compareAndSet(SCHEDULE_STATE_NOT_SCHEDULED, SCHEDULE_STATE_SCHEDULED); -+ } -+ -+ private boolean tryMarkCancelled() { -+ return this.scheduled.compareAndSet(SCHEDULE_STATE_SCHEDULED, SCHEDULE_STATE_CANCELLED); -+ } -+ -+ private boolean isScheduled() { -+ return this.scheduled.get() == SCHEDULE_STATE_SCHEDULED; -+ } -+ -+ protected final long getScheduledStart() { -+ return this.scheduledStart; -+ } -+ -+ /** -+ * If this task is scheduled, then this may only be invoked during {@link #runTick()}, -+ * and {@link #runTasks(BooleanSupplier)} -+ */ -+ protected final void setScheduledStart(final long value) { -+ this.scheduledStart = value; -+ } -+ -+ /** -+ * Executes the tick. -+ *

-+ * It is the callee's responsibility to invoke {@link #setScheduledStart(long)} to adjust the start of -+ * the next tick. -+ *

-+ * @return {@code true} if the task should continue to be scheduled, {@code false} otherwise. -+ */ -+ public abstract boolean runTick(); -+ -+ /** -+ * Returns whether this task has any intermediate tasks that can be executed. -+ */ -+ public abstract boolean hasTasks(); -+ -+ /** -+ * Returns {@code null} if this task should not be scheduled, otherwise returns -+ * {@code Boolean.TRUE} if there are more intermediate tasks to execute and -+ * {@code Boolean.FALSE} if there are no more intermediate tasks to execute. -+ */ -+ public abstract Boolean runTasks(final BooleanSupplier canContinue); -+ -+ @Override -+ public String toString() { -+ return "SchedulableTick:{" + -+ "class=" + this.getClass().getName() + "," + -+ "scheduled_state=" + this.scheduled.get() + "," -+ + "}"; -+ } -+ } -+ -+ private static final class TickThreadRunner implements Runnable { -+ -+ /** -+ * There are no tasks in this thread's runqueue, so it is parked. -+ *

-+ * stateTarget = null -+ *

-+ */ -+ private static final int STATE_IDLE = 0; -+ -+ /** -+ * The runner is waiting to tick a task, as it has no intermediate tasks to execute. -+ *

-+ * stateTarget = the task awaiting tick -+ *

-+ */ -+ private static final int STATE_AWAITING_TICK = 1; -+ -+ /** -+ * The runner is executing a tick for one of the tasks that was in its runqueue. -+ *

-+ * stateTarget = the task being ticked -+ *

-+ */ -+ private static final int STATE_EXECUTING_TICK = 2; -+ -+ public final int id; -+ public final SchedulerThreadPool scheduler; -+ -+ private volatile Thread thread; -+ private volatile TickThreadRunnerState state = new TickThreadRunnerState(null, STATE_IDLE); -+ private static final VarHandle STATE_HANDLE = ConcurrentUtil.getVarHandle(TickThreadRunner.class, "state", TickThreadRunnerState.class); -+ -+ private void setStatePlain(final TickThreadRunnerState state) { -+ STATE_HANDLE.set(this, state); -+ } -+ -+ private void setStateOpaque(final TickThreadRunnerState state) { -+ STATE_HANDLE.setOpaque(this, state); -+ } -+ -+ private void setStateVolatile(final TickThreadRunnerState state) { -+ STATE_HANDLE.setVolatile(this, state); -+ } -+ -+ private static record TickThreadRunnerState(SchedulableTick stateTarget, int state) {} -+ -+ public TickThreadRunner(final int id, final SchedulerThreadPool scheduler) { -+ this.id = id; -+ this.scheduler = scheduler; -+ } -+ -+ private Thread getRunnerThread() { -+ return this.thread; -+ } -+ -+ private void acceptTask(final SchedulableTick task) { -+ if (task.ownedBy != null) { -+ throw new IllegalStateException("Already owned by another runner"); -+ } -+ task.ownedBy = this; -+ final TickThreadRunnerState state = this.state; -+ if (state.state != STATE_IDLE) { -+ throw new IllegalStateException("Cannot accept task in state " + state); -+ } -+ this.setStateVolatile(new TickThreadRunnerState(task, STATE_AWAITING_TICK)); -+ LockSupport.unpark(this.getRunnerThread()); -+ } -+ -+ private void replaceTask(final SchedulableTick task) { -+ final TickThreadRunnerState state = this.state; -+ if (state.state != STATE_AWAITING_TICK) { -+ throw new IllegalStateException("Cannot replace task in state " + state); -+ } -+ if (task.ownedBy != null) { -+ throw new IllegalStateException("Already owned by another runner"); -+ } -+ task.ownedBy = this; -+ -+ state.stateTarget.ownedBy = null; -+ -+ this.setStateVolatile(new TickThreadRunnerState(task, STATE_AWAITING_TICK)); -+ LockSupport.unpark(this.getRunnerThread()); -+ } -+ -+ private void forceIdle() { -+ final TickThreadRunnerState state = this.state; -+ if (state.state != STATE_AWAITING_TICK) { -+ throw new IllegalStateException("Cannot replace task in state " + state); -+ } -+ state.stateTarget.ownedBy = null; -+ this.setStateOpaque(new TickThreadRunnerState(null, STATE_IDLE)); -+ // no need to unpark -+ } -+ -+ private boolean takeTask(final TickThreadRunnerState state, final SchedulableTick task) { -+ synchronized (this.scheduler.scheduleLock) { -+ if (this.state != state) { -+ return false; -+ } -+ this.setStatePlain(new TickThreadRunnerState(task, STATE_EXECUTING_TICK)); -+ this.scheduler.takeTask(this, task); -+ return true; -+ } -+ } -+ -+ private void returnTask(final SchedulableTick task, final boolean reschedule) { -+ synchronized (this.scheduler.scheduleLock) { -+ task.ownedBy = null; -+ -+ final SchedulableTick newWait = this.scheduler.returnTask(this, reschedule && task.isScheduled() ? task : null); -+ if (newWait == null) { -+ this.setStatePlain(new TickThreadRunnerState(null, STATE_IDLE)); -+ } else { -+ if (newWait.ownedBy != null) { -+ throw new IllegalStateException("Already owned by another runner"); -+ } -+ newWait.ownedBy = this; -+ this.setStatePlain(new TickThreadRunnerState(newWait, STATE_AWAITING_TICK)); -+ } -+ } -+ } -+ -+ @Override -+ public void run() { -+ this.thread = Thread.currentThread(); -+ -+ main_state_loop: -+ for (;;) { -+ final TickThreadRunnerState startState = this.state; -+ final int startStateType = startState.state; -+ final SchedulableTick startStateTask = startState.stateTarget; -+ -+ if (this.scheduler.halted) { -+ return; -+ } -+ -+ switch (startStateType) { -+ case STATE_IDLE: { -+ while (this.state.state == STATE_IDLE) { -+ LockSupport.park(); -+ if (this.scheduler.halted) { -+ return; -+ } ++ final ArrayDeque pendingFullLoadUpdate = data.pendingFullLoadUpdate; ++ // Folia end - region threading + + boolean ret = false; + +@@ -1364,9 +1512,7 @@ public final class ChunkHolderManager { + ret |= holder.handleFullStatusChange(changedFullStatus); + + if (!changedFullStatus.isEmpty()) { +- for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { +- pendingFullLoadUpdate.add(changedFullStatus.get(i)); +- } ++ this.addChangedStatuses(changedFullStatus); // Folia - region threading + changedFullStatus.clear(); + } + } +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java +index 8671a90e969d16c7a57ddc38fedb7cf01815f64c..085d035b5d127d14af6b8487bee5446b814bc590 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java +@@ -157,7 +157,7 @@ public final class ChunkTaskScheduler { + private final PrioritisedThreadPool.PrioritisedPoolExecutor radiusAwareGenExecutor; + public final PrioritisedThreadPool.PrioritisedPoolExecutor loadExecutor; + +- private final PrioritisedThreadedTaskQueue mainThreadExecutor = new PrioritisedThreadedTaskQueue(); ++ // Folia - regionised ticking + + public final ChunkHolderManager chunkHolderManager; + +@@ -360,14 +360,13 @@ public final class ChunkTaskScheduler { + }; + + // this may not be good enough, specifically thanks to stupid ass plugins swallowing exceptions +- this.scheduleChunkTask(chunkX, chunkZ, crash, PrioritisedExecutor.Priority.BLOCKING); ++ this.scheduleChunkTaskEventually(chunkX, chunkZ, crash, PrioritisedExecutor.Priority.BLOCKING); // Folia - region threading + // so, make the main thread pick it up + ((ChunkSystemMinecraftServer)this.world.getServer()).moonrise$setChunkSystemCrash(new RuntimeException("Chunk system crash propagated from unrecoverableChunkSystemFailure", reportedException)); + } + + public boolean executeMainThreadTask() { +- TickThread.ensureTickThread("Cannot execute main thread task off-main"); +- return this.mainThreadExecutor.executeTask(); ++ throw new UnsupportedOperationException("Use regionised ticking hooks"); // Folia - regionised ticking + } + + public void raisePriority(final int x, final int z, final PrioritisedExecutor.Priority priority) { +@@ -607,7 +606,7 @@ public final class ChunkTaskScheduler { + this.chunkHolderManager.processTicketUpdates(); + } + +- final Consumer loadCallback = (final ChunkAccess chunk) -> { ++ final Consumer loadCallback = onComplete == null && !addTicket ? null : (final ChunkAccess chunk) -> { + try { + if (onComplete != null) { + onComplete.accept(chunk); +@@ -644,7 +643,9 @@ public final class ChunkTaskScheduler { + if (!chunkHolder.upgradeGenTarget(toStatus)) { + this.schedule(chunkX, chunkZ, toStatus, chunkHolder, tasks); + } +- chunkHolder.addStatusConsumer(toStatus, loadCallback); ++ if (loadCallback != null) { ++ chunkHolder.addStatusConsumer(toStatus, loadCallback); + } -+ continue main_state_loop; -+ } -+ -+ case STATE_AWAITING_TICK: { -+ final long deadline = startStateTask.getScheduledStart(); -+ for (;;) { -+ if (this.state != startState) { -+ continue main_state_loop; -+ } -+ final long diff = deadline - System.nanoTime(); -+ if (diff <= 0L) { -+ break; -+ } -+ LockSupport.parkNanos(startState, diff); -+ if (this.scheduler.halted) { -+ return; -+ } -+ } -+ -+ if (!this.takeTask(startState, startStateTask)) { -+ continue main_state_loop; -+ } -+ -+ // TODO exception handling -+ final boolean reschedule = startStateTask.runTick(); -+ -+ this.returnTask(startStateTask, reschedule); -+ -+ continue main_state_loop; -+ } -+ -+ case STATE_EXECUTING_TICK: { -+ throw new IllegalStateException("Tick execution must be set by runner thread, not by any other thread"); -+ } -+ -+ default: { -+ throw new IllegalStateException("Unknown state: " + startState); -+ } -+ } -+ } -+ } -+ } -+} -diff --git a/src/main/java/ca/spottedleaf/concurrentutil/util/TimeUtil.java b/src/main/java/ca/spottedleaf/concurrentutil/util/TimeUtil.java -new file mode 100644 -index 0000000000000000000000000000000000000000..63688716244066581d5b505703576e3340e3baf3 ---- /dev/null -+++ b/src/main/java/ca/spottedleaf/concurrentutil/util/TimeUtil.java -@@ -0,0 +1,60 @@ -+package ca.spottedleaf.concurrentutil.util; -+ -+public final class TimeUtil { -+ -+ /* -+ * The comparator is not a valid comparator for every long value. To prove where it is valid, see below. -+ * -+ * For reflexivity, we have that x - x = 0. We then have that for any long value x that -+ * compareTimes(x, x) == 0, as expected. -+ * -+ * For symmetry, we have that x - y = -(y - x) except for when y - x = Long.MIN_VALUE. -+ * So, the difference between any times x and y must not be equal to Long.MIN_VALUE. -+ * -+ * As for the transitive relation, consider we have x,y such that x - y = a > 0 and z such that -+ * y - z = b > 0. Then, we will have that the x - z > 0 is equivalent to a + b > 0. For long values, -+ * this holds as long as a + b <= Long.MAX_VALUE. -+ * -+ * Also consider we have x, y such that x - y = a < 0 and z such that y - z = b < 0. Then, we will have -+ * that x - z < 0 is equivalent to a + b < 0. For long values, this holds as long as a + b >= -Long.MAX_VALUE. -+ * -+ * Thus, the comparator is only valid for timestamps such that abs(c - d) <= Long.MAX_VALUE for all timestamps -+ * c and d. -+ */ -+ -+ /** -+ * This function is appropriate to be used as a {@link java.util.Comparator} between two timestamps, which -+ * indicates whether the timestamps represented by t1, t2 that t1 is before, equal to, or after t2. -+ */ -+ public static int compareTimes(final long t1, final long t2) { -+ final long diff = t1 - t2; -+ -+ // HD, Section 2-7 -+ return (int) ((diff >> 63) | (-diff >>> 63)); + } + } + } finally { +@@ -658,7 +659,7 @@ public final class ChunkTaskScheduler { + tasks.get(i).schedule(); + } + +- if (!scheduled) { ++ if (loadCallback != null && !scheduled) { + // couldn't schedule + try { + loadCallback.accept(chunk); +@@ -830,7 +831,7 @@ public final class ChunkTaskScheduler { + */ + @Deprecated + public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final Runnable run) { +- return this.scheduleChunkTask(run, PrioritisedExecutor.Priority.NORMAL); ++ throw new UnsupportedOperationException(); // Folia - regionised ticking + } + + /** +@@ -838,7 +839,7 @@ public final class ChunkTaskScheduler { + */ + @Deprecated + public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final Runnable run, final PrioritisedExecutor.Priority priority) { +- return this.mainThreadExecutor.queueRunnable(run, priority); ++ throw new UnsupportedOperationException(); // Folia - regionised ticking + } + + public PrioritisedExecutor.PrioritisedTask createChunkTask(final int chunkX, final int chunkZ, final Runnable run) { +@@ -847,7 +848,7 @@ public final class ChunkTaskScheduler { + + public PrioritisedExecutor.PrioritisedTask createChunkTask(final int chunkX, final int chunkZ, final Runnable run, + final PrioritisedExecutor.Priority priority) { +- return this.mainThreadExecutor.createTask(run, priority); ++ return MinecraftServer.getServer().regionizedServer.taskQueue.createChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking + } + + public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final int chunkX, final int chunkZ, final Runnable run) { +@@ -856,8 +857,22 @@ public final class ChunkTaskScheduler { + + public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final int chunkX, final int chunkZ, final Runnable run, + final PrioritisedExecutor.Priority priority) { +- return this.mainThreadExecutor.queueRunnable(run, priority); ++ return MinecraftServer.getServer().regionizedServer.taskQueue.queueChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking + } + -+ public static long getGreatestTime(final long t1, final long t2) { -+ final long diff = t1 - t2; -+ return diff < 0L ? t2 : t1; -+ } -+ -+ public static long getLeastTime(final long t1, final long t2) { -+ final long diff = t1 - t2; -+ return diff > 0L ? t2 : t1; -+ } -+ -+ public static long clampTime(final long value, final long min, final long max) { -+ final long diffMax = value - max; -+ final long diffMin = value - min; -+ -+ if (diffMax > 0L) { -+ return max; -+ } -+ if (diffMin < 0L) { -+ return min; -+ } -+ return value; -+ } -+ -+ private TimeUtil() {} -+} ++ // Folia start - region threading ++ // this function is guaranteed to never touch the ticket lock or schedule lock ++ // yes, this IS a hack so that we can avoid deadlock due to region threading introducing the ++ // ticket lock in the schedule logic ++ public PrioritisedExecutor.PrioritisedTask scheduleChunkTaskEventually(final int chunkX, final int chunkZ, final Runnable run, ++ final PrioritisedExecutor.Priority priority) { ++ final PrioritisedExecutor.PrioritisedTask ret = this.createChunkTask(chunkX, chunkZ, run, priority); ++ this.world.taskQueueRegionData.pushGlobalChunkTask(() -> { ++ MinecraftServer.getServer().regionizedServer.taskQueue.queueChunkTask(ChunkTaskScheduler.this.world, chunkX, chunkZ, run, priority); ++ }); ++ return ret; + } ++ // Folia end - region threading + + public boolean halt(final boolean sync, final long maxWaitNS) { + this.radiusAwareGenExecutor.halt(); +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java +index 9fcd1b6eef82cd0bbcddab26cf5aaf880d236969..c467b2d2ef9e1e16b00fee20f6cfc757c30fb100 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java +@@ -1393,7 +1393,7 @@ public final class NewChunkHolder { + } + + // must be scheduled to main, we do not trust the callback to not do anything stupid +- this.scheduler.scheduleChunkTask(this.chunkX, this.chunkZ, () -> { ++ this.scheduler.scheduleChunkTaskEventually(this.chunkX, this.chunkZ, () -> { // Folia - region threading + for (final Consumer consumer : consumers) { + try { + consumer.accept(chunk); +@@ -1421,7 +1421,7 @@ public final class NewChunkHolder { + } + + // must be scheduled to main, we do not trust the callback to not do anything stupid +- this.scheduler.scheduleChunkTask(this.chunkX, this.chunkZ, () -> { ++ this.scheduler.scheduleChunkTaskEventually(this.chunkX, this.chunkZ, () -> { // Folia - region threading + for (final Consumer consumer : consumers) { + try { + consumer.accept(chunk); +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java +index 748ab4d637ce463272bae4fdbab6842a27385126..8e2a3d85b7fb78d4e7198c09f356acb51f5be1e0 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java +@@ -1628,7 +1628,7 @@ public final class CollisionUtil { + + for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { + for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { +- final net.minecraft.world.level.chunk.ChunkAccess chunk = chunkSource.getChunk(currChunkX, currChunkZ, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, loadChunks); ++ final net.minecraft.world.level.chunk.ChunkAccess chunk = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, currChunkX, currChunkZ) ? null : chunkSource.getChunk(currChunkX, currChunkZ, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, loadChunks); // Folia - region threading + + if (chunk == null) { + if ((collisionFlags & COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS) != 0) { diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java index 9f17170179cc99d84ad25a1e838aff3d8cc66f93..780c31121ea62d986fe6918c095f61797083d1da 100644 --- a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java @@ -1372,8 +917,21 @@ index 9f17170179cc99d84ad25a1e838aff3d8cc66f93..780c31121ea62d986fe6918c095f6179 // The variable 'k' holds the maximum redstone power value of any adjacent blocks. // If 'k' has the highest level of all neighbors, then the power level of this +diff --git a/src/main/java/io/papermc/paper/SparksFly.java b/src/main/java/io/papermc/paper/SparksFly.java +index 19ee43e1ca053574a0151b4c43b01972183657e6..c7c396a7a94c35d973eb0796f8aba6e669ed5b7c 100644 +--- a/src/main/java/io/papermc/paper/SparksFly.java ++++ b/src/main/java/io/papermc/paper/SparksFly.java +@@ -46,7 +46,7 @@ public final class SparksFly { + + @Override + public void executeSync(final Runnable runnable) { +- MCUtil.ensureMain(this.catching(runnable, "synchronous")); ++ io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(this.catching(runnable, "synchronous")); // Folia - region threading + } + + private Runnable catching(final Runnable runnable, final String type) { diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java -index e83f9517b31c5171b8dc75ab63a5bfe654221c84..49a52225643a1ec114d35fb4e26782d480f8f25b 100644 +index 14e412ebf75b0e06ab53a1c8f9dd1be6ad1e2680..3f733319482fedcf7461f4b7466e84afeae1fc2b 100644 --- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java +++ b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java @@ -83,7 +83,7 @@ public final class ChatProcessor { @@ -1453,870 +1011,6 @@ index 23432eea862c6df716d7726a32da3a0612a3fb77..f59e8bb72c5233f26a8a0d506ac64bb3 callback.callback.accept(audience); } } -diff --git a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java -index e3f56908cc8a9c3f4580def50fcfdc61bd495a71..175aec52539490eeb71b6c8c5ad1bb40918a80ff 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java -+++ b/src/main/java/io/papermc/paper/chunk/system/ChunkSystem.java -@@ -82,6 +82,9 @@ public final class ChunkSystem { - for (int index = 0, len = chunkMap.regionManagers.size(); index < len; ++index) { - chunkMap.regionManagers.get(index).addChunk(holder.getPos().x, holder.getPos().z); - } -+ // Folia start - threaded regions -+ level.regioniser.addChunk(holder.pos.x, holder.pos.z); -+ // Folia end - threaded regions - } - - public static void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder) { -@@ -89,35 +92,40 @@ public final class ChunkSystem { - for (int index = 0, len = chunkMap.regionManagers.size(); index < len; ++index) { - chunkMap.regionManagers.get(index).removeChunk(holder.getPos().x, holder.getPos().z); - } -+ // Folia start - threaded regions -+ level.regioniser.removeChunk(holder.pos.x, holder.pos.z); -+ // Folia end - threaded regions - } - - public static void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) { - chunk.playerChunk = holder; - chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.FULL; -+ chunk.level.getCurrentWorldData().addChunk(chunk); // Folia - region threading - } - - public static void onChunkNotBorder(final LevelChunk chunk, final ChunkHolder holder) { - chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.INACCESSIBLE; -+ chunk.level.getCurrentWorldData().removeChunk(chunk); // Folia - region threading - } - - public static void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) { -- chunk.level.getChunkSource().tickingChunks.add(chunk); -+ chunk.level.getCurrentWorldData().addTickingChunk(chunk); // Folia - region threading - chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.BLOCK_TICKING; - chunk.level.chunkSource.chunkMap.tickingGenerated.incrementAndGet(); - } - - public static void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) { -- chunk.level.getChunkSource().tickingChunks.remove(chunk); -+ chunk.level.getCurrentWorldData().removeTickingChunk(chunk); // Folia - region threading - chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.FULL; - } - - public static void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) { -- chunk.level.getChunkSource().entityTickingChunks.add(chunk); -+ chunk.level.getCurrentWorldData().addEntityTickingChunk(chunk); // Folia - region threading - chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING; - } - - public static void onChunkNotEntityTicking(final LevelChunk chunk, final ChunkHolder holder) { -- chunk.level.getChunkSource().entityTickingChunks.remove(chunk); -+ chunk.level.getCurrentWorldData().removeEntityTickingChunk(chunk); // Folia - region threading - chunk.chunkStatus = net.minecraft.server.level.FullChunkStatus.BLOCK_TICKING; - } - -diff --git a/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java -index 149cfb0587299f72fcfddf395fb71b70438986c1..239475187fdf0d05823b31e2068651559d3497e5 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java -+++ b/src/main/java/io/papermc/paper/chunk/system/RegionizedPlayerChunkLoader.java -@@ -221,6 +221,7 @@ public class RegionizedPlayerChunkLoader { - public void updatePlayer(final ServerPlayer player) { - final PlayerChunkLoaderData loader = player.chunkLoader; - if (loader != null) { -+ player.serverLevel().chunkSource.chunkMap.getNearbyPlayers().tickPlayer(player); // Folia - region threading - loader.update(); - } - } -@@ -234,7 +235,7 @@ public class RegionizedPlayerChunkLoader { - final PlayerChunkLoaderData loader = player.chunkLoader; - - if (loader == null) { -- return; -+ throw new IllegalStateException("Player is already removed from player chunk loader"); // Folia - region threading - } - - loader.remove(); -@@ -313,7 +314,7 @@ public class RegionizedPlayerChunkLoader { - public void tick() { - TickThread.ensureTickThread("Cannot tick player chunk loader async"); - long currTime = System.nanoTime(); -- for (final ServerPlayer player : new java.util.ArrayList<>(this.world.players())) { -+ for (final ServerPlayer player : new java.util.ArrayList<>(this.world.getLocalPlayers())) { // Folia - region threding - final PlayerChunkLoaderData loader = player.chunkLoader; - if (loader == null || loader.world != this.world) { - // not our problem anymore -diff --git a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java -index 15ee41452992714108efe53b708b5a4e1da7c1ff..5bef4f50082e56b89239cfd62dd7429926b71c09 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java -+++ b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java -@@ -191,7 +191,12 @@ public final class EntityLookup implements LevelEntityGetter { - - @Override - public Iterable getAll() { -- return new ArrayIterable<>(this.accessibleEntities.getRawData(), 0, this.accessibleEntities.size()); -+ // Folia start - region threading -+ synchronized (this.accessibleEntities) { -+ Entity[] iterate = java.util.Arrays.copyOf(this.accessibleEntities.getRawData(), this.accessibleEntities.size()); -+ return new ArrayIterable<>(iterate, 0, iterate.length); -+ } -+ // Folia end - region threading - } - - public Entity[] getAllCopy() { -@@ -277,7 +282,9 @@ public final class EntityLookup implements LevelEntityGetter { - if (newVisibility.ordinal() > oldVisibility.ordinal()) { - // status upgrade - if (!oldVisibility.isAccessible() && newVisibility.isAccessible()) { -+ synchronized (this.accessibleEntities) { // Folia - region threading - this.accessibleEntities.add(entity); -+ } // Folia - region threading - EntityLookup.this.worldCallback.onTrackingStart(entity); - } - -@@ -291,7 +298,9 @@ public final class EntityLookup implements LevelEntityGetter { - } - - if (oldVisibility.isAccessible() && !newVisibility.isAccessible()) { -+ synchronized (this.accessibleEntities) { // Folia - region threading - this.accessibleEntities.remove(entity); -+ } // Folia - region threading - EntityLookup.this.worldCallback.onTrackingEnd(entity); - } - } -@@ -434,6 +443,8 @@ public final class EntityLookup implements LevelEntityGetter { - - entity.setLevelCallback(new EntityCallback(entity)); - -+ this.world.getCurrentWorldData().addEntity(entity); // Folia - region threading -+ - this.entityStatusChange(entity, slices, Visibility.HIDDEN, getEntityStatus(entity), false, !fromDisk, false); - - return true; -@@ -450,6 +461,19 @@ public final class EntityLookup implements LevelEntityGetter { - return slices == null || !slices.isPreventingStatusUpdates(); - } - -+ // Folia start - region threading -+ // only appropriate to use when in shutdown, as this performs no logic hooks to properly add to world -+ public boolean addEntityForShutdownTeleportComplete(final Entity entity) { -+ final BlockPos pos = entity.blockPosition(); -+ final int sectionX = pos.getX() >> 4; -+ final int sectionY = Mth.clamp(pos.getY() >> 4, this.minSection, this.maxSection); -+ final int sectionZ = pos.getZ() >> 4; -+ final ChunkEntitySlices slices = this.getOrCreateChunk(sectionX, sectionZ); -+ -+ return slices.addEntity(entity, sectionY); -+ } -+ // Folia end - region threading -+ - private void removeEntity(final Entity entity) { - final int sectionX = entity.sectionX; - final int sectionY = entity.sectionY; -@@ -864,12 +888,18 @@ public final class EntityLookup implements LevelEntityGetter { - @Override - public void onMove() { - final Entity entity = this.entity; -+ final io.papermc.paper.threadedregions.RegionizedWorldData regionData = entity.level().getCurrentWorldData(); // Folia - region threading - final Visibility oldVisibility = getEntityStatus(entity); - final ChunkEntitySlices newSlices = EntityLookup.this.moveEntity(this.entity); - if (newSlices == null) { - // no new section, so didn't change sections - return; - } -+ // Folia start - region threading -+ if (entity instanceof net.minecraft.server.level.ServerPlayer player) { -+ regionData.getNearbyPlayers().tickPlayer(player); -+ } -+ // Folia end - region threading - final Visibility newVisibility = getEntityStatus(entity); - - EntityLookup.this.entityStatusChange(entity, newSlices, oldVisibility, newVisibility, true, false, false); -@@ -886,6 +916,9 @@ public final class EntityLookup implements LevelEntityGetter { - EntityLookup.this.entityStatusChange(entity, null, tickingState, Visibility.HIDDEN, false, false, reason.shouldDestroy()); - - this.entity.setLevelCallback(NoOpCallback.INSTANCE); -+ -+ // only AFTER full removal callbacks, so that thread checking will work. // Folia - region threading -+ EntityLookup.this.world.getCurrentWorldData().removeEntity(entity); // Folia - region threading - } - } - -diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java -index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..67bf841878eb8e3703782caeb16db4803d13f0d9 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java -+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java -@@ -53,6 +53,14 @@ import java.util.concurrent.atomic.AtomicReference; - import java.util.concurrent.locks.LockSupport; - import java.util.function.Predicate; - -+// Folia start - region threading -+import io.papermc.paper.threadedregions.RegionizedServer; -+import io.papermc.paper.threadedregions.ThreadedRegionizer; -+import io.papermc.paper.threadedregions.TickRegionScheduler; -+import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; -+import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; -+// Folia end - region threading -+ - public final class ChunkHolderManager { - - private static final Logger LOGGER = LogUtils.getClassLogger(); -@@ -112,27 +120,83 @@ public final class ChunkHolderManager { - private final ChunkTaskScheduler taskScheduler; - private long currentTick; - -- private final ArrayDeque pendingFullLoadUpdate = new ArrayDeque<>(); -- private final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> { -- if (c1 == c2) { -- return 0; -+ // Folia start - region threading -+ public static final class HolderManagerRegionData { -+ private final ArrayDeque pendingFullLoadUpdate = new ArrayDeque<>(); -+ private final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> { -+ if (c1 == c2) { -+ return 0; -+ } -+ -+ final int saveTickCompare = Long.compare(c1.lastAutoSave, c2.lastAutoSave); -+ -+ if (saveTickCompare != 0) { -+ return saveTickCompare; -+ } -+ -+ final long coord1 = CoordinateUtils.getChunkKey(c1.chunkX, c1.chunkZ); -+ final long coord2 = CoordinateUtils.getChunkKey(c2.chunkX, c2.chunkZ); -+ -+ if (coord1 == coord2) { -+ throw new IllegalStateException("Duplicate chunkholder in auto save queue"); -+ } -+ -+ return Long.compare(coord1, coord2); -+ }); -+ -+ public void merge(final HolderManagerRegionData into, final long tickOffset) { -+ // Order doesn't really matter for the pending full update... -+ into.pendingFullLoadUpdate.addAll(this.pendingFullLoadUpdate); -+ -+ // We need to copy the set to iterate over, because modifying the field used in compareTo while iterating -+ // will destroy the result from compareTo (However, the set is not destroyed _after_ iteration because a constant -+ // addition to every entry will not affect compareTo). -+ for (final NewChunkHolder holder : new ArrayList<>(this.autoSaveQueue)) { -+ holder.lastAutoSave += tickOffset; -+ into.autoSaveQueue.add(holder); -+ } - } - -- final int saveTickCompare = Long.compare(c1.lastAutoSave, c2.lastAutoSave); -+ public void split(final int chunkToRegionShift, final Long2ReferenceOpenHashMap regionToData, -+ final ReferenceOpenHashSet dataSet) { -+ for (final NewChunkHolder fullLoadUpdate : this.pendingFullLoadUpdate) { -+ final int regionCoordinateX = fullLoadUpdate.chunkX >> chunkToRegionShift; -+ final int regionCoordinateZ = fullLoadUpdate.chunkZ >> chunkToRegionShift; -+ -+ final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ)); -+ if (data != null) { -+ data.pendingFullLoadUpdate.add(fullLoadUpdate); -+ } // else: fullLoadUpdate is an unloaded chunk holder -+ } -+ -+ for (final NewChunkHolder autoSave : this.autoSaveQueue) { -+ final int regionCoordinateX = autoSave.chunkX >> chunkToRegionShift; -+ final int regionCoordinateZ = autoSave.chunkZ >> chunkToRegionShift; - -- if (saveTickCompare != 0) { -- return saveTickCompare; -+ final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ)); -+ if (data != null) { -+ data.autoSaveQueue.add(autoSave); -+ } // else: autoSave is an unloaded chunk holder -+ } - } -+ } - -- final long coord1 = CoordinateUtils.getChunkKey(c1.chunkX, c1.chunkZ); -- final long coord2 = CoordinateUtils.getChunkKey(c2.chunkX, c2.chunkZ); -+ private ChunkHolderManager.HolderManagerRegionData getCurrentRegionData() { -+ final ThreadedRegionizer.ThreadedRegion region = -+ TickRegionScheduler.getCurrentRegion(); - -- if (coord1 == coord2) { -- throw new IllegalStateException("Duplicate chunkholder in auto save queue"); -+ if (region == null) { -+ return null; - } - -- return Long.compare(coord1, coord2); -- }); -+ if (this.world != null && this.world != region.getData().world) { -+ throw new IllegalStateException("World check failed: expected world: " + this.world.getWorld().getKey() + ", region world: " + region.getData().world.getWorld().getKey()); -+ } -+ -+ return region.getData().getHolderManagerRegionData(); -+ } -+ // Folia end - region threading -+ - - public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) { - this.world = world; -@@ -167,8 +231,13 @@ public final class ChunkHolderManager { - } - - public void close(final boolean save, final boolean halt) { -+ // Folia start - region threading -+ this.close(save, halt, true, true, true); -+ } -+ public void close(final boolean save, final boolean halt, final boolean first, final boolean last, final boolean checkRegions) { -+ // Folia end - region threading - TickThread.ensureTickThread("Closing world off-main"); -- if (halt) { -+ if (first && halt) { // Folia - region threading - LOGGER.info("Waiting 60s for chunk system to halt for world '" + this.world.getWorld().getName() + "'"); - if (!this.taskScheduler.halt(true, TimeUnit.SECONDS.toNanos(60L))) { - LOGGER.warn("Failed to halt world generation/loading tasks for world '" + this.world.getWorld().getName() + "'"); -@@ -178,9 +247,10 @@ public final class ChunkHolderManager { - } - - if (save) { -- this.saveAllChunks(true, true, true); -+ this.saveAllChunksRegionised(true, true, true, first, last, checkRegions); // Folia - region threading - } - -+ if (last) { // Folia - region threading - if (this.world.chunkDataControllerNew.hasTasks() || this.world.entityDataControllerNew.hasTasks() || this.world.poiDataControllerNew.hasTasks()) { - RegionFileIOThread.flush(); - } -@@ -201,27 +271,34 @@ public final class ChunkHolderManager { - } catch (final IOException ex) { - LOGGER.error("Failed to close poi regionfile cache for world '" + this.world.getWorld().getName() + "'", ex); - } -+ } // Folia - region threading - } - - void ensureInAutosave(final NewChunkHolder holder) { -- if (!this.autoSaveQueue.contains(holder)) { -- holder.lastAutoSave = MinecraftServer.currentTick; -- this.autoSaveQueue.add(holder); -+ // Folia start - region threading -+ final HolderManagerRegionData regionData = this.getCurrentRegionData(); -+ if (!regionData.autoSaveQueue.contains(holder)) { -+ holder.lastAutoSave = RegionizedServer.getCurrentTick(); -+ // Folia end - region threading -+ regionData.autoSaveQueue.add(holder); - } - } - - public void autoSave() { - final List reschedule = new ArrayList<>(); -- final long currentTick = MinecraftServer.currentTickLong; -+ final long currentTick = RegionizedServer.getCurrentTick(); // Folia - region threading - final long maxSaveTime = currentTick - this.world.paperConfig().chunks.autoSaveInterval.value(); -- for (int autoSaved = 0; autoSaved < this.world.paperConfig().chunks.maxAutoSaveChunksPerTick && !this.autoSaveQueue.isEmpty();) { -- final NewChunkHolder holder = this.autoSaveQueue.first(); -+ // Folia start - region threading -+ final HolderManagerRegionData regionData = this.getCurrentRegionData(); -+ for (int autoSaved = 0; autoSaved < this.world.paperConfig().chunks.maxAutoSaveChunksPerTick && !regionData.autoSaveQueue.isEmpty();) { -+ // Folia end - region threading -+ final NewChunkHolder holder = regionData.autoSaveQueue.first(); - - if (holder.lastAutoSave > maxSaveTime) { - break; - } - -- this.autoSaveQueue.remove(holder); -+ regionData.autoSaveQueue.remove(holder); // Folia - region threading - - holder.lastAutoSave = currentTick; - if (holder.save(false, false) != null) { -@@ -235,15 +312,38 @@ public final class ChunkHolderManager { - - for (final NewChunkHolder holder : reschedule) { - if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) { -- this.autoSaveQueue.add(holder); -+ regionData.autoSaveQueue.add(holder); // Folia start - region threading - } - } - } - - public void saveAllChunks(final boolean flush, final boolean shutdown, final boolean logProgress) { -- final List holders = this.getChunkHolders(); -+ // Folia start - region threading -+ this.saveAllChunksRegionised(flush, shutdown, logProgress, true, true, true); -+ } -+ public void saveAllChunksRegionised(final boolean flush, final boolean shutdown, final boolean logProgress, final boolean first, final boolean last, final boolean checkRegion) { -+ final List holders = new java.util.ArrayList<>(this.chunkHolders.size() / 10); -+ // we could iterate through all chunk holders with thread checks, however for many regions the iteration cost alone -+ // will multiply. to avoid this, we can simply iterate through all owned sections -+ final int regionShift = this.world.getRegionChunkShift(); -+ for (final LongIterator iterator = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion().getOwnedSectionsUnsynchronised(); iterator.hasNext();) { -+ final long sectionKey = iterator.nextLong(); -+ final int width = 1 << regionShift; -+ final int offsetX = CoordinateUtils.getChunkX(sectionKey) << regionShift; -+ final int offsetZ = CoordinateUtils.getChunkZ(sectionKey) << regionShift; -+ -+ for (int dz = 0; dz < width; ++dz) { -+ for (int dx = 0; dx < width; ++dx) { -+ final NewChunkHolder holder = this.getChunkHolder(offsetX | dx, offsetZ | dz); -+ if (holder != null) { -+ holders.add(holder); -+ } -+ } -+ } -+ } -+ // Folia end - region threading - -- if (logProgress) { -+ if (first && logProgress) { // Folia - region threading - LOGGER.info("Saving all chunkholders for world '" + this.world.getWorld().getName() + "'"); - } - -@@ -251,7 +351,7 @@ public final class ChunkHolderManager { - - int saved = 0; - -- long start = System.nanoTime(); -+ final long start = System.nanoTime(); - long lastLog = start; - boolean needsFlush = false; - final int flushInterval = 50; -@@ -262,6 +362,12 @@ public final class ChunkHolderManager { - - for (int i = 0, len = holders.size(); i < len; ++i) { - final NewChunkHolder holder = holders.get(i); -+ // Folia start - region threading -+ if (!checkRegion && !TickThread.isTickThreadFor(this.world, holder.chunkX, holder.chunkZ)) { -+ // skip holders that would fail the thread check -+ continue; -+ } -+ // Folia end - region threading - try { - final NewChunkHolder.SaveStat saveStat = holder.save(shutdown, false); - if (saveStat != null) { -@@ -294,7 +400,7 @@ public final class ChunkHolderManager { - } - } - } -- if (flush) { -+ if (last && flush) { // Folia - region threading - RegionFileIOThread.flush(); - if (this.world.paperConfig().chunks.flushRegionsOnSave) { - try { -@@ -707,6 +813,13 @@ public final class ChunkHolderManager { - } - - public void tick() { -+ // Folia start - region threading -+ final ThreadedRegionizer.ThreadedRegion region = -+ TickRegionScheduler.getCurrentRegion(); -+ if (region == null) { -+ throw new IllegalStateException("Not running tick() while on a region"); -+ } -+ // Folia end - region threading - final int sectionShift = this.world.getRegionChunkShift(); - - final Predicate> expireNow = (final Ticket ticket) -> { -@@ -716,12 +829,12 @@ public final class ChunkHolderManager { - return --ticket.removeDelay <= 0L; - }; - -- for (final Iterator iterator = this.sectionToChunkToExpireCount.keySet().iterator(); iterator.hasNext();) { -- final RegionFileIOThread.ChunkCoordinate section = iterator.next(); -- final long sectionKey = section.key; -- -+ // Folia start - region threading -+ for (final LongIterator iterator = region.getOwnedSectionsUnsynchronised(); iterator.hasNext();) { -+ final long sectionKey = iterator.nextLong(); -+ final RegionFileIOThread.ChunkCoordinate section = new RegionFileIOThread.ChunkCoordinate(sectionKey); - if (!this.sectionToChunkToExpireCount.containsKey(section)) { -- // removed concurrently -+ // Folia end - region threading - continue; - } - -@@ -1024,19 +1137,51 @@ public final class ChunkHolderManager { - if (changedFullStatus.isEmpty()) { - return; - } -- if (!TickThread.isTickThread()) { -- this.taskScheduler.scheduleChunkTask(() -> { -- final ArrayDeque pendingFullLoadUpdate = ChunkHolderManager.this.pendingFullLoadUpdate; -- for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { -- pendingFullLoadUpdate.add(changedFullStatus.get(i)); -- } - -- ChunkHolderManager.this.processPendingFullUpdate(); -- }, PrioritisedExecutor.Priority.HIGHEST); -- } else { -- final ArrayDeque pendingFullLoadUpdate = this.pendingFullLoadUpdate; -- for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { -- pendingFullLoadUpdate.add(changedFullStatus.get(i)); -+ // Folia start - region threading -+ final Long2ObjectOpenHashMap> sectionToUpdates = new Long2ObjectOpenHashMap<>(); -+ final List thisRegionHolders = new ArrayList<>(); -+ -+ final int regionShift = this.world.getRegionChunkShift(); -+ final ThreadedRegionizer.ThreadedRegion thisRegion -+ = TickRegionScheduler.getCurrentRegion(); -+ -+ for (final NewChunkHolder holder : changedFullStatus) { -+ final int regionX = holder.chunkX >> regionShift; -+ final int regionZ = holder.chunkZ >> regionShift; -+ final long holderSectionKey = CoordinateUtils.getChunkKey(regionX, regionZ); -+ -+ // region may be null -+ if (thisRegion != null && this.world.regioniser.getRegionAtUnsynchronised(holder.chunkX, holder.chunkZ) == thisRegion) { -+ thisRegionHolders.add(holder); -+ } else { -+ sectionToUpdates.computeIfAbsent(holderSectionKey, (final long keyInMap) -> { -+ return new ArrayList<>(); -+ }).add(holder); -+ } -+ } -+ // Folia end - region threading -+ -+ // Folia start - region threading -+ if (!thisRegionHolders.isEmpty()) { -+ thisRegion.getData().getHolderManagerRegionData().pendingFullLoadUpdate.addAll(thisRegionHolders); -+ } -+ -+ if (!sectionToUpdates.isEmpty()) { -+ for (final Iterator>> iterator = sectionToUpdates.long2ObjectEntrySet().fastIterator(); -+ iterator.hasNext();) { -+ final Long2ObjectMap.Entry> entry = iterator.next(); -+ final long sectionKey = entry.getLongKey(); -+ -+ final int chunkX = CoordinateUtils.getChunkX(sectionKey) << regionShift; -+ final int chunkZ = CoordinateUtils.getChunkZ(sectionKey) << regionShift; -+ -+ final List regionHolders = entry.getValue(); -+ this.taskScheduler.scheduleChunkTaskEventually(chunkX, chunkZ, () -> { // Folia - region threading -+ ChunkHolderManager.this.getCurrentRegionData().pendingFullLoadUpdate.addAll(regionHolders); -+ ChunkHolderManager.this.processPendingFullUpdate(); -+ }, PrioritisedExecutor.Priority.HIGHEST); -+ // Folia end - region threading - } - } - } -@@ -1044,8 +1189,9 @@ public final class ChunkHolderManager { - private void removeChunkHolder(final NewChunkHolder holder) { - holder.killed = true; - holder.vanillaChunkHolder.onChunkRemove(); -- this.autoSaveQueue.remove(holder); -+ // Folia - region threading - ChunkSystem.onChunkHolderDelete(this.world, holder.vanillaChunkHolder); -+ this.getCurrentRegionData().autoSaveQueue.remove(holder); // Folia - region threading - synchronized (this.chunkHolders) { - this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ)); - } -@@ -1059,7 +1205,7 @@ public final class ChunkHolderManager { - throw new IllegalStateException("Cannot unload chunks recursively"); - } - final int sectionShift = this.unloadQueue.coordinateShift; // sectionShift <= lock shift -- final List unloadSectionsForRegion = this.unloadQueue.retrieveForAllRegions(); -+ final List unloadSectionsForRegion = this.unloadQueue.retrieveForCurrentRegion(); // Folia - threaded regions - int unloadCountTentative = 0; - for (final ChunkQueue.SectionToUnload sectionRef : unloadSectionsForRegion) { - final ChunkQueue.UnloadSection section -@@ -1372,7 +1518,13 @@ public final class ChunkHolderManager { - - // only call on tick thread - protected final boolean processPendingFullUpdate() { -- final ArrayDeque pendingFullLoadUpdate = this.pendingFullLoadUpdate; -+ // Folia start - region threading -+ final HolderManagerRegionData data = this.getCurrentRegionData(); -+ if (data == null) { -+ return false; -+ } -+ final ArrayDeque pendingFullLoadUpdate = data.pendingFullLoadUpdate; -+ // Folia end - region threading - - boolean ret = false; - -@@ -1383,9 +1535,7 @@ public final class ChunkHolderManager { - ret |= holder.handleFullStatusChange(changedFullStatus); - - if (!changedFullStatus.isEmpty()) { -- for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { -- pendingFullLoadUpdate.add(changedFullStatus.get(i)); -- } -+ this.addChangedStatuses(changedFullStatus); // Folia - region threading - changedFullStatus.clear(); - } - } -@@ -1399,7 +1549,7 @@ public final class ChunkHolderManager { - - private JsonObject getDebugJsonNoLock() { - final JsonObject ret = new JsonObject(); -- ret.addProperty("current_tick", Long.valueOf(this.currentTick)); -+ // Folia - region threading - move down - - final JsonArray unloadQueue = new JsonArray(); - ret.add("unload_queue", unloadQueue); -diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkQueue.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkQueue.java -index 4cc1b3ba6d093a9683dbd8b7fe76106ae391e019..47bbd5de5849bef5392e3783322a19de5b351beb 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkQueue.java -+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkQueue.java -@@ -1,5 +1,8 @@ - package io.papermc.paper.chunk.system.scheduling; - -+import io.papermc.paper.threadedregions.ThreadedRegionizer; -+import io.papermc.paper.threadedregions.TickRegionScheduler; -+import io.papermc.paper.threadedregions.TickRegions; - import it.unimi.dsi.fastutil.HashCommon; - import it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet; - import java.util.ArrayList; -@@ -45,6 +48,39 @@ public final class ChunkQueue { - return ret; - } - -+ // Folia start - threaded regions -+ public List retrieveForCurrentRegion() { -+ final ThreadedRegionizer.ThreadedRegion region = -+ TickRegionScheduler.getCurrentRegion(); -+ final ThreadedRegionizer regionizer = region.regioniser; -+ final int shift = this.coordinateShift; -+ -+ final List ret = new ArrayList<>(); -+ -+ for (final Map.Entry entry : this.unloadSections.entrySet()) { -+ final Coordinate coord = entry.getKey(); -+ final long key = coord.key; -+ final UnloadSection section = entry.getValue(); -+ final int sectionX = Coordinate.x(key); -+ final int sectionZ = Coordinate.z(key); -+ final int chunkX = sectionX << shift; -+ final int chunkZ = sectionZ << shift; -+ -+ if (regionizer.getRegionAtUnsynchronised(chunkX, chunkZ) != region) { -+ continue; -+ } -+ -+ ret.add(new SectionToUnload(sectionX, sectionZ, coord, section.order, section.chunks.size())); -+ } -+ -+ ret.sort((final SectionToUnload s1, final SectionToUnload s2) -> { -+ return Long.compare(s1.order, s2.order); -+ }); -+ -+ return ret; -+ } -+ // Folia end - threaded regions -+ - public UnloadSection getSectionUnsynchronized(final int sectionX, final int sectionZ) { - final Coordinate coordinate = new Coordinate(Coordinate.key(sectionX, sectionZ)); - return this.unloadSections.get(coordinate); -diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java -index 049e20407033073b06fcdeb46c38485f4926d778..8288ab66f0996eca844b2bf63c1422c2657b8612 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java -+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkTaskScheduler.java -@@ -115,7 +115,7 @@ public final class ChunkTaskScheduler { - private final PrioritisedThreadPool.PrioritisedPoolExecutor radiusAwareGenExecutor; - public final PrioritisedThreadPool.PrioritisedPoolExecutor loadExecutor; - -- private final PrioritisedThreadedTaskQueue mainThreadExecutor = new PrioritisedThreadedTaskQueue(); -+ // Folia - regionised ticking - - public final ChunkHolderManager chunkHolderManager; - -@@ -303,14 +303,13 @@ public final class ChunkTaskScheduler { - }; - - // this may not be good enough, specifically thanks to stupid ass plugins swallowing exceptions -- this.scheduleChunkTask(chunkX, chunkZ, crash, PrioritisedExecutor.Priority.BLOCKING); -+ this.scheduleChunkTaskEventually(chunkX, chunkZ, crash, PrioritisedExecutor.Priority.BLOCKING); // Folia - region threading - // so, make the main thread pick it up - MinecraftServer.chunkSystemCrash = new RuntimeException("Chunk system crash propagated from unrecoverableChunkSystemFailure", reportedException); - } - - public boolean executeMainThreadTask() { -- TickThread.ensureTickThread("Cannot execute main thread task off-main"); -- return this.mainThreadExecutor.executeTask(); -+ throw new UnsupportedOperationException("Use regionised ticking hooks"); // Folia - regionised ticking - } - - public void raisePriority(final int x, final int z, final PrioritisedExecutor.Priority priority) { -@@ -330,7 +329,7 @@ public final class ChunkTaskScheduler { - public void scheduleTickingState(final int chunkX, final int chunkZ, final FullChunkStatus toStatus, - final boolean addTicket, final PrioritisedExecutor.Priority priority, - final Consumer onComplete) { -- if (!TickThread.isTickThread()) { -+ if (!TickThread.isTickThreadFor(this.world, chunkX, chunkZ)) { - this.scheduleChunkTask(chunkX, chunkZ, () -> { - ChunkTaskScheduler.this.scheduleTickingState(chunkX, chunkZ, toStatus, addTicket, priority, onComplete); - }, priority); -@@ -486,7 +485,7 @@ public final class ChunkTaskScheduler { - - public void scheduleChunkLoad(final int chunkX, final int chunkZ, final ChunkStatus toStatus, final boolean addTicket, - final PrioritisedExecutor.Priority priority, final Consumer onComplete) { -- if (!TickThread.isTickThread()) { -+ if (!TickThread.isTickThreadFor(this.world, chunkX, chunkZ)) { - this.scheduleChunkTask(chunkX, chunkZ, () -> { - ChunkTaskScheduler.this.scheduleChunkLoad(chunkX, chunkZ, toStatus, addTicket, priority, onComplete); - }, priority); -@@ -514,7 +513,7 @@ public final class ChunkTaskScheduler { - this.chunkHolderManager.processTicketUpdates(); - } - -- final Consumer loadCallback = (final ChunkAccess chunk) -> { -+ final Consumer loadCallback = onComplete == null && !addTicket ? null : (final ChunkAccess chunk) -> { - try { - if (onComplete != null) { - onComplete.accept(chunk); -@@ -554,7 +553,9 @@ public final class ChunkTaskScheduler { - if (!chunkHolder.upgradeGenTarget(toStatus)) { - this.schedule(chunkX, chunkZ, toStatus, chunkHolder, tasks); - } -- chunkHolder.addStatusConsumer(toStatus, loadCallback); -+ if (loadCallback != null) { -+ chunkHolder.addStatusConsumer(toStatus, loadCallback); -+ } - } - } - } finally { -@@ -568,7 +569,7 @@ public final class ChunkTaskScheduler { - tasks.get(i).schedule(); - } - -- if (!scheduled) { -+ if (loadCallback != null && !scheduled) { - // couldn't schedule - try { - loadCallback.accept(chunk); -@@ -757,7 +758,7 @@ public final class ChunkTaskScheduler { - */ - @Deprecated - public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final Runnable run) { -- return this.scheduleChunkTask(run, PrioritisedExecutor.Priority.NORMAL); -+ throw new UnsupportedOperationException(); // Folia - regionised ticking - } - - /** -@@ -765,7 +766,7 @@ public final class ChunkTaskScheduler { - */ - @Deprecated - public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final Runnable run, final PrioritisedExecutor.Priority priority) { -- return this.mainThreadExecutor.queueRunnable(run, priority); -+ throw new UnsupportedOperationException(); // Folia - regionised ticking - } - - public PrioritisedExecutor.PrioritisedTask createChunkTask(final int chunkX, final int chunkZ, final Runnable run) { -@@ -774,28 +775,33 @@ public final class ChunkTaskScheduler { - - public PrioritisedExecutor.PrioritisedTask createChunkTask(final int chunkX, final int chunkZ, final Runnable run, - final PrioritisedExecutor.Priority priority) { -- return this.mainThreadExecutor.createTask(run, priority); -+ return MinecraftServer.getServer().regionizedServer.taskQueue.createChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking - } - - public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final int chunkX, final int chunkZ, final Runnable run) { -- return this.mainThreadExecutor.queueRunnable(run); -+ return this.scheduleChunkTask(chunkX, chunkZ, run, PrioritisedExecutor.Priority.NORMAL); // TODO rebase into chunk system patch - } - - public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final int chunkX, final int chunkZ, final Runnable run, - final PrioritisedExecutor.Priority priority) { -- return this.mainThreadExecutor.queueRunnable(run, priority); -+ return MinecraftServer.getServer().regionizedServer.taskQueue.queueChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking -+ } -+ -+ // Folia start - region threading -+ // this function is guaranteed to never touch the ticket lock or schedule lock -+ // yes, this IS a hack so that we can avoid deadlock due to region threading introducing the -+ // ticket lock in the schedule logic -+ public PrioritisedExecutor.PrioritisedTask scheduleChunkTaskEventually(final int chunkX, final int chunkZ, final Runnable run, -+ final PrioritisedExecutor.Priority priority) { -+ final PrioritisedExecutor.PrioritisedTask ret = this.createChunkTask(chunkX, chunkZ, run, priority); -+ this.world.taskQueueRegionData.pushGlobalChunkTask(() -> { -+ MinecraftServer.getServer().regionizedServer.taskQueue.queueChunkTask(ChunkTaskScheduler.this.world, chunkX, chunkZ, run, priority); -+ }); -+ return ret; - } -+ // Folia end - region threading - -- public void executeTasksUntil(final BooleanSupplier exit) { -- if (Bukkit.isPrimaryThread()) { -- this.mainThreadExecutor.executeConditionally(exit); -- } else { -- long counter = 1L; -- while (!exit.getAsBoolean()) { -- counter = ConcurrentUtil.linearLongBackoff(counter, 100_000L, 5_000_000L); // 100us, 5ms -- } -- } -- } -+ // Folia - regionised ticking - - public boolean halt(final boolean sync, final long maxWaitNS) { - this.radiusAwareGenExecutor.halt(); -@@ -803,6 +809,7 @@ public final class ChunkTaskScheduler { - this.loadExecutor.halt(); - final long time = System.nanoTime(); - if (sync) { -+ // start at 10 * 0.5ms -> 5ms - for (long failures = 9L;; failures = ConcurrentUtil.linearLongBackoff(failures, 500_000L, 50_000_000L)) { - if ( - !this.radiusAwareGenExecutor.isActive() && -diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java -index 56b07a3306e5735816c8d89601b519cb0db6379a..014cacbcb537a30566ab756bd884a20c256f9c4c 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java -+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/NewChunkHolder.java -@@ -726,7 +726,7 @@ public final class NewChunkHolder { - boolean killed; - - // must hold scheduling lock -- private void checkUnload() { -+ void checkUnload() { // Folia - region threading - if (this.killed) { - return; - } -@@ -1440,7 +1440,7 @@ public final class NewChunkHolder { - } - - // must be scheduled to main, we do not trust the callback to not do anything stupid -- this.scheduler.scheduleChunkTask(this.chunkX, this.chunkZ, () -> { -+ this.scheduler.scheduleChunkTaskEventually(this.chunkX, this.chunkZ, () -> { // Folia - region threading - for (final Consumer consumer : consumers) { - try { - consumer.accept(chunk); -@@ -1483,7 +1483,7 @@ public final class NewChunkHolder { - } - - // must be scheduled to main, we do not trust the callback to not do anything stupid -- this.scheduler.scheduleChunkTask(this.chunkX, this.chunkZ, () -> { -+ this.scheduler.scheduleChunkTaskEventually(this.chunkX, this.chunkZ, () -> { // Folia - region threading - for (final Consumer consumer : consumers) { - try { - consumer.accept(chunk); -@@ -1744,7 +1744,7 @@ public final class NewChunkHolder { - return this.entityChunk; - } - -- public long lastAutoSave; -+ public long lastAutoSave; // Folia - region threaded - change to relative delay - - public static final record SaveStat(boolean savedChunk, boolean savedEntityChunk, boolean savedPoiChunk) {} - -@@ -1894,7 +1894,7 @@ public final class NewChunkHolder { - } catch (final ThreadDeath death) { - throw death; - } catch (final Throwable thr) { -- LOGGER.error("Failed to save chunk data (" + this.chunkX + "," + this.chunkZ + ") in world '" + this.world.getWorld().getName() + "'"); -+ LOGGER.error("Failed to save chunk data (" + this.chunkX + "," + this.chunkZ + ") in world '" + this.world.getWorld().getName() + "'", thr); // TODO rebase - if (unloading && !completing) { - this.completeAsyncChunkDataSave(null); - } -@@ -1942,7 +1942,7 @@ public final class NewChunkHolder { - } catch (final ThreadDeath death) { - throw death; - } catch (final Throwable thr) { -- LOGGER.error("Failed to save entity data (" + this.chunkX + "," + this.chunkZ + ") in world '" + this.world.getWorld().getName() + "'"); -+ LOGGER.error("Failed to save entity data (" + this.chunkX + "," + this.chunkZ + ") in world '" + this.world.getWorld().getName() + "'", thr); // TODO rebase - } - - return true; -@@ -1968,7 +1968,7 @@ public final class NewChunkHolder { - } catch (final ThreadDeath death) { - throw death; - } catch (final Throwable thr) { -- LOGGER.error("Failed to save poi data (" + this.chunkX + "," + this.chunkZ + ") in world '" + this.world.getWorld().getName() + "'"); -+ LOGGER.error("Failed to save poi data (" + this.chunkX + "," + this.chunkZ + ") in world '" + this.world.getWorld().getName() + "'", thr); // TODO rebase - } - - return true; diff --git a/src/main/java/io/papermc/paper/command/PaperCommands.java b/src/main/java/io/papermc/paper/command/PaperCommands.java index 7b58b2d6297800c2dcdbf7539e5ab8e7703f39f1..a587d83b78af4efc484f939529acf70834f60d7e 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommands.java @@ -2371,10 +1065,10 @@ index bd68139ae635f2ad7ec8e7a21e0056a139c4c62e..48a43341b17247355a531164019d5cc9 } diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index 0467ad99b144aa81a04baa45d4c8bbb2b70185a2..d7ba88f8b3e380392717b5a283c9f2cfa4d14325 100644 +index 214ea75502d4abf9ebbc99a3811e4d2f8465227e..eae1bb367483eb6343a8644f6bac56215298bb43 100644 --- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -346,4 +346,18 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -356,4 +356,18 @@ public class GlobalConfiguration extends ConfigurationPart { public boolean disableChorusPlantUpdates = false; public boolean disableMushroomBlockUpdates = false; } @@ -2394,10 +1088,10 @@ index 0467ad99b144aa81a04baa45d4c8bbb2b70185a2..d7ba88f8b3e380392717b5a283c9f2cf + // Folia end - threaded regions } diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java -index efc91ff91827872c62b8bd060282549ccdcf67dd..9534308bb0a34761f70241b1ba993b814d989753 100644 +index 7509b17414f836e8b53fc62b02b386ba4e8c5ca9..fc9dc8bf31281fc6962489aba2c3e78f25cb5120 100644 --- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java -@@ -471,6 +471,14 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -472,6 +472,14 @@ public class WorldConfiguration extends ConfigurationPart { public Chunks chunks; public class Chunks extends ConfigurationPart { @@ -2432,14 +1126,13 @@ index 3e82ea07ca4194844c5528446e2c4a46ff4acee5..adfd4c16809f6ddd9cc73e4bd845d7ae try { diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java new file mode 100644 -index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d77cbb6626 +index 0000000000000000000000000000000000000000..d1cd3c1428de206d1d0b58e507d5d5a72f846acc --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java -@@ -0,0 +1,175 @@ +@@ -0,0 +1,174 @@ +package io.papermc.paper.threadedregions; + +import com.mojang.logging.LogUtils; -+import io.papermc.paper.util.TickThread; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; @@ -2449,7 +1142,7 @@ index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d7 +import java.util.List; +import java.util.concurrent.TimeUnit; + -+public final class RegionShutdownThread extends TickThread { ++public final class RegionShutdownThread extends ca.spottedleaf.moonrise.common.util.TickThread { + + private static final Logger LOGGER = LogUtils.getClassLogger(); + @@ -2512,7 +1205,7 @@ index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d7 + for (final Entity.EntityTreeNode node : pendingTeleport.rootVehicle().getFullTree()) { + // assume that world and position are set to destination here + node.root.setLevel(world); // in case the pending teleport is from a portal before it finds the exact destination -+ world.getEntityLookup().addEntityForShutdownTeleportComplete(node.root); ++ world.moonrise$getEntityLookup().addEntityForShutdownTeleportComplete(node.root); + } + + // then, rebuild the passenger tree so that when saving only the root vehicle will be written - and if @@ -2536,7 +1229,7 @@ index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d7 + this.shuttingDown = region; + center = region.getCenterChunk(); + LOGGER.info("Saving chunks around region around chunk " + center + " in world '" + region.regioniser.world.getWorld().getName() + "'"); -+ region.regioniser.world.chunkTaskScheduler.chunkHolderManager.close(true, true, false, last, false); ++ region.regioniser.world.moonrise$getChunkTaskScheduler().chunkHolderManager.close(true, true, false, last, false); + } catch (final Throwable thr) { + LOGGER.error("Failed to save chunks for region around chunk " + center + " in world '" + region.regioniser.world.getWorld().getName() + "'", thr); + } finally { @@ -2546,7 +1239,7 @@ index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d7 + + private void haltChunkSystem(final ServerLevel world) { + try { -+ world.chunkTaskScheduler.chunkHolderManager.close(false, true, true, false, false); ++ world.moonrise$getChunkTaskScheduler().chunkHolderManager.close(false, true, true, false, false); + } catch (final Throwable thr) { + LOGGER.error("Failed to halt chunk system for world '" + world.getWorld().getName() + "'", thr); + } @@ -2554,7 +1247,7 @@ index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d7 + + private void haltWorldNoRegions(final ServerLevel world) { + try { -+ world.chunkTaskScheduler.chunkHolderManager.close(true, true, true, true, false); ++ world.moonrise$getChunkTaskScheduler().chunkHolderManager.close(true, true, true, true, false); + } catch (final Throwable thr) { + LOGGER.error("Failed to close world '" + world.getWorld().getName() + "' with no regions", thr); + } @@ -2576,7 +1269,7 @@ index 0000000000000000000000000000000000000000..3f3fd8b1881106f893ffb677272e50d7 + LOGGER.info("Halting chunk systems"); + for (final ServerLevel world : MinecraftServer.getServer().getAllLevels()) { + try { -+ world.chunkTaskScheduler.halt(false, 0L); ++ world.moonrise$getChunkTaskScheduler().halt(false, 0L); + } catch (final Throwable throwable) { + LOGGER.error("Failed to soft halt chunk system for world '" + world.getWorld().getName() + "'", throwable); + } @@ -2854,7 +1547,7 @@ index 0000000000000000000000000000000000000000..1f48ada99d6d24880f9bda1cd05d41a4 +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java new file mode 100644 -index 0000000000000000000000000000000000000000..fc3d332aa1c1d469cedfe2aaa7102dcd78e25642 +index 0000000000000000000000000000000000000000..1d41a6a204068122daa1b5b2cd7541bfeae52f4c --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java @@ -0,0 +1,455 @@ @@ -2862,9 +1555,9 @@ index 0000000000000000000000000000000000000000..fc3d332aa1c1d469cedfe2aaa7102dcd + +import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue; +import ca.spottedleaf.concurrentutil.scheduler.SchedulerThreadPool; ++import ca.spottedleaf.moonrise.common.util.TickThread; +import com.mojang.logging.LogUtils; +import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler; -+import io.papermc.paper.util.TickThread; +import net.minecraft.CrashReport; +import net.minecraft.ReportedException; +import net.minecraft.network.Connection; @@ -3277,7 +1970,7 @@ index 0000000000000000000000000000000000000000..fc3d332aa1c1d469cedfe2aaa7102dcd + + world.updateTickData(); + -+ world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(); // required to eventually process ticket updates ++ world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(); // required to eventually process ticket updates + } + + private void updateRaids(final ServerLevel world) { @@ -3315,18 +2008,18 @@ index 0000000000000000000000000000000000000000..fc3d332aa1c1d469cedfe2aaa7102dcd +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedTaskQueue.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedTaskQueue.java new file mode 100644 -index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf48aa2bc35 +index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66ddba133f --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedTaskQueue.java -@@ -0,0 +1,768 @@ +@@ -0,0 +1,763 @@ +package io.papermc.paper.threadedregions; + +import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue; +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor; -+import ca.spottedleaf.concurrentutil.map.SWMRLong2ObjectHashTable; ++import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable; +import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; -+import io.papermc.paper.chunk.system.scheduling.ChunkHolderManager; -+import io.papermc.paper.util.CoordinateUtils; ++import ca.spottedleaf.moonrise.common.util.CoordinateUtils; ++import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap; +import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap; @@ -3337,7 +2030,6 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 +import java.util.ArrayDeque; +import java.util.Iterator; +import java.util.concurrent.atomic.AtomicLong; -+import java.util.concurrent.locks.ReentrantLock; + +public final class RegionizedTaskQueue { + @@ -3390,7 +2082,7 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 + public static final class WorldRegionTaskData { + private final ServerLevel world; + private final MultiThreadedQueue globalChunkTask = new MultiThreadedQueue<>(); -+ private final java.util.concurrent.ConcurrentHashMap referenceCounters = new java.util.concurrent.ConcurrentHashMap<>(); // Folia - use area based lock to reduce contention ++ private final ConcurrentLong2ReferenceChainedHashTable referenceCounters = new ConcurrentLong2ReferenceChainedHashTable<>(); + + public WorldRegionTaskData(final ServerLevel world) { + this.world = world; @@ -3425,36 +2117,33 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 + } + + private void removeTicket(final long coord) { -+ this.world.chunkTaskScheduler.chunkHolderManager.removeTicketAtLevel( ++ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel( + TASK_QUEUE_TICKET, coord, ChunkHolderManager.MAX_TICKET_LEVEL, Unit.INSTANCE + ); + } + + private void addTicket(final long coord) { -+ this.world.chunkTaskScheduler.chunkHolderManager.addTicketAtLevel( ++ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel( + TASK_QUEUE_TICKET, coord, ChunkHolderManager.MAX_TICKET_LEVEL, Unit.INSTANCE + ); + } + -+ // Folia start - use area based lock to reduce contention + private void processTicketUpdates(final long coord) { -+ this.world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(CoordinateUtils.getChunkX(coord), CoordinateUtils.getChunkZ(coord)); ++ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(CoordinateUtils.getChunkX(coord), CoordinateUtils.getChunkZ(coord)); + } -+ // Folia end - use area based lock to reduce contention + + private void decrementReference(final AtomicLong reference, final long coord) { + final long val = reference.decrementAndGet(); + if (val == 0L) { -+ final int chunkX = CoordinateUtils.getChunkX(coord); // Folia - use area based lock to reduce contention -+ final int chunkZ = CoordinateUtils.getChunkZ(coord); // Folia - use area based lock to reduce contention -+ final io.papermc.paper.chunk.system.io.RegionFileIOThread.ChunkCoordinate key = new io.papermc.paper.chunk.system.io.RegionFileIOThread.ChunkCoordinate(coord); // Folia - use area based lock to reduce contention -+ final ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock.Node ticketLock = this.world.chunkTaskScheduler.chunkHolderManager.ticketLockArea.lock(chunkX, chunkZ); // Folia - use area based lock to reduce contention ++ final int chunkX = CoordinateUtils.getChunkX(coord); ++ final int chunkZ = CoordinateUtils.getChunkZ(coord); ++ final ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock.Node ticketLock = this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.ticketLockArea.lock(chunkX, chunkZ); + try { -+ if (this.referenceCounters.remove(key, reference)) { // Folia - use area based lock to reduce contention ++ if (this.referenceCounters.remove(coord, reference) == reference) { + WorldRegionTaskData.this.removeTicket(coord); + } // else: race condition, something replaced our reference - not our issue anymore + } finally { -+ this.world.chunkTaskScheduler.chunkHolderManager.ticketLockArea.unlock(ticketLock); // Folia - use area based lock to reduce contention ++ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.ticketLockArea.unlock(ticketLock); + } + } else if (val < 0L) { + throw new IllegalStateException("Reference count < 0: " + val); @@ -3462,8 +2151,7 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 + } + + private AtomicLong incrementReference(final long coord) { -+ final io.papermc.paper.chunk.system.io.RegionFileIOThread.ChunkCoordinate key = new io.papermc.paper.chunk.system.io.RegionFileIOThread.ChunkCoordinate(coord); // Folia - use area based lock to reduce contention -+ final AtomicLong ret = this.referenceCounters.get(key); // Folia - use area based lock to reduce contention ++ final AtomicLong ret = this.referenceCounters.get(coord); + if (ret != null) { + // try to fast acquire counter + int failures = 0; @@ -3486,14 +2174,14 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 + } + + // slow acquire -+ final int chunkX = CoordinateUtils.getChunkX(coord); // Folia - use area based lock to reduce contention -+ final int chunkZ = CoordinateUtils.getChunkZ(coord); // Folia - use area based lock to reduce contention -+ final ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock.Node ticketLock = this.world.chunkTaskScheduler.chunkHolderManager.ticketLockArea.lock(chunkX, chunkZ); // Folia - use area based lock to reduce contention ++ final int chunkX = CoordinateUtils.getChunkX(coord); ++ final int chunkZ = CoordinateUtils.getChunkZ(coord); ++ final ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock.Node ticketLock = this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.ticketLockArea.lock(chunkX, chunkZ); + final AtomicLong ret2; + final boolean processTicketUpdates; + try { + final AtomicLong replace = new AtomicLong(1L); -+ final AtomicLong valueInMap = this.referenceCounters.putIfAbsent(key, replace); // Folia - use area based lock to reduce contention ++ final AtomicLong valueInMap = this.referenceCounters.putIfAbsent(coord, replace); + if (valueInMap == null) { + // replaced, we should usually be here + this.addTicket(coord); @@ -3507,7 +2195,7 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 + // don't need to add ticket here, since ticket is only removed during the lock + // we just need to replace the value in the map so that the thread removing fails and doesn't + // remove the ticket (see decrementReference) -+ this.referenceCounters.put(key, replace); // Folia - use area based lock to reduce contention ++ this.referenceCounters.put(coord, replace); + ret2 = replace; + break; + } @@ -3526,7 +2214,7 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 + } + } + } finally { -+ this.world.chunkTaskScheduler.chunkHolderManager.ticketLockArea.unlock(ticketLock); // Folia - use area based lock to reduce contention ++ this.world.moonrise$getChunkTaskScheduler().chunkHolderManager.ticketLockArea.unlock(ticketLock); + } + + if (processTicketUpdates) { @@ -3588,7 +2276,7 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 + + if (allowedChunkTasks > 0) { + // if we executed chunk tasks, we should try to process ticket updates for full status changes -+ this.worldRegionTaskData.world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(); ++ this.worldRegionTaskData.world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(); + } + } + @@ -4089,22 +2777,19 @@ index 0000000000000000000000000000000000000000..98ddb674b63a4777a98152ea960debf4 +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java new file mode 100644 -index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472bd947bb4b +index 0000000000000000000000000000000000000000..ea03d42a4c72924bc96e7d6f487ed23bcfa0e370 --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java -@@ -0,0 +1,795 @@ +@@ -0,0 +1,746 @@ +package io.papermc.paper.threadedregions; + -+import com.destroystokyo.paper.util.maplist.ReferenceList; -+import com.destroystokyo.paper.util.misc.PlayerAreaMap; -+import com.destroystokyo.paper.util.misc.PooledLinkedHashSets; ++import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; ++import ca.spottedleaf.moonrise.common.list.ReferenceList; ++import ca.spottedleaf.moonrise.common.misc.NearbyPlayers; ++import ca.spottedleaf.moonrise.common.util.CoordinateUtils; ++import ca.spottedleaf.moonrise.common.util.TickThread; ++import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; +import com.mojang.logging.LogUtils; -+import io.papermc.paper.chunk.system.scheduling.ChunkHolderManager; -+import io.papermc.paper.util.CoordinateUtils; -+import io.papermc.paper.util.TickThread; -+import io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet; -+import io.papermc.paper.util.player.NearbyPlayers; -+import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ReferenceMap; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; @@ -4141,10 +2826,8 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b +import net.minecraft.world.level.pathfinder.PathTypeCache; +import net.minecraft.world.level.redstone.CollectingNeighborUpdater; +import net.minecraft.world.level.redstone.NeighborUpdater; -+import net.minecraft.world.phys.AABB; +import net.minecraft.world.ticks.LevelTicks; +import org.bukkit.craftbukkit.block.CraftBlockState; -+import org.bukkit.craftbukkit.util.UnsafeList; +import org.slf4j.Logger; +import javax.annotation.Nullable; +import java.util.ArrayDeque; @@ -4163,6 +2846,8 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + + private static final Logger LOGGER = LogUtils.getLogger(); + ++ private static final Entity[] EMPTY_ENTITY_ARRAY = new Entity[0]; ++ + public static final RegionizedData.RegioniserCallback REGION_CALLBACK = new RegionizedData.RegioniserCallback<>() { + @Override + public void merge(final RegionizedWorldData from, final RegionizedWorldData into, final long fromTickOffset) { @@ -4232,8 +2917,6 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + into.redstoneUpdateInfos.add(info); + } + } -+ // light chunks being worked on -+ into.chunksBeingWorkedOn.putAll(from.chunksBeingWorkedOn); + // mob spawning + into.catSpawnerNextTick = Math.max(from.catSpawnerNextTick, into.catSpawnerNextTick); + into.patrolSpawnerNextTick = Math.max(from.patrolSpawnerNextTick, into.patrolSpawnerNextTick); @@ -4379,17 +3062,6 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + } // else: chunk unloaded + } + } -+ // light chunks being worked on -+ for (final Iterator iterator = from.chunksBeingWorkedOn.long2IntEntrySet().fastIterator(); iterator.hasNext();) { -+ final Long2IntOpenHashMap.Entry entry = iterator.next(); -+ final long pos = entry.getLongKey(); -+ final int chunkX = CoordinateUtils.getChunkX(pos); -+ final int chunkZ = CoordinateUtils.getChunkZ(pos); -+ final int value = entry.getIntValue(); -+ -+ // should never be null, as it is a reference counter for ticket -+ regionToData.get(CoordinateUtils.getChunkKey(chunkX >> chunkToRegionShift, chunkZ >> chunkToRegionShift)).chunksBeingWorkedOn.put(pos, value); -+ } + // mob spawning + for (final RegionizedWorldData regionizedWorldData : dataSet) { + regionizedWorldData.catSpawnerNextTick = from.catSpawnerNextTick; @@ -4424,11 +3096,13 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + // entities + private final List localPlayers = new ArrayList<>(); + private final NearbyPlayers nearbyPlayers; -+ private final ReferenceList allEntities = new ReferenceList<>(); -+ private final ReferenceList loadedEntities = new ReferenceList<>(); -+ private final ReferenceList toProcessTrackingUnloading = new ReferenceList<>(); ++ private final ReferenceList allEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); ++ private final ReferenceList loadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); ++ private final ReferenceList toProcessTrackingUnloading = new ReferenceList<>(EMPTY_ENTITY_ARRAY); + private final IteratorSafeOrderedReferenceSet entityTickList = new IteratorSafeOrderedReferenceSet<>(); + private final IteratorSafeOrderedReferenceSet navigatingMobs = new IteratorSafeOrderedReferenceSet<>(); ++ public final ReferenceList trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker ++ public final ReferenceList trackerUnloadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker + + // block ticking + private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet<>(); @@ -4466,8 +3140,8 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + public boolean skipPushModeEventFire = false; + public boolean skipHopperEvents = false; + // Paper end - Optimize Hoppers -+ public long lastMidTickExecuteFailure; + public long lastMidTickExecute; ++ public long lastMidTickExecuteFailure; + // From Level + public boolean populating; + public final NeighborUpdater neighborUpdater; @@ -4484,8 +3158,6 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + public int wakeupInactiveRemainingMonsters; + public int wakeupInactiveRemainingVillagers; + // Paper end -+ public final TempCollisionList tempCollisionList = new TempCollisionList<>(); -+ public final TempCollisionList tempEntitiesList = new TempCollisionList<>(); + public int currentPrimedTnt = 0; // Spigot + @Nullable + @VisibleForDebug @@ -4493,44 +3165,13 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + public boolean shouldSignal = true; + public final Map explosionDensityCache = new HashMap<>(64, 0.25f); + public final PathTypeCache pathTypesByPosCache = new PathTypeCache(); ++ public net.minecraft.server.level.ServerChunkCache.ChunkAndHolder[] iterationCopy; // Paper - chunk tick iteration optimisations + + // not transient + public java.util.ArrayDeque redstoneUpdateInfos; -+ public final Long2IntOpenHashMap chunksBeingWorkedOn = new Long2IntOpenHashMap(); -+ -+ public static final class TempCollisionList { -+ final UnsafeList list = new UnsafeList<>(64); -+ boolean inUse; -+ -+ public UnsafeList get() { -+ if (this.inUse) { -+ return new UnsafeList<>(16); -+ } -+ this.inUse = true; -+ return this.list; -+ } -+ -+ public void ret(List list) { -+ if (list != this.list) { -+ return; -+ } -+ -+ ((UnsafeList)list).setSize(0); -+ this.inUse = false; -+ } -+ -+ public void reset() { -+ this.list.completeReset(); -+ } -+ } -+ public void resetCollisionLists() { -+ this.tempCollisionList.reset(); -+ this.tempEntitiesList.reset(); -+ } + + // Mob spawning -+ private final PooledLinkedHashSets pooledHashSets = new PooledLinkedHashSets<>(); -+ public final PlayerAreaMap mobSpawnMap = new PlayerAreaMap(this.pooledHashSets); ++ public final ca.spottedleaf.moonrise.common.misc.PositionCountingAreaMap spawnChunkTracker = new ca.spottedleaf.moonrise.common.misc.PositionCountingAreaMap<>(); + public int catSpawnerNextTick = 0; + public int patrolSpawnerNextTick = 0; + public int phantomSpawnerNextTick = 0; @@ -4729,7 +3370,6 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + if (this.allEntities.add(entity)) { + if (entity instanceof ServerPlayer player) { + this.localPlayers.add(player); -+ this.nearbyPlayers.addPlayer(player); + } + TickRegions.RegionStats.updateCurrentRegion(); + } @@ -4746,7 +3386,6 @@ index 0000000000000000000000000000000000000000..0180d319f1d79ee48ac71afe7f27472b + if (this.allEntities.remove(entity)) { + if (entity instanceof ServerPlayer player) { + this.localPlayers.remove(player); -+ this.nearbyPlayers.removePlayer(player); + } + TickRegions.RegionStats.updateCurrentRegion(); + } @@ -5063,7 +3702,7 @@ index 0000000000000000000000000000000000000000..7b31c4ea6d01f936271bdadc3626201d +} diff --git a/src/main/java/io/papermc/paper/threadedregions/ThreadedRegionizer.java b/src/main/java/io/papermc/paper/threadedregions/ThreadedRegionizer.java new file mode 100644 -index 0000000000000000000000000000000000000000..531aa50f2c84e13358e8918bb0c15ea3cd036cb5 +index 0000000000000000000000000000000000000000..ce388e0ef231d7d73f75f5778c58eb40f6402f0f --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/ThreadedRegionizer.java @@ -0,0 +1,1405 @@ @@ -5071,9 +3710,9 @@ index 0000000000000000000000000000000000000000..531aa50f2c84e13358e8918bb0c15ea3 + +import ca.spottedleaf.concurrentutil.map.SWMRLong2ObjectHashTable; +import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; ++import ca.spottedleaf.moonrise.common.util.CoordinateUtils; +import com.destroystokyo.paper.util.SneakyThrow; +import com.mojang.logging.LogUtils; -+import io.papermc.paper.util.CoordinateUtils; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongArrayList; +import it.unimi.dsi.fastutil.longs.LongComparator; @@ -6169,7 +4808,7 @@ index 0000000000000000000000000000000000000000..531aa50f2c84e13358e8918bb0c15ea3 + + for (int i = 0, bits = Long.bitCount(value); i < bits; ++i) { + final int valueIdx = Long.numberOfTrailingZeros(value); -+ value ^= io.papermc.paper.util.IntegerUtil.getTrailingBit(value); ++ value ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(value); + + final int idx = valueIdx | (arrIdx << 6); + @@ -6813,16 +5452,17 @@ index 0000000000000000000000000000000000000000..29f9fed5f02530b3256e6b993e607d46 +} diff --git a/src/main/java/io/papermc/paper/threadedregions/TickRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/TickRegionScheduler.java new file mode 100644 -index 0000000000000000000000000000000000000000..150610d7bf25416dbbde7f003c47da562acc68ba +index 0000000000000000000000000000000000000000..54539fecd96a8a4c4a15e147876f7e0985f566cd --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/TickRegionScheduler.java -@@ -0,0 +1,565 @@ +@@ -0,0 +1,570 @@ +package io.papermc.paper.threadedregions; + +import ca.spottedleaf.concurrentutil.scheduler.SchedulerThreadPool; +import ca.spottedleaf.concurrentutil.util.TimeUtil; ++import ca.spottedleaf.moonrise.common.util.TickThread; +import com.mojang.logging.LogUtils; -+import io.papermc.paper.util.TickThread; ++import io.papermc.paper.util.TraceUtil; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.ChunkPos; @@ -6975,7 +5615,11 @@ index 0000000000000000000000000000000000000000..150610d7bf25416dbbde7f003c47da56 + } + + void dumpAliveThreadTraces(final String reason) { -+ this.scheduler.dumpAliveThreadTraces(reason); ++ for (final Thread thread : this.scheduler.getThreads()) { ++ if (thread.isAlive()) { ++ TraceUtil.dumpTraceForThread(thread, reason); ++ } ++ } + } + + public void setHasTasks(final RegionScheduleHandle region) { @@ -7383,18 +6027,18 @@ index 0000000000000000000000000000000000000000..150610d7bf25416dbbde7f003c47da56 + } +} diff --git a/src/main/java/io/papermc/paper/threadedregions/TickRegions.java b/src/main/java/io/papermc/paper/threadedregions/TickRegions.java -index d5d39e9c1f326e91010237b0db80d527ac52f4d6..924ade31b788b161a7c8f587504b2fc86932a2ee 100644 +index 8424cf9d4617b4732d44cc460d25b04481068989..df15b1139e71dfe10b8f24ec6d235b99f6d5006a 100644 --- a/src/main/java/io/papermc/paper/threadedregions/TickRegions.java +++ b/src/main/java/io/papermc/paper/threadedregions/TickRegions.java -@@ -1,9 +1,409 @@ +@@ -1,10 +1,410 @@ package io.papermc.paper.threadedregions; -// placeholder class for Folia -public class TickRegions { +import ca.spottedleaf.concurrentutil.scheduler.SchedulerThreadPool; +import ca.spottedleaf.concurrentutil.util.TimeUtil; ++import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; +import com.mojang.logging.LogUtils; -+import io.papermc.paper.chunk.system.scheduling.ChunkHolderManager; +import io.papermc.paper.configuration.GlobalConfiguration; +import it.unimi.dsi.fastutil.longs.Long2ReferenceMap; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; @@ -7416,7 +6060,7 @@ index d5d39e9c1f326e91010237b0db80d527ac52f4d6..924ade31b788b161a7c8f587504b2fc8 + private static int regionShift = 31; public static int getRegionChunkShift() { -- return 4; +- return ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ThreadedTicketLevelPropagator.SECTION_SHIFT; + return regionShift; + } + @@ -7788,7 +6432,7 @@ index d5d39e9c1f326e91010237b0db80d527ac52f4d6..924ade31b788b161a7c8f587504b2fc8 + + if (processedChunkTask) { + // if we processed any chunk tasks, try to process ticket level updates for full status changes -+ this.region.world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(); ++ this.region.world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates(); + } + return true; + } @@ -7798,6 +6442,7 @@ index d5d39e9c1f326e91010237b0db80d527ac52f4d6..924ade31b788b161a7c8f587504b2fc8 + return this.region.taskQueueData.hasTasks(); + } } + } diff --git a/src/main/java/io/papermc/paper/threadedregions/commands/CommandServerHealth.java b/src/main/java/io/papermc/paper/threadedregions/commands/CommandServerHealth.java new file mode 100644 @@ -8289,7 +6934,7 @@ index 0000000000000000000000000000000000000000..d016294fc7eafbddf6d2a758e5803498 +} diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaRegionScheduler.java new file mode 100644 -index 0000000000000000000000000000000000000000..a12705793a63b289da13ebabeaf441637c4fe2ed +index 0000000000000000000000000000000000000000..85d3965a67cfb59790c664baa7840b50436a5e28 --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaRegionScheduler.java @@ -0,0 +1,424 @@ @@ -8297,11 +6942,11 @@ index 0000000000000000000000000000000000000000..a12705793a63b289da13ebabeaf44163 + +import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; +import ca.spottedleaf.concurrentutil.util.Validate; -+import io.papermc.paper.chunk.system.scheduling.ChunkHolderManager; ++import ca.spottedleaf.moonrise.common.util.CoordinateUtils; ++import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; +import io.papermc.paper.threadedregions.RegionizedData; +import io.papermc.paper.threadedregions.RegionizedServer; +import io.papermc.paper.threadedregions.TickRegionScheduler; -+import io.papermc.paper.util.CoordinateUtils; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; @@ -8488,22 +7133,22 @@ index 0000000000000000000000000000000000000000..a12705793a63b289da13ebabeaf44163 + + private void addTicket(final int sectionX, final int sectionZ) { + final ServerLevel world = TickRegionScheduler.getCurrentRegionizedWorldData().world; -+ final int shift = world.getRegionChunkShift(); ++ final int shift = world.moonrise$getRegionChunkShift(); + final int chunkX = sectionX << shift; + final int chunkZ = sectionZ << shift; + -+ world.chunkTaskScheduler.chunkHolderManager.addTicketAtLevel( ++ world.moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel( + TicketType.REGION_SCHEDULER_API_HOLD, chunkX, chunkZ, ChunkHolderManager.MAX_TICKET_LEVEL, Unit.INSTANCE + ); + } + + private void removeTicket(final long sectionKey) { + final ServerLevel world = TickRegionScheduler.getCurrentRegionizedWorldData().world; -+ final int shift = world.getRegionChunkShift(); ++ final int shift = world.moonrise$getRegionChunkShift(); + final int chunkX = CoordinateUtils.getChunkX(sectionKey) << shift; + final int chunkZ = CoordinateUtils.getChunkZ(sectionKey) << shift; + -+ world.chunkTaskScheduler.chunkHolderManager.removeTicketAtLevel( ++ world.moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel( + TicketType.REGION_SCHEDULER_API_HOLD, chunkX, chunkZ, ChunkHolderManager.MAX_TICKET_LEVEL, Unit.INSTANCE + ); + } @@ -8518,7 +7163,7 @@ index 0000000000000000000000000000000000000000..a12705793a63b289da13ebabeaf44163 + return; + } + -+ final int shift = ((CraftWorld)world).getHandle().getRegionChunkShift(); ++ final int shift = ((CraftWorld)world).getHandle().moonrise$getRegionChunkShift(); + final int sectionX = task.chunkX >> shift; + final int sectionZ = task.chunkZ >> shift; + @@ -8717,150 +7362,11 @@ index 0000000000000000000000000000000000000000..a12705793a63b289da13ebabeaf44163 + } + } +} -diff --git a/src/main/java/io/papermc/paper/util/CachedLists.java b/src/main/java/io/papermc/paper/util/CachedLists.java -index e08f4e39db4ee3fed62e37364d17dcc5c5683504..7e92e14cdb9f3d895550991b2ea154a60f9c091b 100644 ---- a/src/main/java/io/papermc/paper/util/CachedLists.java -+++ b/src/main/java/io/papermc/paper/util/CachedLists.java -@@ -9,49 +9,57 @@ import java.util.List; - public final class CachedLists { - - // Paper start - optimise collisions -- static final UnsafeList TEMP_COLLISION_LIST = new UnsafeList<>(1024); -- static boolean tempCollisionListInUse; -+ // Folia - region threading - - public static UnsafeList getTempCollisionList() { -- if (!Bukkit.isPrimaryThread() || tempCollisionListInUse) { -+ // Folia start - region threading -+ io.papermc.paper.threadedregions.RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); -+ if (worldData == null) { - return new UnsafeList<>(16); - } -- tempCollisionListInUse = true; -- return TEMP_COLLISION_LIST; -+ return worldData.tempCollisionList.get(); -+ // Folia end - region threading - } - - public static void returnTempCollisionList(List list) { -- if (list != TEMP_COLLISION_LIST) { -+ // Folia start - region threading -+ io.papermc.paper.threadedregions.RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); -+ if (worldData == null) { - return; - } -- ((UnsafeList)list).setSize(0); -- tempCollisionListInUse = false; -+ worldData.tempCollisionList.ret(list); -+ // Folia end - region threading - } - -- static final UnsafeList TEMP_GET_ENTITIES_LIST = new UnsafeList<>(1024); -- static boolean tempGetEntitiesListInUse; -+ // Folia - region threading - - public static UnsafeList getTempGetEntitiesList() { -- if (!Bukkit.isPrimaryThread() || tempGetEntitiesListInUse) { -+ // Folia start - region threading -+ io.papermc.paper.threadedregions.RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); -+ if (worldData == null) { - return new UnsafeList<>(16); - } -- tempGetEntitiesListInUse = true; -- return TEMP_GET_ENTITIES_LIST; -+ return worldData.tempEntitiesList.get(); -+ // Folia end - region threading - } - - public static void returnTempGetEntitiesList(List list) { -- if (list != TEMP_GET_ENTITIES_LIST) { -+ // Folia start - region threading -+ io.papermc.paper.threadedregions.RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); -+ if (worldData == null) { - return; - } -- ((UnsafeList)list).setSize(0); -- tempGetEntitiesListInUse = false; -+ worldData.tempEntitiesList.ret(list); -+ // Folia end - region threading - } - // Paper end - optimise collisions - - public static void reset() { -- // Paper start - optimise collisions -- TEMP_COLLISION_LIST.completeReset(); -- TEMP_GET_ENTITIES_LIST.completeReset(); -- // Paper end - optimise collisions -+ // Folia start - region threading -+ io.papermc.paper.threadedregions.RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); -+ if (worldData != null) { -+ worldData.resetCollisionLists(); -+ } -+ // Folia end - region threading - } - } -diff --git a/src/main/java/io/papermc/paper/util/CollisionUtil.java b/src/main/java/io/papermc/paper/util/CollisionUtil.java -index ee8e9c0e3690e78f3cc621ddfca89ea4256d4803..c3271b6048cf61d7d4e5fa66c5f925c1c8c82ca6 100644 ---- a/src/main/java/io/papermc/paper/util/CollisionUtil.java -+++ b/src/main/java/io/papermc/paper/util/CollisionUtil.java -@@ -1623,7 +1623,7 @@ public final class CollisionUtil { - - for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { - for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { -- final ChunkAccess chunk = loadChunks ? chunkSource.getChunk(currChunkX, currChunkZ, ChunkStatus.FULL, true) : chunkSource.getChunkAtIfLoadedImmediately(currChunkX, currChunkZ); -+ final ChunkAccess chunk = !io.papermc.paper.util.TickThread.isTickThreadFor(chunkSource.chunkMap.level, currChunkX, currChunkZ) ? null : (loadChunks ? chunkSource.getChunk(currChunkX, currChunkZ, ChunkStatus.FULL, true) : chunkSource.getChunkAtIfLoadedImmediately(currChunkX, currChunkZ)); // Folia - ignore chunk if we do not own the region - - if (chunk == null) { - if ((collisionFlags & COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS) != 0) { -diff --git a/src/main/java/io/papermc/paper/util/CoordinateUtils.java b/src/main/java/io/papermc/paper/util/CoordinateUtils.java -index 413e4b6da027876dbbe8eb78f2568a440f431547..3a7dbcb9964723b8ed5e6b0a1ee4267923c746e4 100644 ---- a/src/main/java/io/papermc/paper/util/CoordinateUtils.java -+++ b/src/main/java/io/papermc/paper/util/CoordinateUtils.java -@@ -5,6 +5,7 @@ import net.minecraft.core.SectionPos; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.level.ChunkPos; -+import net.minecraft.world.phys.Vec3; - - public final class CoordinateUtils { - -@@ -122,6 +123,31 @@ public final class CoordinateUtils { - return ((long)entity.getX() & 0x7FFFFFF) | (((long)entity.getZ() & 0x7FFFFFF) << 27) | ((long)entity.getY() << 54); - } - -+ // TODO rebase -+ public static int getBlockX(final Vec3 pos) { -+ return Mth.floor(pos.x); -+ } -+ -+ public static int getBlockY(final Vec3 pos) { -+ return Mth.floor(pos.y); -+ } -+ -+ public static int getBlockZ(final Vec3 pos) { -+ return Mth.floor(pos.z); -+ } -+ -+ public static int getChunkX(final Vec3 pos) { -+ return Mth.floor(pos.x) >> 4; -+ } -+ -+ public static int getChunkY(final Vec3 pos) { -+ return Mth.floor(pos.y) >> 4; -+ } -+ -+ public static int getChunkZ(final Vec3 pos) { -+ return Mth.floor(pos.z) >> 4; -+ } -+ - private CoordinateUtils() { - throw new RuntimeException(); - } diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java -index 1d6b3fe2ce240af4ede61588795456b046eee6c9..bb915f30997059f22c9002b1ddc1c3aecbf4e979 100644 +index 0449d4619e3a0752dea0981fb149542e23076c52..5931afeccc17733103641c9d84390617fc9f62c0 100644 --- a/src/main/java/io/papermc/paper/util/MCUtil.java +++ b/src/main/java/io/papermc/paper/util/MCUtil.java -@@ -337,6 +337,7 @@ public final class MCUtil { +@@ -90,6 +90,7 @@ public final class MCUtil { */ public static void ensureMain(String reason, Runnable run) { if (!isMainThread()) { @@ -8868,7 +7374,7 @@ index 1d6b3fe2ce240af4ede61588795456b046eee6c9..bb915f30997059f22c9002b1ddc1c3ae if (reason != null) { MinecraftServer.LOGGER.warn("Asynchronous " + reason + "!", new IllegalStateException()); } -@@ -477,6 +478,30 @@ public final class MCUtil { +@@ -144,6 +145,30 @@ public final class MCUtil { return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); } @@ -8896,467 +7402,11 @@ index 1d6b3fe2ce240af4ede61588795456b046eee6c9..bb915f30997059f22c9002b1ddc1c3ae + } + // Folia end - TODO MERGE INTO MCUTIL + - /** - * Converts an NMS entity's current location to a Bukkit Location - * @param entity -diff --git a/src/main/java/io/papermc/paper/util/TickThread.java b/src/main/java/io/papermc/paper/util/TickThread.java -index bdaf062f9b66ceab303a0807eca301342886a8ea..906f1c9e619a924c622acc76652a4569305edc8d 100644 ---- a/src/main/java/io/papermc/paper/util/TickThread.java -+++ b/src/main/java/io/papermc/paper/util/TickThread.java -@@ -1,5 +1,11 @@ - package io.papermc.paper.util; - -+import io.papermc.paper.threadedregions.RegionShutdownThread; -+import io.papermc.paper.threadedregions.RegionizedServer; -+import io.papermc.paper.threadedregions.RegionizedWorldData; -+import io.papermc.paper.threadedregions.ThreadedRegionizer; -+import io.papermc.paper.threadedregions.TickRegionScheduler; -+import io.papermc.paper.threadedregions.TickRegions; - import net.minecraft.core.BlockPos; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerLevel; -@@ -114,46 +120,149 @@ public class TickThread extends Thread { + public static BlockPos toBlockPosition(Location loc) { + return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); } - - public static boolean isShutdownThread() { -- return false; -+ return Thread.currentThread().getClass() == RegionShutdownThread.class; - } - - public static boolean isTickThreadFor(final ServerLevel world, final BlockPos pos) { -- return isTickThread(); -+ return isTickThreadFor(world, pos.getX() >> 4, pos.getZ() >> 4); - } - - public static boolean isTickThreadFor(final ServerLevel world, final ChunkPos pos) { -- return isTickThread(); -+ return isTickThreadFor(world, pos.x, pos.z); - } - - public static boolean isTickThreadFor(final ServerLevel world, final Vec3 pos) { -- return isTickThread(); -+ return isTickThreadFor(world, Mth.floor(pos.x) >> 4, Mth.floor(pos.z) >> 4); - } - - public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ) { -- return isTickThread(); -+ final ThreadedRegionizer.ThreadedRegion region = -+ TickRegionScheduler.getCurrentRegion(); -+ if (region == null) { -+ return isShutdownThread(); -+ } -+ return world.regioniser.getRegionAtUnsynchronised(chunkX, chunkZ) == region; - } - - public static boolean isTickThreadFor(final ServerLevel world, final AABB aabb) { -- return isTickThread(); -+ return isTickThreadFor( -+ world, -+ CoordinateUtils.getChunkCoordinate(aabb.minX), CoordinateUtils.getChunkCoordinate(aabb.minZ), -+ CoordinateUtils.getChunkCoordinate(aabb.maxX), CoordinateUtils.getChunkCoordinate(aabb.maxZ) -+ ); - } - - public static boolean isTickThreadFor(final ServerLevel world, final double blockX, final double blockZ) { -- return isTickThread(); -+ return isTickThreadFor(world, CoordinateUtils.getChunkCoordinate(blockX), CoordinateUtils.getChunkCoordinate(blockZ)); - } - - public static boolean isTickThreadFor(final ServerLevel world, final Vec3 position, final Vec3 deltaMovement, final int buffer) { -- return isTickThread(); -+ final int fromChunkX = CoordinateUtils.getChunkX(position); -+ final int fromChunkZ = CoordinateUtils.getChunkZ(position); -+ -+ final int toChunkX = CoordinateUtils.getChunkCoordinate(position.x + deltaMovement.x); -+ final int toChunkZ = CoordinateUtils.getChunkCoordinate(position.z + deltaMovement.z); -+ -+ // expect from < to, but that may not be the case -+ return isTickThreadFor( -+ world, -+ Math.min(fromChunkX, toChunkX) - buffer, -+ Math.min(fromChunkZ, toChunkZ) - buffer, -+ Math.max(fromChunkX, toChunkX) + buffer, -+ Math.max(fromChunkZ, toChunkZ) + buffer -+ ); - } - - public static boolean isTickThreadFor(final ServerLevel world, final int fromChunkX, final int fromChunkZ, final int toChunkX, final int toChunkZ) { -- return isTickThread(); -+ final ThreadedRegionizer.ThreadedRegion region = -+ TickRegionScheduler.getCurrentRegion(); -+ if (region == null) { -+ return isShutdownThread(); -+ } -+ -+ final int shift = world.regioniser.sectionChunkShift; -+ -+ final int minSectionX = fromChunkX >> shift; -+ final int maxSectionX = toChunkX >> shift; -+ final int minSectionZ = fromChunkZ >> shift; -+ final int maxSectionZ = toChunkZ >> shift; -+ -+ for (int secZ = minSectionZ; secZ <= maxSectionZ; ++secZ) { -+ for (int secX = minSectionX; secX <= maxSectionX; ++secX) { -+ final int lowerLeftCX = secX << shift; -+ final int lowerLeftCZ = secZ << shift; -+ if (world.regioniser.getRegionAtUnsynchronised(lowerLeftCX, lowerLeftCZ) != region) { -+ return false; -+ } -+ } -+ } -+ -+ return true; - } - - public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ, final int radius) { -- return isTickThread(); -+ return isTickThreadFor(world, chunkX - radius, chunkZ - radius, chunkX + radius, chunkZ + radius); - } - - public static boolean isTickThreadFor(final Entity entity) { -- return isTickThread(); -+ if (entity == null) { -+ return true; -+ } -+ final ThreadedRegionizer.ThreadedRegion region = -+ TickRegionScheduler.getCurrentRegion(); -+ if (region == null) { -+ if (RegionizedServer.isGlobalTickThread()) { -+ if (entity instanceof ServerPlayer serverPlayer) { -+ final ServerGamePacketListenerImpl possibleBad = serverPlayer.connection; -+ if (possibleBad == null) { -+ return true; -+ } -+ -+ final net.minecraft.network.PacketListener packetListener = possibleBad.connection.getPacketListener(); -+ if (packetListener instanceof ServerGamePacketListenerImpl gamePacketListener) { -+ return gamePacketListener.waitingForSwitchToConfig; -+ } -+ if (packetListener instanceof net.minecraft.server.network.ServerConfigurationPacketListenerImpl configurationPacketListener) { -+ return !configurationPacketListener.switchToMain; -+ } -+ return true; -+ } else { -+ return false; -+ } -+ } -+ if (isShutdownThread()) { -+ return true; -+ } -+ if (entity instanceof ServerPlayer serverPlayer) { -+ // off-main access to server player is never ok, server player is owned by one of global context or region context always -+ return false; -+ } -+ // only own entities that have not yet been added to the world -+ -+ // if the entity is removed, then it was in the world previously - which means that a region containing its location -+ // owns it -+ // if the entity has a callback, then it is contained in a world -+ return entity.hasNullCallback() && !entity.isRemoved(); -+ } -+ -+ final Level level = entity.level(); -+ if (level != region.regioniser.world) { -+ // world mismatch -+ return false; -+ } -+ -+ final RegionizedWorldData worldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); -+ -+ // pass through the check if the entity is removed and we own its chunk -+ if (worldData.hasEntity(entity)) { -+ return true; -+ } -+ -+ if (entity instanceof ServerPlayer serverPlayer) { -+ ServerGamePacketListenerImpl conn = serverPlayer.connection; -+ return conn != null && worldData.connections.contains(conn.connection); -+ } else { -+ return ((entity.hasNullCallback() || entity.isRemoved())) && isTickThreadFor((ServerLevel)level, entity.chunkPosition()); -+ } - } - } -diff --git a/src/main/java/io/papermc/paper/util/set/LinkedSortedSet.java b/src/main/java/io/papermc/paper/util/set/LinkedSortedSet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..cf9b66afc1762dbe2c625f09f9e804ca7dc0f128 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/set/LinkedSortedSet.java -@@ -0,0 +1,273 @@ -+package io.papermc.paper.util.set; -+ -+import java.util.Comparator; -+import java.util.Iterator; -+import java.util.NoSuchElementException; -+ -+// TODO rebase into util patch -+public final class LinkedSortedSet implements Iterable { -+ -+ public final Comparator comparator; -+ -+ protected Link head; -+ protected Link tail; -+ -+ public LinkedSortedSet() { -+ this((Comparator)Comparator.naturalOrder()); -+ } -+ -+ public LinkedSortedSet(final Comparator comparator) { -+ this.comparator = comparator; -+ } -+ -+ public void clear() { -+ this.head = this.tail = null; -+ } -+ -+ public boolean isEmpty() { -+ return this.head == null; -+ } -+ -+ public E first() { -+ final Link head = this.head; -+ return head == null ? null : head.element; -+ } -+ -+ public E last() { -+ final Link tail = this.tail; -+ return tail == null ? null : tail.element; -+ } -+ -+ public boolean containsFirst(final E element) { -+ final Comparator comparator = this.comparator; -+ for (Link curr = this.head; curr != null; curr = curr.next) { -+ if (comparator.compare(element, curr.element) == 0) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ public boolean containsLast(final E element) { -+ final Comparator comparator = this.comparator; -+ for (Link curr = this.tail; curr != null; curr = curr.prev) { -+ if (comparator.compare(element, curr.element) == 0) { -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ private void removeNode(final Link node) { -+ final Link prev = node.prev; -+ final Link next = node.next; -+ -+ // help GC -+ node.element = null; -+ node.prev = null; -+ node.next = null; -+ -+ if (prev == null) { -+ this.head = next; -+ } else { -+ prev.next = next; -+ } -+ -+ if (next == null) { -+ this.tail = prev; -+ } else { -+ next.prev = prev; -+ } -+ } -+ -+ public boolean remove(final Link link) { -+ if (link.element == null) { -+ return false; -+ } -+ -+ this.removeNode(link); -+ return true; -+ } -+ -+ public boolean removeFirst(final E element) { -+ final Comparator comparator = this.comparator; -+ for (Link curr = this.head; curr != null; curr = curr.next) { -+ if (comparator.compare(element, curr.element) == 0) { -+ this.removeNode(curr); -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ public boolean removeLast(final E element) { -+ final Comparator comparator = this.comparator; -+ for (Link curr = this.tail; curr != null; curr = curr.prev) { -+ if (comparator.compare(element, curr.element) == 0) { -+ this.removeNode(curr); -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ @Override -+ public Iterator iterator() { -+ return new Iterator<>() { -+ private Link next = LinkedSortedSet.this.head; -+ -+ @Override -+ public boolean hasNext() { -+ return this.next != null; -+ } -+ -+ @Override -+ public E next() { -+ final Link next = this.next; -+ if (next == null) { -+ throw new NoSuchElementException(); -+ } -+ this.next = next.next; -+ return next.element; -+ } -+ }; -+ } -+ -+ public E pollFirst() { -+ final Link head = this.head; -+ if (head == null) { -+ return null; -+ } -+ -+ final E ret = head.element; -+ final Link next = head.next; -+ -+ // unlink head -+ this.head = next; -+ if (next == null) { -+ this.tail = null; -+ } else { -+ next.prev = null; -+ } -+ -+ // help GC -+ head.element = null; -+ head.next = null; -+ -+ return ret; -+ } -+ -+ public E pollLast() { -+ final Link tail = this.tail; -+ if (tail == null) { -+ return null; -+ } -+ -+ final E ret = tail.element; -+ final Link prev = tail.prev; -+ -+ // unlink tail -+ this.tail = prev; -+ if (prev == null) { -+ this.head = null; -+ } else { -+ prev.next = null; -+ } -+ -+ // help GC -+ tail.element = null; -+ tail.prev = null; -+ -+ return ret; -+ } -+ -+ public Link addLast(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.tail; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) < 0) { -+ Link prev = curr; -+ curr = curr.prev; -+ if (curr != null) { -+ continue; -+ } -+ return this.head = prev.prev = new Link<>(element, null, prev); -+ } -+ -+ if (compare != 0) { -+ // insert after curr -+ final Link next = curr.next; -+ final Link insert = new Link<>(element, curr, next); -+ curr.next = insert; -+ -+ if (next == null) { -+ this.tail = insert; -+ } else { -+ next.prev = insert; -+ } -+ return insert; -+ } -+ -+ return null; -+ } else { -+ return this.head = this.tail = new Link<>(element); -+ } -+ } -+ -+ public Link addFirst(final E element) { -+ final Comparator comparator = this.comparator; -+ -+ Link curr = this.head; -+ if (curr != null) { -+ int compare; -+ -+ while ((compare = comparator.compare(element, curr.element)) > 0) { -+ Link prev = curr; -+ curr = curr.next; -+ if (curr != null) { -+ continue; -+ } -+ return this.tail = prev.next = new Link<>(element, prev, null); -+ } -+ -+ if (compare != 0) { -+ // insert before curr -+ final Link prev = curr.prev; -+ final Link insert = new Link<>(element, prev, curr); -+ curr.prev = insert; -+ -+ if (prev == null) { -+ this.head = insert; -+ } else { -+ prev.next = insert; -+ } -+ return insert; -+ } -+ -+ return null; -+ } else { -+ return this.head = this.tail = new Link<>(element); -+ } -+ } -+ -+ public static final class Link { -+ private E element; -+ private Link prev; -+ private Link next; -+ -+ private Link() {} -+ -+ private Link(final E element) { -+ this.element = element; -+ } -+ -+ private Link(final E element, final Link prev, final Link next) { -+ this.element = element; -+ this.prev = prev; -+ this.next = next; -+ } -+ } -+} diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index 59d7e8a3d83d3ab7aa28606401bb129ccaeff240..164202089b4ad0ab832a444e818ffd39aa966e70 100644 +index 2d344df35d47b4b1ecddf32ccaa4dae41e5f58cb..8263a1134582675e67afd5ee07c6d3d06172c460 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java @@ -67,7 +67,7 @@ public class CommandSourceStack implements ExecutionCommandSource(player.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - Brigadier API @@ -9494,10 +7544,10 @@ index 6df0db8b4cdab23494ea34236949ece4989110a3..2fd670d941bd575f99def28732ffee29 } diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index f28705547a62da790f5df071400986aacba39367..4bbed8e057a32ce22d768392cebc27110cf4338b 100644 +index 39c96f5db6e90a470404c6387fa0c1d5531822e5..526a24d30e193a9f6760e9392364360f6f5fe020 100644 --- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -@@ -85,7 +85,7 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior { +@@ -87,7 +87,7 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement())); @@ -9507,10 +7557,10 @@ index f28705547a62da790f5df071400986aacba39367..4bbed8e057a32ce22d768392cebc2711 } diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae0416483b290217 100644 +index 60d3319016beb4f60cbc26dde165f64cf7577602..f2fe380c0cd07afabfaa257d5db04c4064f7a3cb 100644 --- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -@@ -114,7 +114,7 @@ public interface DispenseItemBehavior { +@@ -115,7 +115,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); @@ -9519,7 +7569,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -173,7 +173,7 @@ public interface DispenseItemBehavior { +@@ -174,7 +174,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); @@ -9528,7 +7578,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -228,7 +228,7 @@ public interface DispenseItemBehavior { +@@ -229,7 +229,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); @@ -9537,7 +7587,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 world.getCraftServer().getPluginManager().callEvent(event); } -@@ -284,7 +284,7 @@ public interface DispenseItemBehavior { +@@ -285,7 +285,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity()); @@ -9546,7 +7596,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 world.getCraftServer().getPluginManager().callEvent(event); } -@@ -358,7 +358,7 @@ public interface DispenseItemBehavior { +@@ -359,7 +359,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity()); @@ -9555,7 +7605,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 world.getCraftServer().getPluginManager().callEvent(event); } -@@ -430,7 +430,7 @@ public interface DispenseItemBehavior { +@@ -431,7 +431,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); @@ -9564,7 +7614,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -506,7 +506,7 @@ public interface DispenseItemBehavior { +@@ -496,7 +496,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); @@ -9573,7 +7623,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -553,7 +553,7 @@ public interface DispenseItemBehavior { +@@ -534,7 +534,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); @@ -9582,7 +7632,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -616,7 +616,7 @@ public interface DispenseItemBehavior { +@@ -596,7 +596,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); @@ -9591,7 +7641,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -634,7 +634,8 @@ public interface DispenseItemBehavior { +@@ -614,7 +614,8 @@ public interface DispenseItemBehavior { } } @@ -9601,7 +7651,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 // CraftBukkit end if (!BoneMealItem.growCrop(stack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(stack, worldserver, blockposition, (Direction) null)) { -@@ -643,13 +644,13 @@ public interface DispenseItemBehavior { +@@ -623,13 +624,13 @@ public interface DispenseItemBehavior { worldserver.levelEvent(1505, blockposition, 15); } // CraftBukkit start @@ -9621,7 +7671,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 StructureGrowEvent structureEvent = null; if (treeType != null) { structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks); -@@ -685,7 +686,7 @@ public interface DispenseItemBehavior { +@@ -665,7 +666,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); @@ -9630,7 +7680,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -742,7 +743,7 @@ public interface DispenseItemBehavior { +@@ -722,7 +723,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); @@ -9639,7 +7689,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -791,7 +792,7 @@ public interface DispenseItemBehavior { +@@ -771,7 +772,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); @@ -9648,7 +7698,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -864,7 +865,7 @@ public interface DispenseItemBehavior { +@@ -833,7 +834,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - only single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); @@ -9657,7 +7707,7 @@ index 5dab1e10303177e5a4d97a91ee46ede66f30ae35..2e701ff7dc2c04f77e2f003cae041648 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -946,7 +947,7 @@ public interface DispenseItemBehavior { +@@ -915,7 +916,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); @@ -9680,7 +7730,7 @@ index e37d2d29f3ba67cfe28abe4847a3dca07121f0be..067f888fdaeced3350c858e2b825a384 } diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index a024c697a65bbab27408da1d6a75e531d9719b47..bd8c333e91dff03196ec9e5730225cb37ab83da4 100644 +index 44b79a7c2f8b95a484d1999fa2167ce588f7985b..624df8e8dbf0922c9403d951967312128866515d 100644 --- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java @@ -41,7 +41,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { @@ -9706,7 +7756,7 @@ index cb308808906a8cdb127df8284e106e00553473ca..05bc1f010b50e673e9a185d96e338bae } diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357c72e7f7b 100644 +index 3e550f8e7cd4f4e16f499a8a2a4b95420270f07a..b0136591a37734493a310332b1f56f1259f913af 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java @@ -93,7 +93,7 @@ public class Connection extends SimpleChannelInboundHandler> { @@ -9720,7 +7770,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 // Spigot Start @@ -108,7 +108,7 @@ public class Connection extends SimpleChannelInboundHandler> { @Nullable - private Component disconnectedReason; + private DisconnectionDetails disconnectionDetails; private boolean encrypted; - private boolean disconnectionHandled; + private final java.util.concurrent.atomic.AtomicBoolean disconnectionHandled = new java.util.concurrent.atomic.AtomicBoolean(false); // Folia - region threading - may be called concurrently during configuration stage @@ -9769,7 +7819,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 } public void channelInactive(ChannelHandlerContext channelhandlercontext) { -@@ -443,7 +469,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -451,7 +477,7 @@ public class Connection extends SimpleChannelInboundHandler> { } packet.onPacketDispatch(this.getPlayer()); @@ -9778,7 +7828,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 || (io.papermc.paper.util.MCUtil.isMainThread() && packet.isReady() && this.pendingActions.isEmpty() && (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty())))) { this.sendPacket(packet, callbacks, flush); -@@ -472,11 +498,12 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -480,11 +506,12 @@ public class Connection extends SimpleChannelInboundHandler> { } public void runOnceConnected(Consumer task) { @@ -9792,7 +7842,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 } } -@@ -535,10 +562,11 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -543,10 +570,11 @@ public class Connection extends SimpleChannelInboundHandler> { } public void flushChannel() { @@ -9805,7 +7855,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 } } -@@ -556,53 +584,61 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -564,53 +592,61 @@ public class Connection extends SimpleChannelInboundHandler> { // Paper start - Optimize network: Rewrite this to be safer if ran off main thread private boolean flushQueue() { @@ -9901,7 +7951,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 } // Paper end - Optimize network -@@ -611,19 +647,39 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -619,19 +655,39 @@ public class Connection extends SimpleChannelInboundHandler> { private static int currTick; // Paper - Buffer joins to world public void tick() { this.flushQueue(); @@ -9949,7 +7999,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 // Paper start - detailed watchdog information net.minecraft.network.protocol.PacketUtils.packetProcessing.push(this.packetListener); try { -@@ -634,7 +690,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -642,7 +698,7 @@ public class Connection extends SimpleChannelInboundHandler> { } // Paper end - Buffer joins to world } @@ -9958,15 +8008,15 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 this.handleDisconnection(); } -@@ -680,6 +736,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -692,6 +748,7 @@ public class Connection extends SimpleChannelInboundHandler> { this.channel.close(); // We can't wait as this may be called from an event loop. - this.disconnectedReason = disconnectReason; + this.disconnectionDetails = disconnectionInfo; } + this.becomeActive = true; // Folia - region threading } -@@ -875,10 +932,10 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -887,10 +944,10 @@ public class Connection extends SimpleChannelInboundHandler> { public void handleDisconnection() { if (this.channel != null && !this.channel.isOpen()) { @@ -9979,7 +8029,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 PacketListener packetlistener = this.getPacketListener(); PacketListener packetlistener1 = packetlistener != null ? packetlistener : this.disconnectListener; -@@ -910,6 +967,22 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -922,6 +979,22 @@ public class Connection extends SimpleChannelInboundHandler> { } } // Paper end - Add PlayerConnectionCloseEvent @@ -10002,7 +8052,7 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 } } -@@ -930,15 +1003,25 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -942,15 +1015,25 @@ public class Connection extends SimpleChannelInboundHandler> { // Paper start - Optimize network public void clearPacketQueue() { final net.minecraft.server.level.ServerPlayer player = getPlayer(); @@ -10035,10 +8085,10 @@ index f40420a6841f03983b0837e177ea2ae7c3a37ca1..d5e8dd947cb29343074df8074e791357 private static class InnerUtil { // Attempt to hide these methods from ProtocolLib, so it doesn't accidently pick them up. diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 57e76b53e5e314c3e6b8856010f7a84188121582..9f07a1a5e2c082d16de068de6f47bf8fb06ba99a 100644 +index e2c24813f59c2fd075c740ac1842a38f20ed8554..fbc619a132c6ca6b1abab51ac230be29367e9c6e 100644 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -@@ -45,7 +45,7 @@ public class PacketUtils { +@@ -46,7 +46,7 @@ public class PacketUtils { public static void ensureRunningOnSameThread(Packet packet, T listener, BlockableEventLoop engine) throws RunningOnDifferentThreadException { if (!engine.isSameThread()) { @@ -10047,7 +8097,7 @@ index 57e76b53e5e314c3e6b8856010f7a84188121582..9f07a1a5e2c082d16de068de6f47bf8f packetProcessing.push(listener); // Paper - detailed watchdog information try { // Paper - detailed watchdog information if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players -@@ -74,7 +74,21 @@ public class PacketUtils { +@@ -75,7 +75,23 @@ public class PacketUtils { } // Paper end - detailed watchdog information @@ -10063,6 +8113,8 @@ index 57e76b53e5e314c3e6b8856010f7a84188121582..9f07a1a5e2c082d16de068de6f47bf8f + ); + } else if (listener instanceof net.minecraft.server.network.ServerConfigurationPacketListenerImpl configurationPacketListener) { + io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(run); ++ } else if (listener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener) { ++ io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(run); + } else { + throw new UnsupportedOperationException("Unknown listener: " + listener); + } @@ -10071,10 +8123,10 @@ index 57e76b53e5e314c3e6b8856010f7a84188121582..9f07a1a5e2c082d16de068de6f47bf8f } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 3751c2a077bd13bac330b93c6efc2a640a17f4f2..60cf9cf4120a83c9d634348e434772020a1665aa 100644 +index 23ddd26af762c1cd7fb3920669abb96b3213ab37..eda5f0d099f9f8621de8ad7808098abf6f5cb544 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -204,7 +204,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; // Paper - don't store the vanilla dispatcher -@@ -310,13 +309,41 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); - Thread thread = new io.papermc.paper.util.TickThread(() -> { // Paper - rewrite chunk system -@@ -352,7 +379,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - rewrite chunk system +@@ -357,46 +384,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= MAX_CHUNK_EXEC_TIME) { + if (!moreTasks) { +- this.lastMidTickExecuteFailure = currTime; ++ worldData.lastMidTickExecuteFailure = currTime; // Folia - region threading + } + + // note: negative values reduce the time +@@ -409,7 +420,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 ? Mth.square(ChunkProgressListener.calculateDiameter(i)) : 0; @@ -10219,7 +8334,7 @@ index 3751c2a077bd13bac330b93c6efc2a640a17f4f2..60cf9cf4120a83c9d634348e43477202 // Iterator iterator = this.levels.values().iterator(); if (true) { -@@ -841,7 +880,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= MAX_CHUNK_EXEC_TIME) { - if (!moreTasks) { -- lastMidTickExecuteFailure = currTime; -+ worldData.lastMidTickExecuteFailure = currTime; // Folia - region threading - } - - // note: negative values reduce the time -@@ -1474,7 +1549,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + return scheduledEnd - System.nanoTime() > targetBuffer; + }; ++ this.server.spark.tickStart(); // Paper - spark + new com.destroystokyo.paper.event.server.ServerTickStartEvent((int)region.getCurrentTick()).callEvent(); // Paper + // Folia end - region threading co.aikar.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Paper @@ -10522,6 +8562,7 @@ index 3751c2a077bd13bac330b93c6efc2a640a17f4f2..60cf9cf4120a83c9d634348e43477202 isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); + } // Folia - region threading // Paper end +- this.server.spark.tickStart(); // Paper - spark - new com.destroystokyo.paper.event.server.ServerTickStartEvent(this.tickCount+1).callEvent(); // Paper - Server Tick Events + // Folia - region threading - move up + @@ -10532,7 +8573,7 @@ index 3751c2a077bd13bac330b93c6efc2a640a17f4f2..60cf9cf4120a83c9d634348e43477202 + // now run all the entity schedulers + // TODO there has got to be a more efficient variant of this crap + for (Entity entity : region.world.getCurrentWorldData().getLocalEntitiesCopy()) { -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(entity) || entity.isRemoved()) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity) || entity.isRemoved()) { + continue; + } + org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw(); @@ -10578,9 +8619,9 @@ index 3751c2a077bd13bac330b93c6efc2a640a17f4f2..60cf9cf4120a83c9d634348e43477202 } } } finally { -@@ -1599,29 +1716,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- for (final Entity entity : level.getEntityLookup().getAllCopy()) { // Paper - rewrite chunk system +- for (final Entity entity : level.moonrise$getEntityLookup().getAllCopy()) { // Paper - rewrite chunk system - if (entity.isRemoved()) { - continue; - } @@ -10703,7 +8746,7 @@ index 3751c2a077bd13bac330b93c6efc2a640a17f4f2..60cf9cf4120a83c9d634348e43477202 MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper this.profiler.popPush("levels"); //Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down -@@ -1723,7 +1803,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { String s = String.valueOf(worldserver); -@@ -1776,7 +1853,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop attribute, UUID uuid, double multiplier) throws CommandSyntaxException { + private static int getAttributeModifier(CommandSourceStack source, Entity target, Holder attribute, ResourceLocation id, double multiplier) throws CommandSyntaxException { - LivingEntity livingEntity = getEntityWithAttribute(target, attribute); + // Folia start - region threading + target.getBukkitEntity().taskScheduler.schedule((Entity nmsEntity) -> { @@ -10960,19 +9003,15 @@ index 518057dd550160f9039dbd026b66c37368fb9e8d..21956171278964a0edbf5b99eabf8e9a + // Folia end - region threading + LivingEntity livingEntity = getEntityWithAttribute(nmsEntity, attribute); // Folia - region threading AttributeMap attributeMap = livingEntity.getAttributes(); - if (!attributeMap.hasModifier(attribute, uuid)) { -- throw ERROR_NO_SUCH_MODIFIER.create(target.getName(), getAttributeDescription(attribute), uuid); -+ throw ERROR_NO_SUCH_MODIFIER.create(nmsEntity.getName(), getAttributeDescription(attribute), uuid); // Folia - region threading + if (!attributeMap.hasModifier(attribute, id)) { +- throw ERROR_NO_SUCH_MODIFIER.create(target.getName(), getAttributeDescription(attribute), id); ++ throw ERROR_NO_SUCH_MODIFIER.create(nmsEntity.getName(), getAttributeDescription(attribute), id); // Folia - region threading } else { - double d = attributeMap.getModifierValue(attribute, uuid); + double d = attributeMap.getModifierValue(attribute, id); source.sendSuccess( -@@ -267,55 +299,95 @@ public class AttributeCommand { - "commands.attribute.modifier.value.get.success", - Component.translationArg(uuid), - getAttributeDescription(attribute), -- target.getName(), -+ nmsEntity.getName(), // Folia - region threading - d + () -> Component.translatable( +- "commands.attribute.modifier.value.get.success", Component.translationArg(id), getAttributeDescription(attribute), target.getName(), d ++ "commands.attribute.modifier.value.get.success", Component.translationArg(id), getAttributeDescription(attribute), nmsEntity.getName(), d // Folia - region threading ), false ); @@ -11011,7 +9050,7 @@ index 518057dd550160f9039dbd026b66c37368fb9e8d..21956171278964a0edbf5b99eabf8e9a } private static int addModifier( - CommandSourceStack source, Entity target, Holder attribute, UUID uuid, String name, double value, AttributeModifier.Operation operation + CommandSourceStack source, Entity target, Holder attribute, ResourceLocation id, double value, AttributeModifier.Operation operation ) throws CommandSyntaxException { - AttributeInstance attributeInstance = getAttributeInstance(target, attribute); + // Folia start - region threading @@ -11019,16 +9058,16 @@ index 518057dd550160f9039dbd026b66c37368fb9e8d..21956171278964a0edbf5b99eabf8e9a + try { + // Folia end - region threading + AttributeInstance attributeInstance = getAttributeInstance(nmsEntity, attribute); // Folia - region threading - AttributeModifier attributeModifier = new AttributeModifier(uuid, name, value, operation); - if (attributeInstance.hasModifier(attributeModifier)) { -- throw ERROR_MODIFIER_ALREADY_PRESENT.create(target.getName(), getAttributeDescription(attribute), uuid); -+ throw ERROR_MODIFIER_ALREADY_PRESENT.create(nmsEntity.getName(), getAttributeDescription(attribute), uuid); // Folia - region threading + AttributeModifier attributeModifier = new AttributeModifier(id, value, operation); + if (attributeInstance.hasModifier(id)) { +- throw ERROR_MODIFIER_ALREADY_PRESENT.create(target.getName(), getAttributeDescription(attribute), id); ++ throw ERROR_MODIFIER_ALREADY_PRESENT.create(nmsEntity.getName(), getAttributeDescription(attribute), id); // Folia - region threading } else { attributeInstance.addPermanentModifier(attributeModifier); source.sendSuccess( () -> Component.translatable( -- "commands.attribute.modifier.add.success", Component.translationArg(uuid), getAttributeDescription(attribute), target.getName() -+ "commands.attribute.modifier.add.success", Component.translationArg(uuid), getAttributeDescription(attribute), nmsEntity.getName() // Folia - region threading +- "commands.attribute.modifier.add.success", Component.translationArg(id), getAttributeDescription(attribute), target.getName() ++ "commands.attribute.modifier.add.success", Component.translationArg(id), getAttributeDescription(attribute), nmsEntity.getName() // Folia - region threading ), false ); @@ -11044,26 +9083,26 @@ index 518057dd550160f9039dbd026b66c37368fb9e8d..21956171278964a0edbf5b99eabf8e9a + // Folia end - region threading } - private static int removeModifier(CommandSourceStack source, Entity target, Holder attribute, UUID uuid) throws CommandSyntaxException { + private static int removeModifier(CommandSourceStack source, Entity target, Holder attribute, ResourceLocation id) throws CommandSyntaxException { - AttributeInstance attributeInstance = getAttributeInstance(target, attribute); + // Folia start - region threading + target.getBukkitEntity().taskScheduler.schedule((Entity nmsEntity) -> { + try { + // Folia end - region threading + AttributeInstance attributeInstance = getAttributeInstance(nmsEntity, attribute); // Folia - region threading - if (attributeInstance.removePermanentModifier(uuid)) { + if (attributeInstance.removeModifier(id)) { source.sendSuccess( () -> Component.translatable( -- "commands.attribute.modifier.remove.success", Component.translationArg(uuid), getAttributeDescription(attribute), target.getName() -+ "commands.attribute.modifier.remove.success", Component.translationArg(uuid), getAttributeDescription(attribute), nmsEntity.getName() // Folia - region threading +- "commands.attribute.modifier.remove.success", Component.translationArg(id), getAttributeDescription(attribute), target.getName() ++ "commands.attribute.modifier.remove.success", Component.translationArg(id), getAttributeDescription(attribute), nmsEntity.getName() // Folia - region threading ), false ); - return 1; + return; // Folia - region threading } else { -- throw ERROR_NO_SUCH_MODIFIER.create(target.getName(), getAttributeDescription(attribute), uuid); -+ throw ERROR_NO_SUCH_MODIFIER.create(nmsEntity.getName(), getAttributeDescription(attribute), uuid); // Folia - region threading +- throw ERROR_NO_SUCH_MODIFIER.create(target.getName(), getAttributeDescription(attribute), id); ++ throw ERROR_NO_SUCH_MODIFIER.create(nmsEntity.getName(), getAttributeDescription(attribute), id); // Folia - region threading } + // Folia start - region threading + } catch (CommandSyntaxException ex) { @@ -11212,10 +9251,10 @@ index ed6336065a0061af095d3395b927b8976443cb68..5a6f53cfaded2df14a82ee7639cdd0bb } diff --git a/src/main/java/net/minecraft/server/commands/EnchantCommand.java b/src/main/java/net/minecraft/server/commands/EnchantCommand.java -index 84f1ba6275f04624f46ccd772924b5e075e7b205..1c489bab7d0422473e104d558f686a2024f1abbb 100644 +index 99695e38b6a10c3cffda6e453f9f0619c7406cc0..69a7f9f5dc69836a472af3b4d31c6fefd028505c 100644 --- a/src/main/java/net/minecraft/server/commands/EnchantCommand.java +++ b/src/main/java/net/minecraft/server/commands/EnchantCommand.java -@@ -68,49 +68,76 @@ public class EnchantCommand { +@@ -68,51 +68,78 @@ public class EnchantCommand { ); } @@ -11241,8 +9280,8 @@ index 84f1ba6275f04624f46ccd772924b5e075e7b205..1c489bab7d0422473e104d558f686a20 - ItemStack itemStack = livingEntity.getMainHandItem(); - if (!itemStack.isEmpty()) { - if (enchantment2.canEnchant(itemStack) -- && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(itemStack).keySet(), enchantment2)) { -- itemStack.enchant(enchantment2, level); +- && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(itemStack).keySet(), enchantment)) { +- itemStack.enchant(enchantment, level); - i++; - } else if (targets.size() == 1) { - throw ERROR_INCOMPATIBLE.create(itemStack.getItem().getName(itemStack).getString()); @@ -11253,8 +9292,8 @@ index 84f1ba6275f04624f46ccd772924b5e075e7b205..1c489bab7d0422473e104d558f686a20 + ItemStack itemStack = livingEntity.getMainHandItem(); + if (!itemStack.isEmpty()) { + if (enchantment2.canEnchant(itemStack) -+ && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(itemStack).keySet(), enchantment2)) { -+ itemStack.enchant(enchantment2, level); ++ && EnchantmentHelper.isEnchantmentCompatible(EnchantmentHelper.getEnchantmentsForCrafting(itemStack).keySet(), enchantment)) { ++ itemStack.enchant(enchantment, level); + possibleSingleDisplayName.set(livingEntity.getDisplayName()); + changed.incrementAndGet(); + } else if (targets.size() == 1) { @@ -11270,12 +9309,12 @@ index 84f1ba6275f04624f46ccd772924b5e075e7b205..1c489bab7d0422473e104d558f686a20 - } else if (targets.size() == 1) { - throw ERROR_NO_ITEM.create(livingEntity.getName().getString()); - } -+ sendFeedback(source, enchantment2, level, possibleSingleDisplayName, count, changed); -+ }, ignored -> sendFeedback(source, enchantment2, level, possibleSingleDisplayName, count, changed), 1L); ++ sendFeedback(source, enchantment, level, possibleSingleDisplayName, count, changed); ++ }, ignored -> sendFeedback(source, enchantment, level, possibleSingleDisplayName, count, changed), 1L); } else if (targets.size() == 1) { throw ERROR_NOT_LIVING_ENTITY.create(entity.getName().getString()); + } else { -+ sendFeedback(source, enchantment2, level, possibleSingleDisplayName, count, changed); ++ sendFeedback(source, enchantment, level, possibleSingleDisplayName, count, changed); + // Folia end - region threading } } @@ -11284,7 +9323,7 @@ index 84f1ba6275f04624f46ccd772924b5e075e7b205..1c489bab7d0422473e104d558f686a20 + } + // Folia start - region threading -+ private static void sendFeedback(final CommandSourceStack source, final Enchantment enchantment2, final int level, final java.util.concurrent.atomic.AtomicReference possibleSingleDisplayName, final java.util.concurrent.atomic.AtomicInteger count, final java.util.concurrent.atomic.AtomicInteger changed) { ++ private static void sendFeedback(final CommandSourceStack source, final Holder enchantment, final int level, final java.util.concurrent.atomic.AtomicReference possibleSingleDisplayName, final java.util.concurrent.atomic.AtomicInteger count, final java.util.concurrent.atomic.AtomicInteger changed) { + if (count.decrementAndGet() == 0) { + final int i = changed.get(); if (i == 0) { @@ -11295,14 +9334,16 @@ index 84f1ba6275f04624f46ccd772924b5e075e7b205..1c489bab7d0422473e104d558f686a20 + if (i == 1) { source.sendSuccess( () -> Component.translatable( -- "commands.enchant.success.single", enchantment2.getFullname(level), targets.iterator().next().getDisplayName() -+ "commands.enchant.success.single", enchantment2.getFullname(level), possibleSingleDisplayName.get() +- "commands.enchant.success.single", Enchantment.getFullname(enchantment, level), targets.iterator().next().getDisplayName() ++ "commands.enchant.success.single", Enchantment.getFullname(enchantment, level), possibleSingleDisplayName.get() ), true ); } else { -- source.sendSuccess(() -> Component.translatable("commands.enchant.success.multiple", enchantment2.getFullname(level), targets.size()), true); -+ source.sendSuccess(() -> Component.translatable("commands.enchant.success.multiple", enchantment2.getFullname(level), i), true); + source.sendSuccess( +- () -> Component.translatable("commands.enchant.success.multiple", Enchantment.getFullname(enchantment, level), targets.size()), true ++ () -> Component.translatable("commands.enchant.success.multiple", Enchantment.getFullname(enchantment, level), i), true + ); } - - return i; @@ -11353,7 +9394,7 @@ index 775eb9fd56c2d0eafcfb04ab97ddb270ba3faca9..a5a69f87fe9d35c489a57d4d93e9ad54 if (i == 0) { diff --git a/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java b/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java -index c5bba5ce879b336b43e742eaa21d661dcee379aa..a1a3afd2c65d71ca6f5ad8828097402cbc353461 100644 +index c5bba5ce879b336b43e742eaa21d661dcee379aa..0eda57c785bec699156b2b39919b35046dacb586 100644 --- a/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java +++ b/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java @@ -106,6 +106,16 @@ public class FillBiomeCommand { @@ -11379,7 +9420,7 @@ index c5bba5ce879b336b43e742eaa21d661dcee379aa..a1a3afd2c65d71ca6f5ad8828097402c } else { + // Folia start - region threading + int buffer = 0; // no buffer, we do not touch neighbours -+ world.loadChunksAsync( ++ world.moonrise$loadChunksAsync( + (boundingBox.minX() - buffer) >> 4, + (boundingBox.maxX() + buffer) >> 4, + (boundingBox.minZ() - buffer) >> 4, @@ -11404,7 +9445,7 @@ index c5bba5ce879b336b43e742eaa21d661dcee379aa..a1a3afd2c65d71ca6f5ad8828097402c } diff --git a/src/main/java/net/minecraft/server/commands/FillCommand.java b/src/main/java/net/minecraft/server/commands/FillCommand.java -index 0509e28f79d13615b5baefc34799b0ad2df071be..95bb9d341ff28d37934ceba4ef07c95211cf578a 100644 +index 0509e28f79d13615b5baefc34799b0ad2df071be..b4cc5328964a80c0f1f24085afd3831a4d7611e7 100644 --- a/src/main/java/net/minecraft/server/commands/FillCommand.java +++ b/src/main/java/net/minecraft/server/commands/FillCommand.java @@ -151,6 +151,12 @@ public class FillCommand { @@ -11427,7 +9468,7 @@ index 0509e28f79d13615b5baefc34799b0ad2df071be..95bb9d341ff28d37934ceba4ef07c952 + // Folia start - region threading + int buffer = 32; + // physics may spill into neighbour chunks, so use a buffer -+ serverLevel.loadChunksAsync( ++ serverLevel.moonrise$loadChunksAsync( + (range.minX() - buffer) >> 4, + (range.maxX() + buffer) >> 4, + (range.minZ() - buffer) >> 4, @@ -11574,10 +9615,10 @@ index d1da3600dc07107309b20ebe6e7c0c4da0e8de76..a2075133b0e8ea6299dec0fa5125e429 return i; diff --git a/src/main/java/net/minecraft/server/commands/GiveCommand.java b/src/main/java/net/minecraft/server/commands/GiveCommand.java -index 47355158e5e762540a10dc67b23092a0fc53bce3..b450b4f876d8f18a9f51ef0c594d4471e0d5a6c4 100644 +index 0d9de4c61c7b26a6ff37c12fde629161fd0c3d5a..fca164cd59f1f0bf396e82a4c824c8d779b6c640 100644 --- a/src/main/java/net/minecraft/server/commands/GiveCommand.java +++ b/src/main/java/net/minecraft/server/commands/GiveCommand.java -@@ -89,6 +89,7 @@ public class GiveCommand { +@@ -57,6 +57,7 @@ public class GiveCommand { l -= i1; ItemStack itemstack1 = item.createItemStack(i1, false); @@ -11585,7 +9626,7 @@ index 47355158e5e762540a10dc67b23092a0fc53bce3..b450b4f876d8f18a9f51ef0c594d4471 boolean flag = entityplayer.getInventory().add(itemstack1); ItemEntity entityitem; -@@ -107,6 +108,7 @@ public class GiveCommand { +@@ -75,6 +76,7 @@ public class GiveCommand { entityitem.setTarget(entityplayer.getUUID()); } } @@ -11609,7 +9650,7 @@ index c2974a6bd6851b54d1df2689195d896baf4906ee..57f5c571e63355b0e32480f31b9e5c81 if (targets.size() == 1) { diff --git a/src/main/java/net/minecraft/server/commands/PlaceCommand.java b/src/main/java/net/minecraft/server/commands/PlaceCommand.java -index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..212b4e7a0b1ea796fe3a2e11808e4abd09d466a8 100644 +index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..351b3cb441a0700d961148239f4afed9ed5dcb57 100644 --- a/src/main/java/net/minecraft/server/commands/PlaceCommand.java +++ b/src/main/java/net/minecraft/server/commands/PlaceCommand.java @@ -88,12 +88,25 @@ public class PlaceCommand { @@ -11629,7 +9670,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..212b4e7a0b1ea796fe3a2e11808e4abd PlaceCommand.checkLoaded(worldserver, new ChunkPos(chunkcoordintpair.x - 1, chunkcoordintpair.z - 1), new ChunkPos(chunkcoordintpair.x + 1, chunkcoordintpair.z + 1)); + // Folia start - region threading -+ worldserver.loadChunksAsync( ++ worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, + (chunks) -> { @@ -11661,7 +9702,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..212b4e7a0b1ea796fe3a2e11808e4abd PlaceCommand.checkLoaded(worldserver, chunkcoordintpair, chunkcoordintpair); + // Folia start - region threading -+ worldserver.loadChunksAsync( ++ worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, + (chunks) -> { @@ -11691,7 +9732,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..212b4e7a0b1ea796fe3a2e11808e4abd Structure structure1 = (Structure) structure.value(); ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + // Folia start - region threading -+ worldserver.loadChunksAsync( ++ worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, + (chunks) -> { @@ -11720,7 +9761,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..212b4e7a0b1ea796fe3a2e11808e4abd public static int placeTemplate(CommandSourceStack source, ResourceLocation id, BlockPos pos, Rotation rotation, Mirror mirror, float integrity, int seed) throws CommandSyntaxException { ServerLevel worldserver = source.getLevel(); + // Folia start - region threading -+ worldserver.loadChunksAsync( ++ worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, + (chunks) -> { @@ -12167,10 +10208,10 @@ index 812f2adc6fc20aa126e629284fe594a923b24540..0a5e6961fb37e9a53cd39b1bd233e020 } } diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index ad967cc2283f902c76e48a59d59cf0dbdacbb5e3..cc40d3e69a3635ca7895876159f2821091c14a9a 100644 +index dd56c8e041116ef3602a9f89c998c8208ab89b51..301d7fa29fce2997a5881b3852896eff5af33672 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -463,9 +463,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -469,9 +469,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } @Override @@ -12183,7 +10224,7 @@ index ad967cc2283f902c76e48a59d59cf0dbdacbb5e3..cc40d3e69a3635ca7895876159f28210 } @Override -@@ -787,7 +787,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -792,7 +792,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface Waitable[] waitableArray = new Waitable[1]; // Paper rconConsoleSource.prepareForCommand(); final java.util.concurrent.atomic.AtomicReference command = new java.util.concurrent.atomic.AtomicReference<>(s); // Paper @@ -12192,7 +10233,7 @@ index ad967cc2283f902c76e48a59d59cf0dbdacbb5e3..cc40d3e69a3635ca7895876159f28210 CommandSourceStack wrapper = rconConsoleSource.createCommandSourceStack(); RemoteServerCommandEvent event = new RemoteServerCommandEvent(rconConsoleSource.getBukkitSender(wrapper), s); this.server.getPluginManager().callEvent(event); -@@ -811,7 +811,16 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -816,7 +816,16 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), wrapper); this.server.dispatchServerCommand(event.getSender(), serverCommand); } // Paper @@ -12210,42 +10251,11 @@ index ad967cc2283f902c76e48a59d59cf0dbdacbb5e3..cc40d3e69a3635ca7895876159f28210 // Paper start if (waitableArray[0] != null) { //noinspection unchecked -diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java -index 472b9494f8a34a8ba90d6a2936b0db7530a229ad..e41a352141614a0578af6019bc55f96ea323e090 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkHolder.java -+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java -@@ -79,7 +79,7 @@ public class ChunkHolder { - public void onChunkAdd() { - // Paper start - optimise chunk tick iteration - if (this.needsBroadcastChanges()) { -- this.chunkMap.needsChangeBroadcasting.add(this); -+ this.chunkMap.level.needsChangeBroadcasting.add(this); // Folia - region threading - } - // Paper end - optimise chunk tick iteration - } -@@ -87,7 +87,7 @@ public class ChunkHolder { - public void onChunkRemove() { - // Paper start - optimise chunk tick iteration - if (this.needsBroadcastChanges()) { -- this.chunkMap.needsChangeBroadcasting.remove(this); -+ this.chunkMap.level.needsChangeBroadcasting.remove(this); // Folia - region threading - } - // Paper end - optimise chunk tick iteration - } -@@ -270,7 +270,7 @@ public class ChunkHolder { - - private void addToBroadcastMap() { - io.papermc.paper.util.TickThread.ensureTickThread(this.chunkMap.level, this.pos, "Asynchronous ChunkHolder update is not allowed"); -- this.chunkMap.needsChangeBroadcasting.add(this); -+ this.chunkMap.level.needsChangeBroadcasting.add(this); // Folia - region threading - } - // Paper end - optimise chunk tick iteration - diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa8707bc40 100644 +index 1e0a6e5a3c907ab55ee6f2780a7d43bd455f2b7b..7f161864ee6a43de8d37c0e5c9cba9918f2fed89 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -139,8 +139,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -138,8 +138,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final ChunkMap.ChunkDistanceManager distanceManager; public final AtomicInteger tickingGenerated; // Paper - public private final String storageName; @@ -12255,101 +10265,10 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa + //public final Int2ObjectMap entityMap; // Folia - region threading private final Long2ByteMap chunkTypeCache; private final Long2LongMap chunkSaveCooldowns; - private final Queue unloadQueue; -@@ -148,69 +148,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - private WorldGenContext worldGenContext; public final WorldGenContext getWorldGenContext() { return this.worldGenContext; } // Paper - rewrite chunk system - - // Paper start - distance maps -- private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); -- // Paper start - use distance map to optimise tracker -- public static boolean isLegacyTrackingEntity(Entity entity) { -- return entity.isLegacyTrackingEntity; -- } -- -- // inlined EnumMap, TrackingRange.TrackingRangeType -- static final org.spigotmc.TrackingRange.TrackingRangeType[] TRACKING_RANGE_TYPES = org.spigotmc.TrackingRange.TrackingRangeType.values(); -- public final com.destroystokyo.paper.util.misc.PlayerAreaMap[] playerEntityTrackerTrackMaps; -- final int[] entityTrackerTrackRanges; -- public final int getEntityTrackerRange(final int ordinal) { -- return this.entityTrackerTrackRanges[ordinal]; -- } -- -- private int convertSpigotRangeToVanilla(final int vanilla) { -- return net.minecraft.server.MinecraftServer.getServer().getScaledTrackingDistance(vanilla); -- } -- // Paper end - use distance map to optimise tracker -+ // Folia - region threading - - void addPlayerToDistanceMaps(ServerPlayer player) { - int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX()); - int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -- this.nearbyPlayers.addPlayer(player); -+ // Folia - region threading - this.level.playerChunkLoader.addPlayer(player); // Paper - replace chunk loader -- // Paper start - use distance map to optimise entity tracker -- for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -- com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -- int trackRange = this.entityTrackerTrackRanges[i]; -- -- trackMap.add(player, chunkX, chunkZ, Math.min(trackRange, io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(player))); -- } -- // Paper end - use distance map to optimise entity tracker -+ // Folia - region threading - } - - void removePlayerFromDistanceMaps(ServerPlayer player) { - int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX()); - int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -- this.nearbyPlayers.removePlayer(player); -+ // Folia - region threading - this.level.playerChunkLoader.removePlayer(player); // Paper - replace chunk loader -- // Paper start - use distance map to optimise tracker -- for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -- this.playerEntityTrackerTrackMaps[i].remove(player); -- } -- // Paper end - use distance map to optimise tracker -- this.playerMobSpawnMap.remove(player); // Paper - optimise chunk tick iteration -+ // Folia - region threading - } - - void updateMaps(ServerPlayer player) { - int chunkX = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getX()); - int chunkZ = io.papermc.paper.util.MCUtil.getChunkCoordinate(player.getZ()); - // Note: players need to be explicitly added to distance maps before they can be updated -- this.nearbyPlayers.tickPlayer(player); -+ // Folia - region threading - this.level.playerChunkLoader.updatePlayer(player); // Paper - replace chunk loader -- // Paper start - use distance map to optimise entity tracker -- for (int i = 0, len = TRACKING_RANGE_TYPES.length; i < len; ++i) { -- com.destroystokyo.paper.util.misc.PlayerAreaMap trackMap = this.playerEntityTrackerTrackMaps[i]; -- int trackRange = this.entityTrackerTrackRanges[i]; -- -- trackMap.update(player, chunkX, chunkZ, Math.min(trackRange, io.papermc.paper.chunk.system.ChunkSystem.getSendViewDistance(player))); -- } -- // Paper end - use distance map to optimise entity tracker -+ // Folia - region threading - } - // Paper end - // Paper start -@@ -242,19 +206,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final ChunkHolder getUnloadingChunkHolder(int chunkX, int chunkZ) { - return null; // Paper - rewrite chunk system - } -- public final io.papermc.paper.util.player.NearbyPlayers nearbyPlayers; -+ //public final io.papermc.paper.util.player.NearbyPlayers nearbyPlayers; // Folia - region threading - // Paper end - // Paper start - optimise chunk tick iteration -- public final it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet needsChangeBroadcasting = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); -- public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -+ //public final it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet needsChangeBroadcasting = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Folia - region threading -+ //public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); // Folia - region threading - // Paper end - optimise chunk tick iteration - - public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { - super(new RegionStorageInfo(session.getLevelId(), world.dimension(), "chunk"), session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync); + // Paper - rewrite chunk system +@@ -178,8 +178,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper - rewrite chunk system + this.toDrop = new LongOpenHashSet(); this.tickingGenerated = new AtomicInteger(); - this.playerMap = new PlayerMap(); - this.entityMap = new Int2ObjectOpenHashMap(); @@ -12357,131 +10276,17 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa + //this.entityMap = new Int2ObjectOpenHashMap(); // Folia - region threading this.chunkTypeCache = new Long2ByteOpenHashMap(); this.chunkSaveCooldowns = new Long2LongOpenHashMap(); - this.unloadQueue = Queues.newConcurrentLinkedQueue(); -@@ -298,57 +262,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.worldGenContext = new WorldGenContext(world, chunkGenerator, structureTemplateManager, this.lightEngine); - // Paper start - this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new); -- this.regionManagers.add(this.dataRegionManager); -- this.nearbyPlayers = new io.papermc.paper.util.player.NearbyPlayers(this.level); -+ //this.regionManagers.add(this.dataRegionManager); // Folia - region threading -+ //this.nearbyPlayers = new io.papermc.paper.util.player.NearbyPlayers(this.level); // Folia - region threading - // Paper end - // Paper start - use distance map to optimise entity tracker -- this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; -- this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; -- -- org.spigotmc.SpigotWorldConfig spigotWorldConfig = this.level.spigotConfig; -- -- for (int ordinal = 0, len = TRACKING_RANGE_TYPES.length; ordinal < len; ++ordinal) { -- org.spigotmc.TrackingRange.TrackingRangeType trackingRangeType = TRACKING_RANGE_TYPES[ordinal]; -- int configuredSpigotValue; -- switch (trackingRangeType) { -- case PLAYER: -- configuredSpigotValue = spigotWorldConfig.playerTrackingRange; -- break; -- case ANIMAL: -- configuredSpigotValue = spigotWorldConfig.animalTrackingRange; -- break; -- case MONSTER: -- configuredSpigotValue = spigotWorldConfig.monsterTrackingRange; -- break; -- case MISC: -- configuredSpigotValue = spigotWorldConfig.miscTrackingRange; -- break; -- case OTHER: -- configuredSpigotValue = spigotWorldConfig.otherTrackingRange; -- break; -- case ENDERDRAGON: -- configuredSpigotValue = EntityType.ENDER_DRAGON.clientTrackingRange() * 16; -- break; -- case DISPLAY: -- configuredSpigotValue = spigotWorldConfig.displayTrackingRange; -- break; -- default: -- throw new IllegalStateException("Missing case for enum " + trackingRangeType); -- } -- configuredSpigotValue = convertSpigotRangeToVanilla(configuredSpigotValue); -- -- int trackRange = (configuredSpigotValue >>> 4) + ((configuredSpigotValue & 15) != 0 ? 1 : 0); -- this.entityTrackerTrackRanges[ordinal] = trackRange; -- -- this.playerEntityTrackerTrackMaps[ordinal] = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); -- } -+ // Folia - region threading - // Paper end - use distance map to optimise entity tracker - } - - // Paper start - // always use accessor, so folia can override - public final io.papermc.paper.util.player.NearbyPlayers getNearbyPlayers() { -- return this.nearbyPlayers; -+ return this.level.getCurrentWorldData().getNearbyPlayers(); // Folia - region threading - } - // Paper end - -@@ -691,6 +616,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - duplicate uuid resolving - // rets true if to prevent the entity from being added - public static boolean checkDupeUUID(ServerLevel level, Entity entity) { -+ // Folia start - region threading -+ if (true) { -+ // TODO fix this shit later -+ return false; -+ } -+ // Folia end - region threading - io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode mode = level.paperConfig().entities.spawning.duplicateUuid.mode; - if (mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.WARN - && mode != io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.DuplicateUUID.DuplicateUUIDMode.DELETE -@@ -931,6 +862,38 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkcoordintpair, boolean reducedRange) { -+ // Folia start - region threading -+ if (true) { -+ java.util.List players = this.level.getLocalPlayers(); -+ if (reducedRange) { -+ for (int i = 0, len = players.size(); i < len; ++i) { -+ ServerPlayer player = players.get(i); -+ if (!player.affectsSpawning || player.isSpectator()) { -+ continue; -+ } -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (euclideanDistanceSquared(chunkcoordintpair, player) < player.lastEntitySpawnRadiusSquared) { -+ return true; // in range -+ } -+ } -+ } else { -+ final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.MOB_SPAWN_RANGE * 16); -+ // before spigot, mob spawn range was actually mob spawn range + tick range, but it was split -+ for (int i = 0, len = players.size(); i < len; ++i) { -+ ServerPlayer player = players.get(i); -+ if (!player.affectsSpawning || player.isSpectator()) { -+ continue; -+ } -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (euclideanDistanceSquared(chunkcoordintpair, player) < range) { -+ return true; // in range -+ } -+ } -+ } -+ // no players in range -+ return false; -+ } -+ // Folia end - region threading - int chunkRange = this.level.spigotConfig.mobSpawnRange; - chunkRange = (chunkRange > this.level.spigotConfig.viewDistance) ? (byte) this.level.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; -@@ -942,7 +905,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper - rewrite chunk system +@@ -693,7 +693,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (!this.distanceManager.hasPlayersNearby(chunkcoordintpair.toLong())) { return false; } else { - Iterator iterator = this.playerMap.getAllPlayers().iterator(); -+ Iterator iterator = null; // Folia - region threading ++ Iterator iterator = this.level.getLocalPlayers().iterator(); // Folia - region threading ServerPlayer entityplayer; -@@ -974,7 +937,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -725,7 +725,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return List.of(); } else { Builder builder = ImmutableList.builder(); @@ -12490,11 +10295,10 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -@@ -1003,25 +966,19 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } +@@ -755,13 +755,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider void updatePlayerStatus(ServerPlayer player, boolean added) { -- boolean flag1 = this.skipPlayer(player); + boolean flag1 = this.skipPlayer(player); - boolean flag2 = this.playerMap.ignoredOrUnknown(player); + // Folia - region threading @@ -12502,41 +10306,39 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa - this.playerMap.addPlayer(player, flag1); + // Folia - region threading this.updatePlayerPos(player); -- if (!flag1) { + if (!flag1) { - this.distanceManager.addPlayer(SectionPos.of((EntityAccess) player), player); -- } -+ // Folia - region threading ++ // Folia - region threading + ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager)this.distanceManager).moonrise$addPlayer(player, SectionPos.of(player)); // Paper - chunk tick iteration optimisation + } - // Paper - handled by player chunk loader - this.addPlayerToDistanceMaps(player); // Paper - distance maps +@@ -770,9 +770,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } else { SectionPos sectionposition = player.getLastSectionPos(); - this.playerMap.removePlayer(player); - if (!flag2) { - this.distanceManager.removePlayer(sectionposition, player); -- } + // Folia - region threading ++ if (true) { // Folia - region threading ++ // Folia - region threading + ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager)this.distanceManager).moonrise$removePlayer(player, SectionPos.of(player)); // Paper - chunk tick iteration optimisation + } - this.removePlayerFromDistanceMaps(player); // Paper - distance maps - // Paper - handled by player chunk loader -@@ -1036,31 +993,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } +@@ -792,28 +792,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public void move(ServerPlayer player) { -- // Paper - delay this logic for the entity tracker tick, no need to duplicate it -+ // Folia - region threading - entity tracker optimisations - -- SectionPos sectionposition = player.getLastSectionPos(); -- SectionPos sectionposition1 = SectionPos.of((EntityAccess) player); + SectionPos sectionposition = player.getLastSectionPos(); + SectionPos sectionposition1 = SectionPos.of((EntityAccess) player); - boolean flag = this.playerMap.ignored(player); -- boolean flag1 = this.skipPlayer(player); ++ // Folia - region threading + boolean flag1 = this.skipPlayer(player); - boolean flag2 = sectionposition.asLong() != sectionposition1.asLong(); + // Folia - region threading - if (flag2 || flag != flag1) { + if (true) { // Folia - region threading this.updatePlayerPos(player); +- ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager)this.distanceManager).moonrise$updatePlayer(player, sectionposition, sectionposition1, flag, flag1); // Paper - chunk tick iteration optimisation - if (!flag) { - this.distanceManager.removePlayer(sectionposition, player); - } @@ -12552,36 +10354,42 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa - if (flag && !flag1) { - this.playerMap.unIgnorePlayer(player); - } ++ ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager)this.distanceManager).moonrise$updatePlayer(player, sectionposition, sectionposition1, false, flag1); // Paper - chunk tick iteration optimisation // Folia - region threading + // Folia - region threading - // Paper - replaced by PlayerChunkLoader + // Paper - rewrite chunk system } -@@ -1091,9 +1030,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -844,9 +830,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot // Paper start - ignore and warn about illegal addEntity calls instead of crashing server - if (!entity.valid || entity.level() != this.level || this.entityMap.containsKey(entity.getId())) { -+ if (!entity.valid || entity.level() != this.level || entity.tracker != null) { // Folia - region threading ++ if (!entity.valid || entity.level() != this.level || entity.moonrise$getTrackedEntity() != null) { // Folia - region threading LOGGER.error("Illegal ChunkMap::addEntity for world " + this.level.getWorld().getName() - + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable()); -+ + ": " + entity + (entity.tracker != null ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable()); ++ + ": " + entity + (entity.moonrise$getTrackedEntity() != null ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable()); // Folia - region threading return; } // Paper end - ignore and warn about illegal addEntity calls instead of crashing server -@@ -1106,27 +1045,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -859,32 +845,30 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (i != 0) { int j = entitytypes.updateInterval(); - if (this.entityMap.containsKey(entity.getId())) { -+ if (entity.tracker != null) { // Folia - region threading ++ if (entity.moonrise$getTrackedEntity() != null) { // Folia - region threading throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("Entity is already tracked!")); } else { ChunkMap.TrackedEntity playerchunkmap_entitytracker = new ChunkMap.TrackedEntity(entity, i, j, entitytypes.trackDeltas()); - entity.tracker = playerchunkmap_entitytracker; // Paper - Fast access to tracker - this.entityMap.put(entity.getId(), playerchunkmap_entitytracker); -- playerchunkmap_entitytracker.updatePlayers(entity.getPlayersInTrackRange()); // Paper - don't search all players + // Folia - region threading + // Paper start - optimise entity tracker + if (((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity() != null) { + throw new IllegalStateException("Entity is already tracked"); + } + ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$setTrackedEntity(playerchunkmap_entitytracker); + // Paper end - optimise entity tracker +- playerchunkmap_entitytracker.updatePlayers(this.level.players()); + playerchunkmap_entitytracker.updatePlayers(this.level.getLocalPlayers()); // Folia - region threading if (entity instanceof ServerPlayer) { ServerPlayer entityplayer = (ServerPlayer) entity; @@ -12596,15 +10404,15 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa - playerchunkmap_entitytracker1.updatePlayer(entityplayer); + // Folia start - region threading + for (Entity possible : this.level.getCurrentWorldData().getLoadedEntities()) { -+ if (possible.tracker != null) { -+ possible.tracker.updatePlayer(entityplayer); ++ if (possible.moonrise$getTrackedEntity() != null) { ++ possible.moonrise$getTrackedEntity().updatePlayer(entityplayer); } } + // Folia end - region threading } } -@@ -1138,16 +1075,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -896,16 +880,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider org.spigotmc.AsyncCatcher.catchOp("entity untrack"); // Spigot if (entity instanceof ServerPlayer entityplayer) { this.updatePlayerStatus(entityplayer, false); @@ -12616,70 +10424,44 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa - playerchunkmap_entitytracker.removePlayer(entityplayer); + // Folia start - region threading + for (Entity possible : this.level.getCurrentWorldData().getLocalEntities()) { -+ if (possible.tracker != null) { -+ possible.tracker.removePlayer(entityplayer); ++ if (possible.moonrise$getTrackedEntity() != null) { ++ possible.moonrise$getTrackedEntity().removePlayer(entityplayer); + } } + // Folia end - region threading } - ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = (ChunkMap.TrackedEntity) this.entityMap.remove(entity.getId()); -+ ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = entity.tracker; // Folia - region threading ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker1 = entity.moonrise$getTrackedEntity(); // Folia - region threading if (playerchunkmap_entitytracker1 != null) { playerchunkmap_entitytracker1.broadcastRemoved(); -@@ -1155,82 +1092,37 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - entity.tracker = null; // Paper - We're no longer tracked - } +@@ -916,10 +900,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider -- // Paper start - optimised tracker -- private final void processTrackQueue() { -- this.level.timings.tracker1.startTiming(); -- try { -- for (TrackedEntity tracker : this.entityMap.values()) { -- // update tracker entry -- tracker.updatePlayers(tracker.entity.getPlayersInTrackRange()); -+ // Folia start - region threading - replace entity tracking ticking -+ private void foliaEntityTrackerTick() { -+ io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.level.getCurrentWorldData(); -+ io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = worldData.getNearbyPlayers(); -+ for (Entity entity : worldData.getLoadedEntities()) { -+ TrackedEntity tracker = entity.tracker; -+ if (tracker == null) { -+ continue; - } -- } finally { -- this.level.timings.tracker1.stopTiming(); -- } -- -- -- this.level.timings.tracker2.startTiming(); -- try { -- for (TrackedEntity tracker : this.entityMap.values()) { -- tracker.serverEntity.sendChanges(); -+ tracker.tick(nearbyPlayers.getChunk(entity.chunkPosition())); -+ tracker.serverEntity.sendChanges(); -+ } -+ // process unloads -+ for (Entity entity : worldData.takeTrackingUnloads()) { -+ TrackedEntity tracker = entity.tracker; -+ if (tracker == null) { -+ continue; - } -- } finally { -- this.level.timings.tracker2.stopTiming(); -+ tracker.clearPlayers(); + // Paper start - optimise entity tracker + private void newTrackerTick() { ++ final io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.level.getCurrentWorldData(); // Folia - region threading + final ca.spottedleaf.moonrise.common.misc.NearbyPlayers nearbyPlayers = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getNearbyPlayers(); + final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup entityLookup = (ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup)((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getEntityLookup();; + +- final ca.spottedleaf.moonrise.common.list.ReferenceList trackerEntities = entityLookup.trackerEntities; ++ final ca.spottedleaf.moonrise.common.list.ReferenceList trackerEntities = worldData.trackerEntities; // Folia - region threading + final Entity[] trackerEntitiesRaw = trackerEntities.getRawDataUnchecked(); + for (int i = 0, len = trackerEntities.size(); i < len; ++i) { + final Entity entity = trackerEntitiesRaw[i]; +@@ -932,7 +917,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - } -- // Paper end - optimised tracker -- -- protected void tick() { -- // Paper start - optimized tracker -- if (true) { -- this.processTrackQueue(); -- return; -- } -- // Paper end - optimized tracker + + // process unloads +- final ca.spottedleaf.moonrise.common.list.ReferenceList unloadedEntities = entityLookup.trackerUnloadedEntities; ++ final ca.spottedleaf.moonrise.common.list.ReferenceList unloadedEntities = worldData.trackerUnloadedEntities; // Folia - region threading + final Entity[] unloadedEntitiesRaw = java.util.Arrays.copyOf(unloadedEntities.getRawDataUnchecked(), unloadedEntities.size()); + unloadedEntities.clear(); + +@@ -955,51 +940,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end - optimise entity tracker + // Paper - rewrite chunk system + - List list = Lists.newArrayList(); - List list1 = this.level.players(); - ObjectIterator objectiterator = this.entityMap.values().iterator(); @@ -12692,8 +10474,7 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa - SectionPos sectionposition = playerchunkmap_entitytracker.lastSectionPos; - SectionPos sectionposition1 = SectionPos.of((EntityAccess) playerchunkmap_entitytracker.entity); - boolean flag = !Objects.equals(sectionposition, sectionposition1); -+ // Folia end - region threading - replace entity tracking ticking - +- - if (flag) { - playerchunkmap_entitytracker.updatePlayers(list1); - Entity entity = playerchunkmap_entitytracker.entity; @@ -12721,107 +10502,26 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa - } - level.timings.tracker2.stopTiming(); // Paper - } -+ // Folia - region threading - replace entity tracking ticking ++ // Folia - region threading -+ protected void tick() { -+ this.foliaEntityTrackerTick(); // Folia - region threading - replace entity tracking ticking } public void broadcast(Entity entity, Packet packet) { - ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); -+ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) entity.tracker; // Folia - region threading ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) entity.moonrise$getTrackedEntity(); // Folia - region threading if (playerchunkmap_entitytracker != null) { playerchunkmap_entitytracker.broadcast(packet); -@@ -1239,7 +1131,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1008,7 +954,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected void broadcastAndSend(Entity entity, Packet packet) { - ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) this.entityMap.get(entity.getId()); -+ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) entity.tracker; // Folia - region threading ++ ChunkMap.TrackedEntity playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) entity.moonrise$getTrackedEntity(); // Folia - region threading if (playerchunkmap_entitytracker != null) { playerchunkmap_entitytracker.broadcastAndSend(packet); -@@ -1414,6 +1306,78 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - } -+ // Folia start - region threading -+ private int lastChunkUpdate = -1; -+ private io.papermc.paper.util.player.NearbyPlayers.TrackedChunk lastTrackedChunk; -+ public void tick(io.papermc.paper.util.player.NearbyPlayers.TrackedChunk chunk) { -+ if (chunk == null) { -+ this.clearPlayers(); -+ return; -+ } -+ -+ com.destroystokyo.paper.util.maplist.ReferenceList players = -+ chunk.getPlayers(io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.VIEW_DISTANCE); -+ -+ if (players == null) { -+ this.clearPlayers(); -+ return; -+ } -+ -+ int lastChunkUpdate = this.lastChunkUpdate; -+ int currChunkUpdate = chunk.getUpdateCount(); -+ io.papermc.paper.util.player.NearbyPlayers.TrackedChunk lastTrackedChunk = this.lastTrackedChunk; -+ this.lastChunkUpdate = currChunkUpdate; -+ this.lastTrackedChunk = chunk; -+ -+ for (int i = 0, len = players.size(); i < len; ++i) { -+ ServerPlayer player = players.getUnchecked(i); -+ this.updatePlayer(player); -+ } -+ -+ if (lastChunkUpdate != currChunkUpdate || lastTrackedChunk != chunk) { -+ // need to purge any players possible not in the chunk list -+ for (ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) { -+ ServerPlayer player = conn.getPlayer(); -+ if (!players.contains(player)) { -+ this.removePlayer(player); -+ } -+ } -+ } -+ } -+ -+ public void removeNonTickThreadPlayers() { -+ boolean foundToRemove = false; -+ for (ServerPlayerConnection conn : this.seenBy) { -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(conn.getPlayer())) { -+ foundToRemove = true; -+ break; -+ } -+ } -+ -+ if (!foundToRemove) { -+ return; -+ } -+ -+ for (ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) { -+ ServerPlayer player = conn.getPlayer(); -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(player)) { -+ this.removePlayer(player); -+ } -+ } -+ } -+ -+ public void clearPlayers() { -+ this.lastChunkUpdate = -1; -+ this.lastTrackedChunk = null; -+ if (this.seenBy.isEmpty()) { -+ return; -+ } -+ for (ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) { -+ ServerPlayer player = conn.getPlayer(); -+ this.removePlayer(player); -+ } -+ } -+ // Folia end - region threading - - public void updatePlayer(ServerPlayer player) { - org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot -@@ -1437,9 +1401,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1255,9 +1201,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } // Paper end - Configurable entity tracking range by Y @@ -12833,33 +10533,65 @@ index 7fb9ba3dadb1eca4a1000ea8cf4d13fed2b7db1e..c75990f0549a1267ecb591227b0f97fa // CraftBukkit start - respect vanish API - if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits -+ if (flag && (!io.papermc.paper.util.TickThread.isTickThreadFor(player) || !player.getBukkitEntity().canSee(this.entity.getBukkitEntity()))) { // Paper - only consider hits // Folia - region threading ++ if (flag && (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(player) || !player.getBukkitEntity().canSee(this.entity.getBukkitEntity()))) { // Paper - only consider hits // Folia - region threading flag = false; } // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index cdb3c2cde5d9133ef60cf96d91762e6a7c8aeb4a..8c42c1f0d67f437423bf6d3958c6409f44556d5c 100644 +index 2d2596f04f5addac38037a14a02c6e0622d0c485..ddfbdd7c07be201bbb29fa980b6ba83216704bb0 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -191,11 +191,11 @@ public abstract class DistanceManager { +@@ -62,16 +62,16 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches + } + // Paper end - rewrite chunk system + // Paper start - chunk tick iteration optimisation +- private final ca.spottedleaf.moonrise.common.misc.PositionCountingAreaMap spawnChunkTracker = new ca.spottedleaf.moonrise.common.misc.PositionCountingAreaMap<>(); ++ // Folia - move to regionized world data + + @Override + public final void moonrise$addPlayer(final ServerPlayer player, final SectionPos pos) { +- this.spawnChunkTracker.add(player, pos.x(), pos.z(), ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); ++ this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.add(player, pos.x(), pos.z(), ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); // Folia - region threading + } + + @Override + public final void moonrise$removePlayer(final ServerPlayer player, final SectionPos pos) { +- this.spawnChunkTracker.remove(player); ++ this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.remove(player); // Folia - region threading + } + + @Override +@@ -79,9 +79,9 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches + final SectionPos oldPos, final SectionPos newPos, + final boolean oldIgnore, final boolean newIgnore) { + if (newIgnore) { +- this.spawnChunkTracker.remove(player); ++ this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.remove(player); // Folia - region threading + } else { +- this.spawnChunkTracker.addOrUpdate(player, newPos.x(), newPos.z(), ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); ++ this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.addOrUpdate(player, newPos.x(), newPos.z(), ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickConstants.PLAYER_SPAWN_TRACK_RANGE); // Folia - region threading + } + } + // Paper end - chunk tick iteration optimisation +@@ -216,11 +216,11 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches } public int getNaturalSpawnChunkCount() { -- return this.chunkMap.playerMobSpawnMap.size(); // Paper - optimise chunk tick iteration -+ return this.chunkMap.level.getCurrentWorldData().mobSpawnMap.size(); // Paper - optimise chunk tick iteration // Folia - region threading +- return this.spawnChunkTracker.getTotalPositions(); // Paper - chunk tick iteration optimisation ++ return this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.getTotalPositions(); // Paper - chunk tick iteration optimisation // Folia - region threading } public boolean hasPlayersNearby(long chunkPos) { -- return this.chunkMap.playerMobSpawnMap.getObjectsInRange(chunkPos) != null; // Paper - optimise chunk tick iteration -+ return this.chunkMap.level.getCurrentWorldData().mobSpawnMap.getObjectsInRange(chunkPos) != null; // Paper - optimise chunk tick iteration // Folia - region threading +- return this.spawnChunkTracker.hasObjectsNear(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkPos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkPos)); // Paper - chunk tick iteration optimisation ++ return this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.hasObjectsNear(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkPos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkPos)); // Paper - chunk tick iteration optimisation // Folia - region threading } public String getDebugStatus() { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b9264ca5f 100644 +index dcb5651d1d9b10b40430fb2f713beedf68336704..e13ccac27fa4f4c23185f12c776e80970ab844e6 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -56,23 +56,20 @@ public class ServerChunkCache extends ChunkSource { +@@ -57,16 +57,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; public final ChunkMap chunkMap; private final DimensionDataStorage dataStorage; @@ -12876,130 +10608,60 @@ index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b - private NaturalSpawner.SpawnState lastSpawnState; + // Folia - moved to regionised world data // Paper start -- public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet tickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); -- public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet entityTickingChunks = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(4096, 0.75f, 4096, 0.15, true); -+ // Folia - region threading - move to regionised world data - final com.destroystokyo.paper.util.concurrent.WeakSeqLock loadedChunkMapSeqLock = new com.destroystokyo.paper.util.concurrent.WeakSeqLock(); -- final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap loadedChunkMap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(8192, 0.5f); -+ final ca.spottedleaf.concurrentutil.map.SWMRLong2ObjectHashTable loadedChunkMap = new ca.spottedleaf.concurrentutil.map.SWMRLong2ObjectHashTable<>(8192, 0.5f); // Folia - region threading - final java.util.concurrent.atomic.AtomicLong chunkFutureAwaitCounter = new java.util.concurrent.atomic.AtomicLong(); // Paper - chunk system rewrite -- private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4]; -+ // Folia - region threading - // Paper end + private final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>(); + long chunkFutureAwaitCounter; +@@ -126,7 +124,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + return load ? this.syncLoad(chunkX, chunkZ, toStatus) : null; + } + // Paper end - rewrite chunk system +- private ServerChunkCache.ChunkAndHolder[] iterationCopy; // Paper - chunk tick iteration optimisations ++ // Folia - moved to regionized data public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory) { -@@ -105,52 +102,23 @@ public class ServerChunkCache extends ChunkSource { - } - - public void addLoadedChunk(LevelChunk chunk) { -- this.loadedChunkMapSeqLock.acquireWrite(); -- try { -+ synchronized (this.loadedChunkMap) { // Folia - region threading - this.loadedChunkMap.put(chunk.coordinateKey, chunk); -- } finally { -- this.loadedChunkMapSeqLock.releaseWrite(); -- } -- -- // rewrite cache if we have to -- // we do this since we also cache null chunks -- int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ } // Folia - region threading - -- this.lastLoadedChunks[cacheKey] = chunk; -+ // Folia - region threading - } - - public void removeLoadedChunk(LevelChunk chunk) { -- this.loadedChunkMapSeqLock.acquireWrite(); -- try { -+ synchronized (this.loadedChunkMap) { // Folia - region threading - this.loadedChunkMap.remove(chunk.coordinateKey); -- } finally { -- this.loadedChunkMapSeqLock.releaseWrite(); -- } -- -- // rewrite cache if we have to -- // we do this since we also cache null chunks -- int cacheKey = getChunkCacheKey(chunk.locX, chunk.locZ); -+ } // Folia - region threading - -- LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; -- if (cachedChunk != null && cachedChunk.coordinateKey == chunk.coordinateKey) { -- this.lastLoadedChunks[cacheKey] = null; -- } -+ // Folia - region threading - } - - public final LevelChunk getChunkAtIfLoadedMainThread(int x, int z) { -- int cacheKey = getChunkCacheKey(x, z); -- -- LevelChunk cachedChunk = this.lastLoadedChunks[cacheKey]; -- if (cachedChunk != null && cachedChunk.locX == x & cachedChunk.locZ == z) { -- return cachedChunk; -- } -- -- long chunkKey = ChunkPos.asLong(x, z); -- -- cachedChunk = this.loadedChunkMap.get(chunkKey); -- // Skipping a null check to avoid extra instructions to improve inline capability -- this.lastLoadedChunks[cacheKey] = cachedChunk; -- return cachedChunk; -+ return this.loadedChunkMap.get(ChunkPos.asLong(x, z)); // Folia - region threading - } - - public final LevelChunk getChunkAtIfLoadedMainThreadNoCache(int x, int z) { -@@ -195,26 +163,7 @@ public class ServerChunkCache extends ChunkSource { - public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { - long k = ChunkPos.asLong(x, z); - -- if (io.papermc.paper.util.TickThread.isTickThread()) { // Paper - rewrite chunk system -- return this.getChunkAtIfLoadedMainThread(x, z); -- } -- -- LevelChunk ret = null; -- long readlock; -- do { -- readlock = this.loadedChunkMapSeqLock.acquireRead(); -- try { -- ret = this.loadedChunkMap.get(k); -- } catch (Throwable thr) { -- if (thr instanceof ThreadDeath) { -- throw (ThreadDeath)thr; -- } -- // re-try, this means a CME occurred... -- continue; -- } -- } while (!this.loadedChunkMapSeqLock.tryReleaseRead(readlock)); -- -- return ret; -+ return this.loadedChunkMap.get(k); // Folia - region threading - } - // Paper end - -@@ -308,6 +257,7 @@ public class ServerChunkCache extends ChunkSource { + this.level = world; +@@ -252,6 +250,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } public CompletableFuture> getChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { + if (true) throw new UnsupportedOperationException(); // Folia - region threading - boolean flag1 = io.papermc.paper.util.TickThread.isTickThread(); // Paper - rewrite chunk system + boolean flag1 = Thread.currentThread() == this.mainThread; CompletableFuture completablefuture; -@@ -497,10 +447,11 @@ public class ServerChunkCache extends ChunkSource { +@@ -419,11 +418,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } private void tickChunks() { ++ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading + long chunksTicked = 0; // Paper - rewrite chunk system - long i = this.level.getGameTime(); - long j = i - this.lastInhabitedUpdate; -+ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading + //long i = this.level.getGameTime(); // Folia - region threading -+ long j = 1; // Folia - region threading ++ long j = 1L; // Folia - region threading - this.lastInhabitedUpdate = i; + //this.lastInhabitedUpdate = i; // Folia - region threading if (!this.level.isDebug()) { ProfilerFiller gameprofilerfiller = this.level.getProfiler(); -@@ -520,7 +471,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -438,13 +438,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked(); + final int size = tickingChunks.size(); + +- if (this.iterationCopy == null || this.iterationCopy.length < size) { +- this.iterationCopy = new ServerChunkCache.ChunkAndHolder[raw.length]; ++ if (regionizedWorldData.iterationCopy == null || regionizedWorldData.iterationCopy.length < size) { // Folia - region threading ++ regionizedWorldData.iterationCopy = new ServerChunkCache.ChunkAndHolder[raw.length]; // Folia - region threading + } +- System.arraycopy(raw, 0, this.iterationCopy, 0, size); ++ System.arraycopy(raw, 0, regionizedWorldData.iterationCopy, 0, size); // Folia - region threading + + list = it.unimi.dsi.fastutil.objects.ObjectArrayList.wrap( +- this.iterationCopy, size ++ regionizedWorldData.iterationCopy, size // Folia - region threading + ); + } + // Paper end - chunk tick iteration optimisations +@@ -462,7 +462,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon NaturalSpawner.SpawnState spawnercreature_d; // moved down if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled // re-set mob counts @@ -13008,7 +10670,7 @@ index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b // Paper start - per player mob spawning backoff for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) { player.mobCounts[ii] = 0; -@@ -533,22 +484,22 @@ public class ServerChunkCache extends ChunkSource { +@@ -475,23 +475,23 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } // Paper end - per player mob spawning backoff } @@ -13027,86 +10689,17 @@ index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b - boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit + boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.getLocalPlayers().isEmpty(); // CraftBukkit // Folia - region threadin - // Paper start - optimise chunk tick iteration - ChunkMap playerChunkMap = this.chunkMap; -- for (ServerPlayer player : this.level.players) { -+ for (ServerPlayer player : this.level.getLocalPlayers()) { // Folia - region threading - if (!player.affectsSpawning || player.isSpectator()) { -- playerChunkMap.playerMobSpawnMap.remove(player); -+ regionizedWorldData.mobSpawnMap.remove(player); // Folia - region threading - player.playerNaturallySpawnedEvent = null; - player.lastEntitySpawnRadiusSquared = -1.0; - continue; -@@ -564,7 +515,7 @@ public class ServerChunkCache extends ChunkSource { - com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent event = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(player.getBukkitEntity(), (byte)chunkRange); - event.callEvent(); - if (event.isCancelled() || event.getSpawnRadius() < 0) { -- playerChunkMap.playerMobSpawnMap.remove(player); -+ regionizedWorldData.mobSpawnMap.remove(player); // Folia - region threading - player.playerNaturallySpawnedEvent = null; - player.lastEntitySpawnRadiusSquared = -1.0; - continue; -@@ -574,13 +525,13 @@ public class ServerChunkCache extends ChunkSource { - int chunkX = io.papermc.paper.util.CoordinateUtils.getChunkCoordinate(player.getX()); - int chunkZ = io.papermc.paper.util.CoordinateUtils.getChunkCoordinate(player.getZ()); - -- playerChunkMap.playerMobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); -+ regionizedWorldData.mobSpawnMap.addOrUpdate(player, chunkX, chunkZ, range); // Folia - region threading - player.lastEntitySpawnRadiusSquared = (double)((range << 4) * (range << 4)); // used in anyPlayerCloseEnoughForSpawning - player.playerNaturallySpawnedEvent = event; + if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.level.random); // Paper - per player mob spawns - do not need this when per-player is enabled + // Paper start - PlayerNaturallySpawnCreaturesEvent + int chunkRange = level.spigotConfig.mobSpawnRange; + chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; + chunkRange = Math.min(chunkRange, 8); +- for (ServerPlayer entityPlayer : this.level.players()) { ++ for (ServerPlayer entityPlayer : this.level.getLocalPlayers()) { // Folia - region threading + entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); + entityPlayer.playerNaturallySpawnedEvent.callEvent(); } - // Paper end - optimise chunk tick iteration - int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); -- boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit -+ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getRedstoneGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit // Folia - region threading - // Paper - optimise chunk tick iteration - - int chunksTicked = 0; // Paper -@@ -588,10 +539,10 @@ public class ServerChunkCache extends ChunkSource { - io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = this.chunkMap.getNearbyPlayers(); // Paper - optimise chunk tick iteration - Iterator chunkIterator; - if (this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { -- chunkIterator = this.tickingChunks.iterator(); -+ chunkIterator = regionizedWorldData.getTickingChunks().iterator(); // Folia - region threading - } else { -- chunkIterator = this.tickingChunks.unsafeIterator(); -- List shuffled = Lists.newArrayListWithCapacity(this.tickingChunks.size()); -+ chunkIterator = regionizedWorldData.getTickingChunks().unsafeIterator(); // Folia - region threading -+ List shuffled = Lists.newArrayListWithCapacity(regionizedWorldData.getTickingChunks().size()); // Folia - region threading - while (chunkIterator.hasNext()) { - shuffled.add(chunkIterator.next()); - } -@@ -661,17 +612,21 @@ public class ServerChunkCache extends ChunkSource { - // Paper - optimise chunk tick iteration - this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing - // Paper start - optimise chunk tick iteration -- if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) { -- it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet copy = this.chunkMap.needsChangeBroadcasting.clone(); -- this.chunkMap.needsChangeBroadcasting.clear(); -- for (ChunkHolder holder : copy) { -- holder.broadcastChanges(holder.getFullChunkNowUnchecked()); // LevelChunks are NEVER unloaded -- if (holder.needsBroadcastChanges()) { -- // I DON'T want to KNOW what DUMB plugins might be doing. -- this.chunkMap.needsChangeBroadcasting.add(holder); -+ // Folia start - region threading -+ if (!this.level.needsChangeBroadcasting.isEmpty()) { -+ for (Iterator iterator = this.level.needsChangeBroadcasting.iterator(); iterator.hasNext();) { -+ ChunkHolder holder = iterator.next(); -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(holder.newChunkHolder.world, holder.pos)) { -+ continue; -+ } -+ // don't need to worry about asynchronous chunk holder remove, as that can only be done by this tick thread -+ holder.broadcastChanges(holder.getFullChunkNowUnchecked()); -+ if (!holder.needsBroadcastChanges()) { -+ iterator.remove(); - } - } - } -+ // Folia end - region threading - // Paper end - optimise chunk tick iteration - this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing - // Paper - optimise chunk tick iteration -@@ -734,14 +689,19 @@ public class ServerChunkCache extends ChunkSource { +@@ -604,14 +604,19 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override public void onLightUpdate(LightLayer type, SectionPos pos) { @@ -13128,7 +10721,7 @@ index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b } public void addRegionTicket(TicketType ticketType, ChunkPos pos, int radius, T argument) { -@@ -813,7 +773,8 @@ public class ServerChunkCache extends ChunkSource { +@@ -689,7 +694,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Nullable @VisibleForDebug public NaturalSpawner.SpawnState getLastSpawnState() { @@ -13138,7 +10731,7 @@ index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b } public void removeTicketsOnClosing() { -@@ -846,8 +807,43 @@ public class ServerChunkCache extends ChunkSource { +@@ -729,8 +735,43 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon return ServerChunkCache.this.mainThread; } @@ -13182,7 +10775,7 @@ index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b ServerChunkCache.this.level.getProfiler().incrementCounter("runTask"); super.doRunTask(task); } -@@ -855,10 +851,15 @@ public class ServerChunkCache extends ChunkSource { +@@ -738,12 +779,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task public boolean pollTask() { @@ -13191,25 +10784,27 @@ index fcecfda569d2a8d6b8a7e228831f822fb7327748..0b323e648d4dbe27822b77b846e4861b + throw new IllegalStateException("Polling tasks from non-owned region"); + } + // Folia end - region threading - if (ServerChunkCache.this.runDistanceManagerUpdates()) { + // Paper start - rewrite chunk system + final ServerChunkCache serverChunkCache = ServerChunkCache.this; + if (serverChunkCache.runDistanceManagerUpdates()) { return true; + } else { +- return super.pollTask() | ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)serverChunkCache.level).moonrise$getChunkTaskScheduler().executeMainThreadTask(); ++ return io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion().getData().getTaskQueueData().executeChunkTask(); // Folia - region threading } -- return super.pollTask() | ServerChunkCache.this.level.chunkTaskScheduler.executeMainThreadTask(); // Paper - rewrite chunk system -+ return io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion().getData().getTaskQueueData().executeChunkTask(); // Paper - rewrite chunk system // Folia - region threading - } - } - + // Paper end - rewrite chunk system + // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f0d710173 100644 +index 2fe9d9b38c01d04416843fdd48d3e33899b7de63..f236feba396162ae7545a96a920127c168cb24e3 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -197,38 +197,36 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -198,37 +198,35 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. private final MinecraftServer server; public final PrimaryLevelData serverLevelData; // CraftBukkit - type private int lastSpawnChunkRadius; - final EntityTickList entityTickList; + //final EntityTickList entityTickList; // Folia - region threading - //public final PersistentEntitySectionManager entityManager; // Paper - rewrite chunk system + // Paper - rewrite chunk system private final GameEventDispatcher gameEventDispatcher; public boolean noSave; private final SleepStatus sleepStatus; @@ -13239,8 +10834,6 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f - private final boolean tickTime; + public final boolean tickTime; // Folia - region threading private final RandomSequences randomSequences; -- public long lastMidTickExecuteFailure; // Paper - execute chunk tasks mid tick -+ // Folia - region threading // CraftBukkit start public final LevelStorageSource.LevelStorageAccess convertable; @@ -13252,13 +10845,13 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f public LevelChunk getChunkIfLoaded(int x, int z) { return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately -@@ -258,6 +256,36 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -258,6 +256,36 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. ServerChunkCache chunkProvider = this.getChunkSource(); + // Folia start - region threading + // don't let players move into regions not owned -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this, minChunkX, minChunkZ, maxChunkX, maxChunkZ)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, minChunkX, minChunkZ, maxChunkX, maxChunkZ)) { + return false; + } + @@ -13289,21 +10882,17 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f for (int cx = minChunkX; cx <= maxChunkX; ++cx) { for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) { -@@ -516,7 +544,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -368,7 +396,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - public final int getRegionChunkShift() { - // placeholder for folia + @Override + public final int moonrise$getRegionChunkShift() { - return io.papermc.paper.threadedregions.TickRegions.getRegionChunkShift(); + return this.regioniser.sectionChunkShift; // Folia - region threading } - // Paper end - rewrite chunk system -@@ -571,14 +599,14 @@ public class ServerLevel extends Level implements WorldGenLevel { - } - // Paper end - optimise getPlayerByUUID - // Paper start - lag compensation -- private long lagCompensationTick = net.minecraft.server.MinecraftServer.SERVER_INIT; -+ // Folia - region threading + @Override +@@ -489,13 +517,65 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + private long lagCompensationTick = net.minecraft.server.MinecraftServer.SERVER_INIT; public long getLagCompensationTick() { - return this.lagCompensationTick; @@ -13315,29 +10904,6 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f + throw new UnsupportedOperationException(); // Folia - region threading } // Paper end - lag compensation - // Paper start - optimise nearby player retrieval -@@ -625,7 +653,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - ServerPlayer nearest = null; - double nearestDist = Double.MAX_VALUE; - -- for (ServerPlayer player : this.players()) { -+ for (ServerPlayer player : this.getLocalPlayers()) { // Folia - region threading - double dist = player.distanceToSqr(x, y, z); - if (dist >= nearestDist) { - continue; -@@ -681,7 +709,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - - return nearest; - } else { -- return this.getNearestEntity(this.players(), targetPredicate, entity, x, y, z); -+ return this.getNearestEntity(this.getLocalPlayers(), targetPredicate, entity, x, y, z); // Folia - region threading - } - } - -@@ -690,6 +718,58 @@ public class ServerLevel extends Level implements WorldGenLevel { - return this.getNearestPlayer(targetPredicate, null, x, y, z); - } - // Paper end - optimise nearby player retrieval + // Folia start - region threading + public final io.papermc.paper.threadedregions.TickRegions tickRegions = new io.papermc.paper.threadedregions.TickRegions(); + public final io.papermc.paper.threadedregions.ThreadedRegionizer regioniser; @@ -13380,7 +10946,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f + synchronized (this.pendingTeleports) { + for (final Iterator iterator = this.pendingTeleports.iterator(); iterator.hasNext(); ) { + final PendingTeleport pendingTeleport = iterator.next(); -+ if (io.papermc.paper.util.TickThread.isTickThreadFor(this, pendingTeleport.to())) { ++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, pendingTeleport.to())) { + ret.add(pendingTeleport); + iterator.remove(); + } @@ -13393,7 +10959,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f // Add env and gen to constructor, IWorldDataServer -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { -@@ -702,14 +782,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -508,14 +588,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. this.convertable = convertable_conversionsession; this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); // CraftBukkit end @@ -13415,7 +10981,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f this.dragonParts = new Int2ObjectOpenHashMap(); this.tickTime = flag1; this.server = minecraftserver; -@@ -748,7 +828,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -553,7 +633,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. }); this.chunkSource.getGeneratorState().ensureStructuresGenerated(); this.portalForcer = new PortalForcer(this); @@ -13424,10 +10990,10 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f this.prepareWeather(); this.getWorldBorder().setAbsoluteMaxSize(minecraftserver.getAbsoluteMaxWorldSize()); this.raids = (Raids) this.getDataStorage().computeIfAbsent(Raids.factory(this), Raids.getFileId(this.dimensionTypeRegistration())); -@@ -775,7 +855,14 @@ public class ServerLevel extends Level implements WorldGenLevel { - - this.chunkTaskScheduler = new io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler(this, io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.workerThreads); // Paper - rewrite chunk system - this.entityLookup = new io.papermc.paper.chunk.system.entity.EntityLookup(this, new EntityCallbacks()); // Paper - rewrite chunk system +@@ -590,7 +670,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + this.chunkTaskScheduler = new ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler((ServerLevel)(Object)this, ca.spottedleaf.moonrise.common.util.MoonriseCommon.WORKER_POOL); + // Paper end - rewrite chunk system + this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + this.updateTickData(); // Folia - region threading - make sure it is initialised before ticked + } + @@ -13439,7 +11005,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f // Paper start @Override -@@ -804,48 +891,32 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -619,48 +706,32 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ, this.getChunkSource().randomState().sampler()); } @@ -13481,8 +11047,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f - this.setDayTime(this.getDayTime() + event.getSkipAmount()); - } - } -+ if (region == null) this.tickSleep(); // Folia - region threading - +- - if (!event.isCancelled()) { - this.wakeUpAllPlayers(); - } @@ -13491,13 +11056,14 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f - this.resetWeatherCycle(); - } - } -- ++ if (region == null) this.tickSleep(); // Folia - region threading + - this.updateSkyBrightness(); + if (region == null) this.updateSkyBrightness(); // Folia - region threading if (flag) { this.tickTime(); } -@@ -853,11 +924,11 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -668,11 +739,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. gameprofilerfiller.popPush("tickPending"); this.timings.scheduledBlocks.startTiming(); // Paper if (!this.isDebug() && flag) { @@ -13512,7 +11078,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f gameprofilerfiller.pop(); } this.timings.scheduledBlocks.stopTiming(); // Paper -@@ -880,9 +951,9 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -695,9 +766,9 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. this.timings.doSounds.stopTiming(); // Spigot } @@ -13524,11 +11090,11 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f if (flag1) { this.resetEmptyTime(); -@@ -892,20 +963,30 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -707,20 +778,30 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. gameprofilerfiller.push("entities"); this.timings.tickEntities.startTiming(); // Spigot if (this.dragonFight != null && flag) { -+ if (io.papermc.paper.util.TickThread.isTickThreadFor(this, this.dragonFight.origin)) { // Folia - region threading ++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, this.dragonFight.origin)) { // Folia - region threading gameprofilerfiller.push("dragonFight"); this.dragonFight.tick(); gameprofilerfiller.pop(); @@ -13536,7 +11102,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f + // try to load dragon fight + ChunkPos fightCenter = new ChunkPos(this.dragonFight.origin); + this.chunkSource.addTicketAtLevel( -+ TicketType.UNKNOWN, fightCenter, io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, ++ TicketType.UNKNOWN, fightCenter, ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + fightCenter + ); + } // Folia end - region threading @@ -13554,9 +11120,9 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f entity.checkDespawn(); + if (entity.isRemoved()) return; // Folia - region threading - if we despawned, DON'T TICK IT! gameprofilerfiller.pop(); - if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - now always true if in the ticking list + if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - rewrite chunk system Entity entity1 = entity.getVehicle(); -@@ -936,6 +1017,31 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -751,6 +832,31 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. gameprofilerfiller.pop(); } @@ -13587,8 +11153,8 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f + @Override public boolean shouldTickBlocksAt(long chunkPos) { - // Paper start - replace player chunk loader system -@@ -946,11 +1052,12 @@ public class ServerLevel extends Level implements WorldGenLevel { + // Paper start - rewrite chunk system +@@ -761,11 +867,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. protected void tickTime() { if (this.tickTime) { @@ -13605,7 +11171,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f this.setDayTime(this.levelData.getDayTime() + 1L); } -@@ -979,15 +1086,23 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -794,7 +901,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. private void wakeUpAllPlayers() { this.sleepStatus.removeAllSleepers(); (this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error @@ -13620,46 +11186,8 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f + // Folia end - region threading }); } - // Paper start - optimise random block ticking -- private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); -- private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(this.random.nextLong()); -+ private final ThreadLocal chunkTickMutablePosition = ThreadLocal.withInitial(() -> new BlockPos.MutableBlockPos()); // Folia - region threading -+ private final ThreadLocal randomTickRandom = ThreadLocal.withInitial(() -> new io.papermc.paper.util.math.ThreadUnsafeRandom(this.random.nextLong())); // Folia - region threading - // Paper end - public void tickChunk(LevelChunk chunk, int randomTickSpeed) { -+ io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = this.randomTickRandom.get(); // Folia - region threading - ChunkPos chunkcoordintpair = chunk.getPos(); - boolean flag = this.isRaining(); - int j = chunkcoordintpair.getMinBlockX(); -@@ -995,7 +1110,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - ProfilerFiller gameprofilerfiller = this.getProfiler(); - - gameprofilerfiller.push("thunder"); -- final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change -+ final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition.get(); // Paper - use mutable to reduce allocation rate, final to force compile fail on change // Folia - region threading - - if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - Option to disable thunder - blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper -@@ -1051,7 +1166,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - int yPos = (sectionIndex + minSection) << 4; - for (int a = 0; a < randomTickSpeed; ++a) { - int tickingBlocks = section.tickingList.size(); -- int index = this.randomTickRandom.nextInt(16 * 16 * 16); -+ int index = randomTickRandom.nextInt(16 * 16 * 16); // Folia - region threading - if (index >= tickingBlocks) { - continue; - } -@@ -1065,7 +1180,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - BlockPos blockposition2 = blockposition.set(j + randomX, randomY, k + randomZ); - BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); - -- iblockdata.randomTick(this, blockposition2, this.randomTickRandom); -+ iblockdata.randomTick(this, blockposition2, randomTickRandom); // Folia - region threading - } - // We drop the fluid tick since LAVA is ALREADY TICKED by the above method (See LiquidBlock). - // TODO CHECK ON UPDATE (ping the Canadian) -@@ -1170,7 +1285,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -995,7 +1109,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } public boolean isHandlingTick() { @@ -13668,7 +11196,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } public boolean canSleepThroughNights() { -@@ -1202,6 +1317,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1027,6 +1141,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } public void updateSleepingPlayerList() { @@ -13683,7 +11211,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f if (!this.players.isEmpty() && this.sleepStatus.update(this.players)) { this.announceSleepStatus(); } -@@ -1213,7 +1336,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1038,7 +1160,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. return this.server.getScoreboard(); } @@ -13692,7 +11220,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f boolean flag = this.isRaining(); if (this.dimensionType().hasSkyLight()) { -@@ -1299,23 +1422,24 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1124,23 +1246,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel)); } // */ @@ -13726,26 +11254,17 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } } // CraftBukkit end -@@ -1380,7 +1504,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - - public void tickNonPassenger(Entity entity) { - // Paper start - log detailed entity tick information -- io.papermc.paper.util.TickThread.ensureTickThread("Cannot tick an entity off-main"); -+ io.papermc.paper.util.TickThread.ensureTickThread(entity, "Cannot tick an entity off-main"); // Folia - region threading - try { - if (currentlyTickingEntity.get() == null) { - currentlyTickingEntity.lazySet(entity); -@@ -1413,7 +1537,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1246,7 +1369,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. if (isActive) { // Paper - EAR 2 TimingHistory.activatedEntityTicks++; entity.tick(); - entity.postTick(); // CraftBukkit + // Folia start - region threading -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(entity)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) { + // removed from region while ticking + return; + } -+ if (entity.doPortalLogic()) { ++ if (entity.handlePortal()) { + // portalled + return; + } @@ -13753,7 +11272,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } else { entity.inactiveTick(); } // Paper - EAR 2 this.getProfiler().pop(); } finally { timer.stopTiming(); } // Paper - timings -@@ -1436,7 +1569,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1269,7 +1401,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. private void tickPassenger(Entity vehicle, Entity passenger) { if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { @@ -13762,17 +11281,17 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f // Paper - EAR 2 final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper -@@ -1453,7 +1586,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1286,7 +1418,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. // Paper start - EAR 2 if (isActive) { passenger.rideTick(); - passenger.postTick(); // CraftBukkit + // Folia start - region threading -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(passenger)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(passenger)) { + // removed from region while ticking + return; + } -+ if (passenger.doPortalLogic()) { ++ if (passenger.handlePortal()) { + // portalled + return; + } @@ -13780,9 +11299,9 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } else { passenger.setDeltaMovement(Vec3.ZERO); passenger.inactiveTick(); -@@ -1542,20 +1684,22 @@ public class ServerLevel extends Level implements WorldGenLevel { - - } else if (close) { chunkproviderserver.close(false); } // Paper - rewrite chunk system +@@ -1381,20 +1522,22 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + } + // Paper end - add close param - // CraftBukkit start - moved from MinecraftServer.saveChunks - ServerLevel worldserver1 = this; @@ -13811,7 +11330,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f this.getChunkSource().getDataStorage().save(async); // Paper - Write SavedData IO async } -@@ -1609,6 +1753,19 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1448,6 +1591,19 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. return list; } @@ -13831,7 +11350,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f @Nullable public ServerPlayer getRandomPlayer() { List list = this.getPlayers(LivingEntity::isAlive); -@@ -1696,8 +1853,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1532,8 +1688,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } else { if (entity instanceof net.minecraft.world.entity.item.ItemEntity itemEntity && itemEntity.getItem().isEmpty()) return false; // Paper - Prevent empty items from being added // Paper start - capture all item additions to the world @@ -13842,7 +11361,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f return true; } // Paper end - capture all item additions to the world -@@ -1852,21 +2009,22 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1684,21 +1840,22 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. @Override public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { @@ -13868,7 +11387,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f while (iterator.hasNext()) { // CraftBukkit start - fix SPIGOT-6362 -@@ -1889,7 +2047,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1721,7 +1878,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } try { @@ -13877,7 +11396,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f iterator = list.iterator(); while (iterator.hasNext()) { -@@ -1898,7 +2056,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1730,7 +1887,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. navigationabstract1.recomputePath(); } } finally { @@ -13886,7 +11405,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } } -@@ -1907,23 +2065,23 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1739,23 +1896,23 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. @Override public void updateNeighborsAt(BlockPos pos, Block sourceBlock) { @@ -13915,7 +11434,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } @Override -@@ -1954,7 +2112,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1786,7 +1943,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. explosion.clearToBlow(); } @@ -13924,7 +11443,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -@@ -1969,25 +2127,28 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1801,25 +1958,28 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. @Override public void blockEvent(BlockPos pos, Block block, int type, int data) { @@ -13959,7 +11478,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } private boolean doBlockEvent(BlockEventData event) { -@@ -1998,12 +2159,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1830,12 +1990,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. @Override public LevelTicks getBlockTicks() { @@ -13974,7 +11493,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } @Nonnull -@@ -2027,7 +2188,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1859,7 +2019,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { // Paper start - Particle API @@ -13983,7 +11502,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } public int sendParticles(List receivers, @Nullable ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { // Paper end - Particle API -@@ -2080,7 +2241,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1912,7 +2072,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. public Entity getEntityOrPart(int id) { Entity entity = (Entity) this.getEntities().get(id); @@ -13999,7 +11518,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } @Nullable -@@ -2135,6 +2303,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1967,6 +2134,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. // Paper start - Call missing map initialize event and set id final DimensionDataStorage storage = this.getServer().overworld().getDataStorage(); @@ -14007,7 +11526,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f final net.minecraft.world.level.saveddata.SavedData existing = storage.cache.get(id.key()); if (existing == null && !storage.cache.containsKey(id.key())) { final MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), id.key()); -@@ -2149,6 +2318,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1981,6 +2149,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } return existing instanceof MapItemSavedData data ? data : null; @@ -14015,7 +11534,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f // Paper end - Call missing map initialize event and set id } -@@ -2198,6 +2368,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2030,6 +2199,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } public boolean setChunkForced(int x, int z, boolean forced) { @@ -14023,7 +11542,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) this.getDataStorage().computeIfAbsent(ForcedChunksSavedData.factory(), "chunks"); ChunkPos chunkcoordintpair = new ChunkPos(x, z); long k = chunkcoordintpair.toLong(); -@@ -2206,7 +2377,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2038,7 +2208,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. if (forced) { flag1 = forcedchunk.getChunks().add(k); if (flag1) { @@ -14032,7 +11551,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } } else { flag1 = forcedchunk.getChunks().remove(k); -@@ -2234,13 +2405,18 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2066,13 +2236,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. BlockPos blockposition1 = pos.immutable(); optional.ifPresent((holder) -> { @@ -14054,7 +11573,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f // Paper start - Remove stale POIs if (optional.isEmpty() && this.getPoiManager().exists(blockposition1, poiType -> true)) { this.getPoiManager().remove(blockposition1); -@@ -2248,7 +2424,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2080,7 +2255,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. // Paper end - Remove stale POIs this.getPoiManager().add(blockposition1, holder); DebugPackets.sendPoiAddedPacket(this, blockposition1); @@ -14068,7 +11587,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f }); } } -@@ -2295,7 +2476,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2127,7 +2307,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. BufferedWriter bufferedwriter = Files.newBufferedWriter(path.resolve("stats.txt")); try { @@ -14077,16 +11596,16 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f NaturalSpawner.SpawnState spawnercreature_d = this.getChunkSource().getLastSpawnState(); if (spawnercreature_d != null) { -@@ -2309,7 +2490,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2141,7 +2321,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } - bufferedwriter.write(String.format(Locale.ROOT, "entities: %s\n", this.entityLookup.getDebugInfo())); // Paper - rewrite chunk system + bufferedwriter.write(String.format(Locale.ROOT, "entities: %s\n", this.moonrise$getEntityLookup().getDebugInfo())); // Paper - rewrite chunk system - bufferedwriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size())); + //bufferedwriter.write(String.format(Locale.ROOT, "block_entity_tickers: %d\n", this.blockEntityTickers.size())); // Folia - region threading bufferedwriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count())); bufferedwriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count())); bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); -@@ -2455,7 +2636,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2287,7 +2467,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. private void dumpBlockEntityTickers(Writer writer) throws IOException { CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); @@ -14095,7 +11614,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f while (iterator.hasNext()) { TickingBlockEntity tickingblockentity = (TickingBlockEntity) iterator.next(); -@@ -2468,7 +2649,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2300,7 +2480,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. @VisibleForTesting public void clearBlockEvents(BoundingBox box) { @@ -14104,7 +11623,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f return box.isInside(blockactiondata.pos()); }); } -@@ -2477,7 +2658,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2309,7 +2489,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. public void blockUpdated(BlockPos pos, Block block) { if (!this.isDebug()) { // CraftBukkit start @@ -14113,44 +11632,18 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f return; } // CraftBukkit end -@@ -2520,9 +2701,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2352,9 +2532,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. @VisibleForTesting public String getWatchdogStats() { -- return String.format(Locale.ROOT, "players: %s, entities: %s [%s], block_entities: %d [%s], block_ticks: %d, fluid_ticks: %d, chunk_source: %s", this.players.size(), this.entityLookup.getDebugInfo(), ServerLevel.getTypeCount(this.entityLookup.getAll(), (entity) -> { // Paper - rewrite chunk system +- return String.format(Locale.ROOT, "players: %s, entities: %s [%s], block_entities: %d [%s], block_ticks: %d, fluid_ticks: %d, chunk_source: %s", this.players.size(), this.moonrise$getEntityLookup().getDebugInfo(), ServerLevel.getTypeCount(this.moonrise$getEntityLookup().getAll(), (entity) -> { // Paper - rewrite chunk system - return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); - }), this.blockEntityTickers.size(), ServerLevel.getTypeCount(this.blockEntityTickers, TickingBlockEntity::getType), this.getBlockTicks().count(), this.getFluidTicks().count(), this.gatherChunkSourceStats()); + return "region threading"; // Folia - region threading } private static String getTypeCount(Iterable items, Function classifier) { -@@ -2555,6 +2734,12 @@ public class ServerLevel extends Level implements WorldGenLevel { - public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) { - // CraftBukkit end - BlockPos blockposition = ServerLevel.END_SPAWN_POINT; -+ // Folia start - region threading -+ makeObsidianPlatform(worldserver, entity, blockposition); -+ } -+ -+ public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity, BlockPos blockposition) { -+ // Folia end - region threading - int i = blockposition.getX(); - int j = blockposition.getY() - 2; - int k = blockposition.getZ(); -@@ -2567,11 +2752,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockposition1) -> { - blockList.setBlock(blockposition1, Blocks.OBSIDIAN.defaultBlockState(), 3); - }); -- org.bukkit.World bworld = worldserver.getWorld(); -- org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); -- -- worldserver.getCraftServer().getPluginManager().callEvent(portalEvent); -- if (!portalEvent.isCancelled()) { -+ if (true) { // Folia - region threading - blockList.updateList(); - } - // CraftBukkit end -@@ -2592,17 +2773,18 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2404,17 +2582,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } public void startTickingChunk(LevelChunk chunk) { @@ -14174,16 +11667,16 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } @Override -@@ -2624,7 +2806,7 @@ public class ServerLevel extends Level implements WorldGenLevel { - // Paper end - rewrite chunk system +@@ -2434,7 +2613,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + return this.moonrise$getAnyChunkIfLoaded(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkPos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkPos)) != null; // Paper - rewrite chunk system } - private boolean isPositionTickingWithEntitiesLoaded(long chunkPos) { + public boolean isPositionTickingWithEntitiesLoaded(long chunkPos) { // Folia - region threaded - make public - // Paper start - optimize is ticking ready type functions - io.papermc.paper.chunk.system.scheduling.NewChunkHolder chunkHolder = this.chunkTaskScheduler.chunkHolderManager.getChunkHolder(chunkPos); + // Paper start - rewrite chunk system + final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkPos); // isTicking implies the chunk is loaded, and the chunk is loaded now implies the entities are loaded -@@ -2684,7 +2866,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2494,7 +2673,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. // Paper start - optimize redstone (Alternate Current) @Override public alternate.current.wire.WireHandler getWireHandler() { @@ -14192,7 +11685,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } // Paper end - optimize redstone (Alternate Current) -@@ -2695,16 +2877,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2505,16 +2684,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. public void onCreated(Entity entity) {} public void onDestroyed(Entity entity) { @@ -14212,7 +11705,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f // Paper start - Reset pearls when they stop being ticked if (paperConfig().fixes.disableUnloadedChunkEnderpearlExploit && entity instanceof net.minecraft.world.entity.projectile.ThrownEnderpearl pearl) { pearl.cachedOwner = null; -@@ -2715,6 +2897,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2525,6 +2704,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. public void onTrackingStart(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot @@ -14220,7 +11713,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true if (entity instanceof ServerPlayer entityplayer) { ServerLevel.this.players.add(entityplayer); -@@ -2728,7 +2911,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2538,7 +2718,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -14229,7 +11722,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } if (entity instanceof EnderDragon entityenderdragon) { -@@ -2738,7 +2921,9 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2548,7 +2728,9 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -14239,7 +11732,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } } -@@ -2760,16 +2945,24 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2570,16 +2752,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. public void onTrackingEnd(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot @@ -14265,7 +11758,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f map.carriedByPlayers.remove( (Player) entity ); for ( Iterator iter = (Iterator) map.carriedBy.iterator(); iter.hasNext(); ) { -@@ -2779,6 +2972,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2589,6 +2779,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. iter.remove(); } } @@ -14273,7 +11766,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } } } ); -@@ -2809,7 +3003,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2619,7 +2810,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -14282,7 +11775,7 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f } if (entity instanceof EnderDragon entityenderdragon) { -@@ -2819,13 +3013,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2629,13 +2820,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -14300,11 +11793,19 @@ index ca56a0b596976448da6bb2a0e82b3d5cd4133e12..559b6d0e3611b506ff10e5ae7c42b35f for (ServerPlayer player : ServerLevel.this.players) { player.getBukkitEntity().onEntityRemove(entity); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55aeb84120 100644 +index 5980b70e2d7273239245237189b2debcbccfbac3..436b3c5bf8b524efef4f2c065813764a83ed0f45 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -199,7 +199,7 @@ import org.bukkit.inventory.MainHand; - public class ServerPlayer extends Player { +@@ -15,6 +15,7 @@ import java.util.Objects; + import java.util.Optional; + import java.util.OptionalInt; + import java.util.Set; ++import java.util.function.Consumer; + import java.util.stream.Collectors; + import javax.annotation.Nullable; + import net.minecraft.ChatFormatting; +@@ -203,7 +204,7 @@ import org.bukkit.inventory.MainHand; + public class ServerPlayer extends net.minecraft.world.entity.player.Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system private static final Logger LOGGER = LogUtils.getLogger(); - public long lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving @@ -14312,31 +11813,21 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; private static final int FLY_STAT_RECORDING_SPEED = 25; -@@ -497,51 +497,151 @@ public class ServerPlayer extends Player { +@@ -483,8 +484,153 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple } // CraftBukkit end -- public void fudgeSpawnLocation(ServerLevel world) { -- BlockPos blockposition = world.getSharedSpawnPos(); + // Folia start - region threading + private static final int SPAWN_RADIUS_SELECTION_SEARCH = 5; - -- if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit -- int i = Math.max(0, this.server.getSpawnRadius(world)); -- int j = Mth.floor(world.getWorldBorder().getDistanceToBorder((double) blockposition.getX(), (double) blockposition.getZ())); ++ + private static BlockPos getRandomSpawn(ServerLevel world, RandomSource random) { + BlockPos spawn = world.getSharedSpawnPos(); + double radius = (double)Math.max(0, world.getGameRules().getInt(GameRules.RULE_SPAWN_RADIUS)); - -- if (j < i) { -- i = j; -- } ++ + double spawnX = (double)spawn.getX() + 0.5; + double spawnZ = (double)spawn.getZ() + 0.5; - -- if (j <= 1) { -- i = 1; -+ WorldBorder worldBorder = world.getWorldBorder(); ++ ++ net.minecraft.world.level.border.WorldBorder worldBorder = world.getWorldBorder(); + + double selectMinX = Math.max(worldBorder.getMinX() + 1.0, spawnX - radius); + double selectMinZ = Math.max(worldBorder.getMinZ() + 1.0, spawnZ - radius); @@ -14368,46 +11859,33 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + + AABB checkVolume = player.getBoundingBoxAt((double)inChunk.getX() + 0.5, (double)inChunk.getY(), (double)inChunk.getZ() + 0.5); + -+ if (!world.noCollision(player, checkVolume, true)) { ++ if (!world.noCollision(player, checkVolume)) { + continue; + } + + return inChunk; - } ++ } + } - -- long k = (long) (i * 2 + 1); -- long l = k * k; -- int i1 = l > 2147483647L ? Integer.MAX_VALUE : (int) l; -- int j1 = this.getCoprime(i1); -- int k1 = RandomSource.create().nextInt(i1); ++ + return null; + } - -- for (int l1 = 0; l1 < i1; ++l1) { -- int i2 = (k1 + j1 * l1) % i1; -- int j2 = i2 % (i * 2 + 1); -- int k2 = i2 / (i * 2 + 1); -- BlockPos blockposition1 = PlayerRespawnLogic.getOverworldRespawnPos(world, blockposition.getX() + j2 - i, blockposition.getZ() + k2 - i); ++ + // rets false when another attempt is required + private static boolean trySpawnOrSchedule(ServerLevel world, ServerPlayer player, RandomSource random, int[] attemptCount, int maxAttempts, + ca.spottedleaf.concurrentutil.completable.Completable toComplete) { + ++attemptCount[0]; - -- if (blockposition1 != null) { -- this.moveTo(blockposition1, world.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored -- if (world.noCollision(this, this.getBoundingBox(), true)) { // Paper - make sure this loads chunks, we default to NOT loading now -- break; ++ + BlockPos rough = getRandomSpawn(world, random); + -+ int minX = (rough.getX() - SPAWN_RADIUS_SELECTION_SEARCH) >> 4; -+ int minZ = (rough.getZ() - SPAWN_RADIUS_SELECTION_SEARCH) >> 4; -+ int maxX = (rough.getX() + SPAWN_RADIUS_SELECTION_SEARCH) >> 4; -+ int maxZ = (rough.getZ() + SPAWN_RADIUS_SELECTION_SEARCH) >> 4; ++ // add 2 to ensure that the chunks are loaded for collision checks ++ int minX = (rough.getX() - (SPAWN_RADIUS_SELECTION_SEARCH + 2)) >> 4; ++ int minZ = (rough.getZ() - (SPAWN_RADIUS_SELECTION_SEARCH + 2)) >> 4; ++ int maxX = (rough.getX() + (SPAWN_RADIUS_SELECTION_SEARCH + 2)) >> 4; ++ int maxZ = (rough.getZ() + (SPAWN_RADIUS_SELECTION_SEARCH + 2)) >> 4; + + // we could short circuit this check, but it would possibly recurse. Then, it could end up causing a stack overflow -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(world, minX, minZ, maxX, maxZ) || !world.isAreaLoaded(minX, minZ, maxX, maxZ)) { -+ world.loadChunksAsync(minX, maxX, minZ, maxZ, ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world, minX, minZ, maxX, maxZ) || !world.isAreaLoaded(minX, minZ, maxX, maxZ)) { ++ world.moonrise$loadChunksAsync(minX, maxX, minZ, maxZ, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, + (unused) -> { + BlockPos selected = findSpawnAround(world, player, rough); @@ -14415,20 +11893,15 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + // run more spawn attempts + selectSpawn(world, player, random, attemptCount, maxAttempts, toComplete); + return; - } ++ } + + completeSpawn(world, selected, toComplete); + return; - } -- } -- } else { -- this.moveTo(blockposition, world.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored ++ } + ); + return true; + } - -- while (!world.noCollision(this, this.getBoundingBox(), true) && this.getY() < (double) (world.getMaxBuildHeight() - 1)) { // Paper - make sure this loads chunks, we default to NOT loading now -- this.setPos(this.getX(), this.getY() + 1.0D, this.getZ()); ++ + BlockPos selected = findSpawnAround(world, player, rough); + if (selected == null) { + return false; @@ -14448,7 +11921,7 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + LOGGER.warn("Found no spawn in radius for player '" + player.getName() + "', ignoring radius"); + + // this call requires to return a location with loaded chunks, so we need to schedule a load here -+ io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad( ++ ca.spottedleaf.moonrise.common.util.ChunkSystem.scheduleChunkLoad( + world, selected.getX() >> 4, selected.getZ() >> 4, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + true, ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, + (unused) -> { @@ -14456,52 +11929,52 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + } + ); + return; - } ++ } + } while (!trySpawnOrSchedule(world, player, random, attemptCount, maxAttempts, toComplete)); + } -+ // Folia end - region threading + + public static void fudgeSpawnLocation(ServerLevel world, ServerPlayer player, ca.spottedleaf.concurrentutil.completable.Completable toComplete) { // Folia - region threading + BlockPos blockposition = world.getSharedSpawnPos(); + + if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit -+ // Folia start - region threading + selectSpawn(world, player, player.random, new int[1], 500, toComplete); -+ // Folia end - region threading + } else { -+ // Folia start - region threading + world.loadChunksForMoveAsync(player.getBoundingBoxAt(blockposition.getX() + 0.5, blockposition.getY(), blockposition.getZ() + 0.5), + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, + (c) -> { + BlockPos ret = blockposition; -+ while (!world.noCollision(player, player.getBoundingBoxAt(ret.getX() + 0.5, ret.getY(), ret.getZ() + 0.5), true) && ret.getY() < (double) (world.getMaxBuildHeight() - 1)) { // Paper - make sure this loads chunks, we default to NOT loading now ++ while (!world.noCollision(player, player.getBoundingBoxAt(ret.getX() + 0.5, ret.getY(), ret.getZ() + 0.5)) && ret.getY() < (double) (world.getMaxBuildHeight() - 1)) { // Paper - make sure this loads chunks, we default to NOT loading now + ret = ret.above(); + } ++ while (world.noCollision(player, player.getBoundingBoxAt(ret.getX() + 0.5, ret.getY() - 1, ret.getZ() + 0.5)) && ret.getY() > (double) (world.getMaxBuildHeight() + 1)) { // Paper - make sure this loads chunks, we default to NOT loading now ++ ret = ret.below(); ++ } + toComplete.complete(io.papermc.paper.util.MCUtil.toLocation(world, Vec3.atBottomCenterOf(ret), world.levelData.getSpawnAngle(), 0.0f)); + } + ); -+ // Folia end - region threading - } - - } - -- private int getCoprime(int horizontalSpawnArea) { -+ // Folia start - region threading -+ public final java.util.Set pendingTpas = java.util.concurrent.ConcurrentHashMap.newKeySet(); ++ } ++ ++ } + // Folia end - region threading + -+ private static int getCoprime(int horizontalSpawnArea) { // Folia - region threading - not static - return horizontalSpawnArea <= 16 ? horizontalSpawnArea - 1 : 17; - } + @Override + public BlockPos adjustSpawnLocation(ServerLevel world, BlockPos basePos) { ++ // Folia start - region threading ++ if (true) { ++ throw new UnsupportedOperationException(); ++ } ++ // Folia end - region threading + AABB axisalignedbb = this.getDimensions(Pose.STANDING).makeBoundingBox(Vec3.ZERO); + BlockPos blockposition1 = basePos; + +@@ -1321,6 +1467,332 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple -@@ -1247,6 +1347,337 @@ public class ServerPlayer extends Player { - } } + // Folia start - region threading + /** + * Teleport flag indicating that the player is to be respawned, expected to only be used -+ * internally for {@link #respawn(java.util.function.Consumer)}. ++ * internally for {@link #respawn(Consumer, PlayerRespawnEvent.RespawnReason)} + */ + public static final long TELEPORT_FLAGS_PLAYER_RESPAWN = Long.MIN_VALUE >>> 0; + /** @@ -14513,7 +11986,7 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + public static final long TELEPORT_FLAGS_AVOID_SUFFOCATION = Long.MIN_VALUE >>> 1; + + private void avoidSuffocation() { -+ while (!this.level().noCollision(this, this.getBoundingBox(), true) && this.getY() < (double)this.level().getMaxBuildHeight()) { // Folia - make sure this loads chunks, we default to NOT loading now ++ while (!this.level().noCollision(this, this.getBoundingBox()) && this.getY() < (double)this.level().getMaxBuildHeight()) { + this.setPos(this.getX(), this.getY() + 1.0D, this.getZ()); + } + } @@ -14527,15 +12000,15 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + + this.respawn((player) -> { + CriteriaTriggers.CHANGED_DIMENSION.trigger(player, Level.END, Level.OVERWORLD); -+ }, true); ++ }, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.END_PORTAL, true); + } + -+ public void respawn(java.util.function.Consumer respawnComplete) { -+ this.respawn(respawnComplete, false); ++ public void respawn(java.util.function.Consumer respawnComplete, PlayerRespawnEvent.RespawnReason reason) { ++ this.respawn(respawnComplete, reason, false); + } + -+ private void respawn(java.util.function.Consumer respawnComplete, boolean alive) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot respawn entity async"); ++ private void respawn(java.util.function.Consumer respawnComplete, PlayerRespawnEvent.RespawnReason reason, boolean alive) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot respawn entity async"); + + this.getBukkitEntity(); // force bukkit entity to be created before TPing + @@ -14621,10 +12094,10 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + // load chunk for block + // give at least 1 radius of loaded chunks so that we do not sync load anything + int radiusBlocks = 16; -+ respawnWorld.loadChunksAsync(respawnPos, radiusBlocks, ++ respawnWorld.moonrise$loadChunksAsync(respawnPos, radiusBlocks, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, + (chunks) -> { -+ Vec3 spawnPos = findRespawnPositionAndUseSpawnBlock( ++ ServerPlayer.RespawnPosAngle spawnPos = ServerPlayer.findRespawnAndUseSpawnBlock( + respawnWorld, respawnPos, respawnAngle, isRespawnForced, alive + ).orElse(null); + if (spawnPos == null) { @@ -14641,21 +12114,10 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + return; + } + -+ boolean isRespawnAnchor = respawnWorld.getBlockState(respawnPos).is(Blocks.RESPAWN_ANCHOR); ++ boolean isRespawnAnchor = respawnWorld.getBlockState(respawnPos).is(net.minecraft.world.level.block.Blocks.RESPAWN_ANCHOR); + boolean isBed = respawnWorld.getBlockState(respawnPos).is(net.minecraft.tags.BlockTags.BEDS); + usedRespawnAnchor[0] = !alive && isRespawnAnchor; + -+ // determine angle -+ float locAngle; -+ if (!isBed && !isRespawnAnchor) { -+ // something else -+ locAngle = respawnAngle; -+ } else { -+ // select angle in direction of the difference applied to respawn pos? -+ Vec3 vec3d1 = Vec3.atBottomCenterOf(respawnPos).subtract(spawnPos).normalize(); -+ -+ locAngle = (float)Mth.wrapDegrees(Mth.atan2(vec3d1.z, vec3d1.x) * 57.2957763671875D - 90.0D); -+ } + ServerPlayer.this.setRespawnPosition( + respawnWorld.dimension(), respawnPos, respawnAngle, isRespawnForced, false, + com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.PLAYER_RESPAWN @@ -14663,7 +12125,7 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + + // finished now, pass the location on + spawnPosComplete.complete( -+ io.papermc.paper.util.MCUtil.toLocation(respawnWorld, spawnPos, locAngle, 0.0f) ++ io.papermc.paper.util.MCUtil.toLocation(respawnWorld, spawnPos.position(), spawnPos.yaw(), 0.0f) + ); + return; + } @@ -14672,7 +12134,7 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + } + + @Override -+ protected void teleportSyncSameRegion(Vec3 pos, Float yaw, Float pitch, Vec3 speedDirectionUpdate) { ++ protected void teleportSyncSameRegion(Vec3 pos, Float yaw, Float pitch, Vec3 velocity) { + if (yaw != null) { + this.setYRot(yaw.floatValue()); + this.setYHeadRot(yaw.floatValue()); @@ -14680,8 +12142,8 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + if (pitch != null) { + this.setXRot(pitch.floatValue()); + } -+ if (speedDirectionUpdate != null) { -+ this.setDeltaMovement(speedDirectionUpdate.normalize().scale(this.getDeltaMovement().length())); ++ if (velocity != null) { ++ this.setDeltaMovement(velocity); + } + this.connection.internalTeleport(pos.x, pos.y, pos.z, this.getYRot(), this.getXRot(), java.util.Collections.emptySet()); + this.connection.resetPosition(); @@ -14689,13 +12151,13 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + } + + @Override -+ protected ServerPlayer transformForAsyncTeleport(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 speedDirectionUpdate) { ++ protected ServerPlayer transformForAsyncTeleport(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 velocity) { + // must be manually removed from connections + this.serverLevel().getCurrentWorldData().connections.remove(this.connection.connection); + this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); + + this.spawnIn(destination); -+ this.transform(pos, yaw, pitch, speedDirectionUpdate); ++ this.transform(pos, yaw, pitch, velocity); + + return this; + } @@ -14793,6 +12255,12 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobEffect, false)); + } + ++ // Paper start - Reset shield blocking on dimension change ++ if (this.isBlocking()) { ++ this.stopUsingItem(); ++ } ++ // Paper end - Reset shield blocking on dimension change ++ + this.triggerDimensionChangeTriggers(originWorld); + + // finished @@ -14802,11 +12270,11 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + } + + @Override -+ public boolean endPortalLogicAsync() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); ++ public boolean endPortalLogicAsync(BlockPos portalPos) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); + + if (this.level().getTypeKey() == LevelStem.END) { -+ if (!this.canPortalAsync(false)) { ++ if (!this.canPortalAsync(null, false)) { + return false; + } + this.wonGame = true; @@ -14816,7 +12284,7 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + this.exitEndCredits(); + return true; + } else { -+ return super.endPortalLogicAsync(); ++ return super.endPortalLogicAsync(portalPos); + } + } + @@ -14831,25 +12299,13 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 + @Nullable @Override - public Entity changeDimension(ServerLevel destination) { -@@ -1256,6 +1687,11 @@ public class ServerPlayer extends Player { - - @Nullable - public Entity changeDimension(ServerLevel worldserver, PlayerTeleportEvent.TeleportCause cause) { -+ // Folia start - region threading -+ if (true) { -+ throw new UnsupportedOperationException("Must use teleportAsync while in region threading"); -+ } -+ // Folia end - region threading - // CraftBukkit end - if (this.isSleeping()) return this; // CraftBukkit - SPIGOT-3154 - // this.isChangingDimension = true; // CraftBukkit - Moved down and into PlayerList#changeDimension -@@ -2325,6 +2761,12 @@ public class ServerPlayer extends Player { + public Entity changeDimension(DimensionTransition teleportTarget) { +@@ -2366,6 +2838,12 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple public void setCamera(@Nullable Entity entity) { Entity entity1 = this.getCamera(); + // Folia start - region threading -+ if (entity != null && !io.papermc.paper.util.TickThread.isTickThreadFor(entity)) { ++ if (entity != null && !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) { + return; + } + // Folia end - region threading @@ -14857,7 +12313,7 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 this.camera = (Entity) (entity == null ? this : entity); if (entity1 != this.camera) { // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity -@@ -2848,7 +3290,7 @@ public class ServerPlayer extends Player { +@@ -2919,7 +3397,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.experienceLevel = this.newLevel; this.totalExperience = this.newTotalExp; this.experienceProgress = 0; @@ -14867,28 +12323,28 @@ index 6a4637eef14cbd84bbe26ef16f004b8f93367a3d..337763efee2c62721ec1320bd749ab55 this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); this.effectsDirty = true; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index 1047027610624c9ba4bb5afd5d7f0714a062b198..2fec6e3594b5946077102ca4abded9c2fc301f89 100644 +index cc01ead133cc6859ca5d7a1d0ac3c12955e590da..41fe0aeb3b74499ebce944fd43c3b4e9aec8b821 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -131,7 +131,7 @@ public class ServerPlayerGameMode { +@@ -133,7 +133,7 @@ public class ServerPlayerGameMode { BlockState iblockdata; if (this.hasDelayedDestroy) { - iblockdata = this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper - Don't allow digging into unloaded chunks -+ iblockdata = !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.delayedDestroyPos) ? null : this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper - Don't allow digging into unloaded chunks // Folia - region threading - don't destroy blocks not owned ++ iblockdata = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, this.delayedDestroyPos) ? null : this.level.getBlockStateIfLoaded(this.delayedDestroyPos); // Paper - Don't allow digging into unloaded chunks // Folia - region threading - don't destroy blocks not owned if (iblockdata == null || iblockdata.isAir()) { // Paper - Don't allow digging into unloaded chunks this.hasDelayedDestroy = false; } else { -@@ -144,7 +144,7 @@ public class ServerPlayerGameMode { +@@ -146,7 +146,7 @@ public class ServerPlayerGameMode { } } else if (this.isDestroyingBlock) { // Paper start - Don't allow digging into unloaded chunks; don't want to do same logic as above, return instead - iblockdata = this.level.getBlockStateIfLoaded(this.destroyPos); -+ iblockdata = !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.destroyPos) ? null : this.level.getBlockStateIfLoaded(this.destroyPos); ++ iblockdata = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, this.destroyPos) ? null : this.level.getBlockStateIfLoaded(this.destroyPos); if (iblockdata == null) { this.isDestroyingBlock = false; return; -@@ -419,7 +419,7 @@ public class ServerPlayerGameMode { +@@ -424,7 +424,7 @@ public class ServerPlayerGameMode { } else { // CraftBukkit start org.bukkit.block.BlockState state = bblock.getState(); @@ -14897,7 +12353,7 @@ index 1047027610624c9ba4bb5afd5d7f0714a062b198..2fec6e3594b5946077102ca4abded9c2 // CraftBukkit end BlockState iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player); boolean flag = this.level.removeBlock(pos, false); -@@ -447,8 +447,8 @@ public class ServerPlayerGameMode { +@@ -452,8 +452,8 @@ public class ServerPlayerGameMode { // return true; // CraftBukkit } // CraftBukkit start @@ -14908,123 +12364,32 @@ index 1047027610624c9ba4bb5afd5d7f0714a062b198..2fec6e3594b5946077102ca4abded9c2 if (event.isDropItems()) { org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world } -diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -index 8ef22f8f0d6da49247a90152e5cfa9ffc7f596a4..cc274fee6cd0a8b532ea2cf7be2876d9f5a708ee 100644 ---- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -+++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java -@@ -103,10 +103,15 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - this.chunkMap.level.chunkTaskScheduler.radiusAwareScheduler.queueInfiniteRadiusTask(() -> { // Paper - rewrite chunk system - this.theLightEngine.relightChunks(chunks, (ChunkPos chunkPos) -> { - chunkLightCallback.accept(chunkPos); -- ((java.util.concurrent.Executor)((ServerLevel)this.theLightEngine.getWorld()).getChunkSource().mainThreadProcessor).execute(() -> { -+ Runnable run = () -> { // Folia - region threading - ((ServerLevel)this.theLightEngine.getWorld()).getChunkSource().chunkMap.getUpdatingChunkIfPresent(chunkPos.toLong()).broadcast(new net.minecraft.network.protocol.game.ClientboundLightUpdatePacket(chunkPos, ThreadedLevelLightEngine.this, null, null), false); - ((ServerLevel)this.theLightEngine.getWorld()).getChunkSource().removeTicketAtLevel(TicketType.CHUNK_RELIGHT, chunkPos, io.papermc.paper.util.MCUtil.getTicketLevelFor(ChunkStatus.LIGHT), ticketIds.get(chunkPos)); -- }); -+ }; // Folia - region threading -+ // Folia start - region threading -+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueChunkTask( -+ (ServerLevel)this.theLightEngine.getWorld(), chunkPos.x, chunkPos.z, run -+ ); -+ // Folia end - region threading - }, onComplete); - }); - this.tryScheduleUpdate(); -@@ -114,7 +119,7 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - return totalChunks; - } - -- private final Long2IntOpenHashMap chunksBeingWorkedOn = new Long2IntOpenHashMap(); -+ //private final Long2IntOpenHashMap chunksBeingWorkedOn = new Long2IntOpenHashMap(); // Folia - region threading - - private void queueTaskForSection(final int chunkX, final int chunkY, final int chunkZ, - final Supplier runnable) { // Paper - rewrite chunk system -@@ -134,11 +139,16 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - return; - } - -- if (!world.getChunkSource().chunkMap.mainThreadExecutor.isSameThread()) { -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(world, chunkX, chunkZ)) { // Folia - region threading - // ticket logic is not safe to run off-main, re-schedule -- world.getChunkSource().chunkMap.mainThreadExecutor.execute(() -> { -+ Runnable run = () -> { // Folia - region threading - this.queueTaskForSection(chunkX, chunkY, chunkZ, runnable); -- }); -+ }; // Folia - region threading -+ // Folia start - region threading -+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue( -+ world, chunkX, chunkZ, run -+ ); -+ // Folia end - region threading - return; - } - -@@ -157,22 +167,28 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl - } - updateFuture.isTicketAdded = true; - -- final int references = this.chunksBeingWorkedOn.addTo(key, 1); -+ final int references = this.chunkMap.level.getCurrentWorldData().chunksBeingWorkedOn.addTo(key, 1); // Folia - region threading - if (references == 0) { - final ChunkPos pos = new ChunkPos(chunkX, chunkZ); - world.getChunkSource().addRegionTicket(ca.spottedleaf.starlight.common.light.StarLightInterface.CHUNK_WORK_TICKET, pos, 0, pos); - } - -- updateFuture.onComplete.thenAcceptAsync((final Void ignore) -> { -- final int newReferences = this.chunksBeingWorkedOn.get(key); -- if (newReferences == 1) { -- this.chunksBeingWorkedOn.remove(key); -- final ChunkPos pos = new ChunkPos(chunkX, chunkZ); -- world.getChunkSource().removeRegionTicket(ca.spottedleaf.starlight.common.light.StarLightInterface.CHUNK_WORK_TICKET, pos, 0, pos); -- } else { -- this.chunksBeingWorkedOn.put(key, newReferences - 1); -- } -- }, world.getChunkSource().chunkMap.mainThreadExecutor).whenComplete((final Void ignore, final Throwable thr) -> { -+ // Folia start - region threading -+ updateFuture.onComplete.thenAccept((final Void ignore) -> { -+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue( -+ this.chunkMap.level, chunkX, chunkZ, () -> { -+ final int newReferences = this.chunkMap.level.getCurrentWorldData().chunksBeingWorkedOn.get(key); -+ if (newReferences == 1) { -+ this.chunkMap.level.getCurrentWorldData().chunksBeingWorkedOn.remove(key); -+ final ChunkPos pos = new ChunkPos(chunkX, chunkZ); -+ world.getChunkSource().removeRegionTicket(ca.spottedleaf.starlight.common.light.StarLightInterface.CHUNK_WORK_TICKET, pos, 0, pos); -+ } else { -+ this.chunkMap.level.getCurrentWorldData().chunksBeingWorkedOn.put(key, newReferences - 1); -+ } -+ } -+ ); -+ }).whenComplete((final Void ignore, final Throwable thr) -> { -+ // Folia end - region threading - if (thr != null) { - LOGGER.error("Failed to remove ticket level for post chunk task " + new ChunkPos(chunkX, chunkZ), thr); - } diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index 658e63ebde81dc14c8ab5850fb246dc0aab25dea..7e1f15ac8d2f7c86d4aba1be5df717052ffb31f0 100644 +index f56e5c0f53f9b52a9247b9be9265b949494fc924..765cd1eedda2e9aa928db4ac3b0776d154126fe3 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -37,6 +37,14 @@ public class TicketType { - public static final TicketType NON_FULL_SYNC_LOAD = create("non_full_sync_load", Long::compareTo); - public static final TicketType DELAY_UNLOAD = create("delay_unload", Comparator.comparingLong(ChunkPos::toLong), 1); - // Paper end - rewrite chunk system +@@ -25,6 +25,14 @@ public class TicketType { + public static final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); + public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit + public static final TicketType PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit + // Folia start - region threading -+ public static final TicketType LOGIN = create("login", (u1, u2) -> 0, 20); -+ public static final TicketType DELAYED = create("delay", (u1, u2) -> 0, 5); -+ public static final TicketType END_GATEWAY_EXIT_SEARCH = create("end_gateway_exit_search", Long::compareTo); -+ public static final TicketType NETHER_PORTAL_DOUBLE_CHECK = create("nether_portal_double_check", Long::compareTo); -+ public static final TicketType TELEPORT_HOLD_TICKET = create("teleport_hold_ticket", Long::compareTo); -+ public static final TicketType REGION_SCHEDULER_API_HOLD = create("region_scheduler_api_hold", (a, b) -> 0); ++ public static final TicketType LOGIN = create("folia:login", (u1, u2) -> 0, 20); ++ public static final TicketType DELAYED = create("folia:delay", (u1, u2) -> 0, 5); ++ public static final TicketType END_GATEWAY_EXIT_SEARCH = create("folia:end_gateway_exit_search", Long::compareTo); ++ public static final TicketType NETHER_PORTAL_DOUBLE_CHECK = create("folia:nether_portal_double_check", Long::compareTo); ++ public static final TicketType TELEPORT_HOLD_TICKET = create("folia:teleport_hold_ticket", Long::compareTo); ++ public static final TicketType REGION_SCHEDULER_API_HOLD = create("folia:region_scheduler_api_hold", (a, b) -> 0); + // Folia end - region threading public static TicketType create(String name, Comparator argumentComparator) { return new TicketType<>(name, argumentComparator, 0L); diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -index a6c31a558794a6e626e83176a1cbe78b6bd90f6e..b17bb9b9387b9efa5cc7513e36ea896b17712cae 100644 +index 5a8a33638ceb1d980ffc3e6dd86e7eb11dfd9375..67b45f2916fa061e7430c6f3987bdb25ede58c04 100644 --- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java +++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -@@ -87,6 +87,14 @@ public class WorldGenRegion implements WorldGenLevel { - private final AtomicLong subTickCount = new AtomicLong(); - private static final ResourceLocation WORLDGEN_REGION_RANDOM = new ResourceLocation("worldgen_region_random"); +@@ -115,6 +115,14 @@ public class WorldGenRegion implements WorldGenLevel { + } + // Paper end - rewrite chunk system + // Folia start - region threading + private final net.minecraft.world.level.StructureManager structureManager; @@ -15034,22 +12399,22 @@ index a6c31a558794a6e626e83176a1cbe78b6bd90f6e..b17bb9b9387b9efa5cc7513e36ea896b + } + // Folia end - region threading + - public WorldGenRegion(ServerLevel world, List chunks, ChunkStatus status, int placementRadius) { - this.generatingStatus = status; - this.writeRadiusCutoff = placementRadius; -@@ -106,6 +114,7 @@ public class WorldGenRegion implements WorldGenLevel { - this.biomeManager = new BiomeManager(this, BiomeManager.obfuscateSeed(this.seed)); - this.firstPos = ((ChunkAccess) chunks.get(0)).getPos(); - this.lastPos = ((ChunkAccess) chunks.get(chunks.size() - 1)).getPos(); -+ this.structureManager = world.structureManager().forWorldGenRegion(this); // Folia - region threading - } + public WorldGenRegion(ServerLevel world, StaticCache2D chunks, ChunkStep generationStep, ChunkAccess centerPos) { + this.generatingStep = generationStep; + this.cache = chunks; +@@ -125,6 +133,7 @@ public class WorldGenRegion implements WorldGenLevel { + this.random = world.getChunkSource().randomState().getOrCreateRandomFactory(WorldGenRegion.WORLDGEN_REGION_RANDOM).at(this.center.getPos().getWorldPosition()); + this.dimensionType = world.dimensionType(); + this.biomeManager = new BiomeManager(this, BiomeManager.obfuscateSeed(this.seed)); ++ this.structureManager = world.structureManager().forWorldGenRegion(this); // Folia - region threading } + public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) { diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index 308aef9c4933b2bcdd622a34b68efab4a220fe4d..f907dbb55369395058091dd75ae435d2025d94dd 100644 +index b43f87ff4b9853b5d4bbea5ff9686d64d9d0d26b..d766bb360eb98bab1e067cad032b54fa6455f386 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -@@ -107,6 +107,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -108,6 +108,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } @@ -15058,11 +12423,11 @@ index 308aef9c4933b2bcdd622a34b68efab4a220fe4d..f907dbb55369395058091dd75ae435d2 + // Folia end - region threading + @Override - public void onDisconnect(Component reason) { + public void onDisconnect(DisconnectionDetails info) { // Paper start - Fix kick event leave message not being sent -@@ -114,10 +118,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -115,10 +119,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } - public void onDisconnect(Component reason, @Nullable net.kyori.adventure.text.Component quitMessage) { + public void onDisconnect(DisconnectionDetails info, @Nullable net.kyori.adventure.text.Component quitMessage) { // Paper end - Fix kick event leave message not being sent + // Folia start - region threading + if (this.handledDisconnect) { @@ -15079,19 +12444,19 @@ index 308aef9c4933b2bcdd622a34b68efab4a220fe4d..f907dbb55369395058091dd75ae435d2 } -@@ -131,9 +143,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -132,9 +144,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack this.keepAlivePending = false; } else if (!this.isSingleplayerOwner()) { // Paper start - This needs to be handled on the main thread for plugins - server.submit(() -> { + // Folia - region threading - do not schedule to main anymore, there is no main - this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause + this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause - }); + // Folia - region threading - do not schedule to main anymore, there is no main // Paper end - This needs to be handled on the main thread for plugins } -@@ -348,24 +360,8 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -346,24 +358,8 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack if (this.processedDisconnect) { return; } @@ -15099,7 +12464,7 @@ index 308aef9c4933b2bcdd622a34b68efab4a220fe4d..f907dbb55369395058091dd75ae435d2 - Waitable waitable = new Waitable() { - @Override - protected Object evaluate() { -- ServerCommonPacketListenerImpl.this.disconnect(reason, cause); // Paper - adventure +- ServerCommonPacketListenerImpl.this.disconnect(disconnectionInfo, cause); // Paper - kick event causes - return null; - } - }; @@ -15113,8 +12478,8 @@ index 308aef9c4933b2bcdd622a34b68efab4a220fe4d..f907dbb55369395058091dd75ae435d2 - } catch (ExecutionException e) { - throw new RuntimeException(e); - } -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.player)) { // Folia - region threading -+ this.connection.disconnectSafely(io.papermc.paper.adventure.PaperAdventure.asVanilla(reason), cause); // Folia - region threading - it HAS to be delayed/async to avoid deadlock if we try to wait for another region ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.player)) { // Folia - region threading ++ this.connection.disconnectSafely(disconnectionInfo.reason(), cause); // Folia - region threading - it HAS to be delayed/async to avoid deadlock if we try to wait for another region return; } @@ -15128,10 +12493,10 @@ index 308aef9c4933b2bcdd622a34b68efab4a220fe4d..f907dbb55369395058091dd75ae435d2 protected boolean isSingleplayerOwner() { diff --git a/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java -index e4086bea596e5f5d71491e0b7ad650d76939b8f9..5de4b707c9bf512649924a99afed55d657d03c44 100644 +index 880e5c52746e9e3a9a1f42ec6461be54e3ee136c..34c7fbf154c42d07b3b317b13632243a81904e3c 100644 --- a/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java -@@ -46,6 +46,7 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis +@@ -54,6 +54,7 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis private ClientInformation clientInformation; @Nullable private SynchronizeRegistriesTask synchronizeRegistriesTask; @@ -15139,7 +12504,7 @@ index e4086bea596e5f5d71491e0b7ad650d76939b8f9..5de4b707c9bf512649924a99afed55d6 // CraftBukkit start public ServerConfigurationPacketListenerImpl(MinecraftServer minecraftserver, Connection networkmanager, CommonListenerCookie commonlistenercookie, ServerPlayer player) { -@@ -150,7 +151,58 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis +@@ -170,7 +171,58 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis ServerPlayer entityplayer = playerlist.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit @@ -15164,7 +12529,7 @@ index e4086bea596e5f5d71491e0b7ad650d76939b8f9..5de4b707c9bf512649924a99afed55d6 + world.getChunkSource().addTicketAtLevel( + net.minecraft.server.level.TicketType.LOGIN, + new net.minecraft.world.level.ChunkPos(chunkX, chunkZ), -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.FULL_LOADED_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.FULL_LOADED_TICKET_LEVEL, + net.minecraft.util.Unit.INSTANCE + ); + @@ -15228,7 +12593,7 @@ index 8aff5129f85ab5729b3da2e465871be62d15bdf2..8044271ff01dfc6808f5a3b60be74f6d Collections.shuffle( this.connections ); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c2199052f19 100644 +index 624b80c796e9c95040d71d1595d11f98e2899cf3..73057c695addefd9c8fa0949743803fdeab60dda 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -300,7 +300,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl @@ -15318,18 +12683,15 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 ++this.receivedMovePacketCount; int i = this.receivedMovePacketCount - this.knownMovePacketCount; -@@ -607,7 +634,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -606,16 +633,24 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } entity.absMoveTo(d3, d4, d5, f, f1); - this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + //this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit // Folia - move to repositionAllPassengers + boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); - // Paper start - optimise out extra getCubes - boolean teleportBack = flag2; // violating this is always a fail -@@ -620,11 +647,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - if (teleportBack) { // Paper end - optimise out extra getCubes + if (flag && (flag2 || !flag3)) { entity.absMoveTo(d0, d1, d2, f, f1); - this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + //this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit // Folia - not needed, the player is no longer updated @@ -15348,7 +12710,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 // CraftBukkit start - fire PlayerMoveEvent Player player = this.getCraftPlayer(); if (!this.hasMoved) { -@@ -664,7 +699,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -655,7 +690,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { @@ -15357,7 +12719,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 return; } -@@ -672,7 +707,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -663,7 +698,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. // We only do this if the Event was not cancelled. if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { @@ -15366,7 +12728,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 return; } -@@ -788,7 +823,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -757,7 +792,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async // CraftBukkit start if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper - configurable tab spam limits @@ -15375,7 +12737,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 return; } // CraftBukkit end -@@ -800,7 +835,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -769,7 +804,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper start final int index; if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) { @@ -15384,7 +12746,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 return; } // Paper end -@@ -825,7 +860,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -794,7 +829,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // This needs to be on main @@ -15393,38 +12755,21 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 } else if (!completions.isEmpty()) { final com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); -@@ -1165,7 +1200,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - int byteLength = testString.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; - if (byteLength > 256 * 4) { - ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send a book with with a page too large!"); -- server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause -+ this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Folia - region threading - return; - } - byteTotal += byteLength; -@@ -1188,17 +1223,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - - if (byteTotal > byteAllowed) { - ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send too large of a book. Book Size: " + byteTotal + " - Allowed: "+ byteAllowed + " - Pages: " + pageList.size()); -- server.scheduleOnMain(() -> this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause -+ this.disconnect("Book too large!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Folia - region threading - return; - } +@@ -1163,11 +1198,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // Paper end - Book size limits // CraftBukkit start - if (this.lastBookTick + 20 > MinecraftServer.currentTick) { -- server.scheduleOnMain(() -> this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION)); // Paper - kick event cause // Paper - Also ensure this is called on main -+ if (this.lastBookTick + 20 > this.lastTick) { -+ this.disconnect("Book edited too quickly!", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - Also ensure this is called on main // Folia - region threading ++ if (this.lastBookTick + 20 > this.lastTick) { // Folia - region threading + this.disconnect(Component.literal("Book edited too quickly!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause return; } - this.lastBookTick = MinecraftServer.currentTick; -+ this.lastBookTick = this.lastTick; ++ this.lastBookTick = this.lastTick; // Folia - region threading // CraftBukkit end int i = packet.slot(); -@@ -1218,7 +1253,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1187,7 +1222,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.updateBookContents(list1, i); }; @@ -15445,7 +12790,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 } } -@@ -1374,9 +1421,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1335,9 +1382,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl int i = this.receivedMovePacketCount - this.knownMovePacketCount; // CraftBukkit start - handle custom speeds and skipped ticks @@ -15458,7 +12803,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 if (i > Math.max(this.allowedPlayerTicks, 5)) { ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); -@@ -1568,7 +1616,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1518,7 +1566,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { @@ -15467,7 +12812,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 return; } -@@ -1576,7 +1624,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1526,7 +1574,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. // We only do this if the Event was not cancelled. if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { @@ -15476,7 +12821,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 return; } -@@ -1803,9 +1851,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1743,9 +1791,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (!this.player.isSpectator()) { // limit how quickly items can be dropped // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. @@ -15488,25 +12833,25 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 } else { // Else we increment the drop count and check the amount. this.dropCount++; -@@ -1833,7 +1881,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1773,7 +1821,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl case ABORT_DESTROY_BLOCK: case STOP_DESTROY_BLOCK: // Paper start - Don't allow digging into unloaded chunks - if (this.player.level().getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.player.serverLevel(), blockposition.getX() >> 4, blockposition.getZ() >> 4, 8) || this.player.level().getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { // Folia - region threading - don't destroy blocks not owned ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.player.serverLevel(), blockposition.getX() >> 4, blockposition.getZ() >> 4, 8) || this.player.level().getChunkIfLoadedImmediately(blockposition.getX() >> 4, blockposition.getZ() >> 4) == null) { // Folia - region threading - don't destroy blocks not owned this.player.connection.ackBlockChangesUpTo(packet.getSequence()); return; } -@@ -1916,7 +1964,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1856,7 +1904,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper end - improve distance check BlockPos blockposition = movingobjectpositionblock.getBlockPos(); - if (this.player.canInteractWithBlock(blockposition, 1.0D)) { -+ if (io.papermc.paper.util.TickThread.isTickThreadFor(this.player.serverLevel(), blockposition.getX() >> 4, blockposition.getZ() >> 4, 8) && this.player.canInteractWithBlock(blockposition, 1.0D)) { // Folia - do not allow players to interact with blocks outside the current region ++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.player.serverLevel(), blockposition.getX() >> 4, blockposition.getZ() >> 4, 8) && this.player.canInteractWithBlock(blockposition, 1.0D)) { // Folia - do not allow players to interact with blocks outside the current region Vec3 vec3d1 = vec3d.subtract(Vec3.atCenterOf(blockposition)); double d0 = 1.0000001D; -@@ -2033,7 +2081,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1978,7 +2026,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl Entity entity = packet.getEntity(worldserver); if (entity != null) { @@ -15515,16 +12860,16 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 return; } } -@@ -2068,7 +2116,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2013,7 +2061,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // CraftBukkit end - ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), reason.getString()); + ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), info.reason().getString()); - this.removePlayerFromWorld(quitMessage); // Paper - Fix kick event leave message not being sent + if (!this.waitingForSwitchToConfig) this.removePlayerFromWorld(quitMessage); // Paper - Fix kick event leave message not being sent // Folia - region threading - super.onDisconnect(reason, quitMessage); // Paper - Fix kick event leave message not being sent + super.onDisconnect(info, quitMessage); // Paper - Fix kick event leave message not being sent } -@@ -2077,6 +2125,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2022,6 +2070,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.removePlayerFromWorld(null); } @@ -15533,16 +12878,16 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 private void removePlayerFromWorld(@Nullable net.kyori.adventure.text.Component quitMessage) { // Paper end - Fix kick event leave message not being sent this.chatMessageChain.close(); -@@ -2089,6 +2139,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2034,6 +2084,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.disconnect(); // Paper start - Adventure quitMessage = quitMessage == null ? this.server.getPlayerList().remove(this.player) : this.server.getPlayerList().remove(this.player, quitMessage); // Paper - pass in quitMessage to fix kick message not being used + if (!this.hackSwitchingConfig) this.disconnectPos = this.player.chunkPosition(); // Folia - region threading - note: only set after removing, since it can tick the player -+ if (!this.hackSwitchingConfig) this.player.serverLevel().chunkSource.addTicketAtLevel(DISCONNECT_TICKET, this.disconnectPos, io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, this.disconnectTicketId); // Folia - region threading - force chunk to be loaded so that the region is not lost ++ if (!this.hackSwitchingConfig) this.player.serverLevel().chunkSource.addTicketAtLevel(DISCONNECT_TICKET, this.disconnectPos, ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, this.disconnectTicketId); // Folia - region threading - force chunk to be loaded so that the region is not lost if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { this.server.getPlayerList().broadcastSystemMessage(PaperAdventure.asVanilla(quitMessage), false); // Paper end -@@ -2337,7 +2389,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2282,7 +2334,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.resetLastActionTime(); // CraftBukkit start if (sync) { @@ -15551,7 +12896,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 } else { runnable.run(); } -@@ -2395,7 +2447,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2340,7 +2392,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl String originalFormat = event.getFormat(), originalMessage = event.getMessage(); this.cserver.getPluginManager().callEvent(event); @@ -15560,7 +12905,7 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 // Evil plugins still listening to deprecated event final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); queueEvent.setCancelled(event.isCancelled()); -@@ -2493,6 +2545,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2438,6 +2490,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (s.isEmpty()) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); } else if (this.getCraftPlayer().isConversing()) { @@ -15568,13 +12913,13 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 final String conversationInput = s; this.server.processQueue.add(new Runnable() { @Override -@@ -2724,8 +2777,25 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2669,8 +2722,25 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Spigot End public void switchToConfig() { - this.waitingForSwitchToConfig = true; + // Folia start - rewrite login process -+ io.papermc.paper.util.TickThread.ensureTickThread(this.player, "Cannot switch config off-main"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.player, "Cannot switch config off-main"); + if (io.papermc.paper.threadedregions.RegionizedServer.isGlobalTickThread()) { + throw new IllegalStateException("Cannot switch config while on global tick thread"); + } @@ -15595,16 +12940,16 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 this.send(ClientboundStartConfigurationPacket.INSTANCE); this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); } -@@ -2751,7 +2821,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2696,7 +2766,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.resetLastActionTime(); this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); - if (entity != null) { -+ if (io.papermc.paper.util.TickThread.isTickThreadFor(entity) && entity != null) { // Folia - region threading - do not allow interaction of entities outside the current region ++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity) && entity != null) { // Folia - region threading - do not allow interaction of entities outside the current region if (!worldserver.getWorldBorder().isWithinBounds(entity.blockPosition())) { return; } -@@ -2895,6 +2965,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2840,6 +2910,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl switch (packetplayinclientcommand_enumclientcommand) { case PERFORM_RESPAWN: if (this.player.wonGame) { @@ -15615,9 +12960,9 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 + } + // Folia end - region threading this.player.wonGame = false; - this.player = this.server.getPlayerList().respawn(this.player, this.server.getLevel(this.player.getRespawnDimension()), true, null, true, RespawnReason.END_PORTAL, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); // Paper - Expand PlayerRespawnEvent + this.player = this.server.getPlayerList().respawn(this.player, true, Entity.RemovalReason.CHANGED_DIMENSION, RespawnReason.END_PORTAL); // CraftBukkit CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); -@@ -2903,6 +2979,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2848,6 +2924,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl return; } @@ -15625,27 +12970,17 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 + if (true) { + this.player.respawn((ServerPlayer player) -> { + if (ServerGamePacketListenerImpl.this.server.isHardcore()) { -+ player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper -+ ((GameRules.BooleanValue) player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, player.serverLevel()); // Paper ++ player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - Expand PlayerGameModeChangeEvent ++ ((GameRules.BooleanValue) player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, player.serverLevel()); // CraftBukkit - per-world + } -+ }); ++ }, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.DEATH); + return; + } + // Folia end - region threading -+ - this.player = this.server.getPlayerList().respawn(this.player, false, RespawnReason.DEATH); + this.player = this.server.getPlayerList().respawn(this.player, false, Entity.RemovalReason.KILLED, RespawnReason.DEATH); // CraftBukkit if (this.server.isHardcore()) { this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - Expand PlayerGameModeChangeEvent -@@ -3267,7 +3355,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - // Paper start - auto recipe limit - if (!org.bukkit.Bukkit.isPrimaryThread()) { - if (this.recipeSpamPackets.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamLimit) { -- this.server.scheduleOnMain(() -> this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM)); // Paper - kick event cause -+ this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Folia - region threading - return; - } - } -@@ -3436,7 +3524,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -3381,7 +3468,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.filterTextPacket(list).thenAcceptAsync((list1) -> { this.updateSignText(packet, list1); @@ -15666,10 +13001,10 @@ index 4ae88bfcead40cd05f9514a48a922a37767cb3cf..2ae2527bbe5a08af98eb6405a8403c21 private void updateSignText(ServerboundSignUpdatePacket packet, List signText) { diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index b656741eb68adeb04bf995f1045902cb6bd5f2e7..734f745ce383c8398fdedeb6fd71277e1482a4a6 100644 +index b0f7a378f19b9837c060c891002cd5db756cdae1..bc9956d36ce3adabd50dc4b6467a0fd24386e4e0 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -104,7 +104,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, +@@ -106,7 +106,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, } // Paper end - Do not allow logins while the server is shutting down if (this.state == ServerLoginPacketListenerImpl.State.VERIFYING) { @@ -15682,7 +13017,7 @@ index b656741eb68adeb04bf995f1045902cb6bd5f2e7..734f745ce383c8398fdedeb6fd71277e this.verifyLoginAndFinishConnectionSetup((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); } // Paper - prevent logins to be processed even though disconnect was called } -@@ -250,7 +254,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, +@@ -252,7 +256,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, })); } @@ -15691,7 +13026,7 @@ index b656741eb68adeb04bf995f1045902cb6bd5f2e7..734f745ce383c8398fdedeb6fd71277e if (flag) { this.state = ServerLoginPacketListenerImpl.State.WAITING_FOR_DUPE_DISCONNECT; -@@ -370,7 +374,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, +@@ -372,7 +376,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, uniqueId = gameprofile.getId(); // Paper end - Add more fields to AsyncPlayerPreLoginEvent @@ -15766,7 +13101,7 @@ index 653856d0b8dcf2baf4cc77a276f17c8cc1fa717e..3f5639f26f249ca10e03826231d087ab date1 = fallback; } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7e9becd1e 100644 +index 43eeb8ce4bc350c2b524ade11ca25d8d4d21bea5..cb8233a3c1d49197da7378adda5fa17ac44fd673 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -134,10 +134,10 @@ public abstract class PlayerList { @@ -15867,9 +13202,9 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 + // Folia end - region threading - rewrite login process if (optional.isEmpty() || invalidPlayerWorld[0]) { // Paper end - reset to main world spawn if first spawn or invalid world -- player.fudgeSpawnLocation(worldserver1); // Paper - Don't move existing players to world spawn -+ ServerPlayer.fudgeSpawnLocation(worldserver1, player, toComplete); // Paper - Don't move existing players to world spawn // Folia - region threading -+ } else { // Folia start - region threading - rewrite login process +- player.moveTo(player.adjustSpawnLocation(worldserver1, worldserver1.getSharedSpawnPos()).getBottomCenter(), worldserver1.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored ++ ServerPlayer.fudgeSpawnLocation(worldserver1, player, toComplete); // Paper - MC-200092 - fix first spawn pos yaw being ignored // Folia - region threading ++ } else { + worldserver1.loadChunksForMoveAsync( + player.getBoundingBox(), + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, @@ -15895,7 +13230,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 // Spigot start - spawn location event Player spawnPlayer = player.getBukkitEntity(); - org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new com.destroystokyo.paper.event.player.PlayerInitialSpawnEvent(spawnPlayer, spawnPlayer.getLocation()); // Paper use our duplicate event + org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(spawnPlayer, spawnPlayer.getLocation()); - this.cserver.getPluginManager().callEvent(ev); + //this.cserver.getPluginManager().callEvent(ev); // Folia - region threading - TODO WTF TO DO WITH THIS EVENT? @@ -15910,7 +13245,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 + worldserver1.getCurrentWorldData().connections.add(connection); + // Folia end - rewrite login process - connection.setupInboundProtocol(GameProtocols.SERVERBOUND.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())), playerconnection); + connection.setupInboundProtocol(GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())), playerconnection); GameRules gamerules = worldserver1.getGameRules(); @@ -305,7 +387,7 @@ public abstract class PlayerList { this.sendPlayerPermissionLevel(player); @@ -15940,7 +13275,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { // Paper start - Add Listing API for Player -@@ -482,7 +563,7 @@ public abstract class PlayerList { +@@ -476,7 +557,7 @@ public abstract class PlayerList { // Paper start - Configurable player collision; Add to collideRule team if needed final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName); @@ -15949,7 +13284,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); } // Paper end - Configurable player collision -@@ -575,7 +656,7 @@ public abstract class PlayerList { +@@ -569,7 +650,7 @@ public abstract class PlayerList { protected void save(ServerPlayer player) { if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit @@ -15958,7 +13293,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 this.playerIo.save(player); ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit -@@ -615,7 +696,7 @@ public abstract class PlayerList { +@@ -609,7 +690,7 @@ public abstract class PlayerList { // CraftBukkit end // Paper start - Configurable player collision; Remove from collideRule team if needed @@ -15967,7 +13302,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName); if (entityplayer.getTeam() == team && team != null) { -@@ -655,7 +736,7 @@ public abstract class PlayerList { +@@ -649,7 +730,7 @@ public abstract class PlayerList { entityplayer.unRide(); worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER); @@ -15976,7 +13311,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 entityplayer.getAdvancements().stopListening(); this.players.remove(entityplayer); this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -674,8 +755,7 @@ public abstract class PlayerList { +@@ -668,8 +749,7 @@ public abstract class PlayerList { // CraftBukkit start // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); @@ -15986,7 +13321,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { entityplayer2.connection.send(packet); -@@ -700,19 +780,12 @@ public abstract class PlayerList { +@@ -694,19 +774,12 @@ public abstract class PlayerList { ServerPlayer entityplayer; @@ -16008,7 +13343,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 } // Instead of kicking then returning, we need to store the kick reason -@@ -732,7 +805,7 @@ public abstract class PlayerList { +@@ -726,7 +799,7 @@ public abstract class PlayerList { ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); if (gameprofilebanentry.getExpires() != null) { @@ -16017,7 +13352,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 } // return chatmessage; -@@ -745,14 +818,14 @@ public abstract class PlayerList { +@@ -739,14 +812,14 @@ public abstract class PlayerList { ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason()); if (ipbanentry.getExpires() != null) { @@ -16034,10 +13369,10 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } -@@ -818,6 +891,11 @@ public abstract class PlayerList { +@@ -806,6 +879,11 @@ public abstract class PlayerList { + } - public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { - // Paper end - Expand PlayerRespawnEvent + public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, Entity.RemovalReason entity_removalreason, RespawnReason reason, Location location) { + // Folia start - region threading + if (true) { + throw new UnsupportedOperationException("Must use teleportAsync while in region threading"); @@ -16046,7 +13381,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 entityplayer.stopRiding(); // CraftBukkit this.players.remove(entityplayer); this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -1017,10 +1095,10 @@ public abstract class PlayerList { +@@ -971,10 +1049,10 @@ public abstract class PlayerList { public void tick() { if (++this.sendAllPlayerInfoIn > 600) { // CraftBukkit start @@ -16060,7 +13395,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 @Override public boolean test(ServerPlayer input) { return target.getBukkitEntity().canSee(input.getBukkitEntity()); -@@ -1046,18 +1124,17 @@ public abstract class PlayerList { +@@ -1000,18 +1078,17 @@ public abstract class PlayerList { // CraftBukkit start - add a world/entity limited version public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { @@ -16083,7 +13418,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 } } -@@ -1101,8 +1178,7 @@ public abstract class PlayerList { +@@ -1055,8 +1132,7 @@ public abstract class PlayerList { if (scoreboardteam == null) { this.broadcastSystemMessage(message, false); } else { @@ -16093,7 +13428,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 if (entityplayer.getTeam() != scoreboardteam) { entityplayer.sendSystemMessage(message); -@@ -1113,10 +1189,12 @@ public abstract class PlayerList { +@@ -1067,10 +1143,12 @@ public abstract class PlayerList { } public String[] getPlayerNamesArray() { @@ -16109,7 +13444,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 } return astring; -@@ -1135,7 +1213,9 @@ public abstract class PlayerList { +@@ -1089,7 +1167,9 @@ public abstract class PlayerList { ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { @@ -16119,7 +13454,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 } } -@@ -1145,7 +1225,10 @@ public abstract class PlayerList { +@@ -1099,7 +1179,10 @@ public abstract class PlayerList { ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { @@ -16130,7 +13465,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 } } -@@ -1206,8 +1289,7 @@ public abstract class PlayerList { +@@ -1161,8 +1244,7 @@ public abstract class PlayerList { } public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, Packet packet) { @@ -16140,7 +13475,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 // CraftBukkit start - Test if player receiving packet can see the source of the packet if (player != null && !entityplayer.getBukkitEntity().canSee(player.getBukkitEntity())) { -@@ -1237,12 +1319,21 @@ public abstract class PlayerList { +@@ -1192,12 +1274,21 @@ public abstract class PlayerList { io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main MinecraftTimings.savePlayers.startTiming(); // Paper int numSaved = 0; @@ -16152,7 +13487,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 + int max = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick(); // Folia - region threading + long timeInterval = (long)interval * io.papermc.paper.threadedregions.TickRegionScheduler.TIME_BETWEEN_TICKS; // Folia - region threading + for (ServerPlayer entityplayer : this.players) { // Folia start - region threading -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(entityplayer)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entityplayer)) { + continue; + } + // Folia end - region threading @@ -16167,7 +13502,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 } // Paper end - Incremental chunk and player saving } -@@ -1361,6 +1452,20 @@ public abstract class PlayerList { +@@ -1316,6 +1407,20 @@ public abstract class PlayerList { } public void removeAll(boolean isRestarting) { @@ -16188,7 +13523,7 @@ index a2142930b4d4b05987c90496fb9d733d99040aa0..67b832c9a36f8af245e381c7fa3c56a7 // Paper end // CraftBukkit start - disconnect safely for (ServerPlayer player : this.players) { -@@ -1370,7 +1475,7 @@ public abstract class PlayerList { +@@ -1325,7 +1430,7 @@ public abstract class PlayerList { // CraftBukkit end // Paper start - Configurable player collision; Remove collideRule team if it exists @@ -16229,60 +13564,6 @@ index c038da20b76c0b7b1c18471b20be01e849d29f3a..87114cc9ce7489ff8e29e2d88ebb0d47 + } // Folia - region threading } } -diff --git a/src/main/java/net/minecraft/util/SortedArraySet.java b/src/main/java/net/minecraft/util/SortedArraySet.java -index 0793dfe47e68a2b48b010aad5b12dcfa1701293a..50e3ad4ce20915943fbd9115cec221a374e778fb 100644 ---- a/src/main/java/net/minecraft/util/SortedArraySet.java -+++ b/src/main/java/net/minecraft/util/SortedArraySet.java -@@ -90,7 +90,7 @@ public class SortedArraySet extends AbstractSet { - return Arrays.binarySearch(this.contents, 0, this.size, object, this.comparator); - } - -- private static int getInsertionPosition(int binarySearchResult) { -+ public static int getInsertionPosition(int binarySearchResult) { // Folia - region threading - public - return -binarySearchResult - 1; - } - -@@ -177,6 +177,40 @@ public class SortedArraySet extends AbstractSet { - } - } - // Paper end - rewrite chunk system -+ // Folia start - region threading -+ public int binarySearch(final T search) { -+ return this.findIndex(search); -+ } -+ -+ public int insertAndGetIdx(final T value) { -+ final int idx = this.findIndex(value); -+ if (idx >= 0) { -+ // exists already -+ return idx; -+ } -+ -+ this.addInternal(value, getInsertionPosition(idx)); -+ return idx; -+ } -+ -+ public T removeFirst() { -+ final T ret = this.contents[0]; -+ -+ this.removeInternal(0); -+ -+ return ret; -+ } -+ -+ public T removeLast() { -+ final int index = --this.size; -+ -+ final T ret = this.contents[index]; -+ -+ this.contents[index] = null; -+ -+ return ret; -+ } -+ // Folia end - region threading - - @Override - public boolean remove(Object object) { diff --git a/src/main/java/net/minecraft/util/SpawnUtil.java b/src/main/java/net/minecraft/util/SpawnUtil.java index 5c8e36ea8287029b1789719c687bac1a2c4c3a69..db0fe7fa257842eacd250f4cae6f549b9a0a91c9 100644 --- a/src/main/java/net/minecraft/util/SpawnUtil.java @@ -16297,7 +13578,7 @@ index 5c8e36ea8287029b1789719c687bac1a2c4c3a69..db0fe7fa257842eacd250f4cae6f549b } } diff --git a/src/main/java/net/minecraft/world/RandomSequences.java b/src/main/java/net/minecraft/world/RandomSequences.java -index 24c60dd75bbb59e33d64db70cd31f1f2c1c55c4a..b31681b770dd7e52b434d237124d6d823f7c6a5a 100644 +index c83598bfaa6fc9a6041fd828eb3c8b46334461a4..f8bc3450c054b201b7105e51bbba254efe2c2341 100644 --- a/src/main/java/net/minecraft/world/RandomSequences.java +++ b/src/main/java/net/minecraft/world/RandomSequences.java @@ -21,7 +21,7 @@ public class RandomSequences extends SavedData { @@ -16382,7 +13663,7 @@ index 24c60dd75bbb59e33d64db70cd31f1f2c1c55c4a..b31681b770dd7e52b434d237124d6d82 @Override diff --git a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java -index 99a7e9eb75231c15bd8bb24fbb4e296bc9fdedff..695f5b452d0abc4e474e8e55134a122d3d216c5a 100644 +index 99a7e9eb75231c15bd8bb24fbb4e296bc9fdedff..b4a081392b68ccb869392f93ee1f259f0d4f6adc 100644 --- a/src/main/java/net/minecraft/world/damagesource/CombatTracker.java +++ b/src/main/java/net/minecraft/world/damagesource/CombatTracker.java @@ -53,7 +53,7 @@ public class CombatTracker { @@ -16390,7 +13671,7 @@ index 99a7e9eb75231c15bd8bb24fbb4e296bc9fdedff..695f5b452d0abc4e474e8e55134a122d private Component getMessageForAssistedFall(Entity attacker, Component attackerDisplayName, String itemDeathTranslationKey, String deathTranslationKey) { - ItemStack itemStack = attacker instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem() : ItemStack.EMPTY; -+ ItemStack itemStack = attacker instanceof LivingEntity livingEntity && io.papermc.paper.util.TickThread.isTickThreadFor(livingEntity) ? livingEntity.getMainHandItem() : ItemStack.EMPTY; // Folia - region threading ++ ItemStack itemStack = attacker instanceof LivingEntity livingEntity && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(livingEntity) ? livingEntity.getMainHandItem() : ItemStack.EMPTY; // Folia - region threading return !itemStack.isEmpty() && itemStack.has(DataComponents.CUSTOM_NAME) ? Component.translatable(itemDeathTranslationKey, this.mob.getDisplayName(), attackerDisplayName, itemStack.getDisplayName()) : Component.translatable(deathTranslationKey, this.mob.getDisplayName(), attackerDisplayName); @@ -16399,32 +13680,32 @@ index 99a7e9eb75231c15bd8bb24fbb4e296bc9fdedff..695f5b452d0abc4e474e8e55134a122d @Nullable private static Component getDisplayName(@Nullable Entity entity) { - return entity == null ? null : entity.getDisplayName(); -+ return entity == null || !io.papermc.paper.util.TickThread.isTickThreadFor(entity) ? null : entity.getDisplayName(); // Folia - region threading ++ return entity == null || !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity) ? null : entity.getDisplayName(); // Folia - region threading } public Component getDeathMessage() { diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -index dd9638bdb228a53e72820e0e7cf6fe6fcc08fe4b..0fa04cab50f885f0e03215859c4919c843521d59 100644 +index bb1a60180e58c1333e7bb33e8acf1b0225eda8a8..bc7568c26e6f2b64365712b31d5fce708a0a272d 100644 --- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java +++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java -@@ -173,13 +173,13 @@ public class DamageSource { +@@ -178,13 +178,13 @@ public class DamageSource { LivingEntity entityliving1 = killed.getKillCredit(); String s1 = s + ".player"; - return entityliving1 != null ? Component.translatable(s1, killed.getDisplayName(), entityliving1.getDisplayName()) : Component.translatable(s, killed.getDisplayName()); -+ return entityliving1 != null && io.papermc.paper.util.TickThread.isTickThreadFor(entityliving1) ? Component.translatable(s1, killed.getDisplayName(), entityliving1.getDisplayName()) : Component.translatable(s, killed.getDisplayName()); // Folia - region threading ++ return entityliving1 != null && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entityliving1) ? Component.translatable(s1, killed.getDisplayName(), entityliving1.getDisplayName()) : Component.translatable(s, killed.getDisplayName()); // Folia - region threading } else { Component ichatbasecomponent = this.causingEntity == null ? this.directEntity.getDisplayName() : this.causingEntity.getDisplayName(); Entity entity = this.causingEntity; ItemStack itemstack; - if (entity instanceof LivingEntity) { -+ if (entity instanceof LivingEntity livingEntity && io.papermc.paper.util.TickThread.isTickThreadFor(livingEntity)) { // Folia - region threading ++ if (entity instanceof LivingEntity livingEntity && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(livingEntity)) { // Folia - region threading LivingEntity entityliving2 = (LivingEntity) entity; itemstack = entityliving2.getMainHandItem(); diff --git a/src/main/java/net/minecraft/world/damagesource/FallLocation.java b/src/main/java/net/minecraft/world/damagesource/FallLocation.java -index e9df8f8541b8a1b85c7d2925ff3cba813007a1ef..35e3e67c0c74f95007c55ee8fb44822a712a25b1 100644 +index e9df8f8541b8a1b85c7d2925ff3cba813007a1ef..d3f2775a68121ca80ef55ea4c280a0c9fcae2db3 100644 --- a/src/main/java/net/minecraft/world/damagesource/FallLocation.java +++ b/src/main/java/net/minecraft/world/damagesource/FallLocation.java @@ -35,7 +35,7 @@ public record FallLocation(String id) { @@ -16432,15 +13713,15 @@ index e9df8f8541b8a1b85c7d2925ff3cba813007a1ef..35e3e67c0c74f95007c55ee8fb44822a public static FallLocation getCurrentFallLocation(LivingEntity entity) { Optional optional = entity.getLastClimbablePos(); - if (optional.isPresent()) { -+ if (optional.isPresent() && io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)entity.level(), optional.get())) { // Folia - region threading ++ if (optional.isPresent() && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)entity.level(), optional.get())) { // Folia - region threading BlockState blockState = entity.level().getBlockState(optional.get()); return blockToFallLocation(blockState); } else { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc8f3d878a 100644 +index 490ee48346395fcbaf2eb0151e9248f18974fea6..f736ad7e211c89e4c7edc689b089b1b3b486fbab 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -173,7 +173,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -178,7 +178,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Paper start - Share random for entities to make them more random public static RandomSource SHARED_RANDOM = new RandomRandomSource(); @@ -16449,16 +13730,16 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc private boolean locked = false; @Override -@@ -246,7 +246,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -251,7 +251,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason public boolean collisionLoadChunks = false; // Paper - private CraftEntity bukkitEntity; + private volatile CraftEntity bukkitEntity; // Folia - region threading - public @org.jetbrains.annotations.Nullable net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper public CraftEntity getBukkitEntity() { -@@ -379,7 +379,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (this.bukkitEntity == null) { +@@ -382,7 +382,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess private boolean hasGlowingTag; private final Set tags; private final double[] pistonDeltas; @@ -16467,40 +13748,10 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc private EntityDimensions dimensions; private float eyeHeight; public boolean isInPowderSnow; -@@ -480,28 +480,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - this.isLegacyTrackingEntity = isLegacyTrackingEntity; +@@ -549,6 +549,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } } - -- public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet getPlayersInTrackRange() { -- // determine highest range of passengers -- if (this.passengers.isEmpty()) { -- return ((ServerLevel)this.level).getChunkSource().chunkMap.playerEntityTrackerTrackMaps[this.trackingRangeType.ordinal()] -- .getObjectsInRange(MCUtil.getCoordinateKey(this)); -- } -- Iterable passengers = this.getIndirectPassengers(); -- net.minecraft.server.level.ChunkMap chunkMap = ((ServerLevel)this.level).getChunkSource().chunkMap; -- org.spigotmc.TrackingRange.TrackingRangeType type = this.trackingRangeType; -- int range = chunkMap.getEntityTrackerRange(type.ordinal()); -- -- for (Entity passenger : passengers) { -- org.spigotmc.TrackingRange.TrackingRangeType passengerType = passenger.trackingRangeType; -- int passengerRange = chunkMap.getEntityTrackerRange(passengerType.ordinal()); -- if (passengerRange > range) { -- type = passengerType; -- range = passengerRange; -- } -- } -- -- return chunkMap.playerEntityTrackerTrackMaps[type.ordinal()].getObjectsInRange(MCUtil.getCoordinateKey(this)); -- } -+ // Folia - region ticking - // Paper end - optimise entity tracking - public float getBukkitYaw() { - return this.yRot; -@@ -568,6 +547,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - - public boolean updatingSectionStatus = false; - // Paper end + // Paper end - optimise entity tracker + // Folia start - region ticking + public void updateTicks(long fromTickOffset, long fromRedstoneTimeOffset) { + if (this.activatedTick != Integer.MIN_VALUE) { @@ -16517,29 +13768,35 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); -@@ -868,6 +860,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - - // CraftBukkit start +@@ -696,8 +709,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + // due to interactions on the client. + public void resendPossiblyDesyncedEntityData(net.minecraft.server.level.ServerPlayer player) { + if (player.getBukkitEntity().canSee(this.getBukkitEntity())) { +- ServerLevel world = (net.minecraft.server.level.ServerLevel)this.level(); +- net.minecraft.server.level.ChunkMap.TrackedEntity tracker = world == null ? null : world.getChunkSource().chunkMap.entityMap.get(this.getId()); ++ net.minecraft.server.level.ChunkMap.TrackedEntity tracker = this.moonrise$getTrackedEntity(); // Folia - region threading + if (tracker == null) { + return; + } +@@ -852,7 +864,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public void postTick() { -+ // Folia start - region threading -+ // moved to doPortalLogic -+ if (true) { -+ return; -+ } -+ // Folia end - region threading // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities - this.handleNetherPortal(); -@@ -890,7 +888,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +- this.handlePortal(); ++ //this.handlePortal(); // Folia - region threading + } + } + // CraftBukkit end +@@ -872,7 +884,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.walkDistO = this.walkDist; this.xRotO = this.getXRot(); this.yRotO = this.getYRot(); -- if (this instanceof ServerPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick -+ //if (this instanceof ServerPlayer) this.handleNetherPortal(); // CraftBukkit - // Moved up to postTick // Folia - region threading - ONLY allow in postTick() +- if (this instanceof ServerPlayer) this.handlePortal(); // CraftBukkit - // Moved up to postTick ++ //if (this instanceof ServerPlayer) this.handlePortal(); // CraftBukkit - // Moved up to postTick // Folia - region threading - ONLY allow in postTick() if (this.canSpawnSprintParticle()) { this.spawnSprintParticle(); } -@@ -1146,8 +1144,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1128,8 +1140,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } else { this.wasOnFire = this.isOnFire(); if (movementType == MoverType.PISTON) { @@ -16550,7 +13807,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc movement = this.limitPistonMovement(movement); if (movement.equals(Vec3.ZERO)) { return; -@@ -1474,7 +1472,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1421,7 +1433,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (movement.lengthSqr() <= 1.0E-7D) { return movement; } else { @@ -16559,7 +13816,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc if (i != this.pistonDeltasGameTime) { Arrays.fill(this.pistonDeltas, 0.0D); -@@ -3085,7 +3083,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3124,7 +3136,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.passengers = ImmutableList.copyOf(list); } @@ -16568,7 +13825,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc } } -@@ -3133,7 +3131,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3172,7 +3184,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } entity.boardingCooldown = 60; @@ -16577,7 +13834,48 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc } return true; // CraftBukkit } -@@ -3398,6 +3396,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3255,7 +3267,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } + } + +- protected void handlePortal() { ++ public boolean handlePortal() { // Folia - region threading - public, ret type -> boolean + Level world = this.level(); + + if (world instanceof ServerLevel worldserver) { +@@ -3264,23 +3276,21 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (this.portalProcess.processPortalTeleportation(worldserver, this, this.canUsePortal(false))) { + worldserver.getProfiler().push("portal"); + this.setPortalCooldown(); +- DimensionTransition dimensiontransition = this.portalProcess.getPortalDestination(worldserver, this); +- +- if (dimensiontransition != null) { +- ServerLevel worldserver1 = dimensiontransition.newLevel(); +- +- if (this instanceof ServerPlayer || (worldserver1 != null && (worldserver1.dimension() == worldserver.dimension() || this.canChangeDimensions(worldserver, worldserver1)))) { // CraftBukkit - always call event for players +- this.changeDimension(dimensiontransition); +- } ++ // Folia start - region threading ++ try { ++ return this.portalProcess.portalAsync(worldserver, this); ++ } finally { ++ worldserver.getProfiler().pop(); + } +- +- worldserver.getProfiler().pop(); ++ // Folia end - region threading + } else if (this.portalProcess.hasExpired()) { + this.portalProcess = null; + } + + } + } ++ ++ return false; // Folia - region threading + } + + public int getDimensionChangingDelay() { +@@ -3421,6 +3431,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @Nullable public PlayerTeam getTeam() { @@ -16589,8 +13887,8 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper - Perf: Disable Scoreboards for non players by default return this.level().getScoreboard().getPlayersTeam(this.getScoreboardName()); } -@@ -3687,6 +3690,775 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - this.portalEntrancePos = original.portalEntrancePos; +@@ -3710,8 +3725,751 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + this.portalProcess = original.portalProcess; } + // Folia start - region threading @@ -16655,9 +13953,9 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + + public void addTracker() { + for (final EntityTreeNode node : this.getFullTree()) { -+ if (node.root.tracker != null) { ++ if (node.root.moonrise$getTrackedEntity() != null) { + for (final ServerPlayer player : node.root.level.getLocalPlayers()) { -+ node.root.tracker.updatePlayer(player); ++ node.root.moonrise$getTrackedEntity().updatePlayer(player); + } + } + } @@ -16665,10 +13963,10 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + + public void clearTracker() { + for (final EntityTreeNode node : this.getFullTree()) { -+ if (node.root.tracker != null) { -+ node.root.tracker.removeNonTickThreadPlayers(); ++ if (node.root.moonrise$getTrackedEntity() != null) { ++ node.root.moonrise$getTrackedEntity().moonrise$removeNonTickThreadPlayers(); + for (final ServerPlayer player : node.root.level.getLocalPlayers()) { -+ node.root.tracker.removePlayer(player); ++ node.root.moonrise$getTrackedEntity().removePlayer(player); + } + } + } @@ -16697,7 +13995,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + } + + protected EntityTreeNode makePassengerTree() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot read passengers off of the main thread"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot read passengers off of the main thread"); + + EntityTreeNode root = new EntityTreeNode(null, this); + java.util.ArrayDeque queue = new java.util.ArrayDeque<>(); @@ -16723,7 +14021,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + } + + protected EntityTreeNode detachPassengers() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot adjust passengers/vehicle off of the main thread"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot adjust passengers/vehicle off of the main thread"); + + EntityTreeNode root = new EntityTreeNode(null, this); + java.util.ArrayDeque queue = new java.util.ArrayDeque<>(); @@ -16777,8 +14075,8 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + EntityTreeNode passengerTree, java.util.function.Consumer teleportComplete) { + Vec3 pos = this.position(); + ChunkPos posChunk = new ChunkPos( -+ io.papermc.paper.util.CoordinateUtils.getChunkX(pos), -+ io.papermc.paper.util.CoordinateUtils.getChunkZ(pos) ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(pos), ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(pos) + ); + + // ensure the region is always ticking in case of a shutdown @@ -16786,7 +14084,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + Long teleportHoldId = Long.valueOf(TELEPORT_HOLD_TICKET_GEN.getAndIncrement()); + originWorld.chunkSource.addTicketAtLevel( + TicketType.TELEPORT_HOLD_TICKET, posChunk, -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + teleportHoldId + ); + final ServerLevel.PendingTeleport pendingTeleport = new ServerLevel.PendingTeleport(passengerTree, pos); @@ -16795,7 +14093,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + Runnable scheduleEntityJoin = () -> { + io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue( + destination, -+ io.papermc.paper.util.CoordinateUtils.getChunkX(pos), io.papermc.paper.util.CoordinateUtils.getChunkZ(pos), ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(pos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(pos), + () -> { + if (!destination.removePendingTeleport(pendingTeleport)) { + // shutdown logic placed the entity already, and we are shutting down - do nothing to ensure @@ -16804,7 +14102,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + } + originWorld.chunkSource.removeTicketAtLevel( + TicketType.TELEPORT_HOLD_TICKET, posChunk, -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + teleportHoldId + ); + List fullTree = passengerTree.getFullTree(); @@ -16830,12 +14128,12 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + + if ((teleportFlags & TELEPORT_FLAG_LOAD_CHUNK) != 0L) { + destination.loadChunksForMoveAsync( -+ Entity.this.getBoundingBox(), ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, ++ this.getBoundingBox(), ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, + (chunkList) -> { + for (net.minecraft.world.level.chunk.ChunkAccess chunk : chunkList) { + destination.chunkSource.addTicketAtLevel( + TicketType.POST_TELEPORT, chunk.getPos(), -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.FULL_LOADED_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.FULL_LOADED_TICKET_LEVEL, + Integer.valueOf(Entity.this.getId()) + ); + } @@ -16858,7 +14156,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + this.mainSupportingBlockPos = Optional.empty(); + } + -+ protected void teleportSyncSameRegion(Vec3 pos, Float yaw, Float pitch, Vec3 speedDirectionUpdate) { ++ protected void teleportSyncSameRegion(Vec3 pos, Float yaw, Float pitch, Vec3 velocity) { + if (yaw != null) { + this.setYRot(yaw.floatValue()); + this.setYHeadRot(yaw.floatValue()); @@ -16866,14 +14164,14 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + if (pitch != null) { + this.setXRot(pitch.floatValue()); + } -+ if (speedDirectionUpdate != null) { -+ this.setDeltaMovement(speedDirectionUpdate.normalize().scale(this.getDeltaMovement().length())); ++ if (velocity != null) { ++ this.setDeltaMovement(velocity); + } + this.moveTo(pos.x, pos.y, pos.z); + this.resetStoredPositions(); + } + -+ protected void transform(Vec3 pos, Float yaw, Float pitch, Vec3 speedDirectionUpdate) { ++ protected void transform(Vec3 pos, Float yaw, Float pitch, Vec3 velocity) { + if (yaw != null) { + this.setYRot(yaw.floatValue()); + this.setYHeadRot(yaw.floatValue()); @@ -16881,20 +14179,20 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + if (pitch != null) { + this.setXRot(pitch.floatValue()); + } -+ if (speedDirectionUpdate != null) { -+ this.setDeltaMovement(speedDirectionUpdate); ++ if (velocity != null) { ++ this.setDeltaMovement(velocity); + } + if (pos != null) { + this.setPosRaw(pos.x, pos.y, pos.z); + } + } + -+ protected Entity transformForAsyncTeleport(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 speedDirectionUpdate) { ++ protected Entity transformForAsyncTeleport(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 velocity) { + this.removeAfterChangingDimensions(); // remove before so that any CBEntity#getHandle call affects this entity before copying + + Entity copy = this.getType().create(destination); + copy.restoreFrom(this); -+ copy.transform(pos, yaw, pitch, speedDirectionUpdate); ++ copy.transform(pos, yaw, pitch, velocity); + // vanilla code used to call remove _after_ copying, and some stuff is required to be after copy - so add hook here + // for example, clearing of inventory after switching dimensions + this.postRemoveAfterChangingDimensions(); @@ -16902,12 +14200,12 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + return copy; + } + -+ public final boolean teleportAsync(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 speedDirectionUpdate, ++ public final boolean teleportAsync(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 velocity, + org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, long teleportFlags, + java.util.function.Consumer teleportComplete) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot teleport entity async"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot teleport entity async"); + -+ if (!ServerLevel.isInSpawnableBounds(new BlockPos(io.papermc.paper.util.CoordinateUtils.getBlockX(pos), io.papermc.paper.util.CoordinateUtils.getBlockY(pos), io.papermc.paper.util.CoordinateUtils.getBlockZ(pos)))) { ++ if (!ServerLevel.isInSpawnableBounds(new BlockPos(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getBlockX(pos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getBlockY(pos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getBlockZ(pos)))) { + return false; + } + @@ -16943,9 +14241,9 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + Vec3 currPos = this.position(); + if ( + destination.regioniser.getRegionAtUnsynchronised( -+ io.papermc.paper.util.CoordinateUtils.getChunkX(currPos), io.papermc.paper.util.CoordinateUtils.getChunkZ(currPos) ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(currPos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(currPos) + ) == destination.regioniser.getRegionAtUnsynchronised( -+ io.papermc.paper.util.CoordinateUtils.getChunkX(pos), io.papermc.paper.util.CoordinateUtils.getChunkZ(pos) ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(pos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(pos) + ) + ) { + EntityTreeNode passengerTree = this.detachPassengers(); @@ -16955,7 +14253,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + // first, clear the tracker + passengerTree.clearTracker(); + for (EntityTreeNode entity : passengerTree.getFullTree()) { -+ entity.root.teleportSyncSameRegion(pos, yaw, pitch, speedDirectionUpdate); ++ entity.root.teleportSyncSameRegion(pos, yaw, pitch, velocity); + } + + passengerTree.restore(); @@ -16984,7 +14282,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + } + + for (EntityTreeNode node : fullPassengerTree) { -+ node.root = node.root.transformForAsyncTeleport(destination, pos, yaw, pitch, speedDirectionUpdate); ++ node.root = node.root.transformForAsyncTeleport(destination, pos, yaw, pitch, velocity); + } + + passengerTree.root.placeInAsync(originWorld, destination, teleportFlags, passengerTree, teleportComplete); @@ -17004,79 +14302,28 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + NETHER, END; + } + -+ public boolean doPortalLogic() { -+ if (this.tryNetherPortal()) { -+ return true; -+ } -+ if (this.tryEndPortal()) { -+ return true; -+ } -+ return false; -+ } ++ public boolean endPortalLogicAsync(BlockPos portalPos) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); + -+ protected boolean tryEndPortal() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); -+ BlockPos pos = this.portalBlock; -+ ServerLevel world = this.portalWorld; -+ this.portalBlock = null; -+ this.portalWorld = null; -+ -+ if (pos == null || world == null || world != this.level) { -+ return false; -+ } -+ -+ if (this.isPassenger() || this.isVehicle() || !this.canChangeDimensions() || this.isRemoved() || !this.valid || !this.isAlive()) { -+ return false; -+ } -+ -+ return this.endPortalLogicAsync(); -+ } -+ -+ protected boolean tryNetherPortal() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); -+ -+ int portalWaitTime = this.getPortalWaitTime(); -+ -+ if (this.isInsidePortal) { -+ // if we are in a nether portal still, this flag will be set next tick. -+ this.isInsidePortal = false; -+ if (this.portalTime++ >= portalWaitTime) { -+ this.portalTime = portalWaitTime; -+ if (this.netherPortalLogicAsync()) { -+ return true; -+ } -+ } -+ } else { -+ // rapidly decrease portal time -+ this.portalTime = Math.max(0, this.portalTime - 4); -+ } -+ -+ this.processPortalCooldown(); -+ return false; -+ } -+ -+ public boolean endPortalLogicAsync() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); -+ -+ ServerLevel destination = this.getServer().getLevel(this.level().getTypeKey() == LevelStem.END ? Level.OVERWORLD : Level.END); ++ ServerLevel destination = this.getServer().getLevel(this.level().getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END ? Level.OVERWORLD : Level.END); + if (destination == null) { + // wat + return false; + } + -+ return this.portalToAsync(destination, false, PortalType.END, null); ++ return this.portalToAsync(destination, portalPos, true, PortalType.END, null); + } + -+ public boolean netherPortalLogicAsync() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); ++ public boolean netherPortalLogicAsync(BlockPos portalPos) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); + -+ ServerLevel destination = this.getServer().getLevel(this.level().getTypeKey() == LevelStem.NETHER ? Level.OVERWORLD : Level.NETHER); ++ ServerLevel destination = this.getServer().getLevel(this.level().getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER ? Level.OVERWORLD : Level.NETHER); + if (destination == null) { + // wat + return false; + } + -+ return this.portalToAsync(destination, false, PortalType.NETHER, null); ++ return this.portalToAsync(destination, portalPos, true, PortalType.NETHER, null); + } + + private static final java.util.concurrent.atomic.AtomicLong CREATE_PORTAL_DOUBLE_CHECK = new java.util.concurrent.atomic.AtomicLong(); @@ -17088,32 +14335,36 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + // remove the entity, find/create the portal, and place async. + // If we have to worry about whether the entity may not teleport, + // we need to first search, then report back, ... -+ protected void findOrCreatePortalAsync(ServerLevel origin, ServerLevel destination, PortalType type, -+ ca.spottedleaf.concurrentutil.completable.Completable portalInfoCompletable) { ++ protected void findOrCreatePortalAsync(ServerLevel origin, BlockPos originPortal, ServerLevel destination, PortalType type, ++ ca.spottedleaf.concurrentutil.completable.Completable portalInfoCompletable) { + switch (type) { + // end portal logic is quite simple, the spawn in the end is fixed and when returning to the overworld + // we just select the spawn position + case END: { -+ if (destination.getTypeKey() == LevelStem.END) { ++ if (destination.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.END) { + BlockPos targetPos = ServerLevel.END_SPAWN_POINT; + // need to load chunks so we can create the platform -+ destination.loadChunksAsync( ++ destination.moonrise$loadChunksAsync( + targetPos, 16, // load 16 blocks to be safe from block physics + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, + (chunks) -> { -+ ServerLevel.makeObsidianPlatform(destination, null, targetPos); ++ net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, targetPos.below(), true, null); + + // the portal obsidian is placed at targetPos.y - 2, so if we want to place the entity + // on the obsidian, we need to spawn at targetPos.y - 1 + portalInfoCompletable.complete( -+ new PortalInfo(Vec3.atBottomCenterOf(targetPos.below()), Vec3.ZERO, 90.0f, 0.0f, destination, null) ++ new net.minecraft.world.level.portal.DimensionTransition( ++ destination, Vec3.atBottomCenterOf(targetPos.below()), Vec3.ZERO, 90.0f, 0.0f, ++ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET), ++ org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL ++ ) + ); + } + ); + } else { + BlockPos spawnPos = destination.getSharedSpawnPos(); + // need to load chunk for heightmap -+ destination.loadChunksAsync( ++ destination.moonrise$loadChunksAsync( + spawnPos, 0, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, + (chunks) -> { @@ -17121,7 +14372,11 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + + // done + portalInfoCompletable.complete( -+ new PortalInfo(Vec3.atBottomCenterOf(adjustedSpawn), Vec3.ZERO, 90.0f, 0.0f, destination, null) ++ new net.minecraft.world.level.portal.DimensionTransition( ++ destination, Vec3.atBottomCenterOf(adjustedSpawn), Vec3.ZERO, 90.0f, 0.0f, ++ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET), ++ org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL ++ ) + ); + } + ); @@ -17135,20 +14390,20 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + // create it + case NETHER: { + // hoisted from the create fallback, so that we can avoid the sync load later if we need it -+ BlockState originalPortalBlock = this.portalEntrancePos == null ? null : origin.getBlockStateIfLoaded(this.portalEntrancePos); ++ BlockState originalPortalBlock = origin.getBlockStateIfLoaded(originPortal); + Direction.Axis originalPortalDirection = originalPortalBlock == null ? Direction.Axis.X : + originalPortalBlock.getOptionalValue(net.minecraft.world.level.block.NetherPortalBlock.AXIS).orElse(Direction.Axis.X); + BlockUtil.FoundRectangle originalPortalRectangle = -+ originalPortalBlock == null || !originalPortalBlock.hasProperty(BlockStateProperties.HORIZONTAL_AXIS) ++ originalPortalBlock == null || !originalPortalBlock.hasProperty(net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_AXIS) + ? null + : BlockUtil.getLargestRectangleAround( -+ this.portalEntrancePos, originalPortalDirection, 21, Direction.Axis.Y, 21, ++ originPortal, originalPortalDirection, 21, Direction.Axis.Y, 21, + (blockpos) -> { + return origin.getBlockStateFromEmptyChunkIfLoaded(blockpos) == originalPortalBlock; + } + ); + -+ boolean destinationIsNether = destination.getTypeKey() == LevelStem.NETHER; ++ boolean destinationIsNether = destination.getTypeKey() == net.minecraft.world.level.dimension.LevelStem.NETHER; + + int portalSearchRadius = origin.paperConfig().environment.portalSearchVanillaDimensionScaling && destinationIsNether ? + (int)(destination.paperConfig().environment.portalSearchRadius / destination.dimensionType().coordinateScale()) : @@ -17156,7 +14411,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + int portalCreateRadius = destination.paperConfig().environment.portalCreateRadius; + + WorldBorder destinationBorder = destination.getWorldBorder(); -+ double dimensionScale = DimensionType.getTeleportationScale(origin.dimensionType(), destination.dimensionType()); ++ double dimensionScale = net.minecraft.world.level.dimension.DimensionType.getTeleportationScale(origin.dimensionType(), destination.dimensionType()); + BlockPos targetPos = destination.getWorldBorder().clampToBounds(this.getX() * dimensionScale, this.getY(), this.getZ() * dimensionScale); + + ca.spottedleaf.concurrentutil.completable.Completable portalFound @@ -17168,7 +14423,9 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + // no portal could be created + if (portal == null) { + portalInfoCompletable.complete( -+ new PortalInfo(Vec3.atCenterOf(targetPos), Vec3.ZERO, 90.0f, 0.0f, destination, null) ++ new DimensionTransition(destination, Vec3.atCenterOf(targetPos), Vec3.ZERO, ++ 90.0f, 0.0f, ++ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET)) + ); + return; + } @@ -17178,23 +14435,24 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + Entity.this.getRelativePortalPosition(originalPortalDirection, originalPortalRectangle); + + portalInfoCompletable.complete( -+ PortalShape.createPortalInfo( ++ net.minecraft.world.level.block.NetherPortalBlock.createDimensionTransition( + destination, portal, originalPortalDirection, relativePos, -+ Entity.this, Entity.this.getDeltaMovement(), Entity.this.getYRot(), Entity.this.getXRot(), null ++ Entity.this, Entity.this.getDeltaMovement(), Entity.this.getYRot(), Entity.this.getXRot(), ++ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET) + ) + ); + } + ); + + // kick off search for existing portal or creation -+ destination.loadChunksAsync( ++ destination.moonrise$loadChunksAsync( + // add 32 so that the final search for a portal frame doesn't load any chunks + targetPos, portalSearchRadius + 32, + net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, + (chunks) -> { + BlockUtil.FoundRectangle portal = -+ destination.getPortalForcer().findPortalAround(targetPos, destinationBorder, portalSearchRadius).orElse(null); ++ net.minecraft.world.level.block.NetherPortalBlock.findPortalAround(destination, targetPos, destinationBorder, portalSearchRadius); + if (portal != null) { + portalFound.complete(portal); + return; @@ -17205,13 +14463,13 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + for (net.minecraft.world.level.chunk.ChunkAccess chunk : chunks) { + destination.chunkSource.addTicketAtLevel( + TicketType.NETHER_PORTAL_DOUBLE_CHECK, chunk.getPos(), -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + ticketId + ); + } + + // no portal found - create one -+ destination.loadChunksAsync( ++ destination.moonrise$loadChunksAsync( + targetPos, portalCreateRadius + 32, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, + (chunks2) -> { @@ -17221,7 +14479,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + for (net.minecraft.world.level.chunk.ChunkAccess chunk : chunks) { + destination.chunkSource.removeTicketAtLevel( + TicketType.NETHER_PORTAL_DOUBLE_CHECK, chunk.getPos(), -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + ticketId + ); + } @@ -17231,7 +14489,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + // to fix this, we just issue another search to try and see if another entity created + // a portal nearby + BlockUtil.FoundRectangle existingTryAgain = -+ destination.getPortalForcer().findPortalAround(targetPos, destinationBorder, portalSearchRadius).orElse(null); ++ net.minecraft.world.level.block.NetherPortalBlock.findPortalAround(destination, targetPos, destinationBorder, portalSearchRadius); + if (existingTryAgain != null) { + portalFound.complete(existingTryAgain); + return; @@ -17254,11 +14512,11 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + } + } + -+ public boolean canPortalAsync(boolean considerPassengers) { -+ return this.canPortalAsync(considerPassengers, false); ++ public boolean canPortalAsync(ServerLevel to, boolean considerPassengers) { ++ return this.canPortalAsync(to, considerPassengers, false); + } + -+ protected boolean canPortalAsync(boolean considerPassengers, boolean skipPassengerCheck) { ++ protected boolean canPortalAsync(ServerLevel to, boolean considerPassengers, boolean skipPassengerCheck) { + if (considerPassengers) { + if (!skipPassengerCheck && this.isPassenger()) { + return false; @@ -17269,12 +14527,12 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + } + } + this.getBukkitEntity(); // force bukkit entity to be created before TPing -+ if (!this.canTeleportAsync() || !this.canChangeDimensions() || this.isOnPortalCooldown()) { ++ if (!this.canTeleportAsync() || !this.canChangeDimensions(this.level(), to)) { + return false; + } + if (considerPassengers) { + for (Entity entity : this.passengers) { -+ if (!entity.canPortalAsync(true, true)) { ++ if (!entity.canPortalAsync(to, true, true)) { + return false; + } + } @@ -17287,17 +14545,17 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + + } + -+ protected boolean portalToAsync(ServerLevel destination, boolean takePassengers, ++ protected boolean portalToAsync(ServerLevel destination, BlockPos portalPos, boolean takePassengers, + PortalType type, java.util.function.Consumer teleportComplete) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); -+ if (!this.canPortalAsync(takePassengers)) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot portal entity async"); ++ if (!this.canPortalAsync(destination, takePassengers)) { + return false; + } + + Vec3 initialPosition = this.position(); + ChunkPos initialPositionChunk = new ChunkPos( -+ io.papermc.paper.util.CoordinateUtils.getChunkX(initialPosition), -+ io.papermc.paper.util.CoordinateUtils.getChunkZ(initialPosition) ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(initialPosition), ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(initialPosition) + ); + + // first, remove entity/passengers from world @@ -17322,17 +14580,17 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + Long teleportHoldId = Long.valueOf(TELEPORT_HOLD_TICKET_GEN.getAndIncrement()); + originWorld.chunkSource.addTicketAtLevel( + TicketType.TELEPORT_HOLD_TICKET, initialPositionChunk, -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + teleportHoldId + ); + + ServerLevel.PendingTeleport beforeFindDestination = new ServerLevel.PendingTeleport(passengerTree, initialPosition); + originWorld.pushPendingTeleport(beforeFindDestination); + -+ ca.spottedleaf.concurrentutil.completable.Completable portalInfoCompletable ++ ca.spottedleaf.concurrentutil.completable.Completable portalInfoCompletable + = new ca.spottedleaf.concurrentutil.completable.Completable<>(); + -+ portalInfoCompletable.addWaiter((PortalInfo info, Throwable throwable) -> { ++ portalInfoCompletable.addWaiter((DimensionTransition info, Throwable throwable) -> { + if (!originWorld.removePendingTeleport(beforeFindDestination)) { + // the shutdown thread has placed us back into the origin world at the original position + // we just have to abandon this teleport to prevent duplication @@ -17340,45 +14598,49 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + } + originWorld.chunkSource.removeTicketAtLevel( + TicketType.TELEPORT_HOLD_TICKET, initialPositionChunk, -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + teleportHoldId + ); + // adjust passenger tree to final pos + for (EntityTreeNode node : fullPassengerTree) { -+ node.root.transform(info.pos, Float.valueOf(info.yRot), Float.valueOf(info.xRot), info.speed); ++ node.root.transform(info.pos(), Float.valueOf(info.yRot()), Float.valueOf(info.xRot()), info.speed()); + } + + // place + passengerTree.root.placeInAsync( + originWorld, destination, Entity.TELEPORT_FLAG_LOAD_CHUNK | (takePassengers ? Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS : 0L), -+ passengerTree, teleportComplete ++ passengerTree, ++ (Entity teleported) -> { ++ if (info.postDimensionTransition() != null) { ++ info.postDimensionTransition().onTransition(teleported); ++ } ++ ++ if (teleportComplete != null) { ++ teleportComplete.accept(teleported); ++ } ++ } + ); + }); + + -+ passengerTree.root.findOrCreatePortalAsync(originWorld, destination, type, portalInfoCompletable); ++ passengerTree.root.findOrCreatePortalAsync(originWorld, portalPos, destination, type, portalInfoCompletable); + + return true; + } + // Folia end - region threading + @Nullable - public Entity changeDimension(ServerLevel destination) { - // CraftBukkit start -@@ -3695,6 +4467,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - - @Nullable - public Entity teleportTo(ServerLevel worldserver, Vec3 location) { + public Entity changeDimension(DimensionTransition teleportTarget) { + // Folia start - region threading + if (true) { + throw new UnsupportedOperationException("Must use teleportAsync while in region threading"); + } + // Folia end - region threading - // CraftBukkit end + Level world = this.level(); + // Paper start - Fix item duplication and teleport issues - if (!this.isAlive() || !this.valid) { -@@ -3787,6 +4564,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - } +@@ -3828,6 +4586,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } + // Folia start - region threading - move inventory clearing until after the dimension change @@ -17389,8 +14651,8 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc + protected void removeAfterChangingDimensions() { this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION, null); // CraftBukkit - add Bukkit remove cause - } -@@ -4731,7 +5514,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (this instanceof Leashable leashable) { +@@ -4699,7 +5463,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } // Paper end - Fix MC-4 @@ -17400,7 +14662,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc synchronized (this.posLock) { // Paper this.position = new Vec3(x, y, z); } // Paper -@@ -4752,7 +5536,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4720,7 +5485,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Paper start - Block invalid positions and bounding box; don't allow desync of pos and AABB // hanging has its own special logic @@ -17409,7 +14671,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc this.setBoundingBox(this.makeBoundingBox()); } // Paper end - Block invalid positions and bounding box -@@ -4837,6 +5621,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4805,6 +5570,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this.removalReason != null; } @@ -17422,7 +14684,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc @Nullable public Entity.RemovalReason getRemovalReason() { return this.removalReason; -@@ -4860,6 +5650,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4827,6 +5598,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit end final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers @@ -17432,7 +14694,7 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc if (this.removalReason == null) { this.removalReason = entity_removalreason; } -@@ -4882,6 +5675,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4849,6 +5623,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.removalReason = null; } @@ -17444,19 +14706,19 @@ index 7ef9f67d27cc240191dd5d07e8dcf5fbdebe1049..afc4fced315f2177372597d88eaf90cc /** * Invoked only when the entity is truly removed from the server, never to be added to any world. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbdeba6eab6 100644 +index fe435d4a387bb28be6831cec0c8bb0a7c8b603a4..7c89c3558b6a3ddedfcc3c30274873afce7970b4 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -256,7 +256,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -265,7 +265,7 @@ public abstract class LivingEntity extends Entity implements Attackable { private Optional lastClimbablePos; @Nullable private DamageSource lastDamageSource; - private long lastDamageStamp; + private long lastDamageStamp = Long.MIN_VALUE; // Folia - region threading protected int autoSpinAttackTicks; - private float swimAmount; - private float swimAmountO; -@@ -287,6 +287,21 @@ public abstract class LivingEntity extends Entity implements Attackable { + protected float autoSpinAttackDmg; + @Nullable +@@ -299,6 +299,21 @@ public abstract class LivingEntity extends Entity implements Attackable { ++this.noActionTime; // Above all the floats } // Spigot end @@ -17478,7 +14740,7 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd protected LivingEntity(EntityType type, Level world) { super(type, world); -@@ -494,7 +509,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -519,7 +534,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (this.isDeadOrDying() && this.level().shouldTickDeath(this)) { this.tickDeath(); @@ -17487,7 +14749,7 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd if (this.lastHurtByPlayerTime > 0) { --this.lastHurtByPlayerTime; -@@ -648,11 +663,14 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -609,11 +624,14 @@ public abstract class LivingEntity extends Entity implements Attackable { return true; } @@ -17504,7 +14766,7 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd } } -@@ -891,9 +909,9 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -866,9 +884,9 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.hurtTime = nbt.getShort("HurtTime"); @@ -17516,15 +14778,15 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd String s = nbt.getString("Team"); Scoreboard scoreboard = this.level().getScoreboard(); PlayerTeam scoreboardteam = scoreboard.getPlayerTeam(s); -@@ -1170,6 +1188,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1146,6 +1164,7 @@ public abstract class LivingEntity extends Entity implements Attackable { public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) { // Paper end - Don't fire sync event during generation // org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API -+ if (!this.hasNullCallback()) io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot add effects to entities asynchronously"); // Folia - region threading ++ if (!this.hasNullCallback()) ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot add effects to entities asynchronously"); // Folia - region threading if (this.isTickingEffects) { this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); return true; -@@ -1586,7 +1605,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1594,7 +1613,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (flag2) { this.lastDamageSource = source; @@ -17533,7 +14795,7 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd Iterator iterator = this.getActiveEffects().iterator(); while (iterator.hasNext()) { -@@ -1676,7 +1695,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1696,7 +1715,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @Nullable public DamageSource getLastDamageSource() { @@ -17542,16 +14804,16 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd this.lastDamageSource = null; } -@@ -2396,7 +2415,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2451,7 +2470,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @Nullable public LivingEntity getKillCredit() { - return (LivingEntity) (this.lastHurtByPlayer != null ? this.lastHurtByPlayer : (this.lastHurtByMob != null ? this.lastHurtByMob : null)); -+ return (LivingEntity) (this.lastHurtByPlayer != null && io.papermc.paper.util.TickThread.isTickThreadFor(this.lastHurtByPlayer) ? this.lastHurtByPlayer : (this.lastHurtByMob != null && io.papermc.paper.util.TickThread.isTickThreadFor(this.lastHurtByMob) ? this.lastHurtByMob : null)); // Folia - region threading ++ return (LivingEntity) (this.lastHurtByPlayer != null && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.lastHurtByPlayer) ? this.lastHurtByPlayer : (this.lastHurtByMob != null && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.lastHurtByMob) ? this.lastHurtByMob : null)); // Folia - region threading } public final float getMaxHealth() { -@@ -2474,7 +2493,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2529,7 +2548,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.hurt(this.damageSources().generic(), 0.0F); this.lastDamageSource = damageSource; @@ -17560,7 +14822,7 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd } @Override -@@ -3478,7 +3497,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3553,7 +3572,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.pushEntities(); this.level().getProfiler().pop(); // Paper start - Add EntityMoveEvent @@ -17569,20 +14831,20 @@ index 015134a614a44b610aac1a4c6a1eb6b7b5bb96b5..f792fd137a964a40e2246d31ab2ddbbd if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); -@@ -4167,7 +4186,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -4249,7 +4268,7 @@ public abstract class LivingEntity extends Entity implements Attackable { BlockPos blockposition = BlockPos.containing(d0, d1, d2); Level world = this.level(); - if (world.hasChunkAt(blockposition)) { -+ if (io.papermc.paper.util.TickThread.isTickThreadFor((ServerLevel)world, blockposition) && world.hasChunkAt(blockposition)) { // Folia - region threading ++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((ServerLevel)world, blockposition) && world.hasChunkAt(blockposition)) { // Folia - region threading boolean flag2 = false; while (!flag2 && blockposition.getY() > world.getMinBuildHeight()) { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 8b612b772ca87c852d0b108c2afd6785c261c9b9..bb5de770b6659379a68c077ff1cfc8d95d149c5c 100644 +index bd7c6ce15698aed70376c109ba36f52d6794a2f8..741ba5f0834ab5f0b0ffdeb91a9ff8cfaf922792 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -153,6 +153,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti +@@ -148,6 +148,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab public boolean aware = true; // CraftBukkit @@ -17597,29 +14859,28 @@ index 8b612b772ca87c852d0b108c2afd6785c261c9b9..bb5de770b6659379a68c077ff1cfc8d9 protected Mob(EntityType type, Level world) { super(type, world); this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); -@@ -298,9 +306,21 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti +@@ -293,8 +301,20 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab @Nullable @Override public LivingEntity getTarget() { + // Folia start - region threading -+ if (this.target != null && (!io.papermc.paper.util.TickThread.isTickThreadFor(this.target) || this.target.isRemoved())) { ++ if (this.target != null && (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.target) || this.target.isRemoved())) { + this.target = null; + return null; + } + // Folia end - region threading - return this.target; - } - -+ // Folia start - region threading -+ public LivingEntity getTargetRaw() { + return this.target; + } -+ // Folia end - region threading + - public org.bukkit.craftbukkit.entity.CraftMob getBukkitMob() { return (org.bukkit.craftbukkit.entity.CraftMob) super.getBukkitEntity(); } // Paper ++ // Folia start - region threading ++ public LivingEntity getTargetRaw() { + return this.target; + } ++ // Folia end - region threading @Nullable -@@ -314,7 +334,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti + protected final LivingEntity getTargetFromBrain() { +@@ -307,7 +327,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab } public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { @@ -17628,38 +14889,89 @@ index 8b612b772ca87c852d0b108c2afd6785c261c9b9..bb5de770b6659379a68c077ff1cfc8d9 if (fireEvent) { if (reason == EntityTargetEvent.TargetReason.UNKNOWN && this.getTarget() != null && entityliving == null) { reason = this.getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; -@@ -1879,6 +1899,17 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti +@@ -1784,16 +1804,22 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.goalSelector.removeAllGoals(predicate); } + // Folia start - region threading - move inventory clearing until after the dimension change -+ @Override + @Override +- protected void removeAfterChangingDimensions() { +- super.removeAfterChangingDimensions(); + protected void postRemoveAfterChangingDimensions() { -+ this.getAllSlots().forEach((itemstack) -> { -+ if (!itemstack.isEmpty()) { -+ itemstack.setCount(0); -+ } -+ }); -+ } + this.getAllSlots().forEach((itemstack) -> { + if (!itemstack.isEmpty()) { + itemstack.setCount(0); + } +- + }); + } + // Folia end - region threading - move inventory clearing until after the dimension change + - @Override - protected void removeAfterChangingDimensions() { - super.removeAfterChangingDimensions(); -@@ -1887,12 +1918,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti - this.level().getCraftServer().getPluginManager().callEvent(event); // CraftBukkit - this.dropLeash(true, event.isDropLeash()); - // Paper end - Expand EntityUnleashEvent -- this.getAllSlots().forEach((itemstack) -> { -- if (!itemstack.isEmpty()) { -- itemstack.setCount(0); -- } -- -- }); ++ @Override ++ protected void removeAfterChangingDimensions() { ++ super.removeAfterChangingDimensions(); + // Folia - region threading - move inventory clearing until after the dimension change - move into postRemoveAfterChangingDimensions - } ++ } @Nullable + @Override +diff --git a/src/main/java/net/minecraft/world/entity/PortalProcessor.java b/src/main/java/net/minecraft/world/entity/PortalProcessor.java +index 45761c113116ae7417e6ae99069bff35dbccdf30..c55d795209222a34c349d6f59eea36186324825d 100644 +--- a/src/main/java/net/minecraft/world/entity/PortalProcessor.java ++++ b/src/main/java/net/minecraft/world/entity/PortalProcessor.java +@@ -33,6 +33,12 @@ public class PortalProcessor { + return this.portal.getPortalDestination(world, entity, this.entryPosition); + } + ++ // Folia start - region threading ++ public boolean portalAsync(ServerLevel sourceWorld, Entity portalTarget) { ++ return this.portal.portalAsync(sourceWorld, portalTarget, this.entryPosition); ++ } ++ // Folia end - region threading ++ + public Portal.Transition getPortalLocalTransition() { + return this.portal.getLocalTransition(); + } +diff --git a/src/main/java/net/minecraft/world/entity/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java +index 45224dc3867892b298b006c17f7f85741fcc96d6..a72cc0eff0168e826c923607f693e8eebbb1f42f 100644 +--- a/src/main/java/net/minecraft/world/entity/TamableAnimal.java ++++ b/src/main/java/net/minecraft/world/entity/TamableAnimal.java +@@ -266,6 +266,11 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity { + LivingEntity entityliving = this.getOwner(); + + if (entityliving != null) { ++ // Folia start - region threading ++ if (entityliving.isRemoved() || entityliving.level() != this.level()) { ++ return; ++ } ++ // Folia end - region threading + this.teleportToAroundBlockPos(entityliving.blockPosition()); + } + +@@ -303,7 +308,22 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity { + return false; + } + Location to = event.getTo(); +- this.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); ++ // Folia start - region threading - can't teleport here, we may be removed by teleport logic - delay until next tick ++ // also, use teleportAsync so that crossing region boundaries will not blow up ++ Location finalTo = to; ++ Level sourceWorld = this.level(); ++ this.getBukkitEntity().taskScheduler.schedule((TamableAnimal nmsEntity) -> { ++ if (nmsEntity.level() == sourceWorld) { ++ nmsEntity.teleportAsync( ++ (net.minecraft.server.level.ServerLevel)nmsEntity.level(), ++ new net.minecraft.world.phys.Vec3(finalTo.getX(), finalTo.getY(), finalTo.getZ()), ++ Float.valueOf(finalTo.getYaw()), Float.valueOf(finalTo.getPitch()), ++ net.minecraft.world.phys.Vec3.ZERO, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN, Entity.TELEPORT_FLAG_LOAD_CHUNK, ++ null ++ ); ++ } ++ }, null, 1L); ++ // Folia end - region threading - can't teleport here, we may be removed by teleport logic - delay until next tick + // CraftBukkit end + this.navigation.stop(); + return true; diff --git a/src/main/java/net/minecraft/world/entity/ai/Brain.java b/src/main/java/net/minecraft/world/entity/ai/Brain.java index af6f91c66e9cc7e0d491e6efed992a140947155e..d4e6198fdfbefe54e374479a1f1d835ab98ce93a 100644 --- a/src/main/java/net/minecraft/world/entity/ai/Brain.java @@ -17684,7 +14996,7 @@ index af6f91c66e9cc7e0d491e6efed992a140947155e..d4e6198fdfbefe54e374479a1f1d835a } } diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java b/src/main/java/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java -index 7302d397d39d8400527ab2da4adaf8d792256749..cb92900d5528b953ec4c9f071a75a064987b9a9f 100644 +index 7302d397d39d8400527ab2da4adaf8d792256749..ee3b8de9b700202da776c68579532bf11319a001 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/PoiCompetitorScan.java @@ -19,6 +19,11 @@ public class PoiCompetitorScan { @@ -17692,7 +15004,7 @@ index 7302d397d39d8400527ab2da4adaf8d792256749..cb92900d5528b953ec4c9f071a75a064 (jobSite, mobs) -> (world, entity, time) -> { GlobalPos globalPos = context.get(jobSite); + // Folia start - region threading -+ if (globalPos.dimension() != world.dimension() || !io.papermc.paper.util.TickThread.isTickThreadFor(world, globalPos.pos())) { ++ if (globalPos.dimension() != world.dimension() || !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world, globalPos.pos())) { + return true; + } + // Folia end - region threading @@ -17700,64 +15012,20 @@ index 7302d397d39d8400527ab2da4adaf8d792256749..cb92900d5528b953ec4c9f071a75a064 .getType(globalPos.pos()) .ifPresent( diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java -index edd29c2f4d0151d512618115a8fb4b7423171491..cb6fa1c7345fac3808897ecd46ed2314f2aff139 100644 +index 15d7be9ed4a973044dd4399db46aaa244730b836..df4cce1d3baef0ad386f5bc201663ae569e7b36d 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java -@@ -71,7 +71,7 @@ public class FollowOwnerGoal extends Goal { - - @Override +@@ -51,7 +51,7 @@ public class FollowOwnerGoal extends Goal { public boolean canContinueToUse() { -- return this.navigation.isDone() ? false : (this.unableToMove() ? false : this.tamable.distanceToSqr((Entity) this.owner) > (double) (this.stopDistance * this.stopDistance)); -+ return this.navigation.isDone() ? false : (this.unableToMove() ? false : (this.owner.level() == this.level && this.tamable.distanceToSqr((Entity) this.owner) > (double) (this.stopDistance * this.stopDistance))); // Folia - region threading - check level + return !this.navigation.isDone() + && !this.tamable.unableToMoveToOwner() +- && !(this.tamable.distanceToSqr(this.owner) <= (double)(this.stopDistance * this.stopDistance)); ++ && !(this.owner.level() == this.tamable.level() && this.tamable.distanceToSqr(this.owner) <= (double)(this.stopDistance * this.stopDistance)); // Folia - region threading - check level } - private boolean unableToMove() { -@@ -97,7 +97,7 @@ public class FollowOwnerGoal extends Goal { - if (this.tamable.distanceToSqr(this.owner) <= 16 * 16) this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float) this.tamable.getMaxHeadXRot()); // Paper - Limit pet look distance - if (--this.timeToRecalcPath <= 0) { - this.timeToRecalcPath = this.adjustedTickDelay(10); -- if (this.tamable.distanceToSqr((Entity) this.owner) >= 144.0D) { -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.owner) || this.tamable.distanceToSqr((Entity) this.owner) >= 144.0D) { // Folia - region threading - required in case the player suddenly moves into another dimension - this.teleportToOwner(); - } else { - this.navigation.moveTo((Entity) this.owner, this.speedModifier); -@@ -108,6 +108,11 @@ public class FollowOwnerGoal extends Goal { - - private void teleportToOwner() { - BlockPos blockposition = this.owner.blockPosition(); -+ // Folia start - region threading -+ if (this.owner.isRemoved() || this.owner.level() != level) { -+ return; -+ } -+ // Folia end - region threading - - for (int i = 0; i < 10; ++i) { - int j = this.randomIntInclusive(-3, 3); -@@ -134,7 +139,21 @@ public class FollowOwnerGoal extends Goal { - return false; - } - Location to = event.getTo(); -- this.tamable.moveTo(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); -+ // Folia start - region threading - can't teleport here, we may be removed by teleport logic - delay until next tick -+ // also, use teleportAsync so that crossing region boundaries will not blow up -+ Location finalTo = to; -+ this.tamable.getBukkitEntity().taskScheduler.schedule((TamableAnimal nmsEntity) -> { -+ if (nmsEntity.level() == FollowOwnerGoal.this.level) { -+ nmsEntity.teleportAsync( -+ (net.minecraft.server.level.ServerLevel)nmsEntity.level(), -+ new net.minecraft.world.phys.Vec3(finalTo.getX(), finalTo.getY(), finalTo.getZ()), -+ Float.valueOf(finalTo.getYaw()), Float.valueOf(finalTo.getPitch()), -+ net.minecraft.world.phys.Vec3.ZERO, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN, Entity.TELEPORT_FLAG_LOAD_CHUNK, -+ null -+ ); -+ } -+ }, null, 1L); -+ // Folia start - region threading - can't teleport here, we may be removed by teleport logic - delay until next tick - // CraftBukkit end - this.navigation.stop(); - return true; + @Override diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -index 62634bedd97c5be9ecce24ab0cff205715a68da8..197bbc149e9bf270a304c987ef76373c780b6a86 100644 +index 62634bedd97c5be9ecce24ab0cff205715a68da8..e03e07752e335d694c52c8dd780e71528021f15c 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java @@ -42,6 +42,11 @@ public class GroundPathNavigation extends PathNavigation { @@ -17765,7 +15033,7 @@ index 62634bedd97c5be9ecce24ab0cff205715a68da8..197bbc149e9bf270a304c987ef76373c @Override public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper - EntityPathfindEvent + // Folia start - region threading -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level, target)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level, target)) { + return null; + } + // Folia end - region threading @@ -17822,7 +15090,7 @@ index 4d5372b80b2b1906ecf5bf7e75df08b5d3792bfd..9ee62edd8f71244ea406f19cdd62fa5a }).filter((entityplayer) -> { return entity.closerThan(entityplayer, 10.0D); diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index 36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff..316b5db25f749854052449c1a2a48f20b8ead05b 100644 +index 36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff..a2bc957bd643b90595711270ab88382c957e24b6 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java @@ -21,62 +21,66 @@ import org.slf4j.Logger; @@ -17849,7 +15117,7 @@ index 36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff..316b5db25f749854052449c1a2a48f20 + // Folia start - region threading + // check if the spawn pos is no longer owned by this region + if (worldData.villageSiegeState.siegeState != State.SIEGE_DONE -+ && !io.papermc.paper.util.TickThread.isTickThreadFor(world, worldData.villageSiegeState.spawnX >> 4, worldData.villageSiegeState.spawnZ >> 4, 8)) { ++ && !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world, worldData.villageSiegeState.spawnX >> 4, worldData.villageSiegeState.spawnZ >> 4, 8)) { + // can't spawn here, just re-set + worldData.villageSiegeState = new io.papermc.paper.threadedregions.RegionizedWorldData.VillageSiegeState(); + } @@ -17968,13 +15236,13 @@ index 36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff..316b5db25f749854052449c1a2a48f20 SIEGE_CAN_ACTIVATE, SIEGE_TONIGHT, SIEGE_DONE; diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index c6f193339fdcbcc938d4eafdcad0b112cf1698d5..cf69b4ed4a40015a23d053230c3f326a700788ef 100644 +index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..1e7f11e5dda502fde6ca122f3edb2d2a161f3469 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -50,11 +50,13 @@ public class PoiManager extends SectionStorage { +@@ -58,11 +58,13 @@ public class PoiManager extends SectionStorage implements ca.spotted } - protected void updateDistanceTracking(long section) { + private void updateDistanceTracking(long section) { + synchronized (this.villageDistanceTracker) { // Folia - region threading if (this.isVillageCenter(section)) { this.villageDistanceTracker.setSource(section, POI_DATA_SOURCE); @@ -17983,20 +15251,20 @@ index c6f193339fdcbcc938d4eafdcad0b112cf1698d5..cf69b4ed4a40015a23d053230c3f326a } + } // Folia - region threading } - // Paper end - rewrite chunk system -@@ -229,8 +231,10 @@ public class PoiManager extends SectionStorage { + @Override +@@ -359,8 +361,10 @@ public class PoiManager extends SectionStorage implements ca.spotted } public int sectionsToVillage(SectionPos pos) { + synchronized (this.villageDistanceTracker) { // Folia - region threading - this.villageDistanceTracker.propagateUpdates(); // Paper - replace distance tracking util - return convertBetweenLevels(this.villageDistanceTracker.getLevel(io.papermc.paper.util.CoordinateUtils.getChunkSectionKey(pos))); // Paper - replace distance tracking util + this.villageDistanceTracker.propagateUpdates(); // Paper - rewrite chunk system + return convertBetweenLevels(this.villageDistanceTracker.getLevel(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkSectionKey(pos))); // Paper - rewrite chunk system + } // Folia - region threading } boolean isVillageCenter(long pos) { -@@ -244,7 +248,9 @@ public class PoiManager extends SectionStorage { +@@ -374,7 +378,9 @@ public class PoiManager extends SectionStorage implements ca.spotted @Override public void tick(BooleanSupplier shouldKeepTicking) { @@ -18007,10 +15275,10 @@ index c6f193339fdcbcc938d4eafdcad0b112cf1698d5..cf69b4ed4a40015a23d053230c3f326a @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 0dfb8109fd8c022b079da00f6a0e3fc85b57bf7a..cdc431ab27b1837b852c8fb559d0324b94d33311 100644 +index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9fa53a54f2d39962aec8abe95d8311da0f7b40a6 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -1025,6 +1025,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1036,6 +1036,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public boolean canBeeUse() { @@ -18022,7 +15290,7 @@ index 0dfb8109fd8c022b079da00f6a0e3fc85b57bf7a..cdc431ab27b1837b852c8fb559d0324b return Bee.this.hivePos != null && !Bee.this.hasRestriction() && Bee.this.wantsToEnterHive() && !this.hasReachedTarget(Bee.this.hivePos) && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES); } -@@ -1141,6 +1146,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1152,6 +1157,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public boolean canBeeUse() { @@ -18035,10 +15303,10 @@ index 0dfb8109fd8c022b079da00f6a0e3fc85b57bf7a..cdc431ab27b1837b852c8fb559d0324b } diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java -index 07559b9629d4ecb40b511256f400a781e39820e0..1cd5f0178c016736ebaf0f4449262da680cc2fab 100644 +index 23d4dcc82115fd1a0a77565a0472304042d5f12d..c7cd84527887cf7280b802cc110a9352cf63b4b3 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java -@@ -367,7 +367,7 @@ public class Cat extends TamableAnimal implements VariantHolder= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate // CraftBukkit start - fire ItemDespawnEvent -@@ -560,14 +559,20 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -561,14 +560,22 @@ public class ItemEntity extends Entity implements TraceableEntity { return false; } @@ -18138,46 +15432,50 @@ index 8fd3845c4965843be9c37498760d93f1ebdff541..4b59206a342e7fc4174439df6842d0c6 + @Override + public void postChangeDimension() { + super.postChangeDimension(); -+ this.mergeWithNeighbours(); ++ if (!this.level().isClientSide) { ++ this.mergeWithNeighbours(); ++ } + } + // Folia end - region threading + @Nullable @Override - public Entity changeDimension(ServerLevel destination) { - Entity entity = super.changeDimension(destination); + public Entity changeDimension(DimensionTransition teleportTarget) { + Entity entity = super.changeDimension(teleportTarget); -- if (!this.level().isClientSide && entity instanceof ItemEntity) { -- ((ItemEntity) entity).mergeWithNeighbours(); +- if (!this.level().isClientSide && entity instanceof ItemEntity entityitem) { +- entityitem.mergeWithNeighbours(); - } + if (entity != null) entity.postChangeDimension(); // Folia - region threading - move to post change return entity; } diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -index f1f352ec0e51f5db59254841a06c176c5a876fc9..f11a701b3434b95342a6e8e89f5dea0d0080eff0 100644 +index 42bd2d9a1528b6210e4dfb56233062fd97c9743b..ee818605b7341e90da5e28206ffca04e1213393d 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java -@@ -75,7 +75,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { +@@ -95,8 +95,8 @@ public class PrimedTnt extends Entity implements TraceableEntity { @Override public void tick() { - if (this.level().spigotConfig.maxTntTicksPerTick > 0 && ++this.level().spigotConfig.currentPrimedTnt > this.level().spigotConfig.maxTntTicksPerTick) { return; } // Spigot +- this.handlePortal(); + if (this.level().spigotConfig.maxTntTicksPerTick > 0 && ++this.level().getCurrentWorldData().currentPrimedTnt > this.level().spigotConfig.maxTntTicksPerTick) { return; } // Spigot // Folia - region threading ++ //this.handlePortal(); // Folia - region threading this.applyGravity(); this.move(MoverType.SELF, this.getDeltaMovement()); // Paper start - Configurable TNT height nerf -@@ -114,7 +114,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { +@@ -135,7 +135,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { */ // Send position and velocity updates to nearby players on every tick while the TNT is in water. // This does pretty well at keeping their clients in sync with the server. - net.minecraft.server.level.ChunkMap.TrackedEntity ete = ((net.minecraft.server.level.ServerLevel)this.level()).getChunkSource().chunkMap.entityMap.get(this.getId()); -+ net.minecraft.server.level.ChunkMap.TrackedEntity ete = this.tracker; // Folia - region threading ++ net.minecraft.server.level.ChunkMap.TrackedEntity ete = this.moonrise$getTrackedEntity(); // Folia - region threading if (ete != null) { net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket velocityPacket = new net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket(this); net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket positionPacket = new net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket(this); diff --git a/src/main/java/net/minecraft/world/entity/monster/Vex.java b/src/main/java/net/minecraft/world/entity/monster/Vex.java -index fd3b37dde54623ba38186efb2a64d364c86b81d2..f21beb135e336dcd5aa46e7f0229f29ec780545a 100644 +index 2985296a9a034e535157f55e322fc8c107827752..d9ae587c5d3ef67d5ee8c9238c39a8232b479398 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Vex.java +++ b/src/main/java/net/minecraft/world/entity/monster/Vex.java @@ -349,7 +349,7 @@ public class Vex extends Monster implements TraceableEntity { @@ -18185,15 +15483,15 @@ index fd3b37dde54623ba38186efb2a64d364c86b81d2..f21beb135e336dcd5aa46e7f0229f29e BlockPos blockposition = Vex.this.getBoundOrigin(); - if (blockposition == null) { -+ if (blockposition == null || !io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)Vex.this.level(), blockposition)) { // Folia - region threading ++ if (blockposition == null || !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)Vex.this.level(), blockposition)) { // Folia - region threading blockposition = Vex.this.blockPosition(); } diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index e42dfc62bb179be1ab01b0096c05c6549d38abbc..3715411f337e6adea36fe1ceb2e93e830f703cda 100644 +index 2280004638fd19ed018cb3e77d53a018b34ec516..9460ffdede40a2e3601d3c97b1d1ca4e62dcbf29 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -@@ -92,7 +92,7 @@ public class Zombie extends Monster { +@@ -96,7 +96,7 @@ public class Zombie extends Monster { private boolean canBreakDoors; private int inWaterTime; public int conversionTime; @@ -18202,7 +15500,7 @@ index e42dfc62bb179be1ab01b0096c05c6549d38abbc..3715411f337e6adea36fe1ceb2e93e83 private boolean shouldBurnInDay = true; // Paper - Add more Zombie API public Zombie(EntityType type, Level world) { -@@ -215,10 +215,7 @@ public class Zombie extends Monster { +@@ -219,10 +219,7 @@ public class Zombie extends Monster { public void tick() { if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { if (this.isUnderWaterConverting()) { @@ -18214,7 +15512,7 @@ index e42dfc62bb179be1ab01b0096c05c6549d38abbc..3715411f337e6adea36fe1ceb2e93e83 if (this.conversionTime < 0) { this.doUnderWaterConversion(); } -@@ -235,7 +232,7 @@ public class Zombie extends Monster { +@@ -239,7 +236,7 @@ public class Zombie extends Monster { } super.tick(); @@ -18223,7 +15521,7 @@ index e42dfc62bb179be1ab01b0096c05c6549d38abbc..3715411f337e6adea36fe1ceb2e93e83 } @Override -@@ -274,7 +271,7 @@ public class Zombie extends Monster { +@@ -280,7 +277,7 @@ public class Zombie extends Monster { } // Paper end - Add more Zombie API public void startUnderWaterConversion(int ticksUntilWaterConversion) { @@ -18233,10 +15531,10 @@ index e42dfc62bb179be1ab01b0096c05c6549d38abbc..3715411f337e6adea36fe1ceb2e93e83 this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true); } diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java -index f38acc96f71298e40ce9433e7759fd223ca55e48..474e94390eb68a56c81d91a736b72f6d00577971 100644 +index e0dabbf6d7a87b8722769c78ef0d2ba4353ed2cb..90627c6a0c0e0f03a20cd32a7f15a0cfab7e592e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java +++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java -@@ -71,7 +71,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -74,7 +74,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { @Nullable private MerchantOffers tradeOffers; private int villagerXp; @@ -18245,7 +15543,7 @@ index f38acc96f71298e40ce9433e7759fd223ca55e48..474e94390eb68a56c81d91a736b72f6d public ZombieVillager(EntityType type, Level world) { super(type, world); -@@ -152,10 +152,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -155,10 +155,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { public void tick() { if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { int i = this.getConversionProgress(); @@ -18257,7 +15555,7 @@ index f38acc96f71298e40ce9433e7759fd223ca55e48..474e94390eb68a56c81d91a736b72f6d this.villagerConversionTime -= i; if (this.villagerConversionTime <= 0) { -@@ -164,7 +161,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -167,7 +164,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { } super.tick(); @@ -18267,10 +15565,10 @@ index f38acc96f71298e40ce9433e7759fd223ca55e48..474e94390eb68a56c81d91a736b72f6d @Override diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index d323cf157f2a910916baa9ce3f7e5bc81648c47d..57355dfc6c52e038ef92b7bf7cf7af5b5672704a 100644 +index 49b35fab8ee98a384ee12d36bbe2ac813342f1d6..5f3104b2a46d4b47cf505012438f848e3b744315 100644 --- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -220,10 +220,18 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa +@@ -226,10 +226,18 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa this.readInventoryFromTag(nbt, this.registryAccess()); } @@ -18284,10 +15582,10 @@ index d323cf157f2a910916baa9ce3f7e5bc81648c47d..57355dfc6c52e038ef92b7bf7cf7af5b + @Nullable @Override - public Entity changeDimension(ServerLevel destination) { + public Entity changeDimension(DimensionTransition teleportTarget) { - this.stopTrading(); + this.preChangeDimension(); // Folia - region threading - move into preChangeDimension - return super.changeDimension(destination); + return super.changeDimension(teleportTarget); } diff --git a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java @@ -18319,7 +15617,7 @@ index e0e5046c84941a8d17e18c177f3daea9cb631940..61adcf62cb738d7dd5c785780824f64c return 0; } else { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index a7930f9875aa4aca997caaead46ecdc21e5e11d7..6339967b154af1ca9632c7b8b315d612f4b80ea2 100644 +index 7e1871401ec5e3e9a85232053490259f132aec0a..91728a992a29bc22e46a260750d5dd88e629bfd1 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -204,7 +204,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @@ -18331,7 +15629,7 @@ index a7930f9875aa4aca997caaead46ecdc21e5e11d7..6339967b154af1ca9632c7b8b315d612 } @Override -@@ -722,6 +722,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -724,6 +724,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler ServerLevel worldserver = minecraftserver.getLevel(globalpos.dimension()); if (worldserver != null) { @@ -18340,7 +15638,7 @@ index a7930f9875aa4aca997caaead46ecdc21e5e11d7..6339967b154af1ca9632c7b8b315d612 PoiManager villageplace = worldserver.getPoiManager(); Optional> optional = villageplace.getType(globalpos.pos()); BiPredicate> bipredicate = (BiPredicate) Villager.POI_MEMORIES.get(pos); -@@ -730,6 +732,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -732,6 +734,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler villageplace.release(globalpos.pos()); DebugPackets.sendPoiTicketCountPacket(worldserver, globalpos.pos()); } @@ -18442,10 +15740,10 @@ index c72b6ea5530e54fc373c701028e1c147cea34b59..6677b4cc23253a1b7dfbc2e12e666699 entityvillagertrader.setWanderTarget(blockposition1); entityvillagertrader.restrictTo(blockposition1, 16); diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 25595bef64199c4ddbe69c65fd149eec33e778ad..b0f2e614c90137c526de865bd64469f09b95c964 100644 +index 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..b3377ed06d703f54e01ba174e5a06dc928cdff96 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1533,6 +1533,14 @@ public abstract class Player extends LivingEntity { +@@ -1558,6 +1558,14 @@ public abstract class Player extends LivingEntity { } @@ -18461,15 +15759,15 @@ index 25595bef64199c4ddbe69c65fd149eec33e778ad..b0f2e614c90137c526de865bd64469f0 return false; } diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -index 72c48bf33a0b882e4c94f1a7c343a170b1db0f53..fe92fffd7cab267024af18d010345d9b67c62045 100644 +index 9ca29b3d4bf8bca5f51f3644e12fcbec2cb5d35e..b5edbd36a1114449fe5f9bf1018bff7988fa7262 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -163,6 +163,11 @@ public abstract class AbstractArrow extends Projectile { +@@ -187,6 +187,11 @@ public abstract class AbstractArrow extends Projectile { @Override public void tick() { super.tick(); + // Folia start - region threading - make sure entities do not move into regions they do not own -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { + return; + } + // Folia end - region threading - make sure entities do not move into regions they do not own @@ -18477,31 +15775,31 @@ index 72c48bf33a0b882e4c94f1a7c343a170b1db0f53..fe92fffd7cab267024af18d010345d9b Vec3 vec3d = this.getDeltaMovement(); diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -index a81d6a52674ddf7f818a7665cccd21dd8ea86cbe..b8c981f9d0b284cc459f4d230150ee49090ab346 100644 +index 3107ad04dda9f43976a385976d6952e2f2af3939..dc075e777055508c17ac4fa4d46e51e1721cb2e8 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -@@ -81,6 +81,11 @@ public abstract class AbstractHurtingProjectile extends Projectile { +@@ -80,6 +80,11 @@ public abstract class AbstractHurtingProjectile extends Projectile { this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } else { super.tick(); + // Folia start - region threading - make sure entities do not move into regions they do not own -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { + return; + } + // Folia end - region threading - make sure entities do not move into regions they do not own if (this.shouldBurn()) { - this.igniteForSeconds(1); + this.igniteForSeconds(1.0F); } diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index 6671796d292fbc922a94271136f5a7a4bbdedaca..271724b9df667154ed5e166dfadad51a598d2ea2 100644 +index 09d465947a5720e05c350d455c86002682104079..16bb8fedbfc1618a77c0967eaa0b234d0d82255b 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -134,6 +134,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { +@@ -136,6 +136,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { }); } + // Folia start - region threading -+ if (this.attachedToEntity != null && !io.papermc.paper.util.TickThread.isTickThreadFor(this.attachedToEntity)) { ++ if (this.attachedToEntity != null && !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.attachedToEntity)) { + this.attachedToEntity = null; + } + // Folia end - region threading @@ -18509,19 +15807,19 @@ index 6671796d292fbc922a94271136f5a7a4bbdedaca..271724b9df667154ed5e166dfadad51a if (this.attachedToEntity != null) { if (this.attachedToEntity.isFallFlying()) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index 7dd5e0b935d98d552c916f8412569ff4aa0e9b04..1c2292d25bc42c82b85887055541e5c3f7c14e40 100644 +index 1223c5d23d0ea6aed068bdf0f5725e2ad49fc82c..cd058156c79223991c725882bc04426ad066af28 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -105,7 +105,7 @@ public class FishingHook extends Projectile { +@@ -106,7 +106,7 @@ public class FishingHook extends Projectile { - public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int luckOfTheSeaLevel, int lureLevel) { - this(EntityType.FISHING_BOBBER, world, luckOfTheSeaLevel, lureLevel); + public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int luckBonus, int waitTimeReductionTicks) { + this(EntityType.FISHING_BOBBER, world, luckBonus, waitTimeReductionTicks); - this.setOwner(thrower); + //this.setOwner(thrower); // Folia - region threading - move this down after position so that thread-checks do not fail float f = thrower.getXRot(); float f1 = thrower.getYRot(); float f2 = Mth.cos(-f1 * 0.017453292F - 3.1415927F); -@@ -117,6 +117,7 @@ public class FishingHook extends Projectile { +@@ -118,6 +118,7 @@ public class FishingHook extends Projectile { double d2 = thrower.getZ() - (double) f2 * 0.3D; this.moveTo(d0, d1, d2, f1, f); @@ -18529,19 +15827,19 @@ index 7dd5e0b935d98d552c916f8412569ff4aa0e9b04..1c2292d25bc42c82b85887055541e5c3 Vec3 vec3d = new Vec3((double) (-f3), (double) Mth.clamp(-(f5 / f4), -5.0F, 5.0F), (double) (-f2)); double d3 = vec3d.length(); -@@ -267,6 +268,11 @@ public class FishingHook extends Projectile { +@@ -268,6 +269,11 @@ public class FishingHook extends Projectile { } private boolean shouldStopFishing(net.minecraft.world.entity.player.Player player) { + // Folia start - region threading -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(player)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(player)) { + return true; + } + // Folia end - region threading ItemStack itemstack = player.getMainHandItem(); ItemStack itemstack1 = player.getOffhandItem(); boolean flag = itemstack.is(Items.FISHING_ROD); -@@ -630,10 +636,18 @@ public class FishingHook extends Projectile { +@@ -631,10 +637,18 @@ public class FishingHook extends Projectile { @Override public void remove(Entity.RemovalReason entity_removalreason, EntityRemoveEvent.Cause cause) { // CraftBukkit end @@ -18562,15 +15860,15 @@ index 7dd5e0b935d98d552c916f8412569ff4aa0e9b04..1c2292d25bc42c82b85887055541e5c3 public void onClientRemoval() { this.updateOwnerInfo((FishingHook) null); diff --git a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java -index ffd01d24cbfc90e2a8807757e61b2cf20a944354..4ead19577f218dc3bd84260da8968c0fa00d7710 100644 +index 8575941fd238750c5d56843989a48bcbde2d8a88..185501a2daea0351281c578bff79dc506994e146 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java +++ b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java -@@ -38,6 +38,11 @@ public class LlamaSpit extends Projectile { +@@ -41,6 +41,11 @@ public class LlamaSpit extends Projectile { @Override public void tick() { super.tick(); + // Folia start - region threading - make sure entities do not move into regions they do not own -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { + return; + } + // Folia end - region threading - make sure entities do not move into regions they do not own @@ -18578,10 +15876,10 @@ index ffd01d24cbfc90e2a8807757e61b2cf20a944354..4ead19577f218dc3bd84260da8968c0f HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 74c596264d4da551437bd2a23e1c70022cfc73fc..a8d2f7a9d0bcb6db0b38ac30b098d59951053b47 100644 +index a01c0d9ae53d1b748c5da914069bd672cb1215c7..c7a59234fb1fdc09745b62039011d0d2f7cd3fb6 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -71,9 +71,20 @@ public abstract class Projectile extends Entity implements TraceableEntity { +@@ -77,9 +77,20 @@ public abstract class Projectile extends Entity implements TraceableEntity { } // Paper end - Refresh ProjectileSource for projectiles @@ -18592,32 +15890,32 @@ index 74c596264d4da551437bd2a23e1c70022cfc73fc..a8d2f7a9d0bcb6db0b38ac30b098d599 @Override public Entity getOwner() { + Entity ret = this.getOwnerRaw(); -+ return io.papermc.paper.util.TickThread.isTickThreadFor(ret) ? ret : null; ++ return ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(ret) ? ret : null; + } + // Folia end - region threading + + @Nullable + public Entity getOwnerRaw() { // Folia - region threading -+ io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot update owner state asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, "Cannot update owner state asynchronously"); // Folia - region threading if (this.cachedOwner != null && !this.cachedOwner.isRemoved()) { this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles return this.cachedOwner; -@@ -343,7 +354,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { +@@ -361,7 +372,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { public boolean mayInteract(Level world, BlockPos pos) { Entity entity = this.getOwner(); - return entity instanceof Player ? entity.mayInteract(world, pos) : entity == null || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); -+ return entity instanceof Player && io.papermc.paper.util.TickThread.isTickThreadFor(entity) ? entity.mayInteract(world, pos) : entity == null || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Folia - region threading ++ return entity instanceof Player && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity) ? entity.mayInteract(world, pos) : entity == null || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Folia - region threading } public boolean mayBreak(Level world) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java b/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java -index 3a11ad32d95088a5aca713a1a6a984cc22d4fa9a..6e16c7494490d584785ac8f06fe0f3dae236a97a 100644 +index 1711ad457e7d1233fd32edc3e9e3b9f1e3be9980..62c55a5ef3c6c46d3c7638fd2e726d15690d8a0b 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java +++ b/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java -@@ -26,7 +26,7 @@ public class SmallFireball extends Fireball { - public SmallFireball(Level world, LivingEntity owner, double velocityX, double velocityY, double velocityZ) { - super(EntityType.SMALL_FIREBALL, owner, velocityX, velocityY, velocityZ, world); +@@ -29,7 +29,7 @@ public class SmallFireball extends Fireball { + public SmallFireball(Level world, LivingEntity owner, Vec3 velocity) { + super(EntityType.SMALL_FIREBALL, owner, velocity, world); // CraftBukkit start - if (this.getOwner() != null && this.getOwner() instanceof Mob) { + if (owner != null && owner instanceof Mob) { // Folia - region threading @@ -18625,26 +15923,26 @@ index 3a11ad32d95088a5aca713a1a6a984cc22d4fa9a..6e16c7494490d584785ac8f06fe0f3da } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -index 5b32364f1452e1b395b91921d045060fd94881b8..51f2ec6dd466c12282a68d07b46b8478f25c5135 100644 +index bf4c1883a1257af89428d6580a177f3af3759ee7..38ff937ef3908d344dd43b8934854ea66eb7b733 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -@@ -44,6 +44,11 @@ public abstract class ThrowableProjectile extends Projectile { +@@ -43,6 +43,11 @@ public abstract class ThrowableProjectile extends Projectile { @Override public void tick() { super.tick(); + // Folia start - region threading - make sure entities do not move into regions they do not own -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { + return; + } + // Folia end - region threading - make sure entities do not move into regions they do not own HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); - boolean flag = false; + if (movingobjectposition.getType() != HitResult.Type.MISS) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -index 519755b7f8bc7e8bb9fab135fc5bf7de3a9419f9..b3b7c61db5e640acdc9f4aa70ebf1d8b8e3ec272 100644 +index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582fe430536e 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -@@ -45,6 +45,78 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { +@@ -47,6 +47,76 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { entityHitResult.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F); } @@ -18653,30 +15951,22 @@ index 519755b7f8bc7e8bb9fab135fc5bf7de3a9419f9..b3b7c61db5e640acdc9f4aa70ebf1d8b + // ignore retired callback, in those cases we do not want to teleport + source.getBukkitEntity().taskScheduler.schedule( + (Entity entity) -> { ++ if (!isAllowedToTeleportOwner(entity, checkWorld)) { ++ return; ++ } + // source is now an invalid reference, do not use it, use the entity parameter + net.minecraft.world.phys.Vec3 endermitePos = entity.position(); + -+ if (entity.level() != checkWorld) { -+ // cannot teleport cross-world -+ return; -+ } -+ if (entity.isVehicle()) { -+ // cannot teleport vehicles -+ return; -+ } + // dismount from any vehicles, so we can teleport and to prevent desync + if (entity.isPassenger()) { + entity.stopRiding(); + } + -+ // reset fall damage so that if the entity was falling they do not instantly die -+ entity.resetFallDistance(); -+ + entity.teleportAsync( + checkWorld, to, null, null, null, + PlayerTeleportEvent.TeleportCause.ENDER_PEARL, + // chunk could have been unloaded -+ Entity.TELEPORT_FLAG_LOAD_CHUNK, ++ Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS | Entity.TELEPORT_FLAG_LOAD_CHUNK, + (Entity teleported) -> { + // entity is now an invalid reference, do not use it, instead use teleported + if (teleported instanceof ServerPlayer player) { @@ -18695,13 +15985,13 @@ index 519755b7f8bc7e8bb9fab135fc5bf7de3a9419f9..b3b7c61db5e640acdc9f4aa70ebf1d8b + world.addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL); + }; + -+ if (io.papermc.paper.util.TickThread.isTickThreadFor(world, endermitePos, net.minecraft.world.phys.Vec3.ZERO, 1)) { ++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world, endermitePos, net.minecraft.world.phys.Vec3.ZERO, 1)) { + spawn.run(); + } else { + io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue( + world, -+ io.papermc.paper.util.CoordinateUtils.getChunkCoordinate(endermitePos.x), -+ io.papermc.paper.util.CoordinateUtils.getChunkCoordinate(endermitePos.z), ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkCoordinate(endermitePos.x), ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkCoordinate(endermitePos.z), + spawn + ); + } @@ -18709,13 +15999,19 @@ index 519755b7f8bc7e8bb9fab135fc5bf7de3a9419f9..b3b7c61db5e640acdc9f4aa70ebf1d8b + } + + // damage player -+ player.hurt(player.damageSources().fall(), 5.0F); ++ teleported.resetFallDistance(); ++ player.resetCurrentImpulseContext(); ++ player.hurt(teleported.damageSources().fall().customEventDamager(teleported), 5.0F); // CraftBukkit // Paper - fix DamageSource API ++ playSound(teleported.level(), to); ++ } else { ++ // reset fall damage so that if the entity was falling they do not instantly die ++ teleported.resetFallDistance(); ++ playSound(teleported.level(), to); + } + } + ); + }, -+ null, -+ 1L ++ null, 1L + ); + } + // Folia end - region threading @@ -18723,31 +16019,32 @@ index 519755b7f8bc7e8bb9fab135fc5bf7de3a9419f9..b3b7c61db5e640acdc9f4aa70ebf1d8b @Override protected void onHit(HitResult hitResult) { super.onHit(hitResult); -@@ -54,6 +126,20 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { - } +@@ -59,6 +129,20 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { - if (!this.level().isClientSide && !this.isRemoved()) { -+ // Folia start - region threading -+ if (true) { -+ // we can't fire events, because we do not actually know where the other entity is located -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this)) { -+ throw new IllegalStateException("Must be on tick thread for ticking entity: " + this); + if (world instanceof ServerLevel worldserver) { + if (!this.isRemoved()) { ++ // Folia start - region threading ++ if (true) { ++ // we can't fire events, because we do not actually know where the other entity is located ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this)) { ++ throw new IllegalStateException("Must be on tick thread for ticking entity: " + this); ++ } ++ Entity entity = this.getOwnerRaw(); ++ if (entity != null) { ++ attemptTeleport(entity, (ServerLevel)this.level(), this.position()); ++ } ++ this.discard(EntityRemoveEvent.Cause.HIT); ++ return; + } -+ Entity entity = this.getOwnerRaw(); -+ if (entity != null) { -+ attemptTeleport(entity, (ServerLevel)this.level(), this.position()); -+ } -+ this.discard(EntityRemoveEvent.Cause.HIT); -+ return; -+ } -+ // Folia end - region threading - Entity entity = this.getOwner(); ++ // Folia end - region threading + Entity entity = this.getOwner(); - if (entity instanceof ServerPlayer) { -@@ -112,6 +198,14 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { + if (entity != null && ThrownEnderpearl.isAllowedToTeleportOwner(entity, worldserver)) { +@@ -135,7 +219,15 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { } +- private void playSound(Level world, Vec3 pos) { + // Folia start - region threading + @Override + public void preChangeDimension() { @@ -18756,37 +16053,38 @@ index 519755b7f8bc7e8bb9fab135fc5bf7de3a9419f9..b3b7c61db5e640acdc9f4aa70ebf1d8b + } + // Folia end - region threading + - @Nullable - @Override - public Entity changeDimension(ServerLevel destination) { ++ private static void playSound(Level world, Vec3 pos) { // Folia - region threading - static + world.playSound((Player) null, pos.x, pos.y, pos.z, SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); + } + diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java -index fdff9788eaf663be79214b2ca491f0f0444f6136..7c9d63c94f36c1702fc48570b07393375c77bd21 100644 +index dcbef04bbaab988096bf416163264833e84d1967..e1987d1d6e5fd05e155c05dd1fdaf569e303d74a 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raid.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java -@@ -116,6 +116,13 @@ public class Raid { +@@ -113,6 +113,13 @@ public class Raid { public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(PDC_TYPE_REGISTRY); // Paper end + // Folia start - make raids thread-safe + public boolean ownsRaid() { + BlockPos center = this.getCenter(); -+ return center != null && io.papermc.paper.util.TickThread.isTickThreadFor(this.level, center.getX() >> 4, center.getZ() >> 4, 8); ++ return center != null && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, center.getX() >> 4, center.getZ() >> 4, 8); + } + // Folia end - make raids thread-safe + public Raid(int id, ServerLevel world, BlockPos pos) { this.raidEvent = new ServerBossEvent(Raid.RAID_NAME_COMPONENT, BossEvent.BossBarColor.RED, BossEvent.BossBarOverlay.NOTCHED_10); this.random = RandomSource.create(); -@@ -229,7 +236,7 @@ public class Raid { +@@ -226,7 +233,7 @@ public class Raid { return (entityplayer) -> { BlockPos blockposition = entityplayer.blockPosition(); - return entityplayer.isAlive() && this.level.getRaidAt(blockposition) == this; -+ return io.papermc.paper.util.TickThread.isTickThreadFor(entityplayer) && entityplayer.isAlive() && this.level.getRaidAt(blockposition) == this; // Folia - make raids thread-safe ++ return ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entityplayer) && entityplayer.isAlive() && this.level.getRaidAt(blockposition) == this; // Folia - make raids thread-safe }; } -@@ -553,7 +560,7 @@ public class Raid { +@@ -550,7 +557,7 @@ public class Raid { boolean flag = true; Collection collection = this.raidEvent.getPlayers(); long i = this.random.nextLong(); @@ -18796,10 +16094,10 @@ index fdff9788eaf663be79214b2ca491f0f0444f6136..7c9d63c94f36c1702fc48570b0739337 while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java -index 98e558338b5d9fb03869d2cc21b3e90eb45b95f6..3d3ce2c3be74ce09ae1dbeec4540d72b84c72ed8 100644 +index bbf21ea433f9e3963aac0ede597ed8d3c8e50ed8..bcf7a7d8137b62cd65ac3c6ff517025faa4f84b8 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raider.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java -@@ -96,7 +96,7 @@ public abstract class Raider extends PatrollingMonster { +@@ -89,7 +89,7 @@ public abstract class Raider extends PatrollingMonster { if (this.canJoinRaid()) { if (raid == null) { @@ -18809,7 +16107,7 @@ index 98e558338b5d9fb03869d2cc21b3e90eb45b95f6..3d3ce2c3be74ce09ae1dbeec4540d72b if (raid1 != null && Raids.canJoinRaid(this, raid1)) { diff --git a/src/main/java/net/minecraft/world/entity/raid/Raids.java b/src/main/java/net/minecraft/world/entity/raid/Raids.java -index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..1e441e723382518aff228656a1cb27559bdfd49a 100644 +index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..f4f9670e7aa81e3f60b34f0bc7313784573c74b8 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raids.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raids.java @@ -26,9 +26,9 @@ import net.minecraft.world.phys.Vec3; @@ -18887,7 +16185,7 @@ index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..1e441e723382518aff228656a1cb2755 DimensionType dimensionmanager = player.level().dimensionType(); - if (!dimensionmanager.hasRaids()) { -+ if (!dimensionmanager.hasRaids() || !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, player.chunkPosition().x, player.chunkPosition().z, 8)) { // Folia - region threading ++ if (!dimensionmanager.hasRaids() || !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, player.chunkPosition().x, player.chunkPosition().z, 8)) { // Folia - region threading return null; } else { List list = this.level.getPoiManager().getInRange((holder) -> { @@ -18931,7 +16229,7 @@ index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..1e441e723382518aff228656a1cb2755 if (raid1.isActive() && d1 < d0) { diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java -index 83ef2c3e7b06152b9e68f90002c35e77f148347d..4fa3084cc8d6f4e4ed7722adac40c71ef1b60d43 100644 +index 83ef2c3e7b06152b9e68f90002c35e77f148347d..83d9b685aaf6934acfd0ca9a869723146ec7cfcb 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java @@ -150,5 +150,11 @@ public class MinecartCommandBlock extends AbstractMinecart { @@ -18941,7 +16239,7 @@ index 83ef2c3e7b06152b9e68f90002c35e77f148347d..4fa3084cc8d6f4e4ed7722adac40c71e + // Folia start + @Override + public void threadCheck() { -+ io.papermc.paper.util.TickThread.ensureTickThread(MinecartCommandBlock.this, "Asynchronous sendSystemMessage to a command block"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(MinecartCommandBlock.this, "Asynchronous sendSystemMessage to a command block"); + } + // Folia end } @@ -18960,10 +16258,10 @@ index d7f8464bf3eed0e42a5fc7f14a5b243d171f8b5e..97bd1d7b4613c977376e43e180d8ec2a // Paper end diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java -index 786e4a8700cb84b16dd9b8892a0d1d5803924d81..eddfb0d0e265129db48959c816899415572acebd 100644 +index 647a4601deace52f8d855f512a73671f82b4762a..255f6e720ebe0f76954fdba03cd2aae006852a78 100644 --- a/src/main/java/net/minecraft/world/item/ArmorItem.java +++ b/src/main/java/net/minecraft/world/item/ArmorItem.java -@@ -77,7 +77,7 @@ public class ArmorItem extends Item implements Equipable { +@@ -68,7 +68,7 @@ public class ArmorItem extends Item implements Equipable { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); @@ -18973,10 +16271,10 @@ index 786e4a8700cb84b16dd9b8892a0d1d5803924d81..eddfb0d0e265129db48959c816899415 } diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf29a5dff9 100644 +index 2c312c0b741fb96a008881e9e01fa660a1fb63ab..0f77f1f0d5168c382c90b8bfe521eac801c9708d 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -400,31 +400,32 @@ public final class ItemStack implements DataComponentHolder { +@@ -421,31 +421,32 @@ public final class ItemStack implements DataComponentHolder { DataComponentPatch oldData = this.components.asPatch(); int oldCount = this.getCount(); ServerLevel world = (ServerLevel) context.getLevel(); @@ -19018,7 +16316,7 @@ index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf StructureGrowEvent structureEvent = null; if (treeType != null) { boolean isBonemeal = this.getItem() == Items.BONE_MEAL; -@@ -450,16 +451,16 @@ public final class ItemStack implements DataComponentHolder { +@@ -471,16 +472,16 @@ public final class ItemStack implements DataComponentHolder { entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat } @@ -19039,7 +16337,7 @@ index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf if (blocks.size() > 1) { placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); } else if (blocks.size() == 1 && item != Items.POWDER_SNOW_BUCKET) { // Paper - Fix cancelled powdered snow bucket placement -@@ -470,15 +471,15 @@ public final class ItemStack implements DataComponentHolder { +@@ -491,15 +492,15 @@ public final class ItemStack implements DataComponentHolder { enuminteractionresult = InteractionResult.FAIL; // cancel placement // PAIL: Remove this when MC-99075 fixed placeEvent.getPlayer().updateInventory(); @@ -19060,7 +16358,7 @@ index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf // Brute force all possible updates // Paper start - Don't resync blocks -@@ -487,7 +488,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -508,7 +509,7 @@ public final class ItemStack implements DataComponentHolder { // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir))); // } // Paper end - Don't resync blocks @@ -19069,7 +16367,7 @@ index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf } else { // Change the stack to its new contents if it hasn't been tampered with. if (this.getCount() == oldCount && Objects.equals(this.components.asPatch(), oldData)) { -@@ -495,7 +496,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -516,7 +517,7 @@ public final class ItemStack implements DataComponentHolder { this.setCount(newCount); } @@ -19078,7 +16376,7 @@ index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf world.setBlockEntity(e.getValue()); } -@@ -546,15 +547,15 @@ public final class ItemStack implements DataComponentHolder { +@@ -551,15 +552,15 @@ public final class ItemStack implements DataComponentHolder { } // SPIGOT-4678 @@ -19098,7 +16396,7 @@ index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf } } -@@ -582,8 +583,8 @@ public final class ItemStack implements DataComponentHolder { +@@ -587,8 +588,8 @@ public final class ItemStack implements DataComponentHolder { entityhuman.awardStat(Stats.ITEM_USED.get(item)); } } @@ -19110,7 +16408,7 @@ index f8589837070039b4911a9532b92fa959c7af6352..41400c4fcd5d204ba9624f776a3e2eaf return enuminteractionresult; diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..957396b145b1d1adf265f8b9aaeba052758f007a 100644 +index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6e56ba0ed 100644 --- a/src/main/java/net/minecraft/world/item/MapItem.java +++ b/src/main/java/net/minecraft/world/item/MapItem.java @@ -69,6 +69,7 @@ public class MapItem extends ComplexItem { @@ -19128,7 +16426,7 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..957396b145b1d1adf265f8b9aaeba052 - LevelChunk levelChunk = world.getChunkIfLoaded(SectionPos.blockToSectionCoord(r), SectionPos.blockToSectionCoord(s)); // Paper - Maps shouldn't load chunks - if (levelChunk != null && !levelChunk.isEmpty()) { // Paper - Maps shouldn't load chunks + LevelChunk levelChunk = world.getChunkIfLoaded(SectionPos.blockToSectionCoord(r), SectionPos.blockToSectionCoord(s)); // Paper - Maps shouldn't load chunks // Folia - super important that it uses getChunkIfLoaded -+ if (levelChunk != null && !levelChunk.isEmpty() && io.papermc.paper.util.TickThread.isTickThreadFor((ServerLevel)world, levelChunk.getPos())) { // Paper - Maps shouldn't load chunks // Folia - make sure chunk is owned ++ if (levelChunk != null && !levelChunk.isEmpty() && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((ServerLevel)world, levelChunk.getPos())) { // Paper - Maps shouldn't load chunks // Folia - make sure chunk is owned int t = 0; double e = 0.0; if (world.dimensionType().hasCeiling()) { @@ -19245,10 +16543,10 @@ index e6bfcc50cdf728216084bc00a5bb8b6b3b8f72e4..b8a571fcc44f67ac8f6089e039a8620b this.lastOutput = Component.literal("[" + simpledateformat.format(date) + "] ").append(message); diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea86975402598aacf6c 100644 +index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe127d3ffed 100644 --- a/src/main/java/net/minecraft/world/level/EntityGetter.java +++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -39,6 +39,12 @@ public interface EntityGetter { +@@ -27,6 +27,12 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst return this.getEntities(EntityTypeTest.forClass(entityClass), box, predicate); } @@ -19261,7 +16559,7 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 List players(); default List getEntities(@Nullable Entity except, AABB box) { -@@ -130,7 +136,7 @@ public interface EntityGetter { +@@ -125,7 +131,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst double d = -1.0; Player player = null; @@ -19270,7 +16568,7 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 if (targetPredicate == null || targetPredicate.test(player2)) { double e = player2.distanceToSqr(x, y, z); if ((maxDistance < 0.0 || e < maxDistance * maxDistance) && (d == -1.0 || e < d)) { -@@ -151,7 +157,7 @@ public interface EntityGetter { +@@ -146,7 +152,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { com.google.common.collect.ImmutableList.Builder builder = com.google.common.collect.ImmutableList.builder(); @@ -19279,7 +16577,7 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 if (predicate == null || predicate.test(human)) { double distanceSquared = human.distanceToSqr(x, y, z); -@@ -178,7 +184,7 @@ public interface EntityGetter { +@@ -173,7 +179,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst // Paper start - Affects Spawning API default boolean hasNearbyAlivePlayerThatAffectsSpawning(double x, double y, double z, double range) { @@ -19288,7 +16586,7 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 if (EntitySelector.PLAYER_AFFECTS_SPAWNING.test(player)) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check double distanceSqr = player.distanceToSqr(x, y, z); if (range < 0.0D || distanceSqr < range * range) { -@@ -191,7 +197,7 @@ public interface EntityGetter { +@@ -186,7 +192,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst // Paper end - Affects Spawning API default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { @@ -19297,7 +16595,7 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) { double d = player.distanceToSqr(x, y, z); if (range < 0.0 || d < range * range) { -@@ -205,17 +211,17 @@ public interface EntityGetter { +@@ -200,17 +206,17 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst @Nullable default Player getNearestPlayer(TargetingConditions targetPredicate, LivingEntity entity) { @@ -19318,7 +16616,7 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 } @Nullable -@@ -252,7 +258,7 @@ public interface EntityGetter { +@@ -243,7 +249,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst default List getNearbyPlayers(TargetingConditions targetPredicate, LivingEntity entity, AABB box) { List list = Lists.newArrayList(); @@ -19327,7 +16625,7 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 if (box.contains(player.getX(), player.getY(), player.getZ()) && targetPredicate.test(entity, player)) { list.add(player); } -@@ -278,8 +284,7 @@ public interface EntityGetter { +@@ -269,8 +275,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst @Nullable default Player getPlayerByUUID(UUID uuid) { @@ -19338,19 +16636,19 @@ index ea0aee88c7d901034427db201c1b2430f8a1d522..2a147a839e78b1d7bfb5eea869754025 return player; } diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 638447e8cb74b26f4f8e3862c2fb4a3048979ebc..248e0c46e613bdc831e6203c7fe55932a3da390c 100644 +index 6c66ee69beb55e5c5755bbf4d13c256541ce4468..7e0907638aa35c2f4c2dd083628d895ae9498292 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -865,17 +865,18 @@ public class Explosion { +@@ -844,17 +844,18 @@ public class Explosion { if (!this.level.paperConfig().environment.optimizeExplosions) { - return this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise explosions + return this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise collisions } + io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.level.getCurrentWorldData(); // Folia - region threading CacheKey key = new CacheKey(this, entity.getBoundingBox()); - Float blockDensity = this.level.explosionDensityCache.get(key); + Float blockDensity = worldData.explosionDensityCache.get(key); // Folia - region threading if (blockDensity == null) { - blockDensity = this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise explosions; + blockDensity = this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise collisions - this.level.explosionDensityCache.put(key, blockDensity); + worldData.explosionDensityCache.put(key, blockDensity); // Folia - region threading } @@ -19364,10 +16662,10 @@ index 638447e8cb74b26f4f8e3862c2fb4a3048979ebc..248e0c46e613bdc831e6203c7fe55932 private final double posX, posY, posZ; private final double minX, minY, minZ; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453e5e65518 100644 +index e2a0487089eb5a7bdc1433e4c75f69d8e9f9d5f9..b0ad25daf2d3c1727c61686e35eb4c03e1c60122 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -114,10 +114,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -116,10 +116,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public static final int TICKS_PER_DAY = 24000; public static final int MAX_ENTITY_SPAWN_Y = 20000000; public static final int MIN_ENTITY_SPAWN_Y = -20000000; @@ -19382,7 +16680,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 public final Thread thread; private final boolean isDebug; private int skyDarken; -@@ -127,7 +127,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -129,7 +129,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public float rainLevel; protected float oThunderLevel; public float thunderLevel; @@ -19391,7 +16689,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 /** @deprecated */ @Deprecated private final RandomSource threadSafeRandom = RandomSource.createThreadSafe(); -@@ -140,28 +140,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -142,28 +142,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl private final ResourceKey dimension; private final RegistryAccess registryAccess; private final DamageSources damageSources; @@ -19424,7 +16722,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot // Paper start - add paper world config private final io.papermc.paper.configuration.WorldConfiguration paperConfig; -@@ -175,9 +164,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -177,9 +166,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; @@ -19437,10 +16735,10 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 public CraftWorld getWorld() { return this.world; -@@ -205,6 +194,33 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - public abstract ResourceKey getTypeKey(); - +@@ -683,6 +672,32 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + return chunk != null ? chunk.getNoiseBiome(x, y, z) : this.getUncachedNoiseBiome(x, y, z); + } + // Paper end - optimise random ticking + // Folia start - region ticking + public final io.papermc.paper.threadedregions.RegionizedData worldRegionData + = new io.papermc.paper.threadedregions.RegionizedData<>( @@ -19467,11 +16765,10 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 + return this.getCurrentWorldData().getLocalPlayers(); + } + // Folia end - region ticking -+ - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config; Async-Anti-Xray: Pass executor + + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot - this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config -@@ -245,7 +261,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -724,7 +739,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl this.thread = Thread.currentThread(); this.biomeManager = new BiomeManager(this, i); this.isDebug = flag1; @@ -19480,7 +16777,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 this.registryAccess = iregistrycustom; this.damageSources = new DamageSources(iregistrycustom); // CraftBukkit start -@@ -833,8 +849,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -951,8 +966,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Nullable public final BlockState getBlockStateIfLoaded(BlockPos pos) { // CraftBukkit start - tree generation @@ -19491,11 +16788,11 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 if (previous != null) { return previous.getHandle(); } -@@ -896,16 +912,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1014,16 +1029,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { -+ io.papermc.paper.util.TickThread.ensureTickThread((ServerLevel)this, pos, "Updating block asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, pos, "Updating block asynchronously"); // Folia - region threading + io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.getCurrentWorldData(); // Folia - region threading // CraftBukkit start - tree generation - if (this.captureTreeGeneration) { @@ -19513,7 +16810,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 } blockstate.setData(state); blockstate.setFlag(flags); -@@ -922,10 +940,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1040,10 +1057,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // CraftBukkit start - capture blockstates boolean captured = false; @@ -19526,7 +16823,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 captured = true; } // CraftBukkit end -@@ -935,8 +953,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1053,8 +1070,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl if (iblockdata1 == null) { // CraftBukkit start - remove blockstate if failed (or the same) @@ -19537,7 +16834,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 } // CraftBukkit end return false; -@@ -973,7 +991,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1091,7 +1108,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl */ // CraftBukkit start @@ -19546,7 +16843,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 // Modularize client and physic updates // Spigot start try { -@@ -1023,7 +1041,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1136,7 +1153,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam CraftWorld world = ((ServerLevel) this).getWorld(); boolean cancelledUpdates = false; // Paper - Fix block place logic @@ -19555,7 +16852,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); this.getCraftServer().getPluginManager().callEvent(event); -@@ -1037,7 +1055,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1150,7 +1167,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } // CraftBukkit start - SPIGOT-5710 @@ -19564,7 +16861,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); } // CraftBukkit end -@@ -1121,7 +1139,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1234,7 +1251,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public void neighborShapeChanged(Direction direction, BlockState neighborState, BlockPos pos, BlockPos neighborPos, int flags, int maxUpdateDepth) { @@ -19573,7 +16870,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 } @Override -@@ -1146,11 +1164,34 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1259,11 +1276,34 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl return this.getChunkSource().getLightEngine(); } @@ -19610,7 +16907,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 if (previous != null) { return previous.getHandle(); } -@@ -1245,7 +1286,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1362,7 +1402,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } public void addBlockEntityTicker(TickingBlockEntity ticker) { @@ -19619,7 +16916,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 } protected void tickBlockEntities() { -@@ -1253,11 +1294,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1370,11 +1410,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl gameprofilerfiller.push("blockEntities"); this.timings.tileEntityPending.startTiming(); // Spigot @@ -19635,7 +16932,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 this.timings.tileEntityPending.stopTiming(); // Spigot this.timings.tileEntityTick.startTiming(); // Spigot -@@ -1268,9 +1308,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1387,9 +1426,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl int tilesThisCycle = 0; var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet(); // Paper - Fix MC-117075; use removeAll toRemove.add(null); // Paper - Fix MC-117075 @@ -19647,15 +16944,8 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 // Spigot end if (tickingblockentity.isRemoved()) { -@@ -1281,19 +1320,19 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { - tickingblockentity.tick(); - // Paper start - execute chunk tasks during tick -- if ((this.tileTickPosition & 7) == 0) { -+ if ((i & 7) == 0) { // Folia - regionised ticking - MinecraftServer.getServer().executeMidTickTasks(); - } - // Paper end - execute chunk tasks during tick +@@ -1406,13 +1444,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + // Paper end - rewrite chunk system } } - this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 @@ -19672,7 +16962,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 } public void guardEntityTick(Consumer tickConsumer, T entity) { -@@ -1306,7 +1345,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1424,7 +1462,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ()); MinecraftServer.LOGGER.error(msg, throwable); getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); // Paper - ServerExceptionEvent @@ -19681,13 +16971,13 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 + if (entity instanceof net.minecraft.server.level.ServerPlayer player) player.connection.disconnect(net.minecraft.network.chat.Component.translatable("multiplayer.disconnect.generic"), org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); // Folia - properly disconnect players // Paper end - Prevent block entity and entity crashes } - } -@@ -1411,9 +1451,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + this.moonrise$midTickTasks(); // Paper - rewrite chunk system +@@ -1527,9 +1566,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Nullable public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { + // Folia start - region threading -+ if (!io.papermc.paper.util.TickThread.isTickThread()) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { + return null; + } + // Folia end - region threading @@ -19698,7 +16988,7 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 return blockEntity; } // Paper end - Perf: Optimize capturedTileEntities lookup -@@ -1426,8 +1471,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1542,8 +1586,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl if (!this.isOutsideBuildHeight(blockposition)) { // CraftBukkit start @@ -19709,23 +16999,23 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 return; } // CraftBukkit end -@@ -1507,6 +1552,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1623,6 +1667,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { -+ io.papermc.paper.util.TickThread.ensureTickThread((ServerLevel)this, box, "Cannot getEntities asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, box, "Cannot getEntities asynchronously"); // Folia - region threading + this.getProfiler().incrementCounter("getEntities"); + // Paper start - rewrite chunk system + final List ret = new java.util.ArrayList<>(); +@@ -1649,6 +1694,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + public void getEntities(final EntityTypeTest entityTypeTest, + final AABB boundingBox, final Predicate predicate, + final List into, final int maxCount) { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, boundingBox, "Cannot getEntities asynchronously"); // Folia - region threading this.getProfiler().incrementCounter("getEntities"); - List list = Lists.newArrayList(); - ((ServerLevel)this).getEntityLookup().getEntities(except, box, list, predicate); // Paper - optimise this call -@@ -1526,6 +1572,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - public void getEntities(EntityTypeTest filter, AABB box, Predicate predicate, List result, int limit) { -+ io.papermc.paper.util.TickThread.ensureTickThread((ServerLevel)this, box, "Cannot getEntities asynchronously"); // Folia - region threading - this.getProfiler().incrementCounter("getEntities"); - // Paper start - optimise this call - //TODO use limit -@@ -1563,13 +1610,30 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + if (entityTypeTest instanceof net.minecraft.world.entity.EntityType byType) { +@@ -1734,13 +1780,30 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public void disconnect() {} @@ -19758,17 +17048,17 @@ index 14281a4e72f49dc4eb2ca3da8479c1f81a3a175d..a5e33a174c5aa8e836c3badeaf265453 public boolean mayInteract(Player player, BlockPos pos) { return true; -@@ -1769,8 +1833,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - public final BlockPos.MutableBlockPos getRandomBlockPosition(int x, int y, int z, int l, BlockPos.MutableBlockPos out) { - // Paper end +@@ -1933,8 +1996,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + public abstract RecipeManager getRecipeManager(); + + public BlockPos getBlockRandomPos(int x, int y, int z, int l) { - this.randValue = this.randValue * 3 + 1013904223; - int i1 = this.randValue >> 2; + int i1 = this.random.nextInt() >> 2; // Folia - region threading - out.set(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); // Paper - change to setValues call - return out; // Paper -@@ -1801,7 +1864,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); + } +@@ -1964,7 +2026,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public long nextSubTickCount() { @@ -19807,10 +17097,10 @@ index 54d13eebc9b01e9d77f51011b7de95b80bc21669..47c3e7f15e1ba9ea8a1c1bb1a0af61dd default void scheduleTick(BlockPos pos, Block block, int delay, TickPriority priority) { diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.java -index 32bfeb9aa87b43a9d2ce46dcc99dbd0ff355b412..440fb4f9b2804b71a6cf7e5fddbd0386d4b2af02 100644 +index 1a4dc4b2561dbaf01246b4fb46266b1ac84008b8..345090afeab4f6396244c50bdbe8320887e15d7e 100644 --- a/src/main/java/net/minecraft/world/level/LevelReader.java +++ b/src/main/java/net/minecraft/world/level/LevelReader.java -@@ -205,6 +205,25 @@ public interface LevelReader extends BlockAndTintGetter, CollisionGetter, Signal +@@ -207,6 +207,25 @@ public interface LevelReader extends ca.spottedleaf.moonrise.patches.chunk_syste return maxY >= this.getMinBuildHeight() && minY < this.getMaxBuildHeight() && this.hasChunksAt(minX, minZ, maxX, maxZ); } @@ -19823,7 +17113,7 @@ index 32bfeb9aa87b43a9d2ce46dcc99dbd0ff355b412..440fb4f9b2804b71a6cf7e5fddbd0386 + + for(int m = i; m <= j; ++m) { + for(int n = k; n <= l; ++n) { -+ if (!this.hasChunk(m, n) || (this instanceof net.minecraft.server.level.ServerLevel world && !io.papermc.paper.util.TickThread.isTickThreadFor(world, m, n))) { ++ if (!this.hasChunk(m, n) || (this instanceof net.minecraft.server.level.ServerLevel world && !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world, m, n))) { + return false; + } + } @@ -19837,7 +17127,7 @@ index 32bfeb9aa87b43a9d2ce46dcc99dbd0ff355b412..440fb4f9b2804b71a6cf7e5fddbd0386 default boolean hasChunksAt(int minX, int minZ, int maxX, int maxZ) { int i = SectionPos.blockToSectionCoord(minX); diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index ed8032495af9ce9c23419224814b8d27e4a97c17..db64d88dc26f10304bd10f771f811fcbfaa34bc8 100644 +index e524b27d185da3e88668f8ef107517272860bd66..dd02f20e965e6e4aaaf5992ea3c4bb0b7f3cc270 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java @@ -141,7 +141,7 @@ public final class NaturalSpawner { @@ -19929,7 +17219,7 @@ index 85d598c3354ee62f0fd1b26e485e0084967c0380..8492c8fd3ff448d559b33f27b5491809 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index cf8b8c8efd1c9c81eb5f02d75bd75875eb66771f..b266cc2319177366471ee0bbf570a931974b642a 100644 +index a7108b2be0746aa1f0e574d8c6f5ffad6d369835..bf9d00463627c702c639c7cb625c3eb35c2e44aa 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java @@ -390,8 +390,8 @@ public class Block extends BlockBehaviour implements ItemLike { @@ -20004,19 +17294,65 @@ index f446c40c4d90307c568faa2866800f5326634df6..455be3cd52cf21bc37d54b8d408e458d return; } // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java +index 3f5bb5c9ceb5b31fcc9ef0a7a6157e1e1cb2a09f..deb555743b15afcc22e694dcf1d8ceca21c0c191 100644 +--- a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java +@@ -124,6 +124,29 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { + } + } + ++ // Folia start - region threading ++ @Override ++ public boolean portalAsync(ServerLevel sourceWorld, Entity portalTarget, BlockPos portalPos) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(portalTarget)) { ++ return false; ++ } ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(sourceWorld, portalPos)) { ++ return false; ++ } ++ ++ BlockEntity tile = sourceWorld.getBlockEntity(portalPos); ++ ++ if (!(tile instanceof TheEndGatewayBlockEntity endGateway)) { ++ return false; ++ } ++ ++ return TheEndGatewayBlockEntity.teleportRegionThreading( ++ sourceWorld, portalPos, portalTarget, endGateway, EndGatewayBlock.calculateExitMovement(portalTarget), ++ DimensionTransition.PLACE_PORTAL_TICKET ++ ); ++ } ++ // Folia end - region threading ++ + private static Vec3 calculateExitMovement(Entity entity) { + return entity instanceof ThrownEnderpearl ? new Vec3(0.0D, -1.0D, 0.0D) : entity.getDeltaMovement(); + } diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index 7272d70c672b54dcf595beafd7a2ed33c96e35cb..aeac09f628bd04070fd302842c304a7dfd39b229 100644 +index 01333f69b622141b2eb53441c6cbd69e4a059d55..58e15d7a5f7997a7aec9edaa5d211807b2b1ef6b 100644 --- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -@@ -64,7 +64,7 @@ public class EndPortalBlock extends BaseEntityBlock { - // Paper start - move all of this logic into portal tick - entity.portalWorld = ((ServerLevel)world); - entity.portalBlock = pos.immutable(); -- if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowUnsafeEndPortalTeleportation) { -+ if (false) { // Folia - region threading - synchronous teleports are not allowed - entity.tickEndPortal(); - } - // Paper end - move all of this logic into portal tick +@@ -125,6 +125,20 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { + } + } + ++ // Folia start - region threading ++ @Override ++ public boolean portalAsync(ServerLevel sourceWorld, Entity portalTarget, BlockPos portalPos) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(portalTarget)) { ++ return false; ++ } ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(sourceWorld, portalPos)) { ++ return false; ++ } ++ ++ return portalTarget.endPortalLogicAsync(portalPos); ++ } ++ // Folia end - region threading ++ + @Override + public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { + double d0 = (double) pos.getX() + random.nextDouble(); diff --git a/src/main/java/net/minecraft/world/level/block/FarmBlock.java b/src/main/java/net/minecraft/world/level/block/FarmBlock.java index d59e33e7326489c6d55d316d0130f22235f4c63c..edb22983a17cc22ba01ee28a9ebc685aaae117eb 100644 --- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java @@ -20062,10 +17398,10 @@ index c6f7815b5fad3aad4635208aa2e5c6739e13cb45..be52d9e56559704c7f258502b4c2919a } } diff --git a/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java b/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java -index d230ead6042239178bd5c3345aa5366e3082637f..35edc3fef7584178ad15e8c2b939896e4c8ca3e0 100644 +index a3ccd7ca5b280d4c14100bcc22c644e69262e7a3..97cef8c0d1313f0f4441cdfa96d35e9e891b2529 100644 --- a/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java +++ b/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java -@@ -119,7 +119,7 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc +@@ -108,7 +108,7 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc @Override public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { @@ -20087,6 +17423,81 @@ index 1172d85c5c26ab2142343d91149766e5993cb36a..99d42fdf822c13e8d491b665220d6157 if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(world, world.getChunkSource().getGenerator(), random, pos)) { return true; } else { +diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +index ddab7de1d376e9e486e2f920174397ea8804aa29..eba62f1336697157da94c7dcde389cc2e929bb0b 100644 +--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -170,6 +170,33 @@ public class NetherPortalBlock extends Block implements Portal { + } + } + ++ // Folia start - region threading ++ @Override ++ public boolean portalAsync(ServerLevel sourceWorld, Entity portalTarget, BlockPos portalPos) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(portalTarget)) { ++ return false; ++ } ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(sourceWorld, portalPos)) { ++ return false; ++ } ++ ++ return portalTarget.netherPortalLogicAsync(portalPos); ++ } ++ ++ public static BlockUtil.FoundRectangle findPortalAround(ServerLevel world, BlockPos rough, WorldBorder worldBorder, int searchRadius) { ++ BlockPos found = world.getPortalForcer().findClosestPortalPosition(rough, worldBorder, searchRadius).orElse(null); ++ if (found == null) { ++ return null; ++ } ++ ++ BlockState portalState = world.getBlockStateFromEmptyChunk(found); ++ ++ return BlockUtil.getLargestRectangleAround(found, portalState.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (pos) -> { ++ return world.getBlockStateFromEmptyChunk(pos) == portalState; ++ }); ++ } ++ // Folia end - region threading ++ + @Nullable + private DimensionTransition getExitPortal(ServerLevel worldserver, Entity entity, BlockPos blockposition, BlockPos blockposition1, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { + Optional optional = worldserver.getPortalForcer().findClosestPortalPosition(blockposition1, worldborder, searchRadius); +@@ -178,10 +205,10 @@ public class NetherPortalBlock extends Block implements Portal { + + if (optional.isPresent()) { + BlockPos blockposition2 = (BlockPos) optional.get(); +- BlockState iblockdata = worldserver.getBlockState(blockposition2); ++ BlockState iblockdata = worldserver.getBlockStateFromEmptyChunk(blockposition2); // Folia - region threading + + blockutil_rectangle = BlockUtil.getLargestRectangleAround(blockposition2, (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockposition3) -> { +- return worldserver.getBlockState(blockposition3) == iblockdata; ++ return worldserver.getBlockStateFromEmptyChunk(blockposition3) == iblockdata; // Folia - region threading + }); + dimensiontransition_a = DimensionTransition.PLAY_PORTAL_SOUND.then((entity1) -> { + entity1.placePortalTicket(blockposition2); +@@ -227,7 +254,7 @@ public class NetherPortalBlock extends Block implements Portal { + return NetherPortalBlock.createDimensionTransition(world, exitPortalRectangle, enumdirection_enumaxis, vec3d, entity, entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), postDimensionTransition); + } + +- private static DimensionTransition createDimensionTransition(ServerLevel world, BlockUtil.FoundRectangle exitPortalRectangle, Direction.Axis axis, Vec3 positionInPortal, Entity entity, Vec3 velocity, float yaw, float pitch, DimensionTransition.PostDimensionTransition postDimensionTransition) { ++ public static DimensionTransition createDimensionTransition(ServerLevel world, BlockUtil.FoundRectangle exitPortalRectangle, Direction.Axis axis, Vec3 positionInPortal, Entity entity, Vec3 velocity, float yaw, float pitch, DimensionTransition.PostDimensionTransition postDimensionTransition) { // Folia - region threading - public + BlockPos blockposition = exitPortalRectangle.minCorner; + BlockState iblockdata = world.getBlockState(blockposition); + Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) iblockdata.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); +diff --git a/src/main/java/net/minecraft/world/level/block/Portal.java b/src/main/java/net/minecraft/world/level/block/Portal.java +index 8ab8b76992bd4a222a9c217aba57392bf4d65d71..e2cb99c1cf5fd0468a80a3cebcb884617d0f3281 100644 +--- a/src/main/java/net/minecraft/world/level/block/Portal.java ++++ b/src/main/java/net/minecraft/world/level/block/Portal.java +@@ -14,6 +14,10 @@ public interface Portal { + @Nullable + DimensionTransition getPortalDestination(ServerLevel world, Entity entity, BlockPos pos); + ++ // Folia start - region threading ++ public boolean portalAsync(ServerLevel sourceWorld, Entity portalTarget, BlockPos portalPos); ++ // Folia end - region threading ++ + default Portal.Transition getLocalTransition() { + return Portal.Transition.NONE; + } diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java index c131734cad123a35456d18f8a161f77a4ac9ac99..c4471342eea4f9e2b0916fc1c5f1b24bc07757fd 100644 --- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -20307,7 +17718,7 @@ index bbf59b2577812e74ffd45f694b83a42e043273c0..9d4ecf409098adbf4d47b08d7ef10c6d BlockState iblockdata = blockEntity.getBlockState(); boolean flag = iblockdata.is(Blocks.WITHER_SKELETON_SKULL) || iblockdata.is(Blocks.WITHER_SKELETON_WALL_SKULL); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index a6ffbbc1b5021564864e42c0756342352c2b8290..28d0dbb81a68ecf2dfba6744093e26bbba291966 100644 +index 814e70f558d7a6186233da0ff86c94c95d390e09..412150d8f2c2604bc754ecbb04a1001932f29254 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java @@ -215,7 +215,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name @@ -20319,6 +17730,15 @@ index a6ffbbc1b5021564864e42c0756342352c2b8290..28d0dbb81a68ecf2dfba6744093e26bb if (!blockEntity.beamSections.isEmpty()) { blockEntity.levels = BeaconBlockEntity.updateBase(world, i, j, k); } +@@ -339,7 +339,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name + list = world.getEntitiesOfClass(Player.class, axisalignedbb); + } else { + list = new java.util.ArrayList<>(); +- for (Player player : world.players()) { ++ for (Player player : world.getLocalPlayers()) { // Folia - region threading + if (player.isSpectator()) { + continue; + } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java index c0563260277f9f4bd9ff08993b2efb4bca9a0c60..4c2e8714c64a6fe49554a11471e37078267f1eea 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -20355,7 +17775,7 @@ index c0563260277f9f4bd9ff08993b2efb4bca9a0c60..4c2e8714c64a6fe49554a11471e37078 } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java -index 887957ce1ddc2f32569405642f35df468c08271f..a1cd6dcabe480c1714bdc15d53aadc828e041f6d 100644 +index a2fafef89d5354e2cb02f5672810909950a57777..46011ababdadaafd72a8717911e49f6581ab5688 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java @@ -54,7 +54,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements @@ -20382,7 +17802,7 @@ index 887957ce1ddc2f32569405642f35df468c08271f..a1cd6dcabe480c1714bdc15d53aadc82 // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java -index 6c484f3f8f37a19992ebbfe30aba399cac21acfe..733a3d17b8e06b1c078ccf9e533fdaad89f110cc 100644 +index 6c484f3f8f37a19992ebbfe30aba399cac21acfe..47c32e2639fdb6bac0df935822fff1a54c805aa4 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java @@ -61,6 +61,13 @@ public class CommandBlockEntity extends BlockEntity { @@ -20392,7 +17812,7 @@ index 6c484f3f8f37a19992ebbfe30aba399cac21acfe..733a3d17b8e06b1c078ccf9e533fdaad + // Folia start + @Override + public void threadCheck() { -+ io.papermc.paper.util.TickThread.ensureTickThread((ServerLevel) CommandBlockEntity.this.level, CommandBlockEntity.this.worldPosition, "Asynchronous sendSystemMessage to a command block"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel) CommandBlockEntity.this.level, CommandBlockEntity.this.worldPosition, "Asynchronous sendSystemMessage to a command block"); + } + // Folia end + @@ -20422,7 +17842,7 @@ index 73e532dc998e5701c1a73da846da3d3a79871b81..5e4cb998554791cdfc2e32ae7115f87e if (i % 40L == 0L) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 8310d132006043e93c612890514c4c7f3eb1c74d..1280c358748bbb08f0361acd4ebc095bf6bc3496 100644 +index 53f9d28bf3c6aafd4fdd6c12e0285500fe7350ce..09410e95ebb0fd0089c924f39914287465a453bd 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java @@ -49,7 +49,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @@ -20545,7 +17965,7 @@ index 8310d132006043e93c612890514c4c7f3eb1c74d..1280c358748bbb08f0361acd4ebc095b } if (!result) { cooldownHopper(hopper); -@@ -541,13 +553,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -542,13 +554,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } public static boolean suckInItems(Level world, Hopper hopper) { @@ -20561,7 +17981,7 @@ index 8310d132006043e93c612890514c4c7f3eb1c74d..1280c358748bbb08f0361acd4ebc095b int[] aint = HopperBlockEntity.getSlots(iinventory, enumdirection); int i = aint.length; -@@ -733,9 +746,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -735,9 +748,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen stack = stack.split(to.getMaxStackSize()); } // Spigot end @@ -20574,10 +17994,10 @@ index 8310d132006043e93c612890514c4c7f3eb1c74d..1280c358748bbb08f0361acd4ebc095b flag = true; } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -index 81dd0aa6a90fd9dda9e7752f85b9cf4568e3b575..a56804cd7ba9197993d1c3f83f7c3e054bd08bb0 100644 +index a74732902c0494c67e6acf2fc04581ff9c46b832..f543be7f11511b57d510520a531cf39cd05ddafc 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -@@ -45,9 +45,9 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi +@@ -46,9 +46,9 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi // Paper end - Fix NPE in SculkBloomEvent world access public static void serverTick(Level world, BlockPos pos, BlockState state, SculkCatalystBlockEntity blockEntity) { @@ -20590,10 +18010,10 @@ index 81dd0aa6a90fd9dda9e7752f85b9cf4568e3b575..a56804cd7ba9197993d1c3f83f7c3e05 @Override diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c54425fc55 100644 +index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e6d85df26 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -@@ -52,9 +52,12 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { +@@ -39,9 +39,12 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { public long age; private int teleportCooldown; @Nullable @@ -20607,16 +18027,7 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 public TheEndGatewayBlockEntity(BlockPos pos, BlockState state) { super(BlockEntityType.END_GATEWAY, pos, state); } -@@ -117,7 +120,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { - } - - public static boolean canEntityTeleport(Entity entity) { -- return EntitySelector.NO_SPECTATORS.test(entity) && !entity.getRootVehicle().isOnPortalCooldown(); -+ return EntitySelector.NO_SPECTATORS.test(entity) && !entity.getRootVehicle().isOnPortalCooldown() && entity.canPortalAsync(true); // Folia - region threading - correct portal check - } - - public boolean isSpawning() { -@@ -165,8 +168,136 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { +@@ -140,6 +143,103 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { } } @@ -20628,10 +18039,10 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + this.searchingForExitId = Long.valueOf(SEARCHING_FOR_EXIT_ID_GENERATOR.getAndIncrement()); + int chunkX = fromPos.getX() >> 4; + int chunkZ = fromPos.getZ() >> 4; -+ world.chunkTaskScheduler.chunkHolderManager.addTicketAtLevel( ++ world.moonrise$getChunkTaskScheduler().chunkHolderManager.addTicketAtLevel( + net.minecraft.server.level.TicketType.END_GATEWAY_EXIT_SEARCH, + chunkX, chunkZ, -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.BLOCK_TICKING_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.BLOCK_TICKING_TICKET_LEVEL, + this.searchingForExitId + ); + @@ -20650,10 +18061,10 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + TheEndGatewayBlockEntity.this.exitPortal = tpLoc; + + // remove ticket keeping the gateway loaded -+ world.chunkTaskScheduler.chunkHolderManager.removeTicketAtLevel( ++ world.moonrise$getChunkTaskScheduler().chunkHolderManager.removeTicketAtLevel( + net.minecraft.server.level.TicketType.END_GATEWAY_EXIT_SEARCH, + chunkX, chunkZ, -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.BLOCK_TICKING_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.BLOCK_TICKING_TICKET_LEVEL, + this.searchingForExitId + ); + TheEndGatewayBlockEntity.this.searchingForExitId = null; @@ -20664,58 +18075,33 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + findOrCreateValidTeleportPosRegionThreading(world, fromPos, complete); + } + -+ private static void teleportRegionThreading(Level world, BlockPos pos, BlockState state, Entity entity, TheEndGatewayBlockEntity blockEntity) { ++ public static boolean teleportRegionThreading(ServerLevel portalWorld, BlockPos portalPos, ++ net.minecraft.world.entity.Entity toTeleport, ++ TheEndGatewayBlockEntity portalTile, ++ Vec3 targetSpeed, ++ net.minecraft.world.level.portal.DimensionTransition.PostDimensionTransition post) { + // can we even teleport in this dimension? -+ if (blockEntity.exitPortal == null && world.getTypeKey() != LevelStem.END) { -+ return; ++ if (portalTile.exitPortal == null && portalWorld.getTypeKey() != LevelStem.END) { ++ return false; + } + -+ ServerLevel serverWorld = (ServerLevel)world; -+ + // First, find the position we are trying to teleport to -+ BlockPos teleportPos = blockEntity.exitPortal; -+ boolean isExactTeleport = blockEntity.exactTeleport; ++ BlockPos teleportPos = portalTile.exitPortal; ++ boolean isExactTeleport = portalTile.exactTeleport; + + if (teleportPos == null) { -+ blockEntity.trySearchForExit(serverWorld, pos); -+ return; ++ portalTile.trySearchForExit(portalWorld, portalPos); ++ return false; + } + -+ Entity chosenEntity; -+ if (entity instanceof ThrownEnderpearl pearl) { -+ Entity owner = pearl.getOwner(); -+ -+ if (owner instanceof ServerPlayer player) { -+ CriteriaTriggers.ENTER_BLOCK.trigger(player, state); -+ } -+ -+ if (owner != null) { -+ // vanilla behavior is to just break if the owner is riding anything -+ // it's not likely intentional that throwing a pearl while riding something is intended -+ // to teleport the vehicle, rather just the owner given the lack of getRootVehicle -+ owner.unRide(); -+ chosenEntity = owner; -+ pearl.discard(EntityRemoveEvent.Cause.HIT); -+ } else { -+ // see above for unRide() -+ pearl.unRide(); -+ chosenEntity = pearl; -+ } -+ } else { -+ chosenEntity = entity.getRootVehicle(); -+ } -+ -+ // This needs to be first, as we are only guaranteed to be on the corresponding region tick thread here -+ TheEndGatewayBlockEntity.triggerCooldown(world, pos, state, blockEntity); -+ + if (isExactTeleport) { + // blind teleport -+ chosenEntity.teleportAsync( -+ serverWorld, Vec3.atCenterOf(teleportPos), null, null, null, -+ PlayerTeleportEvent.TeleportCause.END_GATEWAY, Entity.TELEPORT_FLAG_LOAD_CHUNK | Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, -+ (Entity teleportedEntity) -> { -+ for (Entity passenger : teleportedEntity.getSelfAndPassengers().toList()) { -+ passenger.setPortalCooldown(); ++ return toTeleport.teleportAsync( ++ portalWorld, Vec3.atCenterOf(teleportPos), null, null, targetSpeed, ++ org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_GATEWAY, net.minecraft.world.entity.Entity.TELEPORT_FLAG_LOAD_CHUNK | net.minecraft.world.entity.Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, ++ (net.minecraft.world.entity.Entity teleportedEntity) -> { ++ if (post != null) { ++ post.onTransition(teleportedEntity); + } + } + ); @@ -20724,36 +18110,28 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + // should be teleported, something something else... + // however, we know the target location cannot differ by one region section: so we can + // just teleport and adjust the position after -+ chosenEntity.teleportAsync( -+ serverWorld, Vec3.atCenterOf(teleportPos), null, null, null, -+ PlayerTeleportEvent.TeleportCause.END_GATEWAY, Entity.TELEPORT_FLAG_LOAD_CHUNK | Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, -+ (Entity teleportedEntity) -> { -+ for (Entity passenger : teleportedEntity.getSelfAndPassengers().toList()) { -+ passenger.setPortalCooldown(); -+ } -+ ++ return toTeleport.teleportAsync( ++ portalWorld, Vec3.atCenterOf(teleportPos), null, null, targetSpeed, ++ org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_GATEWAY, net.minecraft.world.entity.Entity.TELEPORT_FLAG_LOAD_CHUNK | net.minecraft.world.entity.Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, ++ (net.minecraft.world.entity.Entity teleportedEntity) -> { + // adjust to the final exit position -+ Vec3 adjusted = Vec3.atCenterOf(TheEndGatewayBlockEntity.findExitPosition(serverWorld, teleportPos)); ++ Vec3 adjusted = Vec3.atCenterOf(TheEndGatewayBlockEntity.findExitPosition(portalWorld, teleportPos)); + // teleportTo will adjust rider positions + teleportedEntity.teleportTo(adjusted.x, adjusted.y, adjusted.z); ++ ++ if (post != null) { ++ post.onTransition(teleportedEntity); ++ } + } + ); + } + } + // Folia end - region threading + - public static void teleportEntity(Level world, BlockPos pos, BlockState state, Entity entity, TheEndGatewayBlockEntity blockEntity) { - if (world instanceof ServerLevel worldserver && !blockEntity.isCoolingDown()) { -+ // Folia start - region threading -+ if (true) { -+ teleportRegionThreading(world, pos, state, entity, blockEntity); -+ return; -+ } -+ // Folia end - region threading - blockEntity.teleportCooldown = 100; - BlockPos blockposition1; - -@@ -269,6 +400,129 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + @Nullable + public Vec3 getPortalPosition(ServerLevel world, BlockPos pos) { + BlockPos blockposition1; +@@ -189,6 +289,124 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { return TheEndGatewayBlockEntity.findTallestBlock(world, blockposition1, 16, true); } @@ -20766,11 +18144,7 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + LevelChunk chunk = TheEndGatewayBlockEntity.getChunk(world, vec3d); + BlockPos blockposition1 = TheEndGatewayBlockEntity.findValidSpawnInChunk(chunk); + if (blockposition1 == null) { -+ BlockPos blockposition2 = new BlockPos( -+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(vec3d.x + 0.5D), -+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(75.0D), -+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(vec3d.z + 0.5D) -+ ); ++ BlockPos blockposition2 = BlockPos.containing(vec3d.x + 0.5D, 75.0D, vec3d.z + 0.5D); + + TheEndGatewayBlockEntity.LOGGER.debug("Failed to find a suitable block to teleport to, spawning an island on {}", blockposition2); + world.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { @@ -20792,14 +18166,14 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + int radius = 16; + + BlockPos finalBlockPosition1 = blockposition1; -+ world.loadChunksAsync(blockposition1, radius, ++ world.moonrise$loadChunksAsync(blockposition1, radius, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, -+ (List chunks) -> { ++ (java.util.List chunks) -> { + // make sure chunks are kept loaded + for (net.minecraft.world.level.chunk.ChunkAccess access : chunks) { + world.chunkSource.addTicketAtLevel( + net.minecraft.server.level.TicketType.DELAYED, access.getPos(), -+ io.papermc.paper.chunk.system.scheduling.ChunkHolderManager.FULL_LOADED_TICKET_LEVEL, ++ ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.FULL_LOADED_TICKET_LEVEL, + net.minecraft.util.Unit.INSTANCE + ); + } @@ -20810,7 +18184,7 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + BlockPos tpLoc = TheEndGatewayBlockEntity.findTallestBlock(world, finalBlockPosition1, radius, true); + + // done -+ complete.complete(tpLoc.above(10)); ++ complete.complete(tpLoc); + } + ); + } @@ -20852,24 +18226,23 @@ index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..04743a3e8546655e769442744c32a4c5 + + vars.currPos = vars.currPos.add(posDirFromOrigin.scale(vars.mode ? 16.0 : -16.0)); + // schedule next iteration -+ Runnable handleButInitialised = this; -+ world.chunkTaskScheduler.scheduleChunkLoad( -+ io.papermc.paper.util.CoordinateUtils.getChunkX(vars.currPos), -+ io.papermc.paper.util.CoordinateUtils.getChunkZ(vars.currPos), ++ world.moonrise$getChunkTaskScheduler().scheduleChunkLoad( ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(vars.currPos), ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(vars.currPos), + net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + true, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, + (chunk) -> { -+ handleButInitialised.run(); ++ this.run(); + } + ); + } + }; + + // kick off first chunk load -+ world.chunkTaskScheduler.scheduleChunkLoad( -+ io.papermc.paper.util.CoordinateUtils.getChunkX(posDirExtruded), -+ io.papermc.paper.util.CoordinateUtils.getChunkZ(posDirExtruded), ++ world.moonrise$getChunkTaskScheduler().scheduleChunkLoad( ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(posDirExtruded), ++ ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(posDirExtruded), + net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + true, + ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, @@ -21032,17 +18405,19 @@ index b35f476e26a020cf75e53a5eb488717d996a6935..58b570cfdd52b414752b5a117946d590 if (blockEntity.progressO >= 1.0F) { if (world.isClientSide && blockEntity.deathTicks < 5) { diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 6c6eb7deed281678c05ef27f933e1693b11dae7c..e1572c7d5409bde5e73905d8814d2d1defcfc227 100644 +index 04e62c54f224f7949fde9ceded208e700db55aa1..298b00641580dfab39ac9139d1ea25cec178a0d4 100644 --- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java +++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -@@ -33,19 +33,19 @@ public class WorldBorder { +@@ -34,6 +34,8 @@ public class WorldBorder { public WorldBorder() {} + // Folia - region threading - TODO make this shit thread-safe + public boolean isWithinBounds(BlockPos pos) { - return (double) (pos.getX() + 1) > this.getMinX() && (double) pos.getX() < this.getMaxX() && (double) (pos.getZ() + 1) > this.getMinZ() && (double) pos.getZ() < this.getMaxZ(); + return this.isWithinBounds((double) pos.getX(), (double) pos.getZ()); + } +@@ -47,14 +49,12 @@ public class WorldBorder { } // Paper start - Bound treasure maps to world border @@ -21061,10 +18436,10 @@ index 6c6eb7deed281678c05ef27f933e1693b11dae7c..e1572c7d5409bde5e73905d8814d2d1d // Paper end - Bound treasure maps to world border diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index 927bdebdb8ae01613f0cea074b3367bd7ffe9ab1..9a17f3d0b53b2ab0358012e4238164f8af0a6c6e 100644 +index 488938c32a48437721a71d294c77468f00c035b9..cead18e4f8ea278b999fa0e1aff58580a6604645 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -@@ -326,7 +326,7 @@ public abstract class ChunkGenerator { +@@ -325,7 +325,7 @@ public abstract class ChunkGenerator { } private static boolean tryAddReference(StructureManager structureAccessor, StructureStart start) { @@ -21074,10 +18449,10 @@ index 927bdebdb8ae01613f0cea074b3367bd7ffe9ab1..9a17f3d0b53b2ab0358012e4238164f8 return true; } else { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d43218555278d61eefa 100644 +index 5453b7051337908ac1c8201827c1b5eec9e1608b..2c39642298bf235565b92287efaf55373183c5a1 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -61,6 +61,13 @@ public class LevelChunk extends ChunkAccess { +@@ -60,6 +60,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Override public void tick() {} @@ -21091,15 +18466,15 @@ index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d4321855527 @Override public boolean isRemoved() { return true; -@@ -412,6 +419,7 @@ public class LevelChunk extends ChunkAccess { +@@ -352,6 +359,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Nullable public BlockState setBlockState(BlockPos blockposition, BlockState iblockdata, boolean flag, boolean doPlace) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.level, blockposition, "Updating block asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.level, blockposition, "Updating block asynchronously"); // Folia - region threading // CraftBukkit end int i = blockposition.getY(); LevelChunkSection chunksection = this.getSection(this.getSectionIndex(i)); -@@ -452,7 +460,7 @@ public class LevelChunk extends ChunkAccess { +@@ -392,7 +400,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p boolean flag3 = iblockdata1.hasBlockEntity(); @@ -21108,7 +18483,7 @@ index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d4321855527 iblockdata1.onRemove(this.level, blockposition, iblockdata, flag); } else if (!iblockdata1.is(block) && flag3) { this.removeBlockEntity(blockposition); -@@ -462,7 +470,7 @@ public class LevelChunk extends ChunkAccess { +@@ -402,7 +410,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p return null; } else { // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. @@ -21117,7 +18492,7 @@ index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d4321855527 iblockdata.onPlace(this.level, blockposition, iblockdata1, flag); } -@@ -508,7 +516,7 @@ public class LevelChunk extends ChunkAccess { +@@ -448,7 +456,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Nullable public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { // CraftBukkit start @@ -21126,7 +18501,7 @@ index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d4321855527 if (tileentity == null) { tileentity = (BlockEntity) this.blockEntities.get(pos); } -@@ -795,13 +803,13 @@ public class LevelChunk extends ChunkAccess { +@@ -671,13 +679,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p org.bukkit.World world = this.level.getWorld(); if (world != null) { @@ -21142,16 +18517,16 @@ index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d4321855527 } } server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -@@ -851,7 +859,7 @@ public class LevelChunk extends ChunkAccess { +@@ -704,7 +712,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Override public boolean isUnsaved() { - // Paper start - add dirty system to tick lists -- long gameTime = this.level.getLevelData().getGameTime(); -+ long gameTime = this.level.getRedstoneGameTime(); // Folia - region threading - if (this.blockTicks.isDirty(gameTime) || this.fluidTicks.isDirty(gameTime)) { + // Paper start - rewrite chunk system +- final long gameTime = this.level.getGameTime(); ++ final long gameTime = this.level.getRedstoneGameTime(); // Folia - region threading + if (((ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks)this.blockTicks).moonrise$isDirty(gameTime) + || ((ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks)this.fluidTicks).moonrise$isDirty(gameTime)) { return true; - } -@@ -1115,6 +1123,13 @@ public class LevelChunk extends ChunkAccess { +@@ -975,6 +983,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p this.ticker = wrapped; } @@ -21165,7 +18540,7 @@ index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d4321855527 @Override public void tick() { this.ticker.tick(); -@@ -1151,6 +1166,13 @@ public class LevelChunk extends ChunkAccess { +@@ -1011,6 +1026,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p this.ticker = blockentityticker; } @@ -21180,10 +18555,10 @@ index 14ee7b5b9b804bebd4e2a846b238547a28a36035..fe7b3757c5c3d14cec783d4321855527 public void tick() { if (!this.blockEntity.isRemoved() && this.blockEntity.hasLevel()) { diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 26431a814f6472689484dcc7cd8183fe1676e17e..de1a916c5034a8886bf16ee6ab235185d48a8a2c 100644 +index 4bd048387651250135f963303c78c17f8473cfee..6ec9226b686e7cd9da966edc6b51d4f48dfe4d65 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -633,7 +633,7 @@ public class ChunkSerializer { +@@ -550,7 +550,7 @@ public class ChunkSerializer { } private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) { @@ -21193,7 +18568,7 @@ index 26431a814f6472689484dcc7cd8183fe1676e17e..de1a916c5034a8886bf16ee6ab235185 nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> { return BuiltInRegistries.BLOCK.getKey(block).toString(); diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 18a1b4325cac81b040596071dab99ef9bf6f3142..23b8776fb5379a3cbe5ee95a953cbf7cbd904f94 100644 +index 18a1b4325cac81b040596071dab99ef9bf6f3142..f68907a175329a4a928db8085939a6c5836bd94e 100644 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java @@ -76,7 +76,7 @@ public class EndDragonFight { @@ -21221,7 +18596,7 @@ index 18a1b4325cac81b040596071dab99ef9bf6f3142..23b8776fb5379a3cbe5ee95a953cbf7c + // Folia start - region threading + // we do not want to deal with any dragons NOT nearby + list.removeIf((dragon) -> { -+ return !io.papermc.paper.util.TickThread.isTickThreadFor(dragon); ++ return !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(dragon); + }); + // Folia end - region threading @@ -21235,7 +18610,7 @@ index 18a1b4325cac81b040596071dab99ef9bf6f3142..23b8776fb5379a3cbe5ee95a953cbf7c - - if (!(ichunkaccess instanceof LevelChunk)) { + ChunkAccess ichunkaccess = this.level.getChunkIfLoaded(i, j); // Folia - region threading -+ if (!(ichunkaccess instanceof LevelChunk) || !io.papermc.paper.util.TickThread.isTickThreadFor(this.level, i, j, this.level.regioniser.regionSectionChunkSize)) { // Folia - region threading ++ if (!(ichunkaccess instanceof LevelChunk) || !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, i, j, this.level.regioniser.regionSectionChunkSize)) { // Folia - region threading return false; } @@ -21244,7 +18619,7 @@ index 18a1b4325cac81b040596071dab99ef9bf6f3142..23b8776fb5379a3cbe5ee95a953cbf7c public void onCrystalDestroyed(EndCrystal enderCrystal, DamageSource source) { + // Folia start - region threading -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.origin)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, this.origin)) { + return; + } + // Folia end - region threading @@ -21256,7 +18631,7 @@ index 18a1b4325cac81b040596071dab99ef9bf6f3142..23b8776fb5379a3cbe5ee95a953cbf7c public boolean tryRespawn(@Nullable BlockPos placedEndCrystalPos) { // placedEndCrystalPos is null if the tryRespawn() call was not caused by a placed end crystal // Paper end - Perf: Do crystal-portal proximity check before entity lookup - if (this.dragonKilled && this.respawnStage == null) { -+ if (this.dragonKilled && this.respawnStage == null && io.papermc.paper.util.TickThread.isTickThreadFor(this.level, this.origin)) { // Folia - region threading ++ if (this.dragonKilled && this.respawnStage == null && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, this.origin)) { // Folia - region threading BlockPos blockposition = this.portalLocation; if (blockposition == null) { @@ -21352,8 +18727,25 @@ index 1b1b475ca27e799e251d6f8a8c9fe1a4fd8bae83..3085658976345d095e7c38a0edab42cb while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java +index 0bc659a8427b89b5e3211220c55b52eec6a20494..bcd7b23656bf77e9eca1bc194f9af360742b65be 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java +@@ -60,11 +60,7 @@ public class EndPlatformFeature extends Feature { + return; + } + +- org.bukkit.World bworld = worldaccess.getLevel().getWorld(); +- PortalCreateEvent portalEvent = new PortalCreateEvent((List) (List) blockList.getList(), bworld, entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); +- +- worldaccess.getLevel().getCraftServer().getPluginManager().callEvent(portalEvent); +- if (!portalEvent.isCancelled()) { ++ if (true) { // Folia - region threading + blockList.updateList(); + } + // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java -index 1695cff01932d435848e230921d1680b69a41d73..71658657fdaa858ffd388bb19218c30d84f3d77b 100644 +index c92a2c5bba1525eff39d9a3cad70fdacd426e8cb..04274f48627c40d3ac722e3ec595182d6d44b167 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java +++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java @@ -28,7 +28,7 @@ public final class StructureStart { @@ -21416,32 +18808,15 @@ index 1695cff01932d435848e230921d1680b69a41d73..71658657fdaa858ffd388bb19218c30d } protected int getMaxReferences() { -diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -index 2407d93c11b806701fc7d192f39d535128281e80..e251935b89799046e82228f49ea7a7737078892b 100644 ---- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -+++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java -@@ -89,10 +89,10 @@ public class PortalForcer { - BlockPos blockposition1 = villageplacerecord.getPos(); - - this.level.getChunkSource().addRegionTicket(TicketType.PORTAL, new ChunkPos(blockposition1), 3, blockposition1); -- BlockState iblockdata = this.level.getBlockState(blockposition1); -+ BlockState iblockdata = this.level.getBlockStateFromEmptyChunk(blockposition1); // Folia - region threading - - return BlockUtil.getLargestRectangleAround(blockposition1, (Direction.Axis) iblockdata.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (blockposition2) -> { -- return this.level.getBlockState(blockposition2) == iblockdata; -+ return this.level.getBlockStateFromEmptyChunk(blockposition2) == iblockdata; // Folia - region threading - }); - }); - } diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -index 106af2b2c7ff72c7549975aef75cdcff8d9a7d97..67be58de9f684e440b62541365c079cfffe30e51 100644 +index 106af2b2c7ff72c7549975aef75cdcff8d9a7d97..2c9640001dba727981ad336eefade6d438eeb0ac 100644 --- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java +++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java @@ -48,6 +48,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { } private void addAndRun(BlockPos pos, CollectingNeighborUpdater.NeighborUpdates entry) { -+ io.papermc.paper.util.TickThread.ensureTickThread((net.minecraft.server.level.ServerLevel)this.level, pos, "Adding block without owning region"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((net.minecraft.server.level.ServerLevel)this.level, pos, "Adding block without owning region"); // Folia - region threading boolean bl = this.count > 0; boolean bl2 = this.maxChainedNeighborUpdates >= 0 && this.count >= this.maxChainedNeighborUpdates; this.count++; @@ -21502,10 +18877,10 @@ index 763b315b1d761bc3bd82d9b847ed3f64fd5ce991..7a044d337df8a14150a695d539a8e5c8 } } diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314cc088be03 100644 +index 17f33c83c6033564d6bf4fbd388b0b847c68adb3..684a0a4c7583da882687e010e2f2e051804b6602 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -@@ -211,7 +211,7 @@ public class MapItemSavedData extends SavedData { +@@ -212,7 +212,7 @@ public class MapItemSavedData extends SavedData { } @Override @@ -21514,7 +18889,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c DataResult dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.dimension.location()); // CraftBukkit - decompile error Logger logger = MapItemSavedData.LOGGER; -@@ -261,7 +261,7 @@ public class MapItemSavedData extends SavedData { +@@ -262,7 +262,7 @@ public class MapItemSavedData extends SavedData { return nbt; } @@ -21523,7 +18898,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c MapItemSavedData worldmap = new MapItemSavedData(this.centerX, this.centerZ, this.scale, this.trackingPosition, this.unlimitedTracking, true, this.dimension); worldmap.bannerMarkers.putAll(this.bannerMarkers); -@@ -272,7 +272,7 @@ public class MapItemSavedData extends SavedData { +@@ -273,7 +273,7 @@ public class MapItemSavedData extends SavedData { return worldmap; } @@ -21532,17 +18907,17 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c return MapItemSavedData.createFresh((double) this.centerX, (double) this.centerZ, (byte) Mth.clamp(this.scale + 1, 0, 4), this.trackingPosition, this.unlimitedTracking, this.dimension); } -@@ -284,7 +284,8 @@ public class MapItemSavedData extends SavedData { +@@ -285,7 +285,8 @@ public class MapItemSavedData extends SavedData { }; } - public void tickCarriedBy(Player player, ItemStack stack) { + public synchronized void tickCarriedBy(Player player, ItemStack stack) { // Folia - make map data thread-safe -+ io.papermc.paper.util.TickThread.ensureTickThread(player, "Ticking map player in incorrect region"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(player, "Ticking map player in incorrect region"); // Folia - region threading if (!this.carriedByPlayers.containsKey(player)) { MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); -@@ -378,7 +379,7 @@ public class MapItemSavedData extends SavedData { +@@ -379,7 +380,7 @@ public class MapItemSavedData extends SavedData { rotation += rotation < 0.0D ? -8.0D : 8.0D; b2 = (byte) ((int) (rotation * 16.0D / 360.0D)); if (this.dimension == Level.NETHER && world != null) { @@ -21551,7 +18926,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c b2 = (byte) (j * j * 34187121 + j * 121 >> 15 & 15); } -@@ -437,14 +438,14 @@ public class MapItemSavedData extends SavedData { +@@ -438,14 +439,14 @@ public class MapItemSavedData extends SavedData { } @Nullable @@ -21569,7 +18944,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c Iterator iterator = this.carriedBy.iterator(); while (iterator.hasNext()) { -@@ -452,15 +453,16 @@ public class MapItemSavedData extends SavedData { +@@ -453,15 +454,16 @@ public class MapItemSavedData extends SavedData { worldmap_worldmaphumantracker.markColorsDirty(x, z); } @@ -21590,7 +18965,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); if (worldmap_worldmaphumantracker == null) { -@@ -472,7 +474,7 @@ public class MapItemSavedData extends SavedData { +@@ -473,7 +475,7 @@ public class MapItemSavedData extends SavedData { return worldmap_worldmaphumantracker; } @@ -21599,16 +18974,16 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c double d0 = (double) pos.getX() + 0.5D; double d1 = (double) pos.getZ() + 0.5D; int i = 1 << this.scale; -@@ -481,7 +483,7 @@ public class MapItemSavedData extends SavedData { +@@ -482,7 +484,7 @@ public class MapItemSavedData extends SavedData { boolean flag = true; if (d2 >= -63.0D && d3 >= -63.0D && d2 <= 63.0D && d3 <= 63.0D) { - MapBanner mapiconbanner = MapBanner.fromWorld(world, pos); -+ MapBanner mapiconbanner = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4) == null || !io.papermc.paper.util.TickThread.isTickThreadFor(world.getMinecraftWorld(), pos) ? null : MapBanner.fromWorld(world, pos); // Folia - make map data thread-safe - don't sync load or read data we do not own ++ MapBanner mapiconbanner = world.getChunkIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4) == null || !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world.getMinecraftWorld(), pos) ? null : MapBanner.fromWorld(world, pos); // Folia - make map data thread-safe - don't sync load or read data we do not own if (mapiconbanner == null) { return false; -@@ -502,7 +504,7 @@ public class MapItemSavedData extends SavedData { +@@ -503,7 +505,7 @@ public class MapItemSavedData extends SavedData { return false; } @@ -21617,13 +18992,13 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c Iterator iterator = this.bannerMarkers.values().iterator(); while (iterator.hasNext()) { -@@ -524,12 +526,12 @@ public class MapItemSavedData extends SavedData { +@@ -525,12 +527,12 @@ public class MapItemSavedData extends SavedData { return this.bannerMarkers.values(); } - public void removedFromFrame(BlockPos pos, int id) { + public synchronized void removedFromFrame(BlockPos pos, int id) { // Folia - make map data thread-safe - this.removeDecoration("frame-" + id); + this.removeDecoration(MapItemSavedData.getFrameKey(id)); this.frameMarkers.remove(MapFrame.frameId(pos)); } @@ -21632,7 +19007,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c byte b1 = this.colors[x + z * 128]; if (b1 != color) { -@@ -540,12 +542,12 @@ public class MapItemSavedData extends SavedData { +@@ -541,12 +543,12 @@ public class MapItemSavedData extends SavedData { } } @@ -21647,7 +19022,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c Iterator iterator = this.decorations.values().iterator(); MapDecoration mapicon; -@@ -580,7 +582,7 @@ public class MapItemSavedData extends SavedData { +@@ -581,7 +583,7 @@ public class MapItemSavedData extends SavedData { return this.decorations.values(); } @@ -21656,7 +19031,7 @@ index cf8ae635fce7ea66d4e1ab1dc05575f035fa95ef..6b131c112ca227f9f910d5d88cf8314c return this.trackedDecorationCount >= decorationCount; } -@@ -724,11 +726,13 @@ public class MapItemSavedData extends SavedData { +@@ -729,11 +731,13 @@ public class MapItemSavedData extends SavedData { } public void applyToMap(MapItemSavedData mapState) { @@ -21714,13 +19089,13 @@ index 6e23e69abd56eeda3b52a22019e1b74ae10682e7..2c086f1d4cbfc29a759a77e5c5f9f39d public CompoundTag readTagFromDisk(String id, DataFixTypes dataFixTypes, int currentSaveVersion) throws IOException { diff --git a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java -index 2cdd18f724296f10cd4a522d1e8196723d39cf45..b329d8327d73fc90586945834305fc3a50610c6e 100644 +index c42c0d1e4da30aa15f32d4ca524aeabd26fc50cf..e328d3d22d19b5dd1507c40119801fcfc3289e67 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java +++ b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java -@@ -38,6 +38,21 @@ public class LevelChunkTicks implements SerializableTickContainer, TickCon +@@ -49,6 +49,21 @@ public class LevelChunkTicks implements SerializableTickContainer, TickCon this.dirty = false; } - // Paper end - add dirty flag + // Paper end - rewrite chunk system + // Folia start - region threading + public void offsetTicks(final long offset) { + if (offset == 0 || this.tickQueue.isEmpty()) { @@ -21740,7 +19115,7 @@ index 2cdd18f724296f10cd4a522d1e8196723d39cf45..b329d8327d73fc90586945834305fc3a public LevelChunkTicks() { } diff --git a/src/main/java/net/minecraft/world/ticks/LevelTicks.java b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -index 7a69564572357a7acc043e35b9c113beeb738951..f71661ef4250d3b668fffeea7cd74a28eec95acd 100644 +index 7a69564572357a7acc043e35b9c113beeb738951..ea161048b68de3c8cdcba5f4cb66eb1531364b2e 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelTicks.java +++ b/src/main/java/net/minecraft/world/ticks/LevelTicks.java @@ -39,12 +39,69 @@ public class LevelTicks implements LevelTickAccess { @@ -21786,10 +19161,10 @@ index 7a69564572357a7acc043e35b9c113beeb738951..f71661ef4250d3b668fffeea7cd74a28 + final Long2ObjectMap.Entry> entry = iterator.next(); + + final long chunkKey = entry.getLongKey(); -+ final int chunkX = io.papermc.paper.util.CoordinateUtils.getChunkX(chunkKey); -+ final int chunkZ = io.papermc.paper.util.CoordinateUtils.getChunkZ(chunkKey); ++ final int chunkX = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkKey); ++ final int chunkZ = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkKey); + -+ final long regionSectionKey = io.papermc.paper.util.CoordinateUtils.getChunkKey( ++ final long regionSectionKey = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey( + chunkX >> chunkToRegionShift, chunkZ >> chunkToRegionShift + ); + // Should always be non-null, since containers are removed on unload. @@ -21799,10 +19174,10 @@ index 7a69564572357a7acc043e35b9c113beeb738951..f71661ef4250d3b668fffeea7cd74a28 + iterator.hasNext();) { + final Long2LongMap.Entry entry = iterator.next(); + final long chunkKey = entry.getLongKey(); -+ final int chunkX = io.papermc.paper.util.CoordinateUtils.getChunkX(chunkKey); -+ final int chunkZ = io.papermc.paper.util.CoordinateUtils.getChunkZ(chunkKey); ++ final int chunkX = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkKey); ++ final int chunkZ = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkKey); + -+ final long regionSectionKey = io.papermc.paper.util.CoordinateUtils.getChunkKey( ++ final long regionSectionKey = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey( + chunkX >> chunkToRegionShift, chunkZ >> chunkToRegionShift + ); + @@ -21839,16 +19214,16 @@ index 7a69564572357a7acc043e35b9c113beeb738951..f71661ef4250d3b668fffeea7cd74a28 @Override public void schedule(ScheduledTick orderedTick) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, orderedTick.pos(), "Cannot schedule tick for another region!"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, orderedTick.pos(), "Cannot schedule tick for another region!"); // Folia - region threading long l = ChunkPos.asLong(orderedTick.pos()); LevelChunkTicks levelChunkTicks = this.allContainers.get(l); if (levelChunkTicks == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5db08432b6afd3639688830e717f40ceaf599248..f1bd3c83922367484832ec54ebec17529269ad75 100644 +index c8b82bc41f2042bb4b067f06265a3a22e51f7629..3d93d6f0c352b5540a8fc69c86a68f7584d8525c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -309,7 +309,7 @@ public final class CraftServer implements Server { - private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; // Paper - Custom Potion Mixes +@@ -312,7 +312,7 @@ public final class CraftServer implements Server { + public final io.papermc.paper.SparksFly spark; // Paper - spark // Paper start - Folia region threading API - private final io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler(); @@ -21856,8 +19231,8 @@ index 5db08432b6afd3639688830e717f40ceaf599248..f1bd3c83922367484832ec54ebec1752 private final io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler asyncScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler(); private final io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler globalRegionScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler(); -@@ -377,6 +377,12 @@ public final class CraftServer implements Server { - return io.papermc.paper.util.TickThread.isTickThreadFor(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandleRaw()); +@@ -380,6 +380,12 @@ public final class CraftServer implements Server { + return ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandleRaw()); } // Paper end - Folia reagion threading API + // Folia start - region threading API @@ -21869,7 +19244,7 @@ index 5db08432b6afd3639688830e717f40ceaf599248..f1bd3c83922367484832ec54ebec1752 static { ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); -@@ -958,6 +964,9 @@ public final class CraftServer implements Server { +@@ -972,6 +978,9 @@ public final class CraftServer implements Server { // NOTE: Should only be called from DedicatedServer.ah() public boolean dispatchServerCommand(CommandSender sender, ConsoleInput serverCommand) { @@ -21879,7 +19254,7 @@ index 5db08432b6afd3639688830e717f40ceaf599248..f1bd3c83922367484832ec54ebec1752 if (sender instanceof Conversable) { Conversable conversable = (Conversable) sender; -@@ -977,12 +986,46 @@ public final class CraftServer implements Server { +@@ -991,12 +1000,46 @@ public final class CraftServer implements Server { } } @@ -21912,7 +19287,7 @@ index 5db08432b6afd3639688830e717f40ceaf599248..f1bd3c83922367484832ec54ebec1752 + // Folia start - region threading + if ((sender instanceof Entity entity)) { -+ io.papermc.paper.util.TickThread.ensureTickThread(((org.bukkit.craftbukkit.entity.CraftEntity)entity).getHandle(), "Dispatching command async"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(((org.bukkit.craftbukkit.entity.CraftEntity)entity).getHandle(), "Dispatching command async"); + } else if (sender instanceof ConsoleCommandSender || sender instanceof net.minecraft.server.rcon.RconConsoleSource + || sender instanceof org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender + || sender instanceof io.papermc.paper.commands.FeedbackForwardingSender) { @@ -21926,7 +19301,7 @@ index 5db08432b6afd3639688830e717f40ceaf599248..f1bd3c83922367484832ec54ebec1752 if (this.commandMap.dispatch(sender, commandLine)) { return true; } -@@ -3256,7 +3299,7 @@ public final class CraftServer implements Server { +@@ -3194,7 +3237,7 @@ public final class CraftServer implements Server { @Override public int getCurrentTick() { @@ -21936,10 +19311,10 @@ index 5db08432b6afd3639688830e717f40ceaf599248..f1bd3c83922367484832ec54ebec1752 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc2472d480 100644 +index 362ca138a5cd5ad19f1300015c2571794adc3649..a33a874a845967b78877b7bb4d072c36912165cf 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -193,7 +193,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -192,7 +192,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getTickableTileEntityCount() { @@ -21948,7 +19323,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc } @Override -@@ -263,7 +263,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -262,7 +262,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { // Paper start - per world spawn limits for (SpawnCategory spawnCategory : SpawnCategory.values()) { if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { @@ -21957,15 +19332,15 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc } } // Paper end - per world spawn limits -@@ -350,6 +350,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -326,6 +326,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public Chunk getChunkAt(int x, int z) { -+ io.papermc.paper.util.TickThread.isTickThreadFor(this.getHandle(), x, z); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.getHandle(), x, z); // Folia - region threading warnUnsafeChunk("getting a faraway chunk", x, z); // Paper // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); -@@ -373,7 +374,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -349,7 +350,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { // Paper start private void addTicket(int x, int z) { @@ -21974,55 +19349,55 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc } // Paper end -@@ -392,10 +393,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -368,10 +369,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean isChunkGenerated(int x, int z) { // Paper start - Fix this method - if (!Bukkit.isPrimaryThread()) { -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(this.getHandle(), x, z)) { // Folia - region threading ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.getHandle(), x, z)) { // Folia - region threading return java.util.concurrent.CompletableFuture.supplyAsync(() -> { return CraftWorld.this.isChunkGenerated(x, z); - }, world.getChunkSource().mainThreadProcessor).join(); + }, (run) -> { io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueChunkTask(this.getHandle(), x, z, run);}).join(); // Folia - region threading } ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); - if (chunk == null) { -@@ -449,7 +450,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { + if (chunk != null) { +@@ -428,7 +429,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { } private boolean unloadChunk0(int x, int z, boolean save) { - org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, x, z, "Cannot unload chunk asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot unload chunk asynchronously"); // Folia - region threading if (!this.isChunkLoaded(x, z)) { return true; } -@@ -464,7 +465,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -443,7 +444,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean regenerateChunk(int x, int z) { - org.spigotmc.AsyncCatcher.catchOp("chunk regenerate"); // Spigot -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, x, z, "Cannot regenerate chunk asynchronously"); // Folia - region threading - warnUnsafeChunk("regenerating a faraway chunk", x, z); // Paper - // Paper start - implement regenerateChunk method - final ServerLevel serverLevel = this.world; -@@ -529,6 +530,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot regenerate chunk asynchronously"); // Folia - region threading + throw new UnsupportedOperationException("Not supported in this Minecraft version! Unless you can fix it, this is not a bug :)"); + /* + if (!unloadChunk0(x, z, false)) { +@@ -470,6 +471,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean refreshChunk(int x, int z) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, x, z, "Cannot refresh chunk asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot refresh chunk asynchronously"); // Folia - region threading ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); if (playerChunk == null) return false; -@@ -589,7 +591,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -530,7 +532,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -+ io.papermc.paper.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.getHandle(), x, z, "May not sync load chunks asynchronously"); // Folia - region threading warnUnsafeChunk("loading a faraway chunk", x, z); // Paper - // Paper start - Optimize this method - ChunkPos chunkPos = new ChunkPos(x, z); -@@ -658,7 +660,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { + ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper + +@@ -571,7 +573,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager; if (chunkDistanceManager.addRegionTicketAtDistance(TicketType.PLUGIN_TICKET, new ChunkPos(x, z), 2, plugin)) { // keep in-line with force loading, add at level 31 @@ -22031,13 +19406,13 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc return true; } -@@ -868,13 +870,15 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -782,13 +784,15 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { - this.world.captureTreeGeneration = true; - this.world.captureBlockStates = true; -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot generate tree asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot generate tree asynchronously"); // Folia - region threading + io.papermc.paper.threadedregions.RegionizedWorldData worldData = world.getCurrentWorldData(); // Folia - region threading + worldData.captureTreeGeneration = true; // Folia - region threading + worldData.captureBlockStates = true; // Folia - region threading @@ -22052,7 +19427,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc BlockPos position = ((CraftBlockState) blockstate).getPosition(); net.minecraft.world.level.block.state.BlockState oldBlock = this.world.getBlockState(position); int flag = ((CraftBlockState) blockstate).getFlag(); -@@ -882,10 +886,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -796,10 +800,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { net.minecraft.world.level.block.state.BlockState newBlock = this.world.getBlockState(position); this.world.notifyAndUpdatePhysics(position, null, oldBlock, newBlock, newBlock, flag, 512); } @@ -22065,7 +19440,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc return false; } } -@@ -919,6 +923,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -833,6 +837,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setTime(long time) { @@ -22073,7 +19448,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc long margin = (time - this.getFullTime()) % 24000; if (margin < 0) margin += 24000; this.setFullTime(this.getFullTime() + margin); -@@ -931,6 +936,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -845,6 +850,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setFullTime(long time) { @@ -22081,7 +19456,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc // Notify anyone who's listening TimeSkipEvent event = new TimeSkipEvent(this, TimeSkipEvent.SkipReason.CUSTOM, time - this.world.getDayTime()); this.server.getPluginManager().callEvent(event); -@@ -958,7 +964,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -872,7 +878,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public long getGameTime() { @@ -22090,37 +19465,37 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc } @Override -@@ -987,11 +993,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -901,11 +907,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { explosionType = net.minecraft.world.level.Level.ExplosionInteraction.MOB; // Respect mobGriefing gamerule } -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // Folia - region threading return !this.world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, explosionType).wasCanceled; } // Paper start @Override public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot create explosion asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot create explosion asynchronously"); // Folia - region threading return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? net.minecraft.world.level.Level.ExplosionInteraction.MOB : net.minecraft.world.level.Level.ExplosionInteraction.NONE).wasCanceled; } // Paper end -@@ -1068,6 +1076,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -982,6 +990,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, x >> 4, z >> 4, "Cannot retrieve chunk asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x >> 4, z >> 4, "Cannot retrieve chunk asynchronously"); // Folia - region threading warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper // Transient load for this tick return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z); -@@ -1098,6 +1107,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1012,6 +1021,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setBiome(int x, int y, int z, Holder bb) { BlockPos pos = new BlockPos(x, 0, z); -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, pos, "Cannot retrieve chunk asynchronously"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, pos, "Cannot retrieve chunk asynchronously"); // Folia - region threading if (this.world.hasChunkAt(pos)) { net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos); -@@ -1408,6 +1418,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1322,6 +1332,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setStorm(boolean hasStorm) { @@ -22128,7 +19503,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.world.serverLevelData.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper - Add cause to Weather/ThunderChangeEvents this.setWeatherDuration(0); // Reset weather duration (legacy behaviour) this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) -@@ -1420,6 +1431,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1334,6 +1345,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setWeatherDuration(int duration) { @@ -22136,7 +19511,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.world.serverLevelData.setRainTime(duration); } -@@ -1430,6 +1442,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1344,6 +1356,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setThundering(boolean thundering) { @@ -22144,7 +19519,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.world.serverLevelData.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper - Add cause to Weather/ThunderChangeEvents this.setThunderDuration(0); // Reset weather duration (legacy behaviour) this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) -@@ -1442,6 +1455,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1356,6 +1369,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setThunderDuration(int duration) { @@ -22152,7 +19527,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.world.serverLevelData.setThunderTime(duration); } -@@ -1452,6 +1466,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1366,6 +1380,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setClearWeatherDuration(int duration) { @@ -22160,7 +19535,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.world.serverLevelData.setClearWeatherTime(duration); } -@@ -1646,6 +1661,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1560,6 +1575,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setKeepSpawnInMemory(boolean keepLoaded) { @@ -22168,7 +19543,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc if (keepLoaded) { this.setGameRule(GameRule.SPAWN_CHUNK_RADIUS, this.getGameRuleDefault(GameRule.SPAWN_CHUNK_RADIUS)); } else { -@@ -1714,6 +1730,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1628,6 +1644,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setHardcore(boolean hardcore) { @@ -22176,7 +19551,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.world.serverLevelData.settings.hardcore = hardcore; } -@@ -1726,6 +1743,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1640,6 +1657,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerAnimalSpawns(int ticksPerAnimalSpawns) { @@ -22184,7 +19559,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setTicksPerSpawns(SpawnCategory.ANIMAL, ticksPerAnimalSpawns); } -@@ -1738,6 +1756,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1652,6 +1670,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerMonsterSpawns(int ticksPerMonsterSpawns) { @@ -22192,7 +19567,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setTicksPerSpawns(SpawnCategory.MONSTER, ticksPerMonsterSpawns); } -@@ -1750,6 +1769,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1664,6 +1683,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterSpawns(int ticksPerWaterSpawns) { @@ -22200,7 +19575,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setTicksPerSpawns(SpawnCategory.WATER_ANIMAL, ticksPerWaterSpawns); } -@@ -1762,6 +1782,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1676,6 +1696,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterAmbientSpawns(int ticksPerWaterAmbientSpawns) { @@ -22208,7 +19583,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setTicksPerSpawns(SpawnCategory.WATER_AMBIENT, ticksPerWaterAmbientSpawns); } -@@ -1774,6 +1795,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1688,6 +1709,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterUndergroundCreatureSpawns(int ticksPerWaterUndergroundCreatureSpawns) { @@ -22216,7 +19591,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setTicksPerSpawns(SpawnCategory.WATER_UNDERGROUND_CREATURE, ticksPerWaterUndergroundCreatureSpawns); } -@@ -1786,11 +1808,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1700,11 +1722,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerAmbientSpawns(int ticksPerAmbientSpawns) { @@ -22230,7 +19605,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); -@@ -1807,21 +1831,25 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1721,21 +1745,25 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { @@ -22256,7 +19631,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.server.getWorldMetadata().removeMetadata(this, metadataKey, owningPlugin); } -@@ -1834,6 +1862,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1748,6 +1776,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setMonsterSpawnLimit(int limit) { @@ -22264,7 +19639,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setSpawnLimit(SpawnCategory.MONSTER, limit); } -@@ -1846,6 +1875,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1760,6 +1789,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setAnimalSpawnLimit(int limit) { @@ -22272,7 +19647,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setSpawnLimit(SpawnCategory.ANIMAL, limit); } -@@ -1858,6 +1888,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1772,6 +1802,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterAnimalSpawnLimit(int limit) { @@ -22280,7 +19655,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setSpawnLimit(SpawnCategory.WATER_ANIMAL, limit); } -@@ -1870,6 +1901,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1784,6 +1815,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterAmbientSpawnLimit(int limit) { @@ -22288,7 +19663,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setSpawnLimit(SpawnCategory.WATER_AMBIENT, limit); } -@@ -1882,6 +1914,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1796,6 +1828,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterUndergroundCreatureSpawnLimit(int limit) { @@ -22296,7 +19671,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setSpawnLimit(SpawnCategory.WATER_UNDERGROUND_CREATURE, limit); } -@@ -1894,6 +1927,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1808,6 +1841,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setAmbientSpawnLimit(int limit) { @@ -22304,7 +19679,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc this.setSpawnLimit(SpawnCategory.AMBIENT, limit); } -@@ -1916,6 +1950,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1830,6 +1864,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setSpawnLimit(SpawnCategory spawnCategory, int limit) { @@ -22312,25 +19687,25 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); -@@ -1998,7 +2033,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1912,7 +1947,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return; ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(CraftSound.bukkitToMinecraftHolder(sound), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed); - ChunkMap.TrackedEntity entityTracker = this.getHandle().getChunkSource().chunkMap.entityMap.get(entity.getEntityId()); -+ ChunkMap.TrackedEntity entityTracker = ((CraftEntity) entity).getHandle().tracker; // Folia - region threading ++ ChunkMap.TrackedEntity entityTracker = ((CraftEntity) entity).getHandle().moonrise$getTrackedEntity(); // Folia - region threading if (entityTracker != null) { entityTracker.broadcastAndSend(packet); } -@@ -2010,7 +2045,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1924,7 +1959,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return; - ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(Holder.direct(SoundEvent.createVariableRangeEvent(new ResourceLocation(sound))), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed); + ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(Holder.direct(SoundEvent.createVariableRangeEvent(ResourceLocation.parse(sound))), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed); - ChunkMap.TrackedEntity entityTracker = this.getHandle().getChunkSource().chunkMap.entityMap.get(entity.getEntityId()); -+ ChunkMap.TrackedEntity entityTracker = ((CraftEntity)entity).getHandle().tracker; // Folia - region threading ++ ChunkMap.TrackedEntity entityTracker = ((CraftEntity)entity).getHandle().moonrise$getTrackedEntity(); // Folia - region threading if (entityTracker != null) { entityTracker.broadcastAndSend(packet); } -@@ -2099,6 +2134,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2013,6 +2048,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean setGameRuleValue(String rule, String value) { @@ -22338,7 +19713,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc // No null values allowed if (rule == null || value == null) return false; -@@ -2141,6 +2177,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2055,6 +2091,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean setGameRule(GameRule rule, T newValue) { @@ -22346,7 +19721,7 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc Preconditions.checkArgument(rule != null, "GameRule cannot be null"); Preconditions.checkArgument(newValue != null, "GameRule value cannot be null"); -@@ -2392,6 +2429,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2281,6 +2318,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) { @@ -22354,31 +19729,31 @@ index 6303760f10af17f1da1d92d6c4dc7dd6f5778f94..0a14c9ae6dc9daeeb370eee1da7fc5fc + if (sourceEntity != null && !Bukkit.isOwnedByCurrentRegion(sourceEntity)) { + throw new IllegalStateException("Cannot send game event asynchronously"); + } -+ io.papermc.paper.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); + // Folia end - region threading getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.getHolder(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())).orElseThrow(), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position)); } // Paper end -@@ -2520,7 +2563,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2409,7 +2452,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { // Paper start public java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { warnUnsafeChunk("getting a faraway chunk async", x, z); // Paper - if (Bukkit.isPrimaryThread()) { -+ if (io.papermc.paper.util.TickThread.isTickThreadFor(this.getHandle(), x, z)) { // Folia - region threading ++ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.getHandle(), x, z)) { // Folia - region threading net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); if (immediate != null) { return java.util.concurrent.CompletableFuture.completedFuture(new CraftChunk(immediate)); -@@ -2537,7 +2580,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2426,7 +2469,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { java.util.concurrent.CompletableFuture ret = new java.util.concurrent.CompletableFuture<>(); - io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad(this.getHandle(), x, z, gen, ChunkStatus.FULL, true, priority, (c) -> { + ca.spottedleaf.moonrise.common.util.ChunkSystem.scheduleChunkLoad(this.getHandle(), x, z, gen, ChunkStatus.FULL, true, priority, (c) -> { - net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> { + io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(this.getHandle(), x, z, () -> { // Folia - region threading net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)c; if (chunk != null) this.addTicket(x, z); // Paper ret.complete(chunk == null ? null : new CraftChunk(chunk)); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615b97e5cf6 100644 +index ac11f18690434922179b61ffcc3036dea025b0cb..5bc2c3cd495b752e523510cb6c410ea4ea800732 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -75,6 +75,11 @@ public class CraftBlock implements Block { @@ -22387,7 +19762,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public net.minecraft.world.level.block.state.BlockState getNMS() { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading return this.world.getBlockState(this.position); @@ -22399,7 +19774,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 private void setData(final byte data, int flag) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading this.world.setBlock(this.position, CraftMagicNumbers.getBlock(this.getType(), data), flag); @@ -22411,7 +19786,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics) { + // Folia start - region threading + if (world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // Folia end - region threading // SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in tile entity cleanup @@ -22423,7 +19798,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public Biome getBiome() { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading return this.getWorld().getBiome(this.getX(), this.getY(), this.getZ()); @@ -22434,7 +19809,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public Biome getComputedBiome() { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading return this.getWorld().getComputedBiome(this.getX(), this.getY(), this.getZ()); @@ -22445,7 +19820,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public void setBiome(Biome bio) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading this.getWorld().setBiome(this.getX(), this.getY(), this.getZ(), bio); @@ -22457,7 +19832,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public boolean isBlockFaceIndirectlyPowered(BlockFace face) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading int power = this.world.getMinecraftWorld().getSignal(this.position, CraftBlock.blockFaceToNotch(face)); @@ -22469,7 +19844,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public int getBlockPower(BlockFace face) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading int power = 0; @@ -22481,7 +19856,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public boolean breakNaturally(ItemStack item, boolean triggerEffect, boolean dropExperience) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading // Paper end @@ -22493,7 +19868,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public boolean applyBoneMeal(BlockFace face) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading Direction direction = CraftBlock.blockFaceToNotch(face); @@ -22528,7 +19903,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading Preconditions.checkArgument(start != null, "Location start cannot be null"); @@ -22540,7 +19915,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public boolean canPlace(BlockData data) { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading Preconditions.checkArgument(data != null, "BlockData cannot be null"); @@ -22552,7 +19927,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public void tick() { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading final ServerLevel level = this.world.getMinecraftWorld(); @@ -22564,7 +19939,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public void fluidTick() { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading this.getNMSFluid().tick(this.world.getMinecraftWorld(), this.position); @@ -22574,14 +19949,14 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..9efe9fce59a0b4fe7315dc41d1e21615 public void randomTick() { + // Folia start - region threading + if (this.world instanceof ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading final ServerLevel level = this.world.getMinecraftWorld(); this.getNMS().randomTick(level, this.position, level.random); } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..1afd553624613a7af276fd81770ba9af131eca93 100644 +index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..def7749e6dc4ae8351b72deefc75936629c33d7f 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java @@ -215,6 +215,12 @@ public class CraftBlockState implements BlockState { @@ -22590,7 +19965,7 @@ index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..1afd553624613a7af276fd81770ba9af + // Folia start - region threading + if (access instanceof net.minecraft.server.level.ServerLevel serverWorld) { -+ io.papermc.paper.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, position, "Cannot modify world asynchronously"); + } + // Folia end - region threading + @@ -22602,7 +19977,7 @@ index fa63a6cfcfcc4eee4503a82d85333c139c8c8b2b..1afd553624613a7af276fd81770ba9af @Override public java.util.Collection getDrops(org.bukkit.inventory.ItemStack item, org.bukkit.entity.Entity entity) { + // Folia start - region threading -+ io.papermc.paper.util.TickThread.ensureTickThread(world.getHandle(), position, "Cannot modify world asynchronously"); ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(world.getHandle(), position, "Cannot modify world asynchronously"); + // Folia end - region threading this.requirePlaced(); net.minecraft.world.item.ItemStack nms = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item); @@ -22630,10 +20005,10 @@ index 3e93a6c489972ff2b4ecff3d83cc72b2d5c970f8..66dc7e20544c7000f4824b02cc3a31bc List offers = waitable.get(); if (offers == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index a2d336ceb52b63db5c03432ee7bc94dc6a742b82..cf9282a46534319308e9ccf69f332a5c8c1745cf 100644 +index cd789c235acf740ec29c30b180e7fbe1a140caa9..fe6f31d7db873de64c0cfc5c8248d3e5e96f1500 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -234,6 +234,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -236,6 +236,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @Override public boolean teleport(Location location, TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) { @@ -22645,25 +20020,34 @@ index a2d336ceb52b63db5c03432ee7bc94dc6a742b82..cf9282a46534319308e9ccf69f332a5c // Paper end Preconditions.checkArgument(location != null, "location cannot be null"); location.checkFinite(); -@@ -700,7 +705,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -702,7 +707,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { ImmutableSet.Builder players = ImmutableSet.builder(); ServerLevel world = ((CraftWorld) this.getWorld()).getHandle(); - ChunkMap.TrackedEntity entityTracker = world.getChunkSource().chunkMap.entityMap.get(this.getEntityId()); -+ ChunkMap.TrackedEntity entityTracker = this.getHandle().tracker; // Folia - region threading ++ ChunkMap.TrackedEntity entityTracker = this.getHandle().moonrise$getTrackedEntity(); // Folia - region threading if (entityTracker != null) { for (ServerPlayerConnection connection : entityTracker.seenBy) { -@@ -1004,7 +1009,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1006,7 +1011,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } ServerLevel world = ((CraftWorld) this.getWorld()).getHandle(); - ChunkMap.TrackedEntity entityTracker = world.getChunkSource().chunkMap.entityMap.get(this.getEntityId()); -+ ChunkMap.TrackedEntity entityTracker = this.getHandle().tracker; // Folia - region threading ++ ChunkMap.TrackedEntity entityTracker = this.getHandle().moonrise$getTrackedEntity(); // Folia - region threading if (entityTracker == null) { return; -@@ -1042,29 +1047,43 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1025,7 +1030,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + } + + ServerLevel world = ((CraftWorld) this.getWorld()).getHandle(); +- ChunkMap.TrackedEntity entityTracker = world.getChunkSource().chunkMap.entityMap.get(this.getEntityId()); ++ ChunkMap.TrackedEntity entityTracker = this.entity.moonrise$getTrackedEntity(); // Folia - region threading + + if (entityTracker == null) { + return; +@@ -1059,29 +1064,43 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { location.checkFinite(); Location locationClone = location.clone(); // clone so we don't need to worry about mutations after this call. @@ -22726,11 +20110,21 @@ index a2d336ceb52b63db5c03432ee7bc94dc6a742b82..cf9282a46534319308e9ccf69f332a5c } // Paper end - more teleport API / async chunk API +@@ -1194,8 +1213,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { + // Paper start - tracked players API + @Override + public Set getTrackedPlayers() { +- ServerLevel world = (net.minecraft.server.level.ServerLevel)this.entity.level(); +- ChunkMap.TrackedEntity tracker = world == null ? null : world.getChunkSource().chunkMap.entityMap.get(this.entity.getId()); ++ ChunkMap.TrackedEntity tracker = this.entity.moonrise$getTrackedEntity(); // Folia - region threading + if (tracker == null) { + return java.util.Collections.emptySet(); + } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 32c3c2c6b2eaa90b149d9b425341e75b85bd9764..977aee03906ed28c388cc918fc4bade46933a4cd 100644 +index 992437a6e838f653f32d33b5b3f702c484640a97..5f82de67496fafdeb5364e227fec0c49f3fe9d59 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -647,7 +647,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -649,7 +649,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void kickPlayer(String message) { @@ -22738,8 +20132,8 @@ index 32c3c2c6b2eaa90b149d9b425341e75b85bd9764..977aee03906ed28c388cc918fc4bade4 + //org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot // Folia - thread-safe now, as it will simply delay the kick if (this.getHandle().connection == null) return; - this.getHandle().connection.disconnect(message == null ? "" : message, org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause -@@ -1395,6 +1395,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + this.getHandle().connection.disconnect(CraftChatMessage.fromStringOrEmpty(message, true), org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause +@@ -1408,6 +1408,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public boolean teleport(Location location, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) { @@ -22751,29 +20145,38 @@ index 32c3c2c6b2eaa90b149d9b425341e75b85bd9764..977aee03906ed28c388cc918fc4bade4 Set relativeArguments; Set allFlags; if (flags.length == 0) { -@@ -2041,7 +2046,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2060,7 +2065,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private void unregisterEntity(Entity other) { // Paper end ChunkMap tracker = ((ServerLevel) this.getHandle().level()).getChunkSource().chunkMap; - ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); -+ ChunkMap.TrackedEntity entry = other.tracker; // Folia - region threading ++ ChunkMap.TrackedEntity entry = other.moonrise$getTrackedEntity(); // Folia - region threading if (entry != null) { entry.removePlayer(this.getHandle()); } -@@ -2138,7 +2143,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2157,7 +2162,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (original != null) otherPlayer.setUUID(original); // Paper - uuid override } - ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); -+ ChunkMap.TrackedEntity entry = other.tracker; // Folia - region threading ++ ChunkMap.TrackedEntity entry = other.moonrise$getTrackedEntity(); // Folia - region threading if (entry != null && !entry.seenBy.contains(this.getHandle().connection)) { entry.updatePlayer(this.getHandle()); } +@@ -3353,7 +3358,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + { + if ( CraftPlayer.this.getHealth() <= 0 && CraftPlayer.this.isOnline() ) + { +- CraftPlayer.this.server.getServer().getPlayerList().respawn( CraftPlayer.this.getHandle(), false, Entity.RemovalReason.KILLED, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.PLUGIN ); ++ CraftPlayer.this.getHandle().respawn(null, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.PLUGIN); // Folia - region threading + } + } + diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index dfbe0914ab2771ac632fd064719878ac47559e9f..419ccf2b74a8621e0daa134acea060a39c0f5327 100644 +index 0ab53d46f0b8f3f3791dd01766738522c86932e8..db6937ce9a4c4a0a3aefc9df9909139b23b70afb 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -942,7 +942,7 @@ public class CraftEventFactory { +@@ -947,7 +947,7 @@ public class CraftEventFactory { return CraftEventFactory.handleBlockSpreadEvent(world, source, target, block, 2); } @@ -22782,7 +20185,7 @@ index dfbe0914ab2771ac632fd064719878ac47559e9f..419ccf2b74a8621e0daa134acea060a3 public static boolean handleBlockSpreadEvent(LevelAccessor world, BlockPos source, BlockPos target, net.minecraft.world.level.block.state.BlockState block, int flag) { // Suppress during worldgen -@@ -954,7 +954,7 @@ public class CraftEventFactory { +@@ -959,7 +959,7 @@ public class CraftEventFactory { CraftBlockState state = CraftBlockStates.getBlockState(world, target, flag); state.setData(block); @@ -22791,7 +20194,7 @@ index dfbe0914ab2771ac632fd064719878ac47559e9f..419ccf2b74a8621e0daa134acea060a3 Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { -@@ -2154,7 +2154,7 @@ public class CraftEventFactory { +@@ -2196,7 +2196,7 @@ public class CraftEventFactory { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1)); org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to)); @@ -22801,10 +20204,10 @@ index dfbe0914ab2771ac632fd064719878ac47559e9f..419ccf2b74a8621e0daa134acea060a3 return itemStack; } diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index e85b9bb3f9c225d289a4959921970b9963881199..b00e3b9b628f3d2a2fdbf1d2c77904963c16d3ac 100644 +index 2f4d6b56301195f8d39ed50dffe842464065bfe1..5a24902b735cbd64dd5cd5ad46b096c4bdfa799f 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -532,6 +532,7 @@ public class CraftScheduler implements BukkitScheduler { +@@ -521,6 +521,7 @@ public class CraftScheduler implements BukkitScheduler { } protected CraftTask handle(final CraftTask task, final long delay) { // Paper @@ -22813,10 +20216,10 @@ index e85b9bb3f9c225d289a4959921970b9963881199..b00e3b9b628f3d2a2fdbf1d2c7790496 if (!this.isAsyncScheduler && !task.isSync()) { this.asyncScheduler.handle(task, delay); diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index f99353a60e3f236735ef6e2e6f13381b50ae9b7b..5a349c554000417cebb5c74fd719fad569b15b05 100644 +index 41c34ffdf9d95a04ed55a1e09ebc78e8cf946777..f89e08c22bc76dba5df730a83b37324e38d2956d 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -389,6 +389,12 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -369,6 +369,12 @@ public final class CraftMagicNumbers implements UnsafeValues { throw new InvalidPluginException("Unsupported API version " + pdf.getAPIVersion()); } @@ -22830,7 +20233,7 @@ index f99353a60e3f236735ef6e2e6f13381b50ae9b7b..5a349c554000417cebb5c74fd719fad5 // Older than supported throw new InvalidPluginException("Plugin API version " + pdf.getAPIVersion() + " is lower than the minimum allowed version. Please update or replace it."); diff --git a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java -index 41a291d42667c38d3e5bbe47236772761e85929b..1c0e4f11d4d0be568ed38a02bf9e8f857fca69fc 100644 +index bf18f9ad7dec2b09ebfcb5ec6566f2556e842f22..2dddb661b29c1c3350bfbf71a0a1b961b07ad80f 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java +++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java @@ -68,6 +68,13 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel { @@ -22848,7 +20251,7 @@ index 41a291d42667c38d3e5bbe47236772761e85929b..1c0e4f11d4d0be568ed38a02bf9e8f85 return this.handle; } diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 3283ed99c35ffed6805567705e0518d9f84feedc..4fc4690d03fd5f39e019f16845954052210c7361 100644 +index bf2d18f74b0f0da7c3c30310c74224a1c0853564..91c63c3dceddf09018d3651f4c11bf521eb53ecf 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java @@ -52,7 +52,7 @@ public class ActivationRange @@ -22960,12 +20363,12 @@ index 3283ed99c35ffed6805567705e0518d9f84feedc..4fc4690d03fd5f39e019f16845954052 // Paper start - java.util.List entities = world.getEntities((Entity)null, ActivationRange.maxBB, null); + java.util.List entities = new java.util.ArrayList<>(); // Folia - region ticking - bypass getEntities thread check, we perform a check on the entities later -+ ((net.minecraft.server.level.ServerLevel)world).getEntityLookup().getEntities((Entity)null, maxBB, entities, null); // Folia - region ticking - bypass getEntities thread check, we perform a check on the entities later ++ ((net.minecraft.server.level.ServerLevel)world).moonrise$getEntityLookup().getEntities((Entity)null, maxBB, entities, null); // Folia - region ticking - bypass getEntities thread check, we perform a check on the entities later boolean tickMarkers = world.paperConfig().entities.markers.tick; // Paper - Configurable marker ticking for (Entity entity : entities) { // Paper start - Configurable marker ticking + // Folia start - region ticking -+ if (!io.papermc.paper.util.TickThread.isTickThreadFor(entity)) { ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity)) { + continue; + } + // Folia end - region ticking @@ -23059,10 +20462,10 @@ index ac0fd418fcb437896dfdff53ab3eff19833d25fb..130220977477a5d8d51e17dcb989ae0c return true; diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java -index 6c2a3813e7d63d57f07a8fa2edbb9d231221d818..97ee030af8d5328611e3c0ed2ca1eb59d1907f7b 100644 +index 4dbb109d0526afee99b9190fc256585121aac9b5..5c80e89034c1b3149729684ba4dd4ae26a4261c1 100644 --- a/src/main/java/org/spigotmc/SpigotConfig.java +++ b/src/main/java/org/spigotmc/SpigotConfig.java -@@ -228,7 +228,7 @@ public class SpigotConfig +@@ -224,7 +224,7 @@ public class SpigotConfig SpigotConfig.restartOnCrash = SpigotConfig.getBoolean( "settings.restart-on-crash", SpigotConfig.restartOnCrash ); SpigotConfig.restartScript = SpigotConfig.getString( "settings.restart-script", SpigotConfig.restartScript ); SpigotConfig.restartMessage = SpigotConfig.transform( SpigotConfig.getString( "messages.restart", "Server is restarting" ) ); @@ -23071,7 +20474,7 @@ index 6c2a3813e7d63d57f07a8fa2edbb9d231221d818..97ee030af8d5328611e3c0ed2ca1eb59 // WatchdogThread.doStart( SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); // Paper - moved to after paper config initialization } -@@ -283,7 +283,7 @@ public class SpigotConfig +@@ -279,7 +279,7 @@ public class SpigotConfig private static void tpsCommand() { @@ -23081,7 +20484,7 @@ index 6c2a3813e7d63d57f07a8fa2edbb9d231221d818..97ee030af8d5328611e3c0ed2ca1eb59 public static int playerSample; diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index dbfe355221fb2ee66b79442a749412d9288afc0d..44bcc7e64766647a52f01958b9e087caa94dcdf6 100644 +index 2c408fa4abcbe1171c58aee8799c8cf7867d0f0a..9f38a0763597d9d70cb8d1b636c7d4b14d32c535 100644 --- a/src/main/java/org/spigotmc/SpigotWorldConfig.java +++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java @@ -435,7 +435,7 @@ public class SpigotWorldConfig diff --git a/patches/server/0004-Max-pending-logins.patch b/patches/server/0004-Max-pending-logins.patch index 9a402de..23be29d 100644 --- a/patches/server/0004-Max-pending-logins.patch +++ b/patches/server/0004-Max-pending-logins.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Max pending logins Should help the floodgates on launch diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 734f745ce383c8398fdedeb6fd71277e1482a4a6..83b09feec13a00c35e6f8d4f0ccdae1c8da9c0e5 100644 +index bc9956d36ce3adabd50dc4b6467a0fd24386e4e0..d0f8a81ed0363764d185682c3de667703d30e8eb 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -110,7 +110,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, +@@ -112,7 +112,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, if (this.server.getPlayerList().pushPendingJoin(name, uniqueId, this.connection)) { // Folia end - region threading - rewrite login process this.verifyLoginAndFinishConnectionSetup((GameProfile) Objects.requireNonNull(this.authenticatedProfile)); @@ -19,7 +19,7 @@ index 734f745ce383c8398fdedeb6fd71277e1482a4a6..83b09feec13a00c35e6f8d4f0ccdae1c // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 67b832c9a36f8af245e381c7fa3c56a7e9becd1e..db2903276c694d395f62afdc7c71344466ae505f 100644 +index cb8233a3c1d49197da7378adda5fa17ac44fd673..e0ff51d537dccd0018b8cb7f5a4bb25222f1219c 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -175,6 +175,17 @@ public abstract class PlayerList { diff --git a/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch b/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch index bfdbffc..466d3da 100644 --- a/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch +++ b/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch @@ -4,13 +4,13 @@ Date: Fri, 10 Mar 2023 00:16:26 -0800 Subject: [PATCH] Add chunk system throughput counters to /tps -diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java -index c307b084f59f7bb94dc02f25bbcd3e01e01d2306..b53d15a3979f42cb1b9a4cba24147c32f9a1a676 100644 ---- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java -+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkFullTask.java -@@ -22,6 +22,9 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl - protected final ChunkAccess fromChunk; - protected final PrioritisedExecutor.PrioritisedTask convertToFullTask; +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java +index fbdf721e8b4cfe6cef4ee60c53c680cbfc858d88..8581b8771b8cc89ff7bdb63fbfd5628a1e7d4762 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java +@@ -28,6 +28,9 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl + private final ChunkAccess fromChunk; + private final PrioritisedExecutor.PrioritisedTask convertToFullTask; + public static final io.papermc.paper.util.IntervalledCounter chunkLoads = new io.papermc.paper.util.IntervalledCounter(java.util.concurrent.TimeUnit.SECONDS.toNanos(15L)); + public static final io.papermc.paper.util.IntervalledCounter chunkGenerates = new io.papermc.paper.util.IntervalledCounter(java.util.concurrent.TimeUnit.SECONDS.toNanos(15L)); @@ -18,7 +18,7 @@ index c307b084f59f7bb94dc02f25bbcd3e01e01d2306..b53d15a3979f42cb1b9a4cba24147c32 public ChunkFullTask(final ChunkTaskScheduler scheduler, final ServerLevel world, final int chunkX, final int chunkZ, final NewChunkHolder chunkHolder, final ChunkAccess fromChunk, final PrioritisedExecutor.Priority priority) { super(scheduler, world, chunkX, chunkZ); -@@ -35,6 +38,20 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl +@@ -41,6 +44,20 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl return ChunkStatus.FULL; } @@ -38,9 +38,9 @@ index c307b084f59f7bb94dc02f25bbcd3e01e01d2306..b53d15a3979f42cb1b9a4cba24147c32 + @Override public void run() { - // See Vanilla protoChunkToFullChunk for what this function should be doing -@@ -49,6 +66,17 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl - this.world.getPoiManager().checkConsistency(this.fromChunk); + // See Vanilla ChunkPyramid#LOADING_PYRAMID.FULL for what this function should be doing +@@ -55,6 +72,17 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl + ((ChunkSystemPoiManager)this.world.getPoiManager()).moonrise$checkConsistency(this.fromChunk); } + final long time = System.nanoTime(); @@ -58,15 +58,15 @@ index c307b084f59f7bb94dc02f25bbcd3e01e01d2306..b53d15a3979f42cb1b9a4cba24147c32 chunk = wrappedFull.getWrapped(); } else { diff --git a/src/main/java/io/papermc/paper/threadedregions/commands/CommandServerHealth.java b/src/main/java/io/papermc/paper/threadedregions/commands/CommandServerHealth.java -index 3bcb1dc98c61e025874cc9e008faa722581a530c..0b48f45760829f1f4813b5f0f23e920dca7b1c45 100644 +index 3bcb1dc98c61e025874cc9e008faa722581a530c..012d3a7da7fe483393a0888c823bd2e78f5c3908 100644 --- a/src/main/java/io/papermc/paper/threadedregions/commands/CommandServerHealth.java +++ b/src/main/java/io/papermc/paper/threadedregions/commands/CommandServerHealth.java @@ -170,6 +170,9 @@ public final class CommandServerHealth extends Command { totalUtil += (report == null ? 0.0 : report.utilisation()); } -+ final double genRate = io.papermc.paper.chunk.system.scheduling.ChunkFullTask.genRate(currTime); -+ final double loadRate = io.papermc.paper.chunk.system.scheduling.ChunkFullTask.loadRate(currTime); ++ final double genRate = ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkFullTask.genRate(currTime); ++ final double loadRate = ca.spottedleaf.moonrise.patches.chunk_system.scheduling.task.ChunkFullTask.loadRate(currTime); + totalUtil += globalTickReport.utilisation(); diff --git a/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch b/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch index 71a5084..fff83e0 100644 --- a/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch +++ b/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch @@ -8,7 +8,7 @@ While these checks are painful, it should assist in debugging threading issues for plugins. diff --git a/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java b/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java -index 41bf71d116ffc5431586ce54abba7f8def6c1dcf..519da6886613b8460e989767b1a21e3126cb1894 100644 +index 41bf71d116ffc5431586ce54abba7f8def6c1dcf..1cf9a7677449ab8f03fb23d835e3fadce61542db 100644 --- a/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java +++ b/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java @@ -11,8 +11,16 @@ public class PaperSchoolableFish extends CraftFish implements SchoolableFish { @@ -24,15 +24,15 @@ index 41bf71d116ffc5431586ce54abba7f8def6c1dcf..519da6886613b8460e989767b1a21e31 + @Override public AbstractSchoolingFish getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractSchoolingFish) super.getHandle(); } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index afc4fced315f2177372597d88eaf90cc8f3d878a..fad6a7185e8e9ea160b47ec9da56d08af9df8396 100644 +index f736ad7e211c89e4c7edc689b089b1b3b486fbab..7a102b4e90fbc09b8653e5b566299efe24a04cf6 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2991,6 +2991,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3044,6 +3044,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (!force && (!this.canRide(entity) || !entity.canAddPassenger(this))) { return false; } else { @@ -40,7 +40,7 @@ index afc4fced315f2177372597d88eaf90cc8f3d878a..fad6a7185e8e9ea160b47ec9da56d08a // CraftBukkit start if (entity.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) entity.getBukkitEntity(), this.getBukkitEntity()); -@@ -3012,6 +3013,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3065,6 +3066,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return false; } // CraftBukkit end @@ -48,7 +48,7 @@ index afc4fced315f2177372597d88eaf90cc8f3d878a..fad6a7185e8e9ea160b47ec9da56d08a if (this.isPassenger()) { this.stopRiding(); } -@@ -3095,6 +3097,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3148,6 +3150,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); } else { // CraftBukkit start @@ -56,7 +56,7 @@ index afc4fced315f2177372597d88eaf90cc8f3d878a..fad6a7185e8e9ea160b47ec9da56d08a CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); Entity orig = craft == null ? null : craft.getHandle(); if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { -@@ -3122,6 +3125,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3175,6 +3178,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return false; } // CraftBukkit end @@ -65,7 +65,7 @@ index afc4fced315f2177372597d88eaf90cc8f3d878a..fad6a7185e8e9ea160b47ec9da56d08a this.passengers = ImmutableList.of(); } else { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java -index 591af9d0d2fdc9953415979fc97a4a00afd85885..4d4c88b2464bd1a65082a3377fac8a5ec90fdeae 100644 +index 591af9d0d2fdc9953415979fc97a4a00afd85885..4a0fd1e3203342b7a5ffde579947057fe84a0d80 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java @@ -1,5 +1,6 @@ @@ -93,24 +93,24 @@ index 591af9d0d2fdc9953415979fc97a4a00afd85885..4d4c88b2464bd1a65082a3377fac8a5e @Override public net.minecraft.world.entity.projectile.Projectile getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.Projectile) entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java -index 656e1fc4321a804aa79a08bca8974637d4ffdb1b..b901fbfa0e8de17090cf82d4f4f0844866f335f8 100644 +index 501e2aa3a10dae94c4a8d9dfcdc902e434fcca62..865419a80712e111aeb1e436ff9c27fa4b6f37fb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java -@@ -120,6 +120,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr +@@ -130,6 +130,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr @Override public net.minecraft.world.entity.projectile.AbstractArrow getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.AbstractArrow) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java -index 9bcc0931510607b8fbd01233e2b3c346369b214d..74aeff7b47b1f5325e5ac676d9aed3c94a2a843c 100644 +index 467693a60786688b753cebac3b0a88898e332eee..5c6bd9186e47d1414c5e7bd4fa46a8e305390908 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractHorse.java @@ -17,8 +17,16 @@ public abstract class CraftAbstractHorse extends CraftAnimals implements Abstrac @@ -126,12 +126,12 @@ index 9bcc0931510607b8fbd01233e2b3c346369b214d..74aeff7b47b1f5325e5ac676d9aed3c9 + @Override public net.minecraft.world.entity.animal.horse.AbstractHorse getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.horse.AbstractHorse) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java -index 5beaa2bb0d58fe477ce8d2de8b77600d3b416d8c..fa1bc80ae320c6d04acc20d6dec7df52a39d9920 100644 +index 5beaa2bb0d58fe477ce8d2de8b77600d3b416d8c..c8406f2d83f4c8b60efec0de546f45760c759a2a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java @@ -15,8 +15,17 @@ public abstract class CraftAbstractSkeleton extends CraftMonster implements Abst @@ -148,12 +148,12 @@ index 5beaa2bb0d58fe477ce8d2de8b77600d3b416d8c..fa1bc80ae320c6d04acc20d6dec7df52 + @Override public net.minecraft.world.entity.monster.AbstractSkeleton getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.AbstractSkeleton) super.getHandle(); } // Paper end diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java -index 34e4c763c7ec971885147ab2509281fad56e1ca6..a0a83e9111523a8080f30d0fdd35b9c9373ca359 100644 +index 34e4c763c7ec971885147ab2509281fad56e1ca6..7fb2e28c12dba743d8c2fb0a8a4e2f3e76d151f6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java @@ -17,8 +17,16 @@ public class CraftAbstractVillager extends CraftAgeable implements AbstractVilla @@ -169,24 +169,24 @@ index 34e4c763c7ec971885147ab2509281fad56e1ca6..a0a83e9111523a8080f30d0fdd35b9c9 + @Override public net.minecraft.world.entity.npc.AbstractVillager getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Villager) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java -index 5e6bbeeea0cbf53180fd1260fc53f843469d6588..cb3c3c3294f0760956b6c5643e69afe0e9562f23 100644 +index 59df9031e8b4466c8687671d745318e7ee83d271..b91b11c2e1ed5df27e6ff99eb5cc25b931e0b79d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java @@ -17,6 +17,7 @@ public abstract class CraftAbstractWindCharge extends CraftFireball implements A @Override public net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java -index ae16e8d1bfe8e9315391510eddb367a3fbdc9e03..bdbb54cc60c9afa8a7b89419563fcbe502554aac 100644 +index ae16e8d1bfe8e9315391510eddb367a3fbdc9e03..2b165c209f65de06f55ed51817e33b92463a2987 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java @@ -63,8 +63,16 @@ public class CraftAgeable extends CraftCreature implements Ageable { @@ -202,12 +202,12 @@ index ae16e8d1bfe8e9315391510eddb367a3fbdc9e03..bdbb54cc60c9afa8a7b89419563fcbe5 + @Override public AgeableMob getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AgeableMob) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java -index c64918175ec08d20cde2bda9e0cac8b474385fe0..633c7581f9eec8a04598a62eae64adb617cf0fa7 100644 +index c64918175ec08d20cde2bda9e0cac8b474385fe0..0df0824d56d62f7b82fcca8f0b9a6175f012e8d3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java @@ -16,8 +16,16 @@ public class CraftAllay extends CraftCreature implements org.bukkit.entity.Allay @@ -223,12 +223,12 @@ index c64918175ec08d20cde2bda9e0cac8b474385fe0..633c7581f9eec8a04598a62eae64adb6 + @Override public Allay getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Allay) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java -index 2a2f9f0907eafcabef26a41d20f64a0aa953d181..8f654e3a210a332dc2d526b579d8fcf0c54e4d28 100644 +index 2a2f9f0907eafcabef26a41d20f64a0aa953d181..9d56293083aac5c14e8333366fd4cf6148486585 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java @@ -9,8 +9,16 @@ public class CraftAmbient extends CraftMob implements Ambient { @@ -244,12 +244,12 @@ index 2a2f9f0907eafcabef26a41d20f64a0aa953d181..8f654e3a210a332dc2d526b579d8fcf0 + @Override public AmbientCreature getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AmbientCreature) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java -index ab42bc721d5b6c17c2ca6c7153b757571aea05e8..2887699c16b9452ce948f8b945c595ca55488cf7 100644 +index ab42bc721d5b6c17c2ca6c7153b757571aea05e8..e48528689d49c01aa2b0c1599c66f3c1e94c9cd6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java @@ -15,8 +15,16 @@ public class CraftAnimals extends CraftAgeable implements Animals { @@ -265,12 +265,12 @@ index ab42bc721d5b6c17c2ca6c7153b757571aea05e8..2887699c16b9452ce948f8b945c595ca + @Override public Animal getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Animal) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java -index 88f2a9f310f30a08893f3fa68af13a54cf72fa7f..fc6bae91b4e894bda825b3fc6ccaa3a18acdb868 100644 +index 88f2a9f310f30a08893f3fa68af13a54cf72fa7f..b0cf5c7ee2542985ea704da26d36b272271ad096 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java @@ -28,8 +28,16 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud @@ -286,24 +286,24 @@ index 88f2a9f310f30a08893f3fa68af13a54cf72fa7f..fc6bae91b4e894bda825b3fc6ccaa3a1 + @Override public net.minecraft.world.entity.AreaEffectCloud getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.AreaEffectCloud) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java -index e7f2d8de25a489d7f52c78c750e6f7f9b8fee177..99f331b555cb6c55af4e0d7785d282645f92a570 100644 +index e7f2d8de25a489d7f52c78c750e6f7f9b8fee177..75191dd32bba12b5742702a2af151b1079a6b48f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java @@ -11,6 +11,7 @@ public class CraftArmadillo extends CraftAnimals implements Armadillo { @Override public net.minecraft.world.entity.animal.armadillo.Armadillo getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.armadillo.Armadillo) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 9fe85d6f807e64cf02d8e1921672e3196f6d606f..fd10d353305aa4095edf5f8b01a625fdfed8f1d3 100644 +index 9fe85d6f807e64cf02d8e1921672e3196f6d606f..8a95bc7b1250d47f518a62e625e78a7910ead7ff 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java @@ -20,8 +20,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { @@ -319,19 +319,19 @@ index 9fe85d6f807e64cf02d8e1921672e3196f6d606f..fd10d353305aa4095edf5f8b01a625fd + @Override public net.minecraft.world.entity.decoration.ArmorStand getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.decoration.ArmorStand) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -index 071be344c3265a0cd52b31ffbb02ff7a70bdf231..2d5cffc481ed137a60033d18eab6ce3a9c688fb5 100644 +index 071be344c3265a0cd52b31ffbb02ff7a70bdf231..0152b1ba40f505bfb5ba941f6d6d0a22d825519a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java @@ -26,6 +26,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow { @Override public net.minecraft.world.entity.projectile.Arrow getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.Arrow) this.entity; } @@ -350,7 +350,7 @@ index 071be344c3265a0cd52b31ffbb02ff7a70bdf231..2d5cffc481ed137a60033d18eab6ce3a public void setBasePotionData(PotionData data) { this.setBasePotionType(CraftPotionUtil.fromBukkit(data)); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java -index cbfca242f820d238b112f8ce64e9de8398c48a1c..c5f0cd5e69a20f1fffcd017385bf9fab59630ffc 100644 +index cbfca242f820d238b112f8ce64e9de8398c48a1c..efbfc8480bddf901fe0acebc06408ee625b57418 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java @@ -10,8 +10,16 @@ public class CraftAxolotl extends CraftAnimals implements Axolotl, io.papermc.pa @@ -366,12 +366,12 @@ index cbfca242f820d238b112f8ce64e9de8398c48a1c..c5f0cd5e69a20f1fffcd017385bf9fab + @Override public net.minecraft.world.entity.animal.axolotl.Axolotl getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.axolotl.Axolotl) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java -index 1bb72f28085f3885bec068b586ec222111044884..1d09154b76d7f76e013a6980b5263215d26e81d9 100644 +index 1bb72f28085f3885bec068b586ec222111044884..cb56b6690a385e76197cfc0667ebdec72f0cd096 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java @@ -8,8 +8,16 @@ public class CraftBat extends CraftAmbient implements Bat { @@ -387,12 +387,12 @@ index 1bb72f28085f3885bec068b586ec222111044884..1d09154b76d7f76e013a6980b5263215 + @Override public net.minecraft.world.entity.ambient.Bat getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.ambient.Bat) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java -index 3dac93b0ab5d5acf5b33dc4b0efed60319eb657b..4fce53e012067f2cc91ae89b2254ebfd030017d5 100644 +index 3dac93b0ab5d5acf5b33dc4b0efed60319eb657b..6ade6ca1a32f824271b7deeabc4dd154ae5a67b6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java @@ -13,8 +13,16 @@ public class CraftBee extends CraftAnimals implements Bee { @@ -408,12 +408,12 @@ index 3dac93b0ab5d5acf5b33dc4b0efed60319eb657b..4fce53e012067f2cc91ae89b2254ebfd + @Override public net.minecraft.world.entity.animal.Bee getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Bee) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java -index a4c9c73691300880777483b0beb17e1bd6779d06..e19c8cb6cf3d4306d2779bc7329e0fdc7aef59da 100644 +index a4c9c73691300880777483b0beb17e1bd6779d06..05951297aaed63c22f038703ad6fb68dfcec5227 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java @@ -8,8 +8,16 @@ public class CraftBlaze extends CraftMonster implements Blaze { @@ -429,12 +429,12 @@ index a4c9c73691300880777483b0beb17e1bd6779d06..e19c8cb6cf3d4306d2779bc7329e0fdc + @Override public net.minecraft.world.entity.monster.Blaze getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Blaze) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java -index dd91de8f24c27b9318c2a898a49991d74c100bff..d7c34f601ce66a6b090ec431a0503462865155a8 100644 +index dd91de8f24c27b9318c2a898a49991d74c100bff..b951571eda47da97ee73ba7d9b71b4f6cf0373d6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java @@ -12,8 +12,16 @@ public class CraftBlockDisplay extends CraftDisplay implements BlockDisplay { @@ -450,12 +450,12 @@ index dd91de8f24c27b9318c2a898a49991d74c100bff..d7c34f601ce66a6b090ec431a0503462 + @Override public net.minecraft.world.entity.Display.BlockDisplay getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.Display.BlockDisplay) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index e33b1b6fd50a4eea57500cc00dba20d6edcab75d..f9a8e684a04c4ffdf566b29252e18dbfcf09ade9 100644 +index e33b1b6fd50a4eea57500cc00dba20d6edcab75d..74d1f88ae81b01e7c00ec43fcbe5b9b159d89956 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java @@ -102,8 +102,16 @@ public class CraftBoat extends CraftVehicle implements Boat { @@ -471,48 +471,48 @@ index e33b1b6fd50a4eea57500cc00dba20d6edcab75d..f9a8e684a04c4ffdf566b29252e18dbf + @Override public net.minecraft.world.entity.vehicle.Boat getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.vehicle.Boat) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java -index 93481e2828f945b11ae9a20a8e5286232b449fa9..fc226a73e0938efcbd2b0eb296f6677229dfba72 100644 +index 93481e2828f945b11ae9a20a8e5286232b449fa9..ad5d48c7bb747eb9ea79fd1a3853a242037ed969 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java @@ -12,6 +12,7 @@ public class CraftBogged extends CraftAbstractSkeleton implements Bogged, io.pap @Override public net.minecraft.world.entity.monster.Bogged getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Bogged) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java -index 3f3d087387d3169f352d7377c0e5a24668c3d17e..23f6eac9cec63da625c6328895702bc26c9c8ada 100644 +index 3f3d087387d3169f352d7377c0e5a24668c3d17e..fd22213bc7a8461f5e698792c426384683fb3b7b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java @@ -11,6 +11,7 @@ public class CraftBreeze extends CraftMonster implements Breeze { @Override public net.minecraft.world.entity.monster.breeze.Breeze getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.breeze.Breeze) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java -index e88e52a9b8a4d2d750101b0529cbe2a9976e91dd..8ba5a80bb4847cf33e2618cf5122f1fcffc2453d 100644 +index e88e52a9b8a4d2d750101b0529cbe2a9976e91dd..0eadb421cc505c4639f68c932d284e8ef56f7f57 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java @@ -10,6 +10,7 @@ public class CraftBreezeWindCharge extends CraftAbstractWindCharge implements Br @Override public net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java -index 80e571c977db5cdf43bfbfce035f37a3fa325c95..6fafba37dd7128a397ba046be7b33067c9e88f25 100644 +index 80e571c977db5cdf43bfbfce035f37a3fa325c95..562ac40645f98452d0d923146d4e95c59b029f5b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java @@ -11,8 +11,16 @@ public class CraftCamel extends CraftAbstractHorse implements Camel { @@ -528,15 +528,15 @@ index 80e571c977db5cdf43bfbfce035f37a3fa325c95..6fafba37dd7128a397ba046be7b33067 + @Override public net.minecraft.world.entity.animal.camel.Camel getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.camel.Camel) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java -index a565ac47b3dc9a27e043fc9cb00b6dea950f08cf..d753d481d84f3c6cabef79752b8164ebbb02e605 100644 +index 88e876da7df64b68a5b71fd1deab75b59c5a64e3..3319f46e2c464c553425e33ac31f1d5190c2d1b5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java -@@ -17,8 +17,16 @@ public class CraftCat extends CraftTameableAnimal implements Cat { +@@ -19,8 +19,16 @@ public class CraftCat extends CraftTameableAnimal implements Cat { super(server, entity); } @@ -549,12 +549,12 @@ index a565ac47b3dc9a27e043fc9cb00b6dea950f08cf..d753d481d84f3c6cabef79752b8164eb + @Override public net.minecraft.world.entity.animal.Cat getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Cat) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java -index 4f661fbdb860cf550da0d952b775fe6f990b43b3..4a8b2b6bf80d43bba551c34a1a03fd5c9a9d7a02 100644 +index 4f661fbdb860cf550da0d952b775fe6f990b43b3..2dfbfbbe98815a303516d88e6ea96b9fba9b7f39 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java @@ -8,8 +8,16 @@ public class CraftCaveSpider extends CraftSpider implements CaveSpider { @@ -570,12 +570,12 @@ index 4f661fbdb860cf550da0d952b775fe6f990b43b3..4a8b2b6bf80d43bba551c34a1a03fd5c + @Override public net.minecraft.world.entity.monster.CaveSpider getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.CaveSpider) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java -index e4f899a6a1d055b3ea17d1114ed0228fbba53352..0db4bd89f0b4ca6d1c855f7f6216a5a1511b9e5e 100644 +index e4f899a6a1d055b3ea17d1114ed0228fbba53352..4d9bb569b6a957c4ebd06f93d36a0f351961fd23 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java @@ -15,8 +15,16 @@ public class CraftChestBoat extends CraftBoat implements org.bukkit.entity.Chest @@ -591,12 +591,12 @@ index e4f899a6a1d055b3ea17d1114ed0228fbba53352..0db4bd89f0b4ca6d1c855f7f6216a5a1 + @Override public ChestBoat getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ChestBoat) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java -index 40ee96e31dea64ab3a77553dbb6daad001736f2e..1a9986acde12881e32db67b9e7263072871331cb 100644 +index 40ee96e31dea64ab3a77553dbb6daad001736f2e..9cdb7e5ce6883709b709e88037e70a1953d755a0 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java @@ -10,8 +10,16 @@ public abstract class CraftChestedHorse extends CraftAbstractHorse implements Ch @@ -612,12 +612,12 @@ index 40ee96e31dea64ab3a77553dbb6daad001736f2e..1a9986acde12881e32db67b9e7263072 + @Override public AbstractChestedHorse getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractChestedHorse) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java -index 96f6e2fd9c6b20d34122abfe5c7fba732502d5a0..a32874bc84a13c3be3512b46519e66b24a4dbce0 100644 +index 96f6e2fd9c6b20d34122abfe5c7fba732502d5a0..2546ce4d7a25bfe6be1533bfbc770726815e8148 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java @@ -9,8 +9,16 @@ public class CraftChicken extends CraftAnimals implements Chicken { @@ -633,12 +633,12 @@ index 96f6e2fd9c6b20d34122abfe5c7fba732502d5a0..a32874bc84a13c3be3512b46519e66b2 + @Override public net.minecraft.world.entity.animal.Chicken getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Chicken) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java -index 63e6b07e3b159c74d9ef17be20b5ab43d07f0f5f..7e3a560ff4a3d56e52534eb909eaf60424b84514 100644 +index 63e6b07e3b159c74d9ef17be20b5ab43d07f0f5f..44fa01798eed8368fa0187cecb88de830d7d2e16 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java @@ -9,8 +9,16 @@ public class CraftCod extends io.papermc.paper.entity.PaperSchoolableFish implem @@ -654,12 +654,12 @@ index 63e6b07e3b159c74d9ef17be20b5ab43d07f0f5f..7e3a560ff4a3d56e52534eb909eaf604 + @Override public net.minecraft.world.entity.animal.Cod getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Cod) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java -index c2583982d84c736639eec511daba594d7806a628..963ef176acd9e3a182b51722544001e309f5d7ae 100644 +index c2583982d84c736639eec511daba594d7806a628..d31bba789c51bc344d21a357f54dd8ef55b88873 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java @@ -32,8 +32,16 @@ public class CraftComplexPart extends CraftEntity implements ComplexEntityPart { @@ -675,12 +675,12 @@ index c2583982d84c736639eec511daba594d7806a628..963ef176acd9e3a182b51722544001e3 + @Override public EnderDragonPart getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (EnderDragonPart) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java -index 7babc404e4920cd264206d4e83b1be6f841cdb8c..6fef0910ee934aedc09bac212ef3fba4f546d5ce 100644 +index 7babc404e4920cd264206d4e83b1be6f841cdb8c..7a5312ab0fe3a21907a1d6b82fab9b4dce15c44e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java @@ -9,8 +9,16 @@ public class CraftCow extends CraftAnimals implements Cow { @@ -696,12 +696,12 @@ index 7babc404e4920cd264206d4e83b1be6f841cdb8c..6fef0910ee934aedc09bac212ef3fba4 + @Override public net.minecraft.world.entity.animal.Cow getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Cow) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java -index 664d9c1793b823ed03f198a936f2ebd9b7695898..da9a83f9b020f637e4485ca53bc97bb50596808c 100644 +index 664d9c1793b823ed03f198a936f2ebd9b7695898..6cbe6b6438296b6137ceea01b21ab6a69da2cc9c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java @@ -9,8 +9,16 @@ public class CraftCreature extends CraftMob implements Creature { @@ -717,15 +717,15 @@ index 664d9c1793b823ed03f198a936f2ebd9b7695898..da9a83f9b020f637e4485ca53bc97bb5 + @Override public PathfinderMob getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (PathfinderMob) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -index 4191845bfe05d8691e50143c42090566522f7e74..7aea0d9f5c17c8dcab73ffe9906a456534c292b0 100644 +index 42dd26b9170f7d217d73f725a6b8440b45ac2190..e59a29ee70e8b1f525c370bb711fa77a5732c500 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -@@ -79,8 +79,16 @@ public class CraftCreeper extends CraftMonster implements Creeper { +@@ -87,6 +87,13 @@ public class CraftCreeper extends CraftMonster implements Creeper { this.getHandle().ignite(); } @@ -736,14 +736,19 @@ index 4191845bfe05d8691e50143c42090566522f7e74..7aea0d9f5c17c8dcab73ffe9906a4565 + } + // Folia end - region threading + + @Override + public Entity getIgniter() { + return (this.getHandle().entityIgniter != null) ? this.getHandle().entityIgniter.getBukkitEntity() : null; +@@ -94,6 +101,7 @@ public class CraftCreeper extends CraftMonster implements Creeper { + @Override public net.minecraft.world.entity.monster.Creeper getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Creeper) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java -index 48eeb1d9ba0ad6f895bfe507a6fbe4b9c9530e47..4eb5c99862c38cbaf3ba89be3ffc7a78b1a7276a 100644 +index 48eeb1d9ba0ad6f895bfe507a6fbe4b9c9530e47..65301b94dc8d813c487deff24cd04b379e666e98 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java @@ -12,8 +12,16 @@ public class CraftDisplay extends CraftEntity implements Display { @@ -759,12 +764,12 @@ index 48eeb1d9ba0ad6f895bfe507a6fbe4b9c9530e47..4eb5c99862c38cbaf3ba89be3ffc7a78 + @Override public net.minecraft.world.entity.Display getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.Display) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java -index f93f8f6509b12eb9b1e07c829278bb0822dd7988..c693daa86c2e44165ca6a293563670dc82f30eb2 100644 +index f93f8f6509b12eb9b1e07c829278bb0822dd7988..2c3c2d7f51c60a5ece610edd0bb00cba3b9d5981 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java @@ -9,8 +9,16 @@ public class CraftDolphin extends CraftWaterMob implements Dolphin { @@ -780,12 +785,12 @@ index f93f8f6509b12eb9b1e07c829278bb0822dd7988..c693daa86c2e44165ca6a293563670dc + @Override public net.minecraft.world.entity.animal.Dolphin getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Dolphin) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java -index 51fc4acae9f20e8891069704e4a27f212b870766..9afa5a291deb68fca8e03cb89d2c192ec9bb53d0 100644 +index 51fc4acae9f20e8891069704e4a27f212b870766..2b27d3e685ee1882dc6ecc1ceaee2fb52f1b548f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java @@ -9,8 +9,16 @@ public class CraftDrowned extends CraftZombie implements Drowned, com.destroysto @@ -801,12 +806,12 @@ index 51fc4acae9f20e8891069704e4a27f212b870766..9afa5a291deb68fca8e03cb89d2c192e + @Override public net.minecraft.world.entity.monster.Drowned getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Drowned) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java -index 010e9e922a6e30df4e40da151cfd398d1062633e..250479c6b9c5089c7cc260588ef1ce574c1ce24a 100644 +index 010e9e922a6e30df4e40da151cfd398d1062633e..8f36a715a5fdf1595cdfdad3d9971cca39279777 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java @@ -9,8 +9,16 @@ public class CraftEgg extends CraftThrowableProjectile implements Egg { @@ -822,12 +827,12 @@ index 010e9e922a6e30df4e40da151cfd398d1062633e..250479c6b9c5089c7cc260588ef1ce57 + @Override public ThrownEgg getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ThrownEgg) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java -index 676dd5331bec75407a74aea2a89e78ab72d69724..b87d6ccd12323f1760d83365c1bdd1d55baf3a0a 100644 +index 676dd5331bec75407a74aea2a89e78ab72d69724..4f876511b116dd6e7704f1f047af6fab2c3a3e47 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java @@ -39,8 +39,16 @@ public class CraftEnderCrystal extends CraftEntity implements EnderCrystal { @@ -843,12 +848,12 @@ index 676dd5331bec75407a74aea2a89e78ab72d69724..b87d6ccd12323f1760d83365c1bdd1d5 + @Override public EndCrystal getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (EndCrystal) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java -index 7b7b89e67d53ed70efae714192c5fa32977f3d9c..00f334e5449f76b735b844fed44c98725e607db3 100644 +index 7b7b89e67d53ed70efae714192c5fa32977f3d9c..747907123b9a9b2b7cae4a20f77455ea48bc04e9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java @@ -30,8 +30,16 @@ public class CraftEnderDragon extends CraftMob implements EnderDragon, CraftEnem @@ -864,12 +869,12 @@ index 7b7b89e67d53ed70efae714192c5fa32977f3d9c..00f334e5449f76b735b844fed44c9872 + @Override public net.minecraft.world.entity.boss.enderdragon.EnderDragon getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.boss.enderdragon.EnderDragon) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java -index 33ae03b78b01c005a291a343b42507fb539e81a6..a682c1653679f4f60d91c73681e489b46a0cfdb4 100644 +index 33ae03b78b01c005a291a343b42507fb539e81a6..36aec95539044edd429c17833338638262b9db00 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java @@ -16,8 +16,16 @@ public class CraftEnderDragonPart extends CraftComplexPart implements EnderDrago @@ -885,12 +890,12 @@ index 33ae03b78b01c005a291a343b42507fb539e81a6..a682c1653679f4f60d91c73681e489b4 + @Override public net.minecraft.world.entity.boss.EnderDragonPart getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.boss.EnderDragonPart) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java -index 3bb8d74f2b59c7f0c7c1cbde47a570d628ceceb2..83308195a3a55abeb4c28b9cc69dc98e61c351af 100644 +index 3bb8d74f2b59c7f0c7c1cbde47a570d628ceceb2..25d7577d17d52dc00a355a684f1493efb2e88584 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java @@ -9,8 +9,16 @@ public class CraftEnderPearl extends CraftThrowableProjectile implements EnderPe @@ -906,12 +911,12 @@ index 3bb8d74f2b59c7f0c7c1cbde47a570d628ceceb2..83308195a3a55abeb4c28b9cc69dc98e + @Override public ThrownEnderpearl getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ThrownEnderpearl) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java -index 27f56fa4b7ef92a9a4dfa6b782350424b88210f2..d0b2f8abba0eb5e29beccfebcf48f840715b7908 100644 +index 27f56fa4b7ef92a9a4dfa6b782350424b88210f2..e76390fe22e2e846313c9a5b2c7f5492f798ca3e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java @@ -15,8 +15,16 @@ public class CraftEnderSignal extends CraftEntity implements EnderSignal { @@ -927,12 +932,12 @@ index 27f56fa4b7ef92a9a4dfa6b782350424b88210f2..d0b2f8abba0eb5e29beccfebcf48f840 + @Override public EyeOfEnder getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (EyeOfEnder) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java -index 983b9d6ddb58eff297e96e5c8b28ec427efa267d..6ce0c8f24e5359c68e70092c8f488f1817221704 100644 +index 983b9d6ddb58eff297e96e5c8b28ec427efa267d..16e33e302f8a60f1f9ff67929dc7c63cd5192a37 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java @@ -62,8 +62,16 @@ public class CraftEnderman extends CraftMonster implements Enderman { @@ -948,12 +953,12 @@ index 983b9d6ddb58eff297e96e5c8b28ec427efa267d..6ce0c8f24e5359c68e70092c8f488f18 + @Override public EnderMan getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (EnderMan) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java -index d657fd2c507a5b215aeab0a5f3e9c2ee892a27c8..9fc90b162aab15a9cd60b02aba56318130b394c4 100644 +index d657fd2c507a5b215aeab0a5f3e9c2ee892a27c8..399ef60ab5f1bf02b638c8c46a72d297932f6b38 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java @@ -9,8 +9,16 @@ public class CraftEndermite extends CraftMonster implements Endermite { @@ -969,15 +974,15 @@ index d657fd2c507a5b215aeab0a5f3e9c2ee892a27c8..9fc90b162aab15a9cd60b02aba563181 + @Override public net.minecraft.world.entity.monster.Endermite getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Endermite) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index cf9282a46534319308e9ccf69f332a5c8c1745cf..9e883ff5ffd1298edc682873be248b8319061bb8 100644 +index fe6f31d7db873de64c0cfc5c8248d3e5e96f1500..e30bf9b2cb51e1639b414afa8fbe84a9e69b6d63 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -491,7 +491,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -493,7 +493,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @Override public UUID getUniqueId() { @@ -986,16 +991,16 @@ index cf9282a46534319308e9ccf69f332a5c8c1745cf..9e883ff5ffd1298edc682873be248b83 } @Override -@@ -506,6 +506,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -508,6 +508,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } public Entity getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java -index 3a890cccf1766758794f3a3b5d31428f42590049..06863afd6bd855130ac0e672824aa2755e141286 100644 +index 3a890cccf1766758794f3a3b5d31428f42590049..8c148db1b84c65b89fb2779e5b96a71ea4900083 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java @@ -11,8 +11,16 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { @@ -1011,12 +1016,12 @@ index 3a890cccf1766758794f3a3b5d31428f42590049..06863afd6bd855130ac0e672824aa275 + @Override public net.minecraft.world.entity.monster.Evoker getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Evoker) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java -index 19b368cc862cd7e3e1f0e89401a7d099e3eaefa3..5ae51638114a7931efdfc367b26791a22d7e8e2b 100644 +index 19b368cc862cd7e3e1f0e89401a7d099e3eaefa3..4a1c1af06719ff75f6ec2ac27198858b549b0302 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java @@ -11,8 +11,16 @@ public class CraftEvokerFangs extends CraftEntity implements EvokerFangs { @@ -1032,12 +1037,12 @@ index 19b368cc862cd7e3e1f0e89401a7d099e3eaefa3..5ae51638114a7931efdfc367b26791a2 + @Override public net.minecraft.world.entity.projectile.EvokerFangs getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.EvokerFangs) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java -index 650e4a01cecc4cc08e7ff9ebcc4c367084351f21..9300f5e40a1adb5b381e194d06f15c89a81804f0 100644 +index 650e4a01cecc4cc08e7ff9ebcc4c367084351f21..81b2b850dd7d08f2fae7baf56733d753b68d294c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java @@ -42,8 +42,16 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { @@ -1053,12 +1058,12 @@ index 650e4a01cecc4cc08e7ff9ebcc4c367084351f21..9300f5e40a1adb5b381e194d06f15c89 + @Override public net.minecraft.world.entity.ExperienceOrb getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.ExperienceOrb) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java -index 1359d25a32b4a5d5e8e68ce737bd19f7b5afaf69..0be7f84a50b7568d0c639f5906b5ca76347d95fe 100644 +index 1359d25a32b4a5d5e8e68ce737bd19f7b5afaf69..4c6ac7f2531311d24081b397c60b2f8b183fad34 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java @@ -14,8 +14,16 @@ public class CraftFallingBlock extends CraftEntity implements FallingBlock { @@ -1074,12 +1079,12 @@ index 1359d25a32b4a5d5e8e68ce737bd19f7b5afaf69..0be7f84a50b7568d0c639f5906b5ca76 + @Override public FallingBlockEntity getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (FallingBlockEntity) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java -index 297b7e592caa2a05e1fb18a3ad22a91ae7621f5d..a04f1cd676bddc4f30907679b82edc52f37696da 100644 +index 43d7bea201a52cfeacf60c75caa28dfd2c4ff164..ac7237e8c28377d5f9abf38b628215ac865c9709 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java @@ -83,8 +83,16 @@ public class CraftFireball extends AbstractProjectile implements Fireball { @@ -1095,12 +1100,12 @@ index 297b7e592caa2a05e1fb18a3ad22a91ae7621f5d..a04f1cd676bddc4f30907679b82edc52 + @Override public AbstractHurtingProjectile getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractHurtingProjectile) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java -index 95e35c223f2ad9b6de6749544abd68de71e4f1ab..88d0292ca062ea47b3b98ad6bc3257c1f4d40cc6 100644 +index 759b6e54db93792c9862b1f1625118ac6fa49d7a..6fdd39c78a2f7c1c53d5de16e09e0f271c42039e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java @@ -37,8 +37,16 @@ public class CraftFirework extends CraftProjectile implements Firework { @@ -1116,12 +1121,12 @@ index 95e35c223f2ad9b6de6749544abd68de71e4f1ab..88d0292ca062ea47b3b98ad6bc3257c1 + @Override public FireworkRocketEntity getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (FireworkRocketEntity) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java -index eb10f94d5ed8ca89d3786138647dd43357609a6c..e0ad8cedd4d2646d87f3b5abda23c0c603adfd3a 100644 +index eb10f94d5ed8ca89d3786138647dd43357609a6c..f4d92fb44fd7cee7debe3e283e8b672021e3e23f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java @@ -10,8 +10,16 @@ public class CraftFish extends CraftWaterMob implements Fish, io.papermc.paper.e @@ -1137,12 +1142,12 @@ index eb10f94d5ed8ca89d3786138647dd43357609a6c..e0ad8cedd4d2646d87f3b5abda23c0c6 + @Override public AbstractFish getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractFish) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java -index e0d65df2e5b4c14abeb89a5f72cc2d9fa034dcf5..0dfcc07f64f29be048a7ff2f12536aeaa9f44ed2 100644 +index e0d65df2e5b4c14abeb89a5f72cc2d9fa034dcf5..bd8f1925cb3eee30a5b5ea83225b6d94c80bc69a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java @@ -14,8 +14,16 @@ public class CraftFishHook extends CraftProjectile implements FishHook { @@ -1158,12 +1163,12 @@ index e0d65df2e5b4c14abeb89a5f72cc2d9fa034dcf5..0dfcc07f64f29be048a7ff2f12536aea + @Override public FishingHook getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (FishingHook) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java -index 8117faa0c89a966d057f4bf251c03a09d1e8797e..7bdd9e033862a7d86742e05a63848c2fb804f6b2 100644 +index 8117faa0c89a966d057f4bf251c03a09d1e8797e..7c3827e6ef608ff15be9bced4788b09f1572aecb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java @@ -10,8 +10,16 @@ public class CraftFlying extends CraftMob implements Flying { @@ -1179,12 +1184,12 @@ index 8117faa0c89a966d057f4bf251c03a09d1e8797e..7bdd9e033862a7d86742e05a63848c2f + @Override public FlyingMob getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (FlyingMob) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java -index c455deb4fd2a7684bcc01a8212c362a2375c190b..50ee6d3c3aa157fe69a483e02f33f23193628088 100644 +index c455deb4fd2a7684bcc01a8212c362a2375c190b..5f0ddb932df148859dc6a699082934cac8d48fcf 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java @@ -14,8 +14,16 @@ public class CraftFox extends CraftAnimals implements Fox { @@ -1200,15 +1205,15 @@ index c455deb4fd2a7684bcc01a8212c362a2375c190b..50ee6d3c3aa157fe69a483e02f33f231 + @Override public net.minecraft.world.entity.animal.Fox getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Fox) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java -index 4b0aac4362b773f30dfe7c1867fad98fc30b414c..e83fae32769cc4f258011aa7d15f7b2b64674c1c 100644 +index ebf09c27e02a19d31c777b70a38376e4d01e5ee7..0eb55d6e7541acbc6727a108fdeed1711a17f3cd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java -@@ -17,8 +17,16 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog { +@@ -19,8 +19,16 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog { super(server, entity); } @@ -1221,12 +1226,12 @@ index 4b0aac4362b773f30dfe7c1867fad98fc30b414c..e83fae32769cc4f258011aa7d15f7b2b + @Override public Frog getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Frog) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java -index 97fa4e1e70203194bd939618b2fad92665af6d59..8dc0e1332a5f8dd32e2b478432627a5d0c5cebcd 100644 +index 97fa4e1e70203194bd939618b2fad92665af6d59..27b309c9ce10798e3c3a7a9d39b8c300e471e177 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java @@ -9,8 +9,16 @@ public class CraftGhast extends CraftFlying implements Ghast, CraftEnemy { @@ -1242,12 +1247,12 @@ index 97fa4e1e70203194bd939618b2fad92665af6d59..8dc0e1332a5f8dd32e2b478432627a5d + @Override public net.minecraft.world.entity.monster.Ghast getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Ghast) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java -index 5826205339e99e2536b93c8589d95917749f8417..300f06f78c2814aa5650c02f714fee594ba61f98 100644 +index 5826205339e99e2536b93c8589d95917749f8417..9bb22fc146012310bca849fccb0a1e7e987875e9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java @@ -9,8 +9,16 @@ public class CraftGiant extends CraftMonster implements Giant { @@ -1263,12 +1268,12 @@ index 5826205339e99e2536b93c8589d95917749f8417..300f06f78c2814aa5650c02f714fee59 + @Override public net.minecraft.world.entity.monster.Giant getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Giant) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java -index b9a7576d2481b64b7e5b46d66c1f55d1dc28c540..c288adee8ec60fa2bb83ae83f7be98c391379604 100644 +index b9a7576d2481b64b7e5b46d66c1f55d1dc28c540..00c95313a233a032518e2435922d4044a9d67aee 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java @@ -9,8 +9,16 @@ public class CraftGlowItemFrame extends CraftItemFrame implements GlowItemFrame @@ -1284,12 +1289,12 @@ index b9a7576d2481b64b7e5b46d66c1f55d1dc28c540..c288adee8ec60fa2bb83ae83f7be98c3 + @Override public net.minecraft.world.entity.decoration.GlowItemFrame getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.decoration.GlowItemFrame) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java -index 253a0d2f987163cbbb28d261674b47137cbbcbe2..ad0b9025e38926555b47dee1e056c7c8714c91fe 100644 +index 253a0d2f987163cbbb28d261674b47137cbbcbe2..1ed09d2aa4077165e9f88dd9db34f4083a2953c2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java @@ -10,8 +10,16 @@ public class CraftGlowSquid extends CraftSquid implements GlowSquid { @@ -1305,12 +1310,12 @@ index 253a0d2f987163cbbb28d261674b47137cbbcbe2..ad0b9025e38926555b47dee1e056c7c8 + @Override public net.minecraft.world.entity.GlowSquid getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.GlowSquid) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java -index 2c21de478bff9cdf13ba46cd041831d54c11e924..ab87340df483787d59d8b1e2ce3a69235d39bba5 100644 +index 2c21de478bff9cdf13ba46cd041831d54c11e924..e64d7c4cfe65d34bdab13496741645f808f43dc6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java @@ -9,8 +9,16 @@ public class CraftGoat extends CraftAnimals implements Goat { @@ -1326,12 +1331,12 @@ index 2c21de478bff9cdf13ba46cd041831d54c11e924..ab87340df483787d59d8b1e2ce3a6923 + @Override public net.minecraft.world.entity.animal.goat.Goat getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.goat.Goat) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java -index e27e469894bdd17cf7a004a85fdf0eaa746111a6..9fde15e62fd99c842c7c22e97217cc6d68460dfd 100644 +index e27e469894bdd17cf7a004a85fdf0eaa746111a6..bbb8ff66580e62b5fb66aac22de72b9b9eafd3ef 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java @@ -9,8 +9,16 @@ public class CraftGolem extends CraftCreature implements Golem { @@ -1347,12 +1352,12 @@ index e27e469894bdd17cf7a004a85fdf0eaa746111a6..9fde15e62fd99c842c7c22e97217cc6d + @Override public AbstractGolem getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractGolem) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java -index e232350f2c6ef1900b05fda4d3f94099057d10e5..96e7759b64f075e9f803763403d22573a4e35feb 100644 +index e232350f2c6ef1900b05fda4d3f94099057d10e5..2c411b569cc4b222ed3cdfb95237c86cd6a0fabb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java @@ -13,8 +13,16 @@ public class CraftGuardian extends CraftMonster implements Guardian { @@ -1368,15 +1373,15 @@ index e232350f2c6ef1900b05fda4d3f94099057d10e5..96e7759b64f075e9f803763403d22573 + @Override public net.minecraft.world.entity.monster.Guardian getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Guardian) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java -index cbdcf767c01e2c173913f56747d2dacbda2f0094..f45db5bb1a16bc3be5f70094c3f3902538f29b5b 100644 +index f1e3f2b89bcd969f3c80548e165881a9b290eb53..2e4b86b44ace5eecefc9ab09c6e1f0a31247ad2f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java -@@ -57,8 +57,16 @@ public class CraftHanging extends CraftEntity implements Hanging { +@@ -57,8 +57,16 @@ public class CraftHanging extends CraftBlockAttachedEntity implements Hanging { return CraftBlock.notchToBlockFace(direction); } @@ -1389,12 +1394,12 @@ index cbdcf767c01e2c173913f56747d2dacbda2f0094..f45db5bb1a16bc3be5f70094c3f39025 + @Override public HangingEntity getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (HangingEntity) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java -index 37007775d27598e319c0c78929c6a808b697724a..17265ad2eaa38259f3c311c1c73576a79001aa7e 100644 +index 37007775d27598e319c0c78929c6a808b697724a..b9819fc2c2ffc1a21a6e0973bb0d3595ee9c565d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java @@ -51,8 +51,16 @@ public class CraftHoglin extends CraftAnimals implements Hoglin, CraftEnemy { @@ -1410,12 +1415,12 @@ index 37007775d27598e319c0c78929c6a808b697724a..17265ad2eaa38259f3c311c1c73576a7 + @Override public net.minecraft.world.entity.monster.hoglin.Hoglin getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.hoglin.Hoglin) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java -index 9b6ff0f64966c78a3233860bb0840182b52f01bc..a9b9bebee183992d0abd4de78efae078f41fe4ec 100644 +index 9b6ff0f64966c78a3233860bb0840182b52f01bc..fb34651a9e4ed0cb05721d15524a26f89333d5e7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java @@ -13,8 +13,16 @@ public class CraftHorse extends CraftAbstractHorse implements Horse { @@ -1431,12 +1436,12 @@ index 9b6ff0f64966c78a3233860bb0840182b52f01bc..a9b9bebee183992d0abd4de78efae078 + @Override public net.minecraft.world.entity.animal.horse.Horse getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.horse.Horse) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 41f3cdec7deabf34358b8087df77169f85a5b919..51752a1ef885295e2c50832da1c1550ac0a8fb90 100644 +index c1bad887d1340ebc7c63fda3dceff929e4a44517..37c8bd3dc3e539ca92216ae5c2896b037d9af21e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -290,8 +290,16 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -1452,12 +1457,12 @@ index 41f3cdec7deabf34358b8087df77169f85a5b919..51752a1ef885295e2c50832da1c1550a + @Override public Player getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Player) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java -index fb3c518f02cb4c428f022523d2f838625841332b..7becaa4d26df7309984b7aa271a0ae6f778acc0a 100644 +index fb3c518f02cb4c428f022523d2f838625841332b..846a429493236f5002f0fae85c6cd7d20169dbe0 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java @@ -10,8 +10,16 @@ public class CraftIllager extends CraftRaider implements Illager { @@ -1473,12 +1478,12 @@ index fb3c518f02cb4c428f022523d2f838625841332b..7becaa4d26df7309984b7aa271a0ae6f + @Override public AbstractIllager getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractIllager) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java -index 5b2af80e584977683cd39e6f440e65a76e929be9..89c0121c40da1596a4bf5db6e1d7d611d5053153 100644 +index 5b2af80e584977683cd39e6f440e65a76e929be9..789191168f74b3272e8da2131e0311853033c938 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java @@ -9,8 +9,16 @@ public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com @@ -1494,12 +1499,12 @@ index 5b2af80e584977683cd39e6f440e65a76e929be9..89c0121c40da1596a4bf5db6e1d7d611 + @Override public net.minecraft.world.entity.monster.Illusioner getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Illusioner) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java -index caa3016bf9742222205e3ea9a327fad3c4f912bb..4a77b1cf13cfae35331c1e5c5df0b3b9972a0ac1 100644 +index caa3016bf9742222205e3ea9a327fad3c4f912bb..2e00c7fe8dadd4c57c83a51cdfce165b6bfd6807 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java @@ -12,8 +12,16 @@ public class CraftInteraction extends CraftEntity implements Interaction { @@ -1515,12 +1520,12 @@ index caa3016bf9742222205e3ea9a327fad3c4f912bb..4a77b1cf13cfae35331c1e5c5df0b3b9 + @Override public net.minecraft.world.entity.Interaction getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.Interaction) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java -index 63cae1a2e95d8da17c45c4404a8dd0ca6a413c39..f57139f03da9519802ee156f37691d0824bc531b 100644 +index 63cae1a2e95d8da17c45c4404a8dd0ca6a413c39..e417ff87b047dcffa6121835af6f4e713526e16b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java @@ -8,8 +8,16 @@ public class CraftIronGolem extends CraftGolem implements IronGolem { @@ -1536,12 +1541,12 @@ index 63cae1a2e95d8da17c45c4404a8dd0ca6a413c39..f57139f03da9519802ee156f37691d08 + @Override public net.minecraft.world.entity.animal.IronGolem getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.IronGolem) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java -index 30d62ee4d5cd2ddacb8783b5bbbf475d592b3e02..c78498010a01b7d4c0b5c7350a11d0e1cf8ab013 100644 +index 30d62ee4d5cd2ddacb8783b5bbbf475d592b3e02..3985b6bea750341f5336babb237aab8874a4cbd9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java @@ -18,8 +18,16 @@ public class CraftItem extends CraftEntity implements Item { @@ -1557,12 +1562,12 @@ index 30d62ee4d5cd2ddacb8783b5bbbf475d592b3e02..c78498010a01b7d4c0b5c7350a11d0e1 + @Override public ItemEntity getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ItemEntity) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java -index 787f91566fc53c2b4aeba1ec10d8f46ccf15cbe6..eb2b4272b09e5df06e49afc2ccf7063ebc3d42b8 100644 +index 787f91566fc53c2b4aeba1ec10d8f46ccf15cbe6..04a73a31ba09557e901ff1985dc5d5e53f18d99a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java @@ -13,8 +13,16 @@ public class CraftItemDisplay extends CraftDisplay implements ItemDisplay { @@ -1578,12 +1583,12 @@ index 787f91566fc53c2b4aeba1ec10d8f46ccf15cbe6..eb2b4272b09e5df06e49afc2ccf7063e + @Override public net.minecraft.world.entity.Display.ItemDisplay getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.Display.ItemDisplay) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java -index 2fcd9b836d42e3549a3b6b921c57a4c103146dff..051d15967436109d4267a800ab7e1bdf83cbd47a 100644 +index 350ad61ab3fe66abd528e353b431a4a6dac17506..332f209980d3e645ad469fcebb93cc09253ebc20 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java @@ -157,8 +157,16 @@ public class CraftItemFrame extends CraftHanging implements ItemFrame { @@ -1599,12 +1604,12 @@ index 2fcd9b836d42e3549a3b6b921c57a4c103146dff..051d15967436109d4267a800ab7e1bdf + @Override public net.minecraft.world.entity.decoration.ItemFrame getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.decoration.ItemFrame) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java -index 0848963e61e03aa2a1740208ee372fd9edb7fc11..a55a329125775a7b78b3a779a8525ab1e734235b 100644 +index 0848963e61e03aa2a1740208ee372fd9edb7fc11..de2236f0106330ebe9d76bd308f9eee8751db826 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java @@ -14,8 +14,16 @@ public class CraftLargeFireball extends CraftSizedFireball implements LargeFireb @@ -1620,15 +1625,15 @@ index 0848963e61e03aa2a1740208ee372fd9edb7fc11..a55a329125775a7b78b3a779a8525ab1 + @Override public net.minecraft.world.entity.projectile.LargeFireball getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.LargeFireball) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java -index 06fa256c5528af9c1d63fbd044f53b63bed324ee..896d34bd55e308fe322865f8cf7fd077a382df5e 100644 +index 76a7fc3d6c561d12bde17b9f93cae03a6cbb84b3..cd1ba99a75da644d06c4eb2f2c1ff91bfa5afa01 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java -@@ -24,8 +24,16 @@ public class CraftLeash extends CraftHanging implements LeashHitch { +@@ -24,6 +24,13 @@ public class CraftLeash extends CraftBlockAttachedEntity implements LeashHitch { return BlockFace.SELF; } @@ -1639,14 +1644,19 @@ index 06fa256c5528af9c1d63fbd044f53b63bed324ee..896d34bd55e308fe322865f8cf7fd077 + } + // Folia end - region threading + + @Override + public BlockFace getAttachedFace() { + // Leash hitch has no facing direction, so we return self +@@ -37,6 +44,7 @@ public class CraftLeash extends CraftBlockAttachedEntity implements LeashHitch { + @Override public LeashFenceKnotEntity getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (LeashFenceKnotEntity) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java -index e9f471e60af0725ec34e2985d63ae9ea9f88590a..6a443f42ecec16abea3ddf7bc2e85bb8a6af726e 100644 +index e9f471e60af0725ec34e2985d63ae9ea9f88590a..cd824fc65ac2b1fe55710da4700f7c31f820f205 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java @@ -41,8 +41,16 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike @@ -1662,15 +1672,15 @@ index e9f471e60af0725ec34e2985d63ae9ea9f88590a..6a443f42ecec16abea3ddf7bc2e85bb8 + @Override public LightningBolt getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (LightningBolt) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 0196a49a5822e257b0e065e2383ec92b1bc27bba..c086e530b524186d21607e5edc4bd7d1ae60bbd0 100644 +index d2bb0831394c03b620b2cbd8306cb82b621f34f7..3015910083bae42f200b977f74ed53db46a93342 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -476,6 +476,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -477,6 +477,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { this.getHandle().invulnerableTime = ticks; } @@ -1684,16 +1694,16 @@ index 0196a49a5822e257b0e065e2383ec92b1bc27bba..c086e530b524186d21607e5edc4bd7d1 @Override public int getNoActionTicks() { return this.getHandle().getNoActionTime(); -@@ -489,6 +496,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -490,6 +497,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { @Override public net.minecraft.world.entity.LivingEntity getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.LivingEntity) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java -index 351f42842b780d053cd2e5bad9ae299449141b10..6329f0b069fc03eef14e2c85525c93b47b8d3945 100644 +index 351f42842b780d053cd2e5bad9ae299449141b10..63513eff9b849f240b16ea28060b78c774e23934 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java @@ -14,8 +14,16 @@ public class CraftLlama extends CraftChestedHorse implements Llama, com.destroys @@ -1709,12 +1719,12 @@ index 351f42842b780d053cd2e5bad9ae299449141b10..6329f0b069fc03eef14e2c85525c93b4 + @Override public net.minecraft.world.entity.animal.horse.Llama getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.horse.Llama) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java -index 47633f05b4fab1dcabc2117e7645fe6d6949622a..f1e78960622b71aa63e172a1d856a757d6926a5a 100644 +index 47633f05b4fab1dcabc2117e7645fe6d6949622a..5e51d6eeda2abdc5df9c9a280a191ca1cbf615b9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java @@ -10,8 +10,16 @@ public class CraftLlamaSpit extends AbstractProjectile implements LlamaSpit { @@ -1730,12 +1740,12 @@ index 47633f05b4fab1dcabc2117e7645fe6d6949622a..f1e78960622b71aa63e172a1d856a757 + @Override public net.minecraft.world.entity.projectile.LlamaSpit getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.LlamaSpit) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java -index 58b638ffd338e1b0f4962490c665c1eebcf33dcc..321e41e21723fa3e28f73176c9abe34d16a42fcc 100644 +index 58b638ffd338e1b0f4962490c665c1eebcf33dcc..9f1b4d0561c10fbbfe0daec3d9dabfdaca9cf70b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java @@ -9,8 +9,16 @@ public class CraftMagmaCube extends CraftSlime implements MagmaCube { @@ -1751,12 +1761,12 @@ index 58b638ffd338e1b0f4962490c665c1eebcf33dcc..321e41e21723fa3e28f73176c9abe34d + @Override public net.minecraft.world.entity.monster.MagmaCube getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.MagmaCube) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java -index e6782a48d22ba1e683e3fe463e970e8a5ed60fbd..9c04388e9d38103b40a154b6f0e13920ede451f5 100644 +index e6782a48d22ba1e683e3fe463e970e8a5ed60fbd..afaa4570c1991cd4260ffcdba823ba2452ad156a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java @@ -9,8 +9,16 @@ public class CraftMarker extends CraftEntity implements Marker { @@ -1772,12 +1782,12 @@ index e6782a48d22ba1e683e3fe463e970e8a5ed60fbd..9c04388e9d38103b40a154b6f0e13920 + @Override public net.minecraft.world.entity.Marker getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.Marker) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -index 8920af5a0dfe737c1f38d906b53e6a278456d2aa..8bc87cfe29d61b09eee8ecfccda319b5610c6969 100644 +index 8920af5a0dfe737c1f38d906b53e6a278456d2aa..5652ec4aea839fae3f8ea31d7cd5c80ecf129fb5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java @@ -86,8 +86,16 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { @@ -1793,12 +1803,12 @@ index 8920af5a0dfe737c1f38d906b53e6a278456d2aa..8bc87cfe29d61b09eee8ecfccda319b5 + @Override public AbstractMinecart getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractMinecart) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java -index f34fa6715e477936097367a7aefd1a2bf87d3d90..40ecce7b710650a893ff5d4e5fac99cfa1b06cf9 100644 +index f34fa6715e477936097367a7aefd1a2bf87d3d90..e5310b138b13d54448072c15f6768acc1c33a45c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java @@ -20,8 +20,16 @@ public class CraftMinecartCommand extends CraftMinecart implements CommandMineca @@ -1814,12 +1824,12 @@ index f34fa6715e477936097367a7aefd1a2bf87d3d90..40ecce7b710650a893ff5d4e5fac99cf + @Override public MinecartCommandBlock getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (MinecartCommandBlock) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java -index 451f3a6f0b47493da3af3f5d6baced6a8c97f350..f89a5d7c4e76f2061b72006917c626d53ba550a0 100644 +index 451f3a6f0b47493da3af3f5d6baced6a8c97f350..d4f98fe5eb5e463679ebc5b82b077c98e4448203 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java @@ -13,8 +13,16 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements co @@ -1835,12 +1845,12 @@ index 451f3a6f0b47493da3af3f5d6baced6a8c97f350..f89a5d7c4e76f2061b72006917c626d5 + @Override public AbstractMinecartContainer getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractMinecartContainer) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java -index 1b41026ab638bb2764b19429706eb0aded5aad12..c04acbffe5e0b1024f885490c5238cd40b36e701 100644 +index 1b41026ab638bb2764b19429706eb0aded5aad12..4d242bed3bd40c9749236e138f81d5e8583f7dc3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java @@ -11,8 +11,16 @@ public class CraftMinecartFurnace extends CraftMinecart implements PoweredMineca @@ -1856,12 +1866,12 @@ index 1b41026ab638bb2764b19429706eb0aded5aad12..c04acbffe5e0b1024f885490c5238cd4 + @Override public MinecartFurnace getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (MinecartFurnace) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java -index 3a3563a1bdbc0d84d973b3a04b50b78b4bc3d379..9a9f37b9c8931771d90ae22c4ca9a684e24fff32 100644 +index 3a3563a1bdbc0d84d973b3a04b50b78b4bc3d379..1e86ce7c1a3fc1f4eae2d8136fc0d879fbde5301 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java @@ -34,8 +34,17 @@ public final class CraftMinecartHopper extends CraftMinecartContainer implements @@ -1878,12 +1888,12 @@ index 3a3563a1bdbc0d84d973b3a04b50b78b4bc3d379..9a9f37b9c8931771d90ae22c4ca9a684 + @Override public net.minecraft.world.entity.vehicle.MinecartHopper getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.vehicle.MinecartHopper) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java -index 79b608e89d4d1f76a58868c585bb87c82e2689b1..7767a342b3d8bf9c07fbd73ad4ccacd8065c5869 100644 +index 79b608e89d4d1f76a58868c585bb87c82e2689b1..7884de5348f325ee12db41a521a042be4b33a793 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java @@ -42,8 +42,16 @@ public final class CraftMinecartTNT extends CraftMinecart implements ExplosiveMi @@ -1899,15 +1909,15 @@ index 79b608e89d4d1f76a58868c585bb87c82e2689b1..7767a342b3d8bf9c07fbd73ad4ccacd8 + @Override public MinecartTNT getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (MinecartTNT) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index e155501fb3a88edf3ddac3aa0aae1b6a5a84962e..c17d5f6e60c4e2e0266e5c4288418d127e0ccdc8 100644 +index deb66c04abefb4a88521483db1612e494bd27164..4f5083171f67decff5021e0bb638fbb16a147adc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -@@ -53,8 +53,16 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { +@@ -54,8 +54,16 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { return (sound != null) ? CraftSound.minecraftToBukkit(sound) : null; } @@ -1920,11 +1930,11 @@ index e155501fb3a88edf3ddac3aa0aae1b6a5a84962e..c17d5f6e60c4e2e0266e5c4288418d12 + @Override public net.minecraft.world.entity.Mob getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.Mob) this.entity; } -@@ -62,7 +70,7 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { +@@ -63,7 +71,7 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob { @Override public void setHandle(net.minecraft.world.entity.Entity entity) { super.setHandle(entity); @@ -1934,7 +1944,7 @@ index e155501fb3a88edf3ddac3aa0aae1b6a5a84962e..c17d5f6e60c4e2e0266e5c4288418d12 // Paper end - Mob Pathfinding API diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java -index 706c74c832f6893df3797023f68add31139c7d57..80a612f16669e571e336dd6369a968b4664c98e4 100644 +index 706c74c832f6893df3797023f68add31139c7d57..1cf155fc23f13691f86673eac3084d7530d69ab5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java @@ -9,8 +9,16 @@ public class CraftMonster extends CraftCreature implements Monster, CraftEnemy { @@ -1950,12 +1960,12 @@ index 706c74c832f6893df3797023f68add31139c7d57..80a612f16669e571e336dd6369a968b4 + @Override public net.minecraft.world.entity.monster.Monster getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Monster) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java -index 5c5b64bd058684520fa175bfd10622ff57856b7c..ab8d6052c7f11b0563ea49a4766aa1cac93a5c1b 100644 +index 5c5b64bd058684520fa175bfd10622ff57856b7c..8acaa5f8153d643e2558110bb7be512514a27532 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java @@ -19,6 +19,13 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm @@ -1976,12 +1986,12 @@ index 5c5b64bd058684520fa175bfd10622ff57856b7c..ab8d6052c7f11b0563ea49a4766aa1ca @Override public net.minecraft.world.entity.animal.MushroomCow getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.MushroomCow) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java -index 5c60a30e80448fbf04b5fa4b1ef12fb2ee99bfd5..77eefdff4a5102fbc3abba7d7037fa7a5bcc61fa 100644 +index 5c60a30e80448fbf04b5fa4b1ef12fb2ee99bfd5..4ba52939450c0a89e5ba1fa57a84b3ceccb9fef0 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java @@ -9,8 +9,16 @@ public class CraftOcelot extends CraftAnimals implements Ocelot { @@ -1997,24 +2007,24 @@ index 5c60a30e80448fbf04b5fa4b1ef12fb2ee99bfd5..77eefdff4a5102fbc3abba7d7037fa7a + @Override public net.minecraft.world.entity.animal.Ocelot getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Ocelot) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java -index ecdac2cf74e99f0d69e053dece11ab891973dc2b..14a1c58aacf7e07ffc254b5f02b6eb6dfc1a6277 100644 +index ecdac2cf74e99f0d69e053dece11ab891973dc2b..fa365c38c9e0f671df1481c8b36bc993eee42afd 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java @@ -13,6 +13,7 @@ public class CraftOminousItemSpawner extends CraftEntity implements OminousItemS @Override public net.minecraft.world.entity.OminousItemSpawner getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.OminousItemSpawner) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java -index bcac1359c667ef1ee46384f9c7a5adf4010d2b08..f131a80df94a9f0d42a64a86424451fb06755b12 100644 +index bcac1359c667ef1ee46384f9c7a5adf4010d2b08..e740abd53d99f549acb5048d748241560dfeddd1 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java @@ -50,8 +50,16 @@ public class CraftPainting extends CraftHanging implements Painting { @@ -2030,12 +2040,12 @@ index bcac1359c667ef1ee46384f9c7a5adf4010d2b08..f131a80df94a9f0d42a64a86424451fb + @Override public net.minecraft.world.entity.decoration.Painting getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.decoration.Painting) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java -index 01d104d91de9e1319d27e39d3f474318c7809486..a4d201e832d59c64d932f8b26564a783bd4bbdf4 100644 +index 01d104d91de9e1319d27e39d3f474318c7809486..c298b263175dc82097c0ad2c35194f3e326c6658 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java @@ -11,8 +11,16 @@ public class CraftPanda extends CraftAnimals implements Panda { @@ -2051,12 +2061,12 @@ index 01d104d91de9e1319d27e39d3f474318c7809486..a4d201e832d59c64d932f8b26564a783 + @Override public net.minecraft.world.entity.animal.Panda getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Panda) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java -index 04d6cf6a1f3ae8316e3b2862c2d1b04e84a3b20a..b1cdcfee5e575b29d844f04140dd0b0486d1dc45 100644 +index 04d6cf6a1f3ae8316e3b2862c2d1b04e84a3b20a..4ed79610b50be635a7a7c8a8f7d7af8f91ce2d0d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java @@ -11,8 +11,16 @@ public class CraftParrot extends CraftTameableAnimal implements Parrot { @@ -2072,12 +2082,12 @@ index 04d6cf6a1f3ae8316e3b2862c2d1b04e84a3b20a..b1cdcfee5e575b29d844f04140dd0b04 + @Override public net.minecraft.world.entity.animal.Parrot getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Parrot) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java -index 8338effd39b1709dbe578e247710a8e58d83e3aa..1d998942280db00ba7dab1c9d9a0f818490fe328 100644 +index 83e77c6d287d8e239d2f55f3e9f19ef74946be7c..10e385066d29834eb3d8c9d539bb8655407cabb5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java @@ -9,8 +9,16 @@ public class CraftPhantom extends CraftFlying implements Phantom, CraftEnemy { @@ -2093,12 +2103,12 @@ index 8338effd39b1709dbe578e247710a8e58d83e3aa..1d998942280db00ba7dab1c9d9a0f818 + @Override public net.minecraft.world.entity.monster.Phantom getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Phantom) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java -index 8016c810aeaf6ee953bca549bc1e7f9a85f860fc..4566f5d84e70b0296aabb4bf0d2caf517809132a 100644 +index 8016c810aeaf6ee953bca549bc1e7f9a85f860fc..e96e58fa4fb2a73e3e44c5213c73f332df4daa97 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java @@ -55,8 +55,16 @@ public class CraftPig extends CraftAnimals implements Pig { @@ -2114,12 +2124,12 @@ index 8016c810aeaf6ee953bca549bc1e7f9a85f860fc..4566f5d84e70b0296aabb4bf0d2caf51 + @Override public net.minecraft.world.entity.animal.Pig getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Pig) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java -index 49beb836d2801aadf869feefa602616daebe633f..0de7eadb1cac6979ce7cffd38a3b250812cae260 100644 +index 49beb836d2801aadf869feefa602616daebe633f..d220874f678649acfae549691262c370f0228908 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java @@ -30,8 +30,16 @@ public class CraftPigZombie extends CraftZombie implements PigZombie { @@ -2135,12 +2145,12 @@ index 49beb836d2801aadf869feefa602616daebe633f..0de7eadb1cac6979ce7cffd38a3b2508 + @Override public ZombifiedPiglin getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ZombifiedPiglin) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java -index 5124a383b60b2c8de89fa992547d0c61db760c21..2ba9b61a164c6afed15a0919124c8241d2aebf78 100644 +index 5124a383b60b2c8de89fa992547d0c61db760c21..d75230de45102434660b3b7926a804d26e10ab2c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java @@ -75,8 +75,16 @@ public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.dest @@ -2156,12 +2166,12 @@ index 5124a383b60b2c8de89fa992547d0c61db760c21..2ba9b61a164c6afed15a0919124c8241 + @Override public net.minecraft.world.entity.monster.piglin.Piglin getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.piglin.Piglin) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java -index e7957d6051244ba410f8633f9c16eeb8c5ac3ce0..ce763867f9c6c2d4773d76387afc0ecb479b6259 100644 +index e7957d6051244ba410f8633f9c16eeb8c5ac3ce0..f8465f75c15d96ccd82ee394c9e658966837ad07 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java @@ -95,8 +95,16 @@ public class CraftPiglinAbstract extends CraftMonster implements PiglinAbstract @@ -2177,12 +2187,12 @@ index e7957d6051244ba410f8633f9c16eeb8c5ac3ce0..ce763867f9c6c2d4773d76387afc0ecb + @Override public AbstractPiglin getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (AbstractPiglin) super.getHandle(); } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java -index be874dc973fe632e8ace86041392ca69beaefd16..6889b4599aac0bd03badeefd74c891857f566c30 100644 +index be874dc973fe632e8ace86041392ca69beaefd16..efb64160089eeb6be8faf7790989909145c22a4b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java @@ -9,8 +9,16 @@ public class CraftPiglinBrute extends CraftPiglinAbstract implements PiglinBrute @@ -2198,12 +2208,12 @@ index be874dc973fe632e8ace86041392ca69beaefd16..6889b4599aac0bd03badeefd74c89185 + @Override public net.minecraft.world.entity.monster.piglin.PiglinBrute getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.piglin.PiglinBrute) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java -index 2638c341bc02f201f7ab17fdebcdbdf3a7ec05bf..0f5c2d31a2dea13a46ba81e353393633d097dcc7 100644 +index 2638c341bc02f201f7ab17fdebcdbdf3a7ec05bf..074b2919be2b5544b0a46e6cd32f6c57dad6bfdc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java @@ -11,8 +11,16 @@ public class CraftPillager extends CraftIllager implements Pillager, com.destroy @@ -2219,15 +2229,15 @@ index 2638c341bc02f201f7ab17fdebcdbdf3a7ec05bf..0f5c2d31a2dea13a46ba81e353393633 + @Override public net.minecraft.world.entity.monster.Pillager getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Pillager) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 977aee03906ed28c388cc918fc4bade46933a4cd..639b8678ad7711582f2e912772a98233c5313f63 100644 +index 5f82de67496fafdeb5364e227fec0c49f3fe9d59..eb1e14be98b3731e0557726324593dee2eadd31b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -667,7 +667,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -669,7 +669,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { @@ -2236,7 +2246,7 @@ index 977aee03906ed28c388cc918fc4bade46933a4cd..639b8678ad7711582f2e912772a98233 final ServerGamePacketListenerImpl connection = this.getHandle().connection; if (connection != null) { connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); -@@ -2292,9 +2292,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2311,9 +2311,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this; } @@ -2254,17 +2264,8 @@ index 977aee03906ed28c388cc918fc4bade46933a4cd..639b8678ad7711582f2e912772a98233 } public void setHandle(final ServerPlayer entity) { -@@ -3339,7 +3346,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - { - if ( CraftPlayer.this.getHealth() <= 0 && CraftPlayer.this.isOnline() ) - { -- CraftPlayer.this.server.getServer().getPlayerList().respawn( CraftPlayer.this.getHandle(), false, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.PLUGIN ); -+ CraftPlayer.this.getHandle().respawn(null); // Folia - region threading - } - } - diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java -index fe075cfdf3097d6cb768e71b8cc360abb8eaf367..9147771e26d2dbd29754d3fc07c02596669cd602 100644 +index fe075cfdf3097d6cb768e71b8cc360abb8eaf367..657886dfb8e152ed4a64a64878da23526dad0160 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java @@ -8,8 +8,17 @@ public class CraftPolarBear extends CraftAnimals implements PolarBear { @@ -2281,12 +2282,12 @@ index fe075cfdf3097d6cb768e71b8cc360abb8eaf367..9147771e26d2dbd29754d3fc07c02596 + @Override public net.minecraft.world.entity.animal.PolarBear getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.PolarBear) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java -index 4f1fa7dec78970bdfc184d3c1f1632dc9d75a574..d4889dbca359aab6e11fa6231b0ddcb6f33ef18b 100644 +index 4f1fa7dec78970bdfc184d3c1f1632dc9d75a574..99fd39c60d1b0a50bddf7b9b9f45f22c189a2f25 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java @@ -12,8 +12,16 @@ public abstract class CraftProjectile extends AbstractProjectile implements Proj @@ -2302,12 +2303,12 @@ index 4f1fa7dec78970bdfc184d3c1f1632dc9d75a574..d4889dbca359aab6e11fa6231b0ddcb6 + @Override public net.minecraft.world.entity.projectile.Projectile getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.Projectile) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java -index 35a8219734633529325430810e88755b2dd23125..85ebd34ed143304c603078f2e949179a8e628ed2 100644 +index 35a8219734633529325430810e88755b2dd23125..7ba16121cb1828cf5c0ff8f027fa05e9c1814ffa 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java @@ -10,8 +10,16 @@ public class CraftPufferFish extends CraftFish implements PufferFish { @@ -2323,12 +2324,12 @@ index 35a8219734633529325430810e88755b2dd23125..85ebd34ed143304c603078f2e949179a + @Override public Pufferfish getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Pufferfish) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java -index 519ef701a7d6534f7cb516f6296b95ee521f661d..effbc1a3ef8c6c9cd424f49b8bfce05d40e0772a 100644 +index 519ef701a7d6534f7cb516f6296b95ee521f661d..6407b4e6ca793a676e7d669920ae90b762207970 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java @@ -10,8 +10,16 @@ public class CraftRabbit extends CraftAnimals implements Rabbit { @@ -2344,12 +2345,12 @@ index 519ef701a7d6534f7cb516f6296b95ee521f661d..effbc1a3ef8c6c9cd424f49b8bfce05d + @Override public net.minecraft.world.entity.animal.Rabbit getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Rabbit) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java -index 763c368e299588f9a0e085a8a5e04e97e1f33428..58de24aeb98f19b2cf3fa9b0ad17e8b14bc1e475 100644 +index 763c368e299588f9a0e085a8a5e04e97e1f33428..3e85638f3941c2085a7ddb102d0ccc23446cc1d6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java @@ -16,8 +16,16 @@ public abstract class CraftRaider extends CraftMonster implements Raider { @@ -2365,12 +2366,12 @@ index 763c368e299588f9a0e085a8a5e04e97e1f33428..58de24aeb98f19b2cf3fa9b0ad17e8b1 + @Override public net.minecraft.world.entity.raid.Raider getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.raid.Raider) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java -index 09796ce15658e3f7c223a265a547a51ee729ed40..824db5f9f0b5c5f79bc073acaeb4f46aade740af 100644 +index 09796ce15658e3f7c223a265a547a51ee729ed40..bfca2951d18f7451787877b5a6503b0572945447 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java @@ -9,8 +9,16 @@ public class CraftRavager extends CraftRaider implements Ravager { @@ -2386,12 +2387,12 @@ index 09796ce15658e3f7c223a265a547a51ee729ed40..824db5f9f0b5c5f79bc073acaeb4f46a + @Override public net.minecraft.world.entity.monster.Ravager getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Ravager) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java -index d4d8ce60098c74508e2de9541bf6534988779764..081d7f454b3556110f5a300602fbe9239d9b77c7 100644 +index d4d8ce60098c74508e2de9541bf6534988779764..bf4b61e56345b1f2ee83d8aceaf66c199590c258 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java @@ -9,8 +9,16 @@ public class CraftSalmon extends io.papermc.paper.entity.PaperSchoolableFish imp @@ -2407,12 +2408,12 @@ index d4d8ce60098c74508e2de9541bf6534988779764..081d7f454b3556110f5a300602fbe923 + @Override public net.minecraft.world.entity.animal.Salmon getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Salmon) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java -index 37291d7ad9fdf0fe78894f82a418f40bb581f58b..1a0041a788f65ec30d329a86f65c04659a68ad7c 100644 +index 37291d7ad9fdf0fe78894f82a418f40bb581f58b..6c7e54a929b46fd160726e41bf63023a8622d044 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java @@ -29,8 +29,16 @@ public class CraftSheep extends CraftAnimals implements Sheep, io.papermc.paper. @@ -2428,12 +2429,12 @@ index 37291d7ad9fdf0fe78894f82a418f40bb581f58b..1a0041a788f65ec30d329a86f65c0465 + @Override public net.minecraft.world.entity.animal.Sheep getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Sheep) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java -index 05ec06b71642ab1ef03829039f7ac1e4c527ee50..fd4168a8bcf1537ccc2496139f5c5b63c5e2f41a 100644 +index 05ec06b71642ab1ef03829039f7ac1e4c527ee50..1e1e908cbc08df06996128e3dd6d277a19f9a2df 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java @@ -18,8 +18,16 @@ public class CraftShulker extends CraftGolem implements Shulker, CraftEnemy { @@ -2449,15 +2450,15 @@ index 05ec06b71642ab1ef03829039f7ac1e4c527ee50..fd4168a8bcf1537ccc2496139f5c5b63 + @Override public net.minecraft.world.entity.monster.Shulker getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Shulker) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java -index 636c4481e3afdf20197e502cf221f5d34d18f101..436a921106697916118cec8007ffd1cac1745fcd 100644 +index b3797a43eeee11cb7ae0774d61bd5f195d0aa3ad..d045d50d1cfccb696153b8c33e86e193194271fc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java -@@ -65,8 +65,16 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul +@@ -69,8 +69,16 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul return "CraftShulkerBullet"; } @@ -2470,12 +2471,12 @@ index 636c4481e3afdf20197e502cf221f5d34d18f101..436a921106697916118cec8007ffd1ca + @Override public net.minecraft.world.entity.projectile.ShulkerBullet getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.ShulkerBullet) this.entity; } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java -index 7c75d78e5e28d7320c6dbe979bcd576658fb310b..83de93bd751b1c15ad763819e4fe87ecb13bf6e8 100644 +index 7c75d78e5e28d7320c6dbe979bcd576658fb310b..a25ca7fa49a3bb213f6af5804079b2efe43ef0e4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java @@ -8,8 +8,16 @@ public class CraftSilverfish extends CraftMonster implements Silverfish { @@ -2491,12 +2492,12 @@ index 7c75d78e5e28d7320c6dbe979bcd576658fb310b..83de93bd751b1c15ad763819e4fe87ec + @Override public net.minecraft.world.entity.monster.Silverfish getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Silverfish) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java -index de3327812c08b3bb8f5907ae657f67962d1e4e8b..d2452b8efdd066df985e4a55f80f09275a589a9c 100644 +index de3327812c08b3bb8f5907ae657f67962d1e4e8b..c479f4adb945e8bb6ea2279ad23d679ca0dee606 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java @@ -27,8 +27,16 @@ public class CraftSizedFireball extends CraftFireball implements SizedFireball { @@ -2512,12 +2513,12 @@ index de3327812c08b3bb8f5907ae657f67962d1e4e8b..d2452b8efdd066df985e4a55f80f0927 + @Override public Fireball getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Fireball) this.entity; } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java -index 6f98da9be6aef35e3b5c940188b872459a383c8e..79465c30d59c50574b215e1f4ad75a2b426404a3 100644 +index 6f98da9be6aef35e3b5c940188b872459a383c8e..dc93b8aaf48671d66d3bb3fb413b83fc4b4b26cf 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java @@ -31,8 +31,16 @@ public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton { @@ -2533,12 +2534,12 @@ index 6f98da9be6aef35e3b5c940188b872459a383c8e..79465c30d59c50574b215e1f4ad75a2b + @Override public net.minecraft.world.entity.monster.Skeleton getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Skeleton) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java -index fbb47491dcc75f8247dee9f123f946f99ef1467f..9dfd108be5185eb897faa802411297183a960cee 100644 +index fbb47491dcc75f8247dee9f123f946f99ef1467f..6cc1ea31340298037c2a00d64d70928f31278a4a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java @@ -20,8 +20,16 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo @@ -2554,12 +2555,12 @@ index fbb47491dcc75f8247dee9f123f946f99ef1467f..9dfd108be5185eb897faa80241129718 + @Override public net.minecraft.world.entity.animal.horse.SkeletonHorse getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.horse.SkeletonHorse) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java -index e48f7d1cbec4a2319745ba48a5d44ab9925214e2..1ffb16e5e8e243f684c7c0b9fbdd2a7b885d412d 100644 +index e48f7d1cbec4a2319745ba48a5d44ab9925214e2..27b07865edfa659d9cdfcf2d84935ad313472e87 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java @@ -19,8 +19,16 @@ public class CraftSlime extends CraftMob implements Slime, CraftEnemy { @@ -2575,12 +2576,12 @@ index e48f7d1cbec4a2319745ba48a5d44ab9925214e2..1ffb16e5e8e243f684c7c0b9fbdd2a7b + @Override public net.minecraft.world.entity.monster.Slime getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Slime) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java -index 072df206858944ef78179b0a6d61ed990a844d2b..c022ca9c630cfe9a37583c65afc6d390c13f5886 100644 +index 072df206858944ef78179b0a6d61ed990a844d2b..71625cc4e4b2fd3773baf1b2c1ea7e463b854ffa 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java @@ -8,8 +8,16 @@ public class CraftSmallFireball extends CraftSizedFireball implements SmallFireb @@ -2596,12 +2597,12 @@ index 072df206858944ef78179b0a6d61ed990a844d2b..c022ca9c630cfe9a37583c65afc6d390 + @Override public net.minecraft.world.entity.projectile.SmallFireball getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.SmallFireball) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java -index 555337018fe218ac5a296a5e6a1d82720fee05e1..a6929f512a99eed376878ae11aa7bac0b5828e27 100644 +index 555337018fe218ac5a296a5e6a1d82720fee05e1..873b7e7a05b3465b79a82ed583ce16bb245ebcbf 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java @@ -16,8 +16,16 @@ public class CraftSniffer extends CraftAnimals implements Sniffer { @@ -2617,12 +2618,12 @@ index 555337018fe218ac5a296a5e6a1d82720fee05e1..a6929f512a99eed376878ae11aa7bac0 + @Override public net.minecraft.world.entity.animal.sniffer.Sniffer getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.sniffer.Sniffer) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java -index d959825fd11a94aba175934cd7739544a23958fc..e22be41875f2d772bcc1219e54f4f436813034a1 100644 +index d959825fd11a94aba175934cd7739544a23958fc..9f53ba11a2adabdebd70eee5a811fec7dccd7b10 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java @@ -8,8 +8,16 @@ public class CraftSnowball extends CraftThrowableProjectile implements Snowball @@ -2638,12 +2639,12 @@ index d959825fd11a94aba175934cd7739544a23958fc..e22be41875f2d772bcc1219e54f4f436 + @Override public net.minecraft.world.entity.projectile.Snowball getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.Snowball) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index 4ce2373ff71c3c1b8951646e057587a3ab09e145..9041c121b9bc41152640c8e2ed983b9ec29df81a 100644 +index 4ce2373ff71c3c1b8951646e057587a3ab09e145..6f88f18fc23cb793d4394b80201e40b09a0a7f9d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java @@ -19,8 +19,16 @@ public class CraftSnowman extends CraftGolem implements Snowman, com.destroystok @@ -2659,12 +2660,12 @@ index 4ce2373ff71c3c1b8951646e057587a3ab09e145..9041c121b9bc41152640c8e2ed983b9e + @Override public SnowGolem getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (SnowGolem) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java -index 70f1f8740091d5a3d5983227ef2e6e166bb6ce7e..eed30dd92b9741718f7b9f2446ec0e45d21fead6 100644 +index 70f1f8740091d5a3d5983227ef2e6e166bb6ce7e..4886c9ba4bf952415ee4b1395adfeca8d928cdf5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java @@ -9,8 +9,16 @@ public class CraftSpectralArrow extends CraftAbstractArrow implements SpectralAr @@ -2680,12 +2681,12 @@ index 70f1f8740091d5a3d5983227ef2e6e166bb6ce7e..eed30dd92b9741718f7b9f2446ec0e45 + @Override public net.minecraft.world.entity.projectile.SpectralArrow getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.SpectralArrow) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java -index 525827f1747631fa108be7e1b7395b47d33aa397..3dbb5f7f88979d616e185980d96cc2c377977000 100644 +index 525827f1747631fa108be7e1b7395b47d33aa397..3ec5d458a895300da462f63bae683980a741e477 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java @@ -12,8 +12,16 @@ public class CraftSpellcaster extends CraftIllager implements Spellcaster { @@ -2701,12 +2702,12 @@ index 525827f1747631fa108be7e1b7395b47d33aa397..3dbb5f7f88979d616e185980d96cc2c3 + @Override public SpellcasterIllager getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (SpellcasterIllager) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java -index b4afc37c21fc478df44fca7ec3fbc33d337dc6b7..911822f4e2e1eba6a9d3e9b781499314d7f9427f 100644 +index b4afc37c21fc478df44fca7ec3fbc33d337dc6b7..bf3236f673118539d7cfb883bcdf84de7ae5bd73 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java @@ -9,8 +9,16 @@ public class CraftSpider extends CraftMonster implements Spider { @@ -2722,12 +2723,12 @@ index b4afc37c21fc478df44fca7ec3fbc33d337dc6b7..911822f4e2e1eba6a9d3e9b781499314 + @Override public net.minecraft.world.entity.monster.Spider getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Spider) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java -index a6e3b61c391a8b266d2b030d9ba600ac6be76952..f93b160ae82b7cae6b11d214531df4618fd79f74 100644 +index a6e3b61c391a8b266d2b030d9ba600ac6be76952..abc26a620552659fbcfbcbb90a3fd203f995c46f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java @@ -9,8 +9,16 @@ public class CraftSquid extends CraftWaterMob implements Squid { @@ -2743,12 +2744,12 @@ index a6e3b61c391a8b266d2b030d9ba600ac6be76952..f93b160ae82b7cae6b11d214531df461 + @Override public net.minecraft.world.entity.animal.Squid getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Squid) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java -index 9472a6f9c9584048abf1f8d11ab6254b7c7a287d..f2daf0fc0f07d90040887b0cee8f1924d3c146bc 100644 +index 9472a6f9c9584048abf1f8d11ab6254b7c7a287d..de8f656818192f35cca228724db3d17ede40b556 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java @@ -65,8 +65,16 @@ public class CraftStrider extends CraftAnimals implements Strider { @@ -2764,12 +2765,12 @@ index 9472a6f9c9584048abf1f8d11ab6254b7c7a287d..f2daf0fc0f07d90040887b0cee8f1924 + @Override public net.minecraft.world.entity.monster.Strider getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Strider) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java -index dac3d34677688ac560bc1be2087a08479ef71b87..b28221a616613698e6a627d461429cb1f91d738b 100644 +index dac3d34677688ac560bc1be2087a08479ef71b87..ec4ae01daa16139b4d2d42c3771eb51d00f55c0a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java @@ -42,8 +42,16 @@ public class CraftTNTPrimed extends CraftEntity implements TNTPrimed { @@ -2785,12 +2786,12 @@ index dac3d34677688ac560bc1be2087a08479ef71b87..b28221a616613698e6a627d461429cb1 + @Override public PrimedTnt getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (PrimedTnt) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java -index d7c6a0bbc5671ea8f2488230c94df5146a1e98b9..71faf263dd5ac43ab9b89b5a152dd0d1ee93b91b 100644 +index d7c6a0bbc5671ea8f2488230c94df5146a1e98b9..ea001c3e91478cde59eb6b7663013d43554e5fb5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java @@ -9,8 +9,16 @@ public class CraftTadpole extends CraftFish implements org.bukkit.entity.Tadpole @@ -2806,12 +2807,12 @@ index d7c6a0bbc5671ea8f2488230c94df5146a1e98b9..71faf263dd5ac43ab9b89b5a152dd0d1 + @Override public Tadpole getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Tadpole) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java -index cedb8e67e208cdf954d052a4f0a100c1c07a962b..cb6bb7ce434dd72e5f23da0a257958dbffdc0547 100644 +index cedb8e67e208cdf954d052a4f0a100c1c07a962b..8bf3936ad7a42a98a14e82fcabd238712e8532c8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java @@ -12,8 +12,16 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat @@ -2827,12 +2828,12 @@ index cedb8e67e208cdf954d052a4f0a100c1c07a962b..cb6bb7ce434dd72e5f23da0a257958db + @Override public TamableAnimal getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (TamableAnimal) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java -index 9ef939b76d06874b856e0c850addb364146f5a00..d3975a461778d9815f68f323e616e25c24bf649c 100644 +index 9ef939b76d06874b856e0c850addb364146f5a00..7dfed8c0be93bc2083ea40def6e2a806d336094e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java @@ -13,8 +13,16 @@ public class CraftTextDisplay extends CraftDisplay implements TextDisplay { @@ -2848,12 +2849,12 @@ index 9ef939b76d06874b856e0c850addb364146f5a00..d3975a461778d9815f68f323e616e25c + @Override public net.minecraft.world.entity.Display.TextDisplay getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.Display.TextDisplay) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java -index bf7b111abdf42969218a3608d86a3313432bc0a0..51bfd27170e8aceb2274918d9c8ff71cbc2625a5 100644 +index bf7b111abdf42969218a3608d86a3313432bc0a0..b2b1b7ad56d0adc452b32a866fa0c6682fcd4882 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java @@ -26,8 +26,16 @@ public abstract class CraftThrowableProjectile extends CraftProjectile implement @@ -2869,12 +2870,12 @@ index bf7b111abdf42969218a3608d86a3313432bc0a0..51bfd27170e8aceb2274918d9c8ff71c + @Override public ThrowableItemProjectile getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ThrowableItemProjectile) this.entity; } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java -index 5e7fef664c56d6087502e56a0eb4fc07d34ade9f..7538d449e24a8d680628f31b22924e7de9e8b503 100644 +index 5e7fef664c56d6087502e56a0eb4fc07d34ade9f..00d578700c09cab5b5ae99bcb27fa17048ac24b1 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java @@ -9,8 +9,16 @@ public class CraftThrownExpBottle extends CraftThrowableProjectile implements Th @@ -2890,12 +2891,12 @@ index 5e7fef664c56d6087502e56a0eb4fc07d34ade9f..7538d449e24a8d680628f31b22924e7d + @Override public ThrownExperienceBottle getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ThrownExperienceBottle) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java -index 42462fac097aeb1cfd367f8c240da63f513ec5a8..bee84fee81eb8fca431d982ea88df71b3136c182 100644 +index 65b6de9d21da6843d7c7087f0dea98d3b75f24cf..8988f2a1e3fe6a296c245e893ddb927da1d59167 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java @@ -61,8 +61,17 @@ public class CraftThrownPotion extends CraftThrowableProjectile implements Throw @@ -2912,12 +2913,12 @@ index 42462fac097aeb1cfd367f8c240da63f513ec5a8..bee84fee81eb8fca431d982ea88df71b + @Override public net.minecraft.world.entity.projectile.ThrownPotion getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.ThrownPotion) this.entity; } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java -index 4b3a764114c8372e1549dadeeced26dc7727f2d1..04cbe165b99d348a864da5d342225fc929b2bfd0 100644 +index 4b3a764114c8372e1549dadeeced26dc7727f2d1..b800efe68124c27f97114a69a096fca2d66e671e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java @@ -9,8 +9,16 @@ public class CraftTraderLlama extends CraftLlama implements TraderLlama { @@ -2933,12 +2934,12 @@ index 4b3a764114c8372e1549dadeeced26dc7727f2d1..04cbe165b99d348a864da5d342225fc9 + @Override public net.minecraft.world.entity.animal.horse.TraderLlama getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.horse.TraderLlama) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java -index 4fc893378fb0568ddcffc7593d66df6bfe23f659..fe730d081e93ea6b2854b246389fde9ed8b40a94 100644 +index 4fc893378fb0568ddcffc7593d66df6bfe23f659..5ddc96b17ddbd152929b0548bfedc802bd6dd7ca 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java @@ -12,8 +12,16 @@ public class CraftTrident extends CraftAbstractArrow implements Trident { @@ -2954,12 +2955,12 @@ index 4fc893378fb0568ddcffc7593d66df6bfe23f659..fe730d081e93ea6b2854b246389fde9e + @Override public ThrownTrident getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (ThrownTrident) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java -index 9e53c30801c700719c78c0fd521fd615c94e02c8..201d4db7a455cde7c6feb4263a054a5cb66ea672 100644 +index 9e53c30801c700719c78c0fd521fd615c94e02c8..11884c20e73846ec95288edcb514d3ae638eb803 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java @@ -13,8 +13,16 @@ public class CraftTropicalFish extends io.papermc.paper.entity.PaperSchoolableFi @@ -2975,12 +2976,12 @@ index 9e53c30801c700719c78c0fd521fd615c94e02c8..201d4db7a455cde7c6feb4263a054a5c + @Override public net.minecraft.world.entity.animal.TropicalFish getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.TropicalFish) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java -index d44e6f4bb682d18c1497eee9fb2802f2bda6e840..f2d589721a335d1f92ab04ce70e7678a244314fd 100644 +index d44e6f4bb682d18c1497eee9fb2802f2bda6e840..a857258419c666a0fe38f54a6197d19c84891028 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java @@ -9,8 +9,16 @@ public class CraftTurtle extends CraftAnimals implements Turtle { @@ -2996,12 +2997,12 @@ index d44e6f4bb682d18c1497eee9fb2802f2bda6e840..f2d589721a335d1f92ab04ce70e7678a + @Override public net.minecraft.world.entity.animal.Turtle getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Turtle) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java -index e9ec3455eabc473e104b5342a615a38c1ac25a4f..2f0aac537bd71e6db8e3554ce8d615e521897e27 100644 +index e9ec3455eabc473e104b5342a615a38c1ac25a4f..3a65ae7e6ac1894855e4eafecc9c2bb87476298f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java @@ -13,8 +13,16 @@ public class CraftVex extends CraftMonster implements Vex { @@ -3017,15 +3018,15 @@ index e9ec3455eabc473e104b5342a615a38c1ac25a4f..2f0aac537bd71e6db8e3554ce8d615e5 + @Override public net.minecraft.world.entity.monster.Vex getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Vex) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index 6c15d40979fd3e3d246a447c432b321fbf29ada3..771eb799b032fcf4fc33c5e445b7fa252baee72b 100644 +index bd2987fa1fb194a581567134ed980e8fc043f435..46c4a33c4cb82049aa60fc7fc47707dcbd8c733e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -31,8 +31,16 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { +@@ -33,8 +33,16 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { super(server, entity); } @@ -3038,12 +3039,12 @@ index 6c15d40979fd3e3d246a447c432b321fbf29ada3..771eb799b032fcf4fc33c5e445b7fa25 + @Override public net.minecraft.world.entity.npc.Villager getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.npc.Villager) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java -index 3aa23d9f22d5cd22231293fd7d1ca4cb79eb7cb3..f340cf90512a7097153d7fa1a2b38fe3e0f1e8d5 100644 +index 3aa23d9f22d5cd22231293fd7d1ca4cb79eb7cb3..e705d49eafcf1def6e849bfc0ded4b7269a40ffb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java @@ -14,8 +14,16 @@ public class CraftVillagerZombie extends CraftZombie implements ZombieVillager { @@ -3059,12 +3060,12 @@ index 3aa23d9f22d5cd22231293fd7d1ca4cb79eb7cb3..f340cf90512a7097153d7fa1a2b38fe3 + @Override public net.minecraft.world.entity.monster.ZombieVillager getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.ZombieVillager) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java -index bcd3370bc48520ea4bb53af25b892131d6ca0b33..c89dfec6f61d4f487bd6292d509a33922127162f 100644 +index bcd3370bc48520ea4bb53af25b892131d6ca0b33..8be282b028bc30056afc8852e8f47b287b238e73 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java @@ -9,8 +9,16 @@ public class CraftVindicator extends CraftIllager implements Vindicator { @@ -3080,12 +3081,12 @@ index bcd3370bc48520ea4bb53af25b892131d6ca0b33..c89dfec6f61d4f487bd6292d509a3392 + @Override public net.minecraft.world.entity.monster.Vindicator getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Vindicator) super.getHandle(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java -index 3cceefa0d6278924a19641a49bdf16bcdacb2233..0664afee1d66c44318f12ff38ac8c8509491b9d6 100644 +index 3cceefa0d6278924a19641a49bdf16bcdacb2233..07d6b1296aeee0de3455380a8aeaedc8a9344735 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java @@ -9,8 +9,16 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande @@ -3101,12 +3102,12 @@ index 3cceefa0d6278924a19641a49bdf16bcdacb2233..0664afee1d66c44318f12ff38ac8c850 + @Override public net.minecraft.world.entity.npc.WanderingTrader getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.npc.WanderingTrader) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java -index c284eb96a1e330078076cbe61f0f6e2ff4ed89bd..68094bea75635376665ef850ed01484a2b27f630 100644 +index c284eb96a1e330078076cbe61f0f6e2ff4ed89bd..a53dee61a4669ac9c1d051ad9f881230a186e92c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java @@ -15,8 +15,16 @@ public class CraftWarden extends CraftMonster implements org.bukkit.entity.Warde @@ -3122,12 +3123,12 @@ index c284eb96a1e330078076cbe61f0f6e2ff4ed89bd..68094bea75635376665ef850ed01484a + @Override public Warden getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (Warden) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java -index 1b347deb6eb0b39c4a23936f7cd387421f06350d..4e5d311e10736f84964c22cb01a9fafe38bc445c 100644 +index 1b347deb6eb0b39c4a23936f7cd387421f06350d..4f26f0caca8a97d7770a569a65c1addaf6e9512c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java @@ -10,8 +10,16 @@ public class CraftWaterMob extends CraftCreature implements WaterMob { @@ -3143,24 +3144,24 @@ index 1b347deb6eb0b39c4a23936f7cd387421f06350d..4e5d311e10736f84964c22cb01a9fafe + @Override public WaterAnimal getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (WaterAnimal) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java -index 46447b9651dc48181916ce1306ee5deec397be12..37d205c3186ea6fa8a6ca78812b4c310ce553992 100644 +index 46447b9651dc48181916ce1306ee5deec397be12..c26120711251a17b558a97ae0e20789d5c33b104 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java @@ -10,6 +10,7 @@ public class CraftWindCharge extends CraftAbstractWindCharge implements WindChar @Override public net.minecraft.world.entity.projectile.windcharge.WindCharge getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.windcharge.WindCharge) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java -index 4b3d783cabcb2de1a67d7fbfb6f525bfb493aed1..b8d1fe35b9c0b00389b2aaca229f31a6d0de85c6 100644 +index 4b3d783cabcb2de1a67d7fbfb6f525bfb493aed1..216c97fb1d611b84322927c6eb97871dd05cf600 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java @@ -15,8 +15,16 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. @@ -3176,12 +3177,12 @@ index 4b3d783cabcb2de1a67d7fbfb6f525bfb493aed1..b8d1fe35b9c0b00389b2aaca229f31a6 + @Override public net.minecraft.world.entity.monster.Witch getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Witch) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java -index 7a8ce6956db56061af93ba9761f5d1057a90bc49..97891857b2c942c7f6e95c94e3c00abc3da2feea 100644 +index 7881c6253c1d652c0c0d54a9a8accdf0a1ff0f3e..077b5685ccd1b5972ef92aa759ebabe5ec6d23c6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java @@ -21,8 +21,16 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok @@ -3197,12 +3198,12 @@ index 7a8ce6956db56061af93ba9761f5d1057a90bc49..97891857b2c942c7f6e95c94e3c00abc + @Override public WitherBoss getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (WitherBoss) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java -index bc978391255c9414e06ff393f2e6707d329d020a..5af2d0f7c496d49dcb66b888047836c05299ffc7 100644 +index bc978391255c9414e06ff393f2e6707d329d020a..8d436a1453c8a66422c2a735764273176a6a4545 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java @@ -18,8 +18,16 @@ public class CraftWitherSkull extends CraftFireball implements WitherSkull { @@ -3218,12 +3219,12 @@ index bc978391255c9414e06ff393f2e6707d329d020a..5af2d0f7c496d49dcb66b888047836c0 + @Override public net.minecraft.world.entity.projectile.WitherSkull getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.projectile.WitherSkull) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java -index 86574da257731de7646a712ed73384955fe35aa3..0e81a82f92934ceb03dae6908b321c9b15caa15b 100644 +index 86574da257731de7646a712ed73384955fe35aa3..94b699c156884c28c017b528d07f21c041b4ceb1 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java @@ -31,8 +31,16 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf { @@ -3239,12 +3240,12 @@ index 86574da257731de7646a712ed73384955fe35aa3..0e81a82f92934ceb03dae6908b321c9b + @Override public net.minecraft.world.entity.animal.Wolf getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.animal.Wolf) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java -index c134c4bb8c0377ceb7f8a5c40c94fd6312a9e448..e119b2d0f9b3264a6105d18c9c67b91ae3466540 100644 +index c134c4bb8c0377ceb7f8a5c40c94fd6312a9e448..d334e4a3ea075670e0aa7ea1429ffe4231eb0559 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java @@ -19,8 +19,16 @@ public class CraftZoglin extends CraftMonster implements Zoglin { @@ -3260,12 +3261,12 @@ index c134c4bb8c0377ceb7f8a5c40c94fd6312a9e448..e119b2d0f9b3264a6105d18c9c67b91a + @Override public net.minecraft.world.entity.monster.Zoglin getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Zoglin) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 46336111dcf62a29390e724b1879c84c697076e9..ff6965694ffeee0e895a128351270361360c701d 100644 +index 46336111dcf62a29390e724b1879c84c697076e9..dbb43c825724c3f13171e8991d53e7d40899670d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java @@ -12,8 +12,16 @@ public class CraftZombie extends CraftMonster implements Zombie { @@ -3281,7 +3282,7 @@ index 46336111dcf62a29390e724b1879c84c697076e9..ff6965694ffeee0e895a128351270361 + @Override public net.minecraft.world.entity.monster.Zombie getHandle() { -+ io.papermc.paper.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading return (net.minecraft.world.entity.monster.Zombie) this.entity; } diff --git a/patches/server/0007-Disable-mid-tick-task-execution.patch b/patches/server/0007-Disable-mid-tick-task-execution.patch deleted file mode 100644 index 05631cf..0000000 --- a/patches/server/0007-Disable-mid-tick-task-execution.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Mon, 20 Mar 2023 02:07:43 -0700 -Subject: [PATCH] Disable mid-tick task execution - -Mid-tick task execution acquires the ticket lock at least, -which can possibly be a significant performance bottleneck -at a high tick thread + region count. This change should reduce -the impact from scaling the region threads, but is not a fix -to the underlying issue. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 60cf9cf4120a83c9d634348e434772020a1665aa..7570c2f6048f3b937fa331e1b65ee1a6a1e03498 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1518,6 +1518,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> CURRENT_TICKET_UPDATE_SCHEDULING = new ThreadLocal<>(); +diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java +index c467b2d2ef9e1e16b00fee20f6cfc757c30fb100..7a719d427a537c6fa1f60d8ebb9130e7eda9618a 100644 +--- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java ++++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java +@@ -1687,6 +1687,8 @@ public final class NewChunkHolder { - public SaveStat save(final boolean shutdown, final boolean unloading) { + public SaveStat save(final boolean shutdown) { TickThread.ensureTickThread(this.world, this.chunkX, this.chunkZ, "Cannot save data off-main"); + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_SAVE); try { // Folia - profiler ChunkAccess chunk = this.getCurrentChunk(); PoiChunk poi = this.getPoiChunk(); -@@ -1796,6 +1798,7 @@ public final class NewChunkHolder { +@@ -1733,6 +1735,7 @@ public final class NewChunkHolder { } return executedUnloadTask | canSaveChunk | canSaveEntities | canSavePOI ? new SaveStat(executedUnloadTask || canSaveChunk, canSaveEntities, canSavePOI): null; @@ -975,10 +974,10 @@ index a587d83b78af4efc484f939529acf70834f60d7e..45f76aaaa7dedb77a83b4a2c87905bf9 public static void registerCommands(final MinecraftServer server) { diff --git a/src/main/java/io/papermc/paper/threadedregions/TickRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/TickRegionScheduler.java -index 150610d7bf25416dbbde7f003c47da562acc68ba..865044d40a95d201765435cbc14b0384980eebf6 100644 +index 54539fecd96a8a4c4a15e147876f7e0985f566cd..c43b263e6502ba48a876803385f8d05c5e84ba3e 100644 --- a/src/main/java/io/papermc/paper/threadedregions/TickRegionScheduler.java +++ b/src/main/java/io/papermc/paper/threadedregions/TickRegionScheduler.java -@@ -66,8 +66,13 @@ public final class TickRegionScheduler { +@@ -67,8 +67,13 @@ public final class TickRegionScheduler { tickThreadRunner.currentTickingRegion = region; if (region != null) { tickThreadRunner.currentTickingWorldRegionizedData = region.regioniser.world.worldRegionData.get(); @@ -992,7 +991,7 @@ index 150610d7bf25416dbbde7f003c47da562acc68ba..865044d40a95d201765435cbc14b0384 } } -@@ -122,6 +127,17 @@ public final class TickRegionScheduler { +@@ -123,6 +128,17 @@ public final class TickRegionScheduler { return tickThreadRunner.currentTickingTask; } @@ -1010,7 +1009,7 @@ index 150610d7bf25416dbbde7f003c47da562acc68ba..865044d40a95d201765435cbc14b0384 /** * Schedules the given region * @throws IllegalStateException If the region is already scheduled or is ticking -@@ -199,6 +215,9 @@ public final class TickRegionScheduler { +@@ -204,6 +220,9 @@ public final class TickRegionScheduler { private ThreadedRegionizer.ThreadedRegion currentTickingRegion; private RegionizedWorldData currentTickingWorldRegionizedData; private SchedulerThreadPool.SchedulableTick currentTickingTask; @@ -1021,7 +1020,7 @@ index 150610d7bf25416dbbde7f003c47da562acc68ba..865044d40a95d201765435cbc14b0384 public TickThreadRunner(final Runnable run, final String name) { super(run, name); diff --git a/src/main/java/io/papermc/paper/threadedregions/TickRegions.java b/src/main/java/io/papermc/paper/threadedregions/TickRegions.java -index 924ade31b788b161a7c8f587504b2fc86932a2ee..2ad25dd345ab42125d456f2b9cf67d8c4515c8b7 100644 +index df15b1139e71dfe10b8f24ec6d235b99f6d5006a..b1c07e582dbf0a203cf734fdbcd8387a422af3a6 100644 --- a/src/main/java/io/papermc/paper/threadedregions/TickRegions.java +++ b/src/main/java/io/papermc/paper/threadedregions/TickRegions.java @@ -81,6 +81,11 @@ public final class TickRegions implements ThreadedRegionizer.RegionCallbacks 0 && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % autosavePeriod == 0; // Folia - region threading @@ -1424,15 +1423,15 @@ index 7570c2f6048f3b937fa331e1b65ee1a6a1e03498..355c8408da189a4805e206db0932c41f try { this.isSaving = true; if (playerSaveInterval > 0) { -@@ -1713,6 +1724,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Folia - region threading entityplayer.connection.suspendFlushing(); -@@ -1854,12 +1867,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop trackerEntities = worldData.trackerEntities; // Folia - region threading + final Entity[] trackerEntitiesRaw = trackerEntities.getRawDataUnchecked(); +- for (int i = 0, len = trackerEntities.size(); i < len; ++i) { ++ for (int i = 0, len = totalEntities = trackerEntities.size(); i < len; ++i) { // Folia - region threading + final Entity entity = trackerEntitiesRaw[i]; + final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity(); if (tracker == null) { - continue; -@@ -1106,12 +1116,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // process unloads - for (Entity entity : worldData.takeTrackingUnloads()) { -+ ++totalUnloadedEntities; // Folia - profiler - TrackedEntity tracker = entity.tracker; - if (tracker == null) { - continue; +@@ -928,6 +938,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - tracker.clearPlayers(); + ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity)tracker).moonrise$clearPlayers(); } -+ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.TRACKED_ENTITY_COUNTS, totalEntities); // Folia - profiler -+ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.TRACKED_UNLOADED_ENTITY_COUNTS, totalUnloadedEntities); // Folia - profiler ++ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.TRACKED_ENTITY_COUNTS, (long)totalEntities); // Folia - profiler ++ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.TRACKED_UNLOADED_ENTITY_COUNTS, (long)unloadedEntitiesRaw.length); // Folia - profiler + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TRACKER_TICK); } // Folia - profiler } - // Folia end - region threading - replace entity tracking ticking + // Paper end - optimise entity tracker diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 0b323e648d4dbe27822b77b846e4861b9264ca5f..69feb8ee4dd959554a6fb9ccae78e32870b0e7b3 100644 +index e13ccac27fa4f4c23185f12c776e80970ab844e6..135fa024d81b962761f0edc6896a2a507b6981f9 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -421,19 +421,26 @@ public class ServerChunkCache extends ChunkSource { +@@ -392,19 +392,26 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override public void tick(BooleanSupplier shouldKeepTicking, boolean tickChunks) { @@ -1546,7 +1535,7 @@ index 0b323e648d4dbe27822b77b846e4861b9264ca5f..69feb8ee4dd959554a6fb9ccae78e328 if (tickChunks) { this.level.timings.chunks.startTiming(); // Paper - timings + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_CHUNK_LOADER_TICK); try { // Folia - profiler - this.chunkMap.level.playerChunkLoader.tick(); // Paper - replace player chunk loader - this is mostly required to account for view distance changes + ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getPlayerChunkLoader().tick(); // Paper - rewrite chunk system + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_CHUNK_LOADER_TICK); } // Folia - profiler + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK); try { // Folia - profiler this.tickChunks(); @@ -1554,15 +1543,31 @@ index 0b323e648d4dbe27822b77b846e4861b9264ca5f..69feb8ee4dd959554a6fb9ccae78e328 this.level.timings.chunks.stopTiming(); // Paper - timings this.chunkMap.tick(); } -@@ -448,6 +455,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -419,6 +426,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon private void tickChunks() { io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler + long chunksTicked = 0; // Paper - rewrite chunk system //long i = this.level.getGameTime(); // Folia - region threading - long j = 1; // Folia - region threading - -@@ -469,6 +477,7 @@ public class ServerChunkCache extends ChunkSource { + long j = 1L; // Folia - region threading +@@ -431,6 +439,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + gameprofilerfiller.push("filteringLoadedChunks"); + // Paper start - chunk tick iteration optimisations + List list; ++ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK_COLLECT_CHUNKS); try { // Folia - profiler + { + final ca.spottedleaf.moonrise.common.list.ReferenceList tickingChunks = + ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel) this.level).moonrise$getTickingChunks(); +@@ -447,6 +456,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + regionizedWorldData.iterationCopy, size // Folia - region threading + ); + } ++ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK_COLLECT_CHUNKS); } // Folia - profiler + // Paper end - chunk tick iteration optimisations + Iterator iterator = null; // Paper - chunk tick iteration optimisations + if (this.level.getServer().tickRateManager().runsNormally()) this.level.timings.chunkTicks.startTiming(); // Paper +@@ -460,6 +470,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon // Paper start - Optional per player mob spawns int naturalSpawnChunkCount = k; NaturalSpawner.SpawnState spawnercreature_d; // moved down @@ -1570,7 +1575,7 @@ index 0b323e648d4dbe27822b77b846e4861b9264ca5f..69feb8ee4dd959554a6fb9ccae78e328 if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled // re-set mob counts for (ServerPlayer player : this.level.getLocalPlayers()) { // Folia - region threading -@@ -488,6 +497,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -479,6 +490,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } else { spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all } @@ -1578,38 +1583,37 @@ index 0b323e648d4dbe27822b77b846e4861b9264ca5f..69feb8ee4dd959554a6fb9ccae78e328 // Paper end - Optional per player mob spawns this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings -@@ -551,6 +561,9 @@ public class ServerChunkCache extends ChunkSource { - } - try { - // Paper end - optimise chunk tick iteration +@@ -500,6 +512,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit + Iterator iterator1 = list.iterator(); + + long spawnChunkCount = 0L; // Folia - profiler + long randomChunkCount = 0L; // Folia - profiler + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_AND_RANDOM_TICK); try { // Folia - profiler - while (chunkIterator.hasNext()) { - LevelChunk chunk1 = chunkIterator.next(); - // Paper end - optimise chunk tick iteration -@@ -582,15 +595,20 @@ public class ServerChunkCache extends ChunkSource { - // Paper end - optimise chunk tick iteration + while (iterator1.hasNext()) { + ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next(); + LevelChunk chunk1 = chunkproviderserver_a.chunk; +@@ -508,10 +523,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + if (true && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { // Paper - rewrite chunk system chunk1.incrementInhabitedTime(j); - if (spawn && flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration + if (flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot + ++spawnChunkCount; // Folia - profiler NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); } - if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration + if (true) { // Paper - rewrite chunk system + ++randomChunkCount; // Folia - profiler this.level.tickChunk(chunk1, l); - if ((chunksTicked++ & 1) == 0) net.minecraft.server.MinecraftServer.getServer().executeMidTickTasks(); // Paper + // Paper start - rewrite chunk system + if ((++chunksTicked & 7L) == 0L) { +@@ -521,19 +538,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } } } + profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_CHUNK_COUNT, spawnChunkCount); // Folia - profiler + profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.RANDOM_CHUNK_TICK_COUNT, randomChunkCount); // Folia - profiler + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_AND_RANDOM_TICK); } // Folia - profiler - // Paper start - optimise chunk tick iteration - } finally { - if (chunkIterator instanceof io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator safeIterator) { -@@ -602,9 +620,11 @@ public class ServerChunkCache extends ChunkSource { + this.level.timings.chunkTicks.stopTiming(); // Paper gameprofilerfiller.popPush("customSpawners"); if (flag) { @@ -1621,27 +1625,26 @@ index 0b323e648d4dbe27822b77b846e4861b9264ca5f..69feb8ee4dd959554a6fb9ccae78e328 } } -@@ -614,6 +634,7 @@ public class ServerChunkCache extends ChunkSource { - // Paper start - optimise chunk tick iteration - // Folia start - region threading - if (!this.level.needsChangeBroadcasting.isEmpty()) { -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); try { // Folia - profiler - for (Iterator iterator = this.level.needsChangeBroadcasting.iterator(); iterator.hasNext();) { - ChunkHolder holder = iterator.next(); - if (!io.papermc.paper.util.TickThread.isTickThreadFor(holder.newChunkHolder.world, holder.pos)) { -@@ -625,6 +646,7 @@ public class ServerChunkCache extends ChunkSource { - iterator.remove(); - } + gameprofilerfiller.popPush("broadcast"); + // Paper start - chunk tick iteration optimisations + this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing ++ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); try { // Folia - profiler + { + final it.unimi.dsi.fastutil.objects.ObjectArrayList chunks = (it.unimi.dsi.fastutil.objects.ObjectArrayList)list; + final ServerChunkCache.ChunkAndHolder[] raw = chunks.elements(); +@@ -547,6 +570,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + holder.holder().broadcastChanges(holder.chunk()); } -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); } // Folia - profiler } - // Folia end - region threading - // Paper end - optimise chunk tick iteration ++ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); } // Folia - profiler + this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing + // Paper end - chunk tick iteration optimisations + gameprofilerfiller.pop(); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e80803a77d 100644 +index f236feba396162ae7545a96a920127c168cb24e3..72aa1b66950c1111793dad1583c19ac0d7e5823d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -898,6 +898,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -713,6 +713,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. public void tick(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - regionised ticking final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking @@ -1649,7 +1652,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 ProfilerFiller gameprofilerfiller = this.getProfiler(); regionizedWorldData.setHandlingTick(true); // Folia - regionised ticking -@@ -926,9 +927,13 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -741,9 +742,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. if (!this.isDebug() && flag) { j = regionizedWorldData.getRedstoneGameTime(); // Folia - region threading gameprofilerfiller.push("blockTicks"); @@ -1663,7 +1666,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 gameprofilerfiller.pop(); } this.timings.scheduledBlocks.stopTiming(); // Paper -@@ -936,18 +941,24 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -751,18 +756,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. gameprofilerfiller.popPush("raid"); if (flag) { this.timings.raids.startTiming(); // Paper - timings @@ -1688,15 +1691,15 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 this.timings.doSounds.stopTiming(); // Spigot } -@@ -963,6 +974,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -778,6 +789,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. gameprofilerfiller.push("entities"); this.timings.tickEntities.startTiming(); // Spigot if (this.dragonFight != null && flag) { + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.DRAGON_FIGHT_TICK); try { // Folia - profiler - if (io.papermc.paper.util.TickThread.isTickThreadFor(this, this.dragonFight.origin)) { // Folia - region threading + if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, this.dragonFight.origin)) { // Folia - region threading gameprofilerfiller.push("dragonFight"); this.dragonFight.tick(); -@@ -975,10 +987,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -790,10 +802,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. fightCenter ); } // Folia end - region threading @@ -1709,7 +1712,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 regionizedWorldData.forEachTickingEntity((entity) -> { // Folia - regionised ticking if (!entity.isRemoved()) { if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed -@@ -1006,10 +1020,13 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -821,10 +835,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } } }); @@ -1723,7 +1726,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 } gameprofilerfiller.push("entityManagement"); -@@ -1069,12 +1086,15 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -884,12 +901,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. } public void tickCustomSpawners(boolean spawnMonsters, boolean spawnAnimals) { @@ -1739,7 +1742,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 } } -@@ -1524,6 +1544,11 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1356,6 +1376,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. // Paper start- timings final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper @@ -1751,7 +1754,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 try { // Paper end - timings entity.setOldPosAndRot(); -@@ -1549,7 +1574,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1381,7 +1406,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. // Folia end - region threading } else { entity.inactiveTick(); } // Paper - EAR 2 this.getProfiler().pop(); @@ -1760,7 +1763,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { -@@ -1573,6 +1598,11 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1405,6 +1430,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. // Paper - EAR 2 final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper @@ -1772,7 +1775,7 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 try { // Paper end passenger.setOldPosAndRot(); -@@ -1612,7 +1642,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1444,7 +1474,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. this.tickPassenger(passenger, entity2); } @@ -1782,10 +1785,10 @@ index 559b6d0e3611b506ff10e5ae7c42b35f0d710173..b194f3448b5199e1204da31e1408f2e8 } else { passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 5f9c89dbbfa9b3e4d2b68c0d8628cf223c1f7aa0..771b259ce930d2c857a08ca9150a243679c88c80 100644 +index 7203bd2660514c444a09b3be42464180a8f1154b..683b5c164bf40a9d900cb96134350f2fdd06b620 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1334,6 +1334,7 @@ public abstract class PlayerList { +@@ -1289,6 +1289,7 @@ public abstract class PlayerList { public void saveAll(int interval) { io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main @@ -1793,7 +1796,7 @@ index 5f9c89dbbfa9b3e4d2b68c0d8628cf223c1f7aa0..771b259ce930d2c857a08ca9150a2436 MinecraftTimings.savePlayers.startTiming(); // Paper int numSaved = 0; long now = System.nanoTime(); // Folia - region threading -@@ -1345,7 +1346,9 @@ public abstract class PlayerList { +@@ -1300,7 +1301,9 @@ public abstract class PlayerList { } // Folia end - region threading if (interval == -1 || now - entityplayer.lastSave >= timeInterval) { // Folia - region threading @@ -1804,7 +1807,7 @@ index 5f9c89dbbfa9b3e4d2b68c0d8628cf223c1f7aa0..771b259ce930d2c857a08ca9150a2436 if (interval != -1 && max != -1 && ++numSaved >= max) { break; diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index a46bf73c608641bf1f00fd55242de71a0f2ee06e..a2f0fb8b4057bd3a84d18298e49c4d02955240d3 100644 +index cb61462d4691a055a4b25f7b953609d8a154fdfe..c74a01a8551457507441d266b6923b4248560abf 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java @@ -338,6 +338,13 @@ public class EntityType implements FeatureElement, EntityTypeT @@ -1835,30 +1838,30 @@ index a46bf73c608641bf1f00fd55242de71a0f2ee06e..a2f0fb8b4057bd3a84d18298e49c4d02 this.factory = factory; this.category = spawnGroup; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index a57d89b35fa04cd02dc1df87b7d0924550a3e573..75ecbdb5bdacb4d4b27d60fe1c1a35c3a9c16207 100644 +index d963e8a6a498232a9ae760b2befaa17578a192f8..4bb14874912557008fab7361754f2d2eb98fc5aa 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -220,6 +220,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return this.getCurrentWorldData().getLocalPlayers(); +@@ -203,6 +203,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + public final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup moonrise$getEntityLookup() { + return this.entityLookup; } - // Folia end - region ticking + // Folia start - profiler + public final int tickTimerId; + // Folia end - profiler - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config; Async-Anti-Xray: Pass executor - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot -@@ -308,6 +311,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - this.minSection = io.papermc.paper.util.WorldUtil.getMinSection(this); - this.maxSection = io.papermc.paper.util.WorldUtil.getMaxSection(this); + @Override + public void moonrise$setEntityLookup(final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup entityLookup) { +@@ -787,6 +790,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + this.maxSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMaxSection(this); // Paper end - optimise collisions + this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + // Folia start - profiler + this.tickTimerId = ca.spottedleaf.leafprofiler.LProfilerRegistry.GLOBAL_REGISTRY.getOrCreateTimer(" Tick World: " + resourcekey.location().toString()); + // Folia end - profiler } // Paper start - Cancel hit for vanished players -@@ -1290,17 +1296,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1406,17 +1412,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } protected void tickBlockEntities() { @@ -1880,7 +1883,7 @@ index a57d89b35fa04cd02dc1df87b7d0924550a3e573..75ecbdb5bdacb4d4b27d60fe1c1a35c3 // Spigot start // Iterator iterator = this.blockEntityTickers.iterator(); boolean flag = this.tickRateManager().runsNormally(); -@@ -1327,6 +1337,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1445,6 +1455,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } } blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 // Folia - regionised ticking @@ -1926,10 +1929,10 @@ index 96b99aab3720e5bdf293fd4a95944c7218ce43c0..e7691f856f85469c06f2b5a2a3db3120 } } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index fe7b3757c5c3d14cec783d43218555278d61eefa..5f60010d44f2a3df8645a0e7dafa3f28d882aecf 100644 +index 2c39642298bf235565b92287efaf55373183c5a1..e0359a8857387428d44c19af8dd0e2e743a0b2b5 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1179,11 +1179,14 @@ public class LevelChunk extends ChunkAccess { +@@ -1039,11 +1039,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p BlockPos blockposition = this.blockEntity.getBlockPos(); if (LevelChunk.this.isTicking(blockposition)) { @@ -1944,7 +1947,7 @@ index fe7b3757c5c3d14cec783d43218555278d61eefa..5f60010d44f2a3df8645a0e7dafa3f28 BlockState iblockdata = LevelChunk.this.getBlockState(blockposition); if (this.blockEntity.getType().isValid(iblockdata)) { -@@ -1198,6 +1201,7 @@ public class LevelChunk extends ChunkAccess { +@@ -1058,6 +1061,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p } // Paper end - Remove the Block Entity if it's invalid } @@ -1953,7 +1956,7 @@ index fe7b3757c5c3d14cec783d43218555278d61eefa..5f60010d44f2a3df8645a0e7dafa3f28 gameprofilerfiller.pop(); } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/ticks/LevelTicks.java b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -index f71661ef4250d3b668fffeea7cd74a28eec95acd..71b13d6b4c1c3db272ccd7c021af00c34c5a0956 100644 +index ea161048b68de3c8cdcba5f4cb66eb1531364b2e..073d8176a7ee347f81edb18292de26629ca95e06 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelTicks.java +++ b/src/main/java/net/minecraft/world/ticks/LevelTicks.java @@ -250,6 +250,12 @@ public class LevelTicks implements LevelTickAccess {