From b2002c14fab455d6fd64aa504e8ceaff29b603a4 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 27 May 2023 20:34:33 +0200 Subject: [PATCH] Pull a few Folia patches --- ...access-to-lookups-field-in-RegistryO.patch | 30 +++++++++++++++ ...eehive-without-any-players-nearby-th.patch | 25 +++++++++++++ ...recalcBlockCounts-for-empty-sections.patch | 37 +++++++++++++++++++ .../incremental-chunk-and-player-saving.patch | 2 +- 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch create mode 100644 patches/server/Fix-destroying-beehive-without-any-players-nearby-th.patch create mode 100644 patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch diff --git a/patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch b/patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch new file mode 100644 index 0000000000..70065fbc20 --- /dev/null +++ b/patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 15 May 2023 00:20:59 -0700 +Subject: [PATCH] Fix concurrenct access to lookups field in RegistryOps + +The concurrent access occurs on the Netty IO threads when +serializing packets. Thus, it seems it was an oversight of +the implementator of this function as there are typically +more than one Netty IO thread. + +Fixes https://github.com/PaperMC/Folia/issues/11 + +diff --git a/src/main/java/net/minecraft/resources/RegistryOps.java b/src/main/java/net/minecraft/resources/RegistryOps.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/resources/RegistryOps.java ++++ b/src/main/java/net/minecraft/resources/RegistryOps.java +@@ -0,0 +0,0 @@ public class RegistryOps extends DelegatingOps { + + private static RegistryOps.RegistryInfoLookup memoizeLookup(final RegistryOps.RegistryInfoLookup registryInfoGetter) { + return new RegistryOps.RegistryInfoLookup() { +- private final Map>, Optional>> lookups = new HashMap<>(); ++ private final Map>, Optional>> lookups = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - fix concurrent access to lookups field + + @Override + public Optional> lookup(ResourceKey> registryRef) { +- return this.lookups.computeIfAbsent(registryRef, registryInfoGetter::lookup); ++ return (Optional>)this.lookups.computeIfAbsent(registryRef, registryInfoGetter::lookup); // Paper - fix concurrent access to lookups field + } + }; + } diff --git a/patches/server/Fix-destroying-beehive-without-any-players-nearby-th.patch b/patches/server/Fix-destroying-beehive-without-any-players-nearby-th.patch new file mode 100644 index 0000000000..dee3277662 --- /dev/null +++ b/patches/server/Fix-destroying-beehive-without-any-players-nearby-th.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 3 Apr 2023 21:14:19 -0700 +Subject: [PATCH] Fix destroying beehive without any players nearby throwing an + exception + +If the player moves out of range by the time the block is destroyed, +then the exception would throw and remove the player from the world + +diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java ++++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java +@@ -0,0 +0,0 @@ public class BeehiveBlock extends BaseEntityBlock { + + if (!list.isEmpty()) { + List list1 = world.getEntitiesOfClass(Player.class, (new AABB(pos)).inflate(8.0D, 6.0D, 8.0D)); ++ // Paper start - if there are no players nearby, then nextInt() will throw ++ if (list1.isEmpty()) { ++ return; ++ } ++ // Paper end - if there are no players nearby, then nextInt() will throw + int i = list1.size(); + Iterator iterator = list.iterator(); + diff --git a/patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch b/patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch new file mode 100644 index 0000000000..67b9ef3557 --- /dev/null +++ b/patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Mon, 15 May 2023 20:25:26 -0700 +Subject: [PATCH] Optimise recalcBlockCounts() for empty sections + +In 1.18, every chunk section is initialised to a non-null value +and recalcBlockCounts() is invoked for each section. +However, in a standard world, most sections are empty. In such cases, +recalcBlockCounts() would iterate over ever position - even though +the block data would all be air. To avoid this, we skip +searching the section unless the palette indicates there _could_ be +a non-air block state or non-empty fluid state. + +Chunk loading initially showed that recalcBlockCounts() over +sections with a ZeroBitStorage data to to take ~20% of the process, +now it takes <1%. + +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +@@ -0,0 +0,0 @@ public class LevelChunkSection { + this.nonEmptyBlockCount = 0; + this.tickingBlockCount = 0; + this.tickingFluidCount = 0; ++ if (this.maybeHas((BlockState state) -> !state.isAir() || !state.getFluidState().isEmpty())) { // Paper - do not run forEachLocation on clearly empty sections + this.states.forEachLocation((BlockState iblockdata, int i) -> { + FluidState fluid = iblockdata.getFluidState(); + +@@ -0,0 +0,0 @@ public class LevelChunkSection { + } + + }); ++ } // Paper - do not run forEachLocation on clearly empty sections + // Paper end + this.initBlockCollisionData(); // Paper + } diff --git a/patches/server/incremental-chunk-and-player-saving.patch b/patches/server/incremental-chunk-and-player-saving.patch index 456546e66c..07ce138b95 100644 --- a/patches/server/incremental-chunk-and-player-saving.patch +++ b/patches/server/incremental-chunk-and-player-saving.patch @@ -156,7 +156,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ServerPlayer entityplayer = this.players.get(i); + if (interval == -1 || now - entityplayer.lastSave >= interval) { + this.save(entityplayer); -+ if (interval != -1 && io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick() != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; } ++ if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; } + } + // Paper end }