diff --git a/patches/server/0065-Hearse-Fix-a-dead-lock.patch b/patches/server/0065-Hearse-Fix-a-dead-lock.patch new file mode 100644 index 00000000..3f42d21b --- /dev/null +++ b/patches/server/0065-Hearse-Fix-a-dead-lock.patch @@ -0,0 +1,91 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: wangxyper +Date: Fri, 13 Jan 2023 09:01:48 +0800 +Subject: [PATCH] Hearse: Fix a dead lock + +Original license: MIT +Original project: https://github.com/NaturalCodeClub/HearseRewrite + +diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java +index 71d6a399898402139550830605181b94a60f028c..f77c8a054c9bdc1c74e01108b924561408ac86ba 100644 +--- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java ++++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java +@@ -39,9 +39,9 @@ public final class ChunkEntitySlices { + protected final Reference2ObjectMap, EntityCollectionBySection> entitiesByClass; + public final EntityList entities = new EntityList(); + +- public ChunkHolder.FullChunkStatus status; ++ public volatile ChunkHolder.FullChunkStatus status; + +- protected boolean isTransient; ++ protected volatile boolean isTransient; + + public boolean isTransient() { + return this.isTransient; +@@ -119,33 +119,33 @@ public final class ChunkEntitySlices { + + // returns true if this chunk has transient entities remaining + public boolean unload() { ++ Entity[] collectedEntities; ++ int len; + long id = this.accessLock.readLock(); + try { +- final int len = this.entities.size(); +- final Entity[] collectedEntities = Arrays.copyOf(this.entities.getRawData(), len); +- +- for (int i = 0; i < len; ++i) { +- final Entity entity = collectedEntities[i]; +- if (entity.isRemoved()) { +- // removed by us below +- continue; +- } +- if (entity.shouldBeSaved()) { +- entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); +- if (entity.isVehicle()) { +- // we cannot assume that these entities are contained within this chunk, because entities can +- // desync - so we need to remove them all +- for (final Entity passenger : entity.getIndirectPassengers()) { +- passenger.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); +- } ++ len = this.entities.size(); ++ collectedEntities = Arrays.copyOf(this.entities.getRawData(), len); ++ } finally { ++ this.accessLock.unlockRead(id); ++ } ++ for (int i = 0; i < len; ++i) { ++ final Entity entity = collectedEntities[i]; ++ if (entity.isRemoved()) { ++ // removed by us below ++ continue; ++ } ++ if (entity.shouldBeSaved()) { ++ entity.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); ++ if (entity.isVehicle()) { ++ // we cannot assume that these entities are contained within this chunk, because entities can ++ // desync - so we need to remove them all ++ for (final Entity passenger : entity.getIndirectPassengers()) { ++ passenger.setRemoved(Entity.RemovalReason.UNLOADED_TO_CHUNK); + } + } + } +- +- return this.entities.size() != 0; +- } finally { +- this.accessLock.unlockRead(id); + } ++ return this.entities.size() != 0; + } + + private List getAllEntities() { +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 483c19ac24b074cbdb924d684c0892ddc546af3e..4216b4bba7c601660b7c39733f626f95d9b20507 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -4367,6 +4367,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { + // Paper start + this.setPosRaw(x, y, z, false); + } ++ + public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { + // Paper start - block invalid positions + if (!checkPosition(this, x, y, z)) { diff --git a/patches/server/0066-Hearse-Fix-a-concurrent-problem.patch b/patches/server/0066-Hearse-Fix-a-concurrent-problem.patch new file mode 100644 index 00000000..d60bbd75 --- /dev/null +++ b/patches/server/0066-Hearse-Fix-a-concurrent-problem.patch @@ -0,0 +1,67 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: wangxyper +Date: Fri, 13 Jan 2023 09:35:26 +0800 +Subject: [PATCH] Hearse: Fix a concurrent problem + +Original license: MIT +Original project: https://github.com/NaturalCodeClub/HearseRewrite + +diff --git a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java +index f77c8a054c9bdc1c74e01108b924561408ac86ba..a2eb98393729a99e9d3fd43abc90c1f097cd55a2 100644 +--- a/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java ++++ b/src/main/java/io/papermc/paper/world/ChunkEntitySlices.java +@@ -2,7 +2,6 @@ package io.papermc.paper.world; + + import com.destroystokyo.paper.util.maplist.EntityList; + import io.papermc.paper.chunk.system.entity.EntityLookup; +-import io.papermc.paper.util.TickThread; + import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; + import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps; + import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +@@ -21,7 +20,6 @@ import net.minecraft.world.phys.AABB; + import org.bukkit.craftbukkit.event.CraftEventFactory; + import java.util.ArrayList; + import java.util.Arrays; +-import java.util.Iterator; + import java.util.List; + import java.util.concurrent.locks.StampedLock; + import java.util.function.Predicate; +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index e254b2d04e4fc1dc76c26f61ea38aeb27755143f..948abd93c64a5b3679f3552945d7a9a2edaf7c3f 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -17,6 +17,9 @@ import java.util.function.Function; + import java.util.function.Supplier; + import java.util.stream.Stream; + import javax.annotation.Nullable; ++ ++import it.unimi.dsi.fastutil.shorts.ShortLists; ++import net.himeki.mcmtfabric.parallelised.fastutil.ConcurrentShortHashSet; + import net.minecraft.CrashReport; + import net.minecraft.CrashReportCategory; + import net.minecraft.ReportedException; +@@ -384,7 +387,7 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom + + public static ShortList getOrCreateOffsetList(ShortList[] lists, int index) { + if (lists[index] == null) { +- lists[index] = new ShortArrayList(); ++ lists[index] = ShortLists.synchronize(new ShortArrayList()); + } + + return lists[index]; +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 a78f04ae5eb2d0f11579cb0a40384f3f103371af..f1aae5aa6d2951e21e5e0f84fc87117d41876695 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -1075,10 +1075,8 @@ public class LevelChunk extends ChunkAccess { + + for (int i = 0; i < this.postProcessing.length; ++i) { + if (this.postProcessing[i] != null) { +- ShortListIterator shortlistiterator = this.postProcessing[i].iterator(); + +- while (shortlistiterator.hasNext()) { +- Short oshort = (Short) shortlistiterator.next(); ++ for (Short oshort : this.postProcessing[i]) { + BlockPos blockposition = ProtoChunk.unpackOffsetCoordinates(oshort, this.getSectionYFromSectionIndex(i), chunkcoordintpair); + BlockState iblockdata = this.getBlockState(blockposition); + FluidState fluid = iblockdata.getFluidState();