From 388cdacd1b373031caec202fca400f3fd7898285 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Tue, 30 Jul 2024 20:09:52 -0700 Subject: [PATCH] Initial pass of 1.21 Most significant changes are to portal/teleport logic, there may be some bugs there. Not really concerned about the passenger teleport, as Folia had already added support for that. Not sure how the spark changes are going to work. --- build-data/dev-imports.txt | 3 - build.gradle.kts | 2 +- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- patches/api/0001-Force-disable-timings.patch | 12 +- ...king-ownership-of-region-by-position.patch | 8 +- patches/server/0001-Build-changes.patch | 6 +- patches/server/0003-Threaded-Regions.patch | 7855 ++++++----------- patches/server/0004-Max-pending-logins.patch | 6 +- ...nk-system-throughput-counters-to-tps.patch | 28 +- ...-getHandle-and-overrides-perform-thr.patch | 679 +- ...0007-Disable-mid-tick-task-execution.patch | 23 - ...dOperationException-for-broken-APIs.patch} | 6 +- ... => 0008-Fix-tests-by-removing-them.patch} | 2 +- ...o-be-explicitly-marked-as-Folia-sup.patch} | 4 +- ...ates-in-non-loaded-or-non-owned-chu.patch} | 26 +- ...world-tile-entities-on-worldgen-thr.patch} | 6 +- ...ccess-when-waking-players-up-during.patch} | 8 +- ...cess-POI-data-for-lodestone-compass.patch} | 0 ...-Synchronize-PaperPermissionManager.patch} | 0 ... => 0015-Fix-off-region-raid-heroes.patch} | 4 +- ...tion-to-player-position-on-player-d.patch} | 4 +- ...filer.patch => 0017-Region-profiler.patch} | 289 +- 24 files changed, 3181 insertions(+), 5800 deletions(-) delete mode 100644 patches/server/0007-Disable-mid-tick-task-execution.patch rename patches/server/{0008-Throw-UnsupportedOperationException-for-broken-APIs.patch => 0007-Throw-UnsupportedOperationException-for-broken-APIs.patch} (95%) rename patches/server/{0009-Fix-tests-by-removing-them.patch => 0008-Fix-tests-by-removing-them.patch} (90%) rename patches/server/{0010-Require-plugins-to-be-explicitly-marked-as-Folia-sup.patch => 0009-Require-plugins-to-be-explicitly-marked-as-Folia-sup.patch} (96%) rename patches/server/{0011-Prevent-block-updates-in-non-loaded-or-non-owned-chu.patch => 0010-Prevent-block-updates-in-non-loaded-or-non-owned-chu.patch} (75%) rename patches/server/{0012-Block-reading-in-world-tile-entities-on-worldgen-thr.patch => 0011-Block-reading-in-world-tile-entities-on-worldgen-thr.patch} (82%) rename patches/server/{0013-Skip-worldstate-access-when-waking-players-up-during.patch => 0012-Skip-worldstate-access-when-waking-players-up-during.patch} (81%) rename patches/server/{0014-Do-not-access-POI-data-for-lodestone-compass.patch => 0013-Do-not-access-POI-data-for-lodestone-compass.patch} (100%) rename patches/server/{0015-Synchronize-PaperPermissionManager.patch => 0014-Synchronize-PaperPermissionManager.patch} (100%) rename patches/server/{0016-Fix-off-region-raid-heroes.patch => 0015-Fix-off-region-raid-heroes.patch} (95%) rename patches/server/{0017-Sync-vehicle-position-to-player-position-on-player-d.patch => 0016-Sync-vehicle-position-to-player-position-on-player-d.patch} (91%) rename patches/server/{0018-Region-profiler.patch => 0017-Region-profiler.patch} (87%) 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 {