From 950216171d836f989a30453e8b66d7df8c4b7fbd Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Wed, 8 Mar 2023 20:15:22 -0800 Subject: [PATCH] Do not let projectiles travel into chunks not owned by current region Otherwise, the thread checks for moving the entity into the new entity chunk section would throw and cause the projectile to be deleted. --- patches/server/0004-Threaded-Regions.patch | 254 ++++++++++++++------- 1 file changed, 172 insertions(+), 82 deletions(-) diff --git a/patches/server/0004-Threaded-Regions.patch b/patches/server/0004-Threaded-Regions.patch index c9d9353..b988c3c 100644 --- a/patches/server/0004-Threaded-Regions.patch +++ b/patches/server/0004-Threaded-Regions.patch @@ -9713,7 +9713,7 @@ index 6898c704e60d89d53c8ed114e5e12f73ed63605a..594ada3cdec25784c7bd6abb9ad42d3f * 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 fc57850b80303fcade89ca95794f63910404a407..911a4590e8c45b917c9245d7e719d79bbd3e5f3d 100644 +index fc57850b80303fcade89ca95794f63910404a407..2e3b030aced80803a544a9c836b00086b767da7a 100644 --- a/src/main/java/io/papermc/paper/util/TickThread.java +++ b/src/main/java/io/papermc/paper/util/TickThread.java @@ -1,8 +1,19 @@ @@ -9757,7 +9757,7 @@ index fc57850b80303fcade89ca95794f63910404a407..911a4590e8c45b917c9245d7e719d79b public static void ensureTickThread(final ServerLevel world, final int chunkX, final int chunkZ, final String reason) { if (!isTickThreadFor(world, chunkX, chunkZ)) { MinecraftServer.LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); -@@ -77,11 +102,75 @@ public class TickThread extends Thread { +@@ -77,11 +102,96 @@ public class TickThread extends Thread { return Thread.currentThread() instanceof TickThread; } @@ -9787,17 +9787,34 @@ index fc57850b80303fcade89ca95794f63910404a407..911a4590e8c45b917c9245d7e719d79b + return world.regioniser.getRegionAtUnsynchronised(chunkX, chunkZ) == region; + } + -+ public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ, final int radius) { ++ public static boolean isTickThreadFor(final ServerLevel world, final Vec3 position, final Vec3 deltaMovement, final int buffer) { ++ 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) { + final ThreadedRegioniser.ThreadedRegion region = + TickRegionScheduler.getCurrentRegion(); + if (region == null) { + return isShutdownThread(); + } + -+ final int minSectionX = (chunkX - radius) >> world.regioniser.sectionChunkShift; -+ final int maxSectionX = (chunkX + radius) >> world.regioniser.sectionChunkShift; -+ final int minSectionZ = (chunkZ - radius) >> world.regioniser.sectionChunkShift; -+ final int maxSectionZ = (chunkZ + radius) >> world.regioniser.sectionChunkShift; ++ final int minSectionX = fromChunkX >> world.regioniser.sectionChunkShift; ++ final int maxSectionX = toChunkX >> world.regioniser.sectionChunkShift; ++ final int minSectionZ = fromChunkZ >> world.regioniser.sectionChunkShift; ++ final int maxSectionZ = toChunkZ >> world.regioniser.sectionChunkShift; + + for (int secZ = minSectionZ; secZ <= maxSectionZ; ++secZ) { + for (int secX = minSectionX; secX <= maxSectionX; ++secX) { @@ -9810,6 +9827,10 @@ index fc57850b80303fcade89ca95794f63910404a407..911a4590e8c45b917c9245d7e719d79b + } + + return true; ++ } ++ ++ public static boolean isTickThreadFor(final ServerLevel world, final int chunkX, final int chunkZ, final int radius) { ++ return isTickThreadFor(world, chunkX - radius, chunkZ - radius, chunkX + radius, chunkZ + radius); } public static boolean isTickThreadFor(final Entity entity) { @@ -13760,7 +13781,7 @@ index 736f37979c882e41e7571202df38eb6a2923fcb0..09a6a74f9bbcbbfba8bfc0424cde6000 } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1dd0a0381 100644 +index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..80ff2f28521f3d6d00ff21fbe76ab4e932673e48 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -192,35 +192,34 @@ public class ServerLevel extends Level implements WorldGenLevel { @@ -13808,16 +13829,21 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) public static Throwable getAddToWorldStackTrace(Entity entity) { final Throwable thr = new Throwable(entity + " Added to world at " + new java.util.Date()); -@@ -258,7 +257,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -256,6 +255,13 @@ public class ServerLevel extends Level implements WorldGenLevel { + 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)) { ++ return false; ++ } ++ // Folia end - region threading ++ for (int cx = minChunkX; cx <= maxChunkX; ++cx) { for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { -- if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) { -+ if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null || !io.papermc.paper.util.TickThread.isTickThreadFor(this, cx, cz)) { - return false; - } - } -@@ -267,50 +266,64 @@ public class ServerLevel extends Level implements WorldGenLevel { + if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) { +@@ -267,50 +273,64 @@ public class ServerLevel extends Level implements WorldGenLevel { return true; } @@ -13909,7 +13935,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 chunkProvider.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); chunkProvider.removeTicketAtLevel(TicketType.FUTURE_AWAIT, chunkPos, ticketLevel, holderIdentifier); -@@ -322,11 +335,31 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -322,11 +342,31 @@ public class ServerLevel extends Level implements WorldGenLevel { for (int cx = minChunkX; cx <= maxChunkX; ++cx) { for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { io.papermc.paper.chunk.system.ChunkSystem.scheduleChunkLoad( @@ -13942,7 +13968,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // Paper start - rewrite chunk system public final io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler chunkTaskScheduler; -@@ -446,81 +479,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -446,81 +486,16 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper end // Paper start - optimise checkDespawn @@ -13978,8 +14004,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 - closestDistanceSquared = distanceSquared; - } - } -+ // Folia - region threading - +- - return closest; - } - @@ -14000,17 +14025,17 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 - double centerX = (axisalignedbb.maxX + axisalignedbb.minX) * 0.5; - double centerZ = (axisalignedbb.maxZ + axisalignedbb.minZ) * 0.5; - nearby = this.getChunkSource().chunkMap.playerGeneralAreaMap.getObjectsInRange(Mth.floor(centerX) >> 4, Mth.floor(centerZ) >> 4); -- ++ // Folia - region threading + - List ret = new java.util.ArrayList<>(); -- ++ // Folia - region threading + - if (nearby == null) { - return ret; - } -+ // Folia - region threading - +- - Object[] backingSet = nearby.getBackingSet(); -+ // Folia - region threading - +- - for (int i = 0, len = backingSet.length; i < len; ++i) { - Object _player = backingSet[i]; - if (!(_player instanceof ServerPlayer)) { @@ -14022,14 +14047,15 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 - ret.add(player); - } - } -- ++ // Folia - region threading + - return ret; - } + // Folia - region threading // Paper end - optimise get nearest players for entity AI public final io.papermc.paper.chunk.system.RegionisedPlayerChunkLoader playerChunkLoader = new io.papermc.paper.chunk.system.RegionisedPlayerChunkLoader(this); -@@ -565,6 +533,59 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -565,6 +540,59 @@ public class ServerLevel extends Level implements WorldGenLevel { }); } @@ -14089,7 +14115,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // 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, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { // Holder holder = worlddimension.type(); // CraftBukkit - decompile error -@@ -574,13 +595,13 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -574,13 +602,13 @@ public class ServerLevel extends Level implements WorldGenLevel { this.convertable = convertable_conversionsession; this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); // CraftBukkit end @@ -14109,7 +14135,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 this.dragonParts = new Int2ObjectOpenHashMap(); this.tickTime = flag1; this.server = minecraftserver; -@@ -619,7 +640,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -619,7 +647,7 @@ public class ServerLevel extends Level implements WorldGenLevel { }); this.chunkSource.getGeneratorState().ensureStructuresGenerated(); this.portalForcer = new PortalForcer(this); @@ -14118,7 +14144,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 this.prepareWeather(); this.getWorldBorder().setAbsoluteMaxSize(minecraftserver.getAbsoluteMaxWorldSize()); this.raids = (Raids) this.getDataStorage().computeIfAbsent((nbttagcompound) -> { -@@ -647,7 +668,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -647,7 +675,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 @@ -14133,7 +14159,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 public void setWeatherParameters(int clearDuration, int rainDuration, boolean raining, boolean thundering) { this.serverLevelData.setClearWeatherTime(clearDuration); -@@ -666,55 +694,31 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -666,55 +701,31 @@ public class ServerLevel extends Level implements WorldGenLevel { return this.structureManager; } @@ -14201,7 +14227,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 gameprofilerfiller.pop(); } timings.scheduledBlocks.stopTiming(); // Paper -@@ -731,7 +735,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -731,7 +742,7 @@ public class ServerLevel extends Level implements WorldGenLevel { timings.doSounds.startTiming(); // Spigot this.runBlockEvents(); timings.doSounds.stopTiming(); // Spigot @@ -14210,7 +14236,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 gameprofilerfiller.pop(); boolean flag = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players -@@ -743,20 +747,30 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -743,20 +754,30 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.push("entities"); timings.tickEntities.startTiming(); // Spigot if (this.dragonFight != null) { @@ -14242,7 +14268,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 gameprofilerfiller.pop(); if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - now always true if in the ticking list Entity entity1 = entity.getVehicle(); -@@ -787,6 +801,31 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -787,6 +808,31 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.pop(); } @@ -14274,7 +14300,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 @Override public boolean shouldTickBlocksAt(long chunkPos) { // Paper start - replace player chunk loader system -@@ -797,11 +836,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -797,11 +843,12 @@ public class ServerLevel extends Level implements WorldGenLevel { protected void tickTime() { if (this.tickTime) { @@ -14291,7 +14317,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 this.setDayTime(this.levelData.getDayTime() + 1L); } -@@ -830,15 +870,23 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -830,15 +877,23 @@ public class ServerLevel extends Level implements WorldGenLevel { private void wakeUpAllPlayers() { this.sleepStatus.removeAllSleepers(); (this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error @@ -14318,7 +14344,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); int j = chunkcoordintpair.getMinBlockX(); -@@ -846,7 +894,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -846,7 +901,7 @@ public class ServerLevel extends Level implements WorldGenLevel { ProfilerFiller gameprofilerfiller = this.getProfiler(); gameprofilerfiller.push("thunder"); @@ -14327,7 +14353,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - disable thunder blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper -@@ -941,7 +989,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -941,7 +996,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(); @@ -14336,7 +14362,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 if (index >= tickingBlocks) { continue; } -@@ -955,7 +1003,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -955,7 +1010,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); @@ -14345,7 +14371,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // We drop the fluid tick since LAVA is ALREADY TICKED by the above method (See LiquidBlock). // TODO CHECK ON UPDATE (ping the Canadian) } -@@ -1009,7 +1057,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1009,7 +1064,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } public boolean isHandlingTick() { @@ -14354,7 +14380,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } public boolean canSleepThroughNights() { -@@ -1041,6 +1089,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1041,6 +1096,14 @@ public class ServerLevel extends Level implements WorldGenLevel { } public void updateSleepingPlayerList() { @@ -14369,7 +14395,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 if (!this.players.isEmpty() && this.sleepStatus.update(this.players)) { this.announceSleepStatus(); } -@@ -1052,7 +1108,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1052,7 +1115,7 @@ public class ServerLevel extends Level implements WorldGenLevel { return this.server.getScoreboard(); } @@ -14378,7 +14404,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 boolean flag = this.isRaining(); if (this.dimensionType().hasSkyLight()) { -@@ -1138,23 +1194,24 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1138,23 +1201,24 @@ public class ServerLevel extends Level implements WorldGenLevel { this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel)); } // */ @@ -14412,7 +14438,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } } // CraftBukkit end -@@ -1218,7 +1275,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1218,7 +1282,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public void tickNonPassenger(Entity entity) { // Paper start - log detailed entity tick information @@ -14421,7 +14447,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 try { if (currentlyTickingEntity.get() == null) { currentlyTickingEntity.lazySet(entity); -@@ -1251,7 +1308,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1251,7 +1315,16 @@ public class ServerLevel extends Level implements WorldGenLevel { if (isActive) { // Paper - EAR 2 TimingHistory.activatedEntityTicks++; entity.tick(); @@ -14439,7 +14465,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } else { entity.inactiveTick(); } // Paper - EAR 2 this.getProfiler().pop(); } finally { timer.stopTiming(); } // Paper - timings -@@ -1274,7 +1340,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1274,7 +1347,7 @@ public class ServerLevel extends Level implements WorldGenLevel { private void tickPassenger(Entity vehicle, Entity passenger) { if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { @@ -14448,7 +14474,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // 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 -@@ -1291,7 +1357,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1291,7 +1364,16 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper start - EAR 2 if (isActive) { passenger.rideTick(); @@ -14466,7 +14492,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } else { passenger.setDeltaMovement(Vec3.ZERO); passenger.inactiveTick(); -@@ -1379,7 +1454,15 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1379,7 +1461,15 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper - rewrite chunk system - entity saving moved into ChunkHolder } else if (close) { chunkproviderserver.close(false); } // Paper - rewrite chunk system @@ -14482,7 +14508,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // CraftBukkit start - moved from MinecraftServer.saveChunks ServerLevel worldserver1 = this; -@@ -1387,12 +1470,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1387,12 +1477,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save()); this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); // CraftBukkit end @@ -14496,7 +14522,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 this.getChunkSource().getDataStorage().save(); } -@@ -1447,6 +1525,19 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1447,6 +1532,19 @@ public class ServerLevel extends Level implements WorldGenLevel { return list; } @@ -14516,7 +14542,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 @Nullable public ServerPlayer getRandomPlayer() { List list = this.getPlayers(LivingEntity::isAlive); -@@ -1548,8 +1639,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1548,8 +1646,8 @@ public class ServerLevel extends Level implements WorldGenLevel { } 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 @@ -14527,7 +14553,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 return true; } // Paper end -@@ -1688,7 +1779,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1688,7 +1786,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { @@ -14536,7 +14562,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 String s = "recursive call to sendBlockUpdated"; Util.logAndPauseIfInIde("recursive call to sendBlockUpdated", new IllegalStateException("recursive call to sendBlockUpdated")); -@@ -1701,7 +1792,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1701,7 +1799,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) { List list = new ObjectArrayList(); @@ -14545,7 +14571,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 while (iterator.hasNext()) { // CraftBukkit start - fix SPIGOT-6362 -@@ -1724,7 +1815,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1724,7 +1822,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } try { @@ -14554,7 +14580,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 iterator = list.iterator(); while (iterator.hasNext()) { -@@ -1733,7 +1824,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1733,7 +1831,7 @@ public class ServerLevel extends Level implements WorldGenLevel { navigationabstract1.recomputePath(); } } finally { @@ -14563,7 +14589,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } } -@@ -1742,23 +1833,23 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1742,23 +1840,23 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public void updateNeighborsAt(BlockPos pos, Block sourceBlock) { @@ -14592,7 +14618,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } @Override -@@ -1784,7 +1875,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1784,7 +1882,7 @@ public class ServerLevel extends Level implements WorldGenLevel { explosion.clearToBlow(); } @@ -14601,7 +14627,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -@@ -1799,25 +1890,28 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1799,25 +1897,28 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public void blockEvent(BlockPos pos, Block block, int type, int data) { @@ -14636,7 +14662,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } private boolean doBlockEvent(BlockEventData event) { -@@ -1828,12 +1922,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1828,12 +1929,12 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public LevelTicks getBlockTicks() { @@ -14651,7 +14677,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } @Nonnull -@@ -1857,7 +1951,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1857,7 +1958,7 @@ public class ServerLevel extends Level implements WorldGenLevel { 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 Expansion @@ -14660,7 +14686,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } public int sendParticles(List receivers, ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { // Paper end -@@ -1910,7 +2004,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1910,7 +2011,14 @@ public class ServerLevel extends Level implements WorldGenLevel { public Entity getEntityOrPart(int id) { Entity entity = (Entity) this.getEntities().get(id); @@ -14676,7 +14702,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } @Nullable -@@ -1918,6 +2019,61 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1918,6 +2026,61 @@ public class ServerLevel extends Level implements WorldGenLevel { return (Entity) this.getEntities().get(uuid); } @@ -14738,7 +14764,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 @Nullable public BlockPos findNearestMapStructure(TagKey structureTag, BlockPos pos, int radius, boolean skipReferencedStructures) { if (!this.serverLevelData.worldGenOptions().generateStructures()) { // CraftBukkit -@@ -2082,7 +2238,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2082,7 +2245,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (forced) { flag1 = forcedchunk.getChunks().add(k); if (flag1) { @@ -14747,7 +14773,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } } else { flag1 = forcedchunk.getChunks().remove(k); -@@ -2110,13 +2266,18 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2110,13 +2273,18 @@ public class ServerLevel extends Level implements WorldGenLevel { BlockPos blockposition1 = pos.immutable(); optional.ifPresent((holder) -> { @@ -14769,7 +14795,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // Paper start if (optional.isEmpty() && this.getPoiManager().exists(blockposition1, poiType -> true)) { this.getPoiManager().remove(blockposition1); -@@ -2124,7 +2285,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2124,7 +2292,12 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper end this.getPoiManager().add(blockposition1, holder); DebugPackets.sendPoiAddedPacket(this, blockposition1); @@ -14783,7 +14809,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 }); } } -@@ -2171,7 +2337,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2171,7 +2344,7 @@ public class ServerLevel extends Level implements WorldGenLevel { BufferedWriter bufferedwriter = Files.newBufferedWriter(path.resolve("stats.txt")); try { @@ -14792,7 +14818,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 NaturalSpawner.SpawnState spawnercreature_d = this.getChunkSource().getLastSpawnState(); if (spawnercreature_d != null) { -@@ -2185,7 +2351,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2185,7 +2358,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } bufferedwriter.write(String.format(Locale.ROOT, "entities: %s\n", this.entityLookup.getDebugInfo())); // Paper - rewrite chunk system @@ -14801,7 +14827,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 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"); -@@ -2331,7 +2497,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2331,7 +2504,7 @@ public class ServerLevel extends Level implements WorldGenLevel { private void dumpBlockEntityTickers(Writer writer) throws IOException { CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); @@ -14810,7 +14836,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 while (iterator.hasNext()) { TickingBlockEntity tickingblockentity = (TickingBlockEntity) iterator.next(); -@@ -2344,7 +2510,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2344,7 +2517,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @VisibleForTesting public void clearBlockEvents(BoundingBox box) { @@ -14819,7 +14845,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 return box.isInside(blockactiondata.pos()); }); } -@@ -2353,7 +2519,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2353,7 +2526,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public void blockUpdated(BlockPos pos, Block block) { if (!this.isDebug()) { // CraftBukkit start @@ -14828,7 +14854,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 return; } // CraftBukkit end -@@ -2396,9 +2562,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2396,9 +2569,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @VisibleForTesting public String getWatchdogStats() { @@ -14839,7 +14865,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } private static String getTypeCount(Iterable items, Function classifier) { -@@ -2431,6 +2595,12 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2431,6 +2602,12 @@ public class ServerLevel extends Level implements WorldGenLevel { public static void makeObsidianPlatform(ServerLevel worldserver, Entity entity) { // CraftBukkit end BlockPos blockposition = ServerLevel.END_SPAWN_POINT; @@ -14852,7 +14878,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 int i = blockposition.getX(); int j = blockposition.getY() - 2; int k = blockposition.getZ(); -@@ -2443,11 +2613,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2443,11 +2620,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); }); @@ -14865,7 +14891,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 blockList.updateList(); } // CraftBukkit end -@@ -2468,13 +2634,14 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2468,13 +2641,14 @@ public class ServerLevel extends Level implements WorldGenLevel { } public void startTickingChunk(LevelChunk chunk) { @@ -14884,7 +14910,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } @Override -@@ -2496,7 +2663,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2496,7 +2670,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // Paper end - rewrite chunk system } @@ -14893,7 +14919,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // Paper start - optimize is ticking ready type functions io.papermc.paper.chunk.system.scheduling.NewChunkHolder chunkHolder = this.chunkTaskScheduler.chunkHolderManager.getChunkHolder(chunkPos); // isTicking implies the chunk is loaded, and the chunk is loaded now implies the entities are loaded -@@ -2544,16 +2711,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2544,16 +2718,16 @@ public class ServerLevel extends Level implements WorldGenLevel { public void onCreated(Entity entity) {} public void onDestroyed(Entity entity) { @@ -14913,7 +14939,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 // 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; -@@ -2581,7 +2748,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2581,7 +2755,7 @@ public class ServerLevel extends Level implements WorldGenLevel { Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -14922,7 +14948,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } if (entity instanceof EnderDragon) { -@@ -2592,7 +2759,9 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2592,7 +2766,9 @@ public class ServerLevel extends Level implements WorldGenLevel { for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -14932,7 +14958,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } } -@@ -2618,11 +2787,18 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2618,11 +2794,18 @@ public class ServerLevel extends Level implements WorldGenLevel { { com.google.common.collect.Streams.stream( ServerLevel.this.getServer().getAllLevels() ).map( ServerLevel::getDataStorage ).forEach( (worldData) -> { @@ -14952,7 +14978,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 map.carriedByPlayers.remove( (Player) entity ); for ( Iterator iter = (Iterator) map.carriedBy.iterator(); iter.hasNext(); ) { -@@ -2632,6 +2808,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2632,6 +2815,7 @@ public class ServerLevel extends Level implements WorldGenLevel { iter.remove(); } } @@ -14960,7 +14986,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } } } ); -@@ -2666,7 +2843,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2666,7 +2850,7 @@ public class ServerLevel extends Level implements WorldGenLevel { Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -14969,7 +14995,7 @@ index 714637cdd9dcdbffa344b19e77944fb3c7541ff7..440e39238560059d3c13a98c66fd7dd1 } if (entity instanceof EnderDragon) { -@@ -2677,13 +2854,16 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2677,13 +2861,16 @@ public class ServerLevel extends Level implements WorldGenLevel { for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -18565,6 +18591,38 @@ index 0ae8e9134a3671cdf2a480cd4dd6598653e261ab..d9d832b7978d03417912408564f6e21b // entityvillagertrader.setDespawnDelay(48000); // CraftBukkit - moved to EntityVillagerTrader constructor. This lets the value be modified by plugins on CreatureSpawnEvent entityvillagertrader.setWanderTarget(blockposition1); entityvillagertrader.restrictTo(blockposition1, 16); +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 9788e477ff1446ad2ea3669922cc7dfc09900ce8..b3ff974a8e77810b79b179e5f46d5b8b14cf1ae0 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +@@ -149,6 +149,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.getLevel(), this.position(), this.getDeltaMovement(), 1)) { ++ return; ++ } ++ // Folia end - region threading - make sure entities do not move into regions they do not own + boolean flag = this.isNoPhysics(); + 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 97231f7328f0eebffcacdae5469027be8aeec3ae..6c3d7118b08445a430e200688234d5d4230a94fd 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +@@ -77,6 +77,11 @@ public abstract class AbstractHurtingProjectile extends Projectile { + this.discard(); + } 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.getLevel(), 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.setSecondsOnFire(1); + } diff --git a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java b/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java index c7265a650a5d6bdc42d41c5c90cad401d7f1c99d..c95d80ee142dc056874af6baf2d058cc932985e9 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java @@ -18620,6 +18678,22 @@ index 5406925cd66f46ab8744123c670d72cea7bfc3a1..d0fa197283a3bf14ead356e832500430 } } } +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 4132c1113f5437a776e5e3c1cb306904775aed88..a756a7373985152eceaa03255e3f0fb39c53d081 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java +@@ -31,6 +31,11 @@ public class LlamaSpit extends Projectile { + public void tick() { + super.tick(); + Vec3 vec3d = this.getDeltaMovement(); ++ // 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.getLevel(), 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.getHitResult(this, this::canHitEntity); + + this.preOnHit(movingobjectposition); // CraftBukkit - projectile hit event 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 66476b33cede1e44db5ec166a0cea81f82ffe47a..26a17e3098317f6f623cdcab59dceb9d213c7f63 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java @@ -18665,6 +18739,22 @@ index 00ac1cdc4734cc57f15433c5c6e7a3a545739d33..39b0034b7c612759fed87b6a5fff1819 isIncendiary = this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); } // 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 88181c59e604ba3b132b9e695cef5eaf5b836029..0146b150b6cb70a7272e8d9781e100a012f93d9b 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 { + @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.getLevel(), 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.getHitResult(this, this::canHitEntity); + boolean flag = false; + 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 f224ebbc0efefddede43d87f0300c014077b9931..2627610b77e779722bb33eeb1096d862aa9639d2 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java