diff --git a/patches/server/0111-Run-tasks-while-reading-poi-data.patch b/patches/server/0111-Run-tasks-while-reading-poi-data.patch new file mode 100644 index 0000000..498e827 --- /dev/null +++ b/patches/server/0111-Run-tasks-while-reading-poi-data.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PureGero +Date: Sat, 25 Dec 2021 18:34:04 +1000 +Subject: [PATCH] Run tasks while reading poi data + +Original license: GPLv3 +Original project: https://github.com/MultiPaper/MultiPaper + +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 210b0cdd4831421c8f43c3d823ac8e962b56bbbc..a52955c51988c821ab00f0c2298193aaa8126330 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 +@@ -1,5 +1,6 @@ + package net.minecraft.world.entity.ai.village.poi; + ++import com.destroystokyo.paper.io.PaperFileIOThread; + import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper + import com.mojang.datafixers.DataFixer; + import com.mojang.datafixers.util.Pair; +@@ -11,6 +12,7 @@ import java.nio.file.Path; + import java.util.Comparator; + import java.util.List; + import java.util.Optional; ++import java.util.concurrent.CompletableFuture; + import java.util.function.BiConsumer; + import java.util.function.BiPredicate; + import java.util.function.BooleanSupplier; +@@ -460,9 +462,15 @@ public class PoiManager extends SectionStorage { + @Override + public net.minecraft.nbt.CompoundTag read(ChunkPos chunkcoordintpair) throws java.io.IOException { + if (this.world != null && Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { +- net.minecraft.nbt.CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ // MultiPaper start - don't block the main thread, run tasks in the meantime ++ CompletableFuture completablefuture = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE + .loadChunkDataAsyncFuture(this.world, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), +- true, false, true).join().poiData; ++ true, false, true); ++ if (!completablefuture.isDone()) { ++ world.chunkSource.mainThreadProcessor.managedBlock(completablefuture::isDone); ++ } ++ net.minecraft.nbt.CompoundTag ret = completablefuture.join().poiData; ++ // MultiPaper end + + if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { + throw new java.io.IOException("See logs for further detail"); diff --git a/patches/server/0112-Run-tasks-while-reading-chunk-data.patch b/patches/server/0112-Run-tasks-while-reading-chunk-data.patch new file mode 100644 index 0000000..92cbbf6 --- /dev/null +++ b/patches/server/0112-Run-tasks-while-reading-chunk-data.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PureGero +Date: Sun, 13 Feb 2022 14:02:25 +1000 +Subject: [PATCH] Run tasks while reading chunk data + +Original license: GPLv3 +Original project: https://github.com/MultiPaper/MultiPaper + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index d7e941fe4224cdc18aaf56090fcc87e395464826..941bbf409043ec0deb64ee761c70bd0084ad7b78 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -1,6 +1,7 @@ + package net.minecraft.server.level; + + import co.aikar.timings.Timing; // Paper ++import com.destroystokyo.paper.io.PaperFileIOThread; + import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableList.Builder; + import com.google.common.collect.Iterables; +@@ -1717,9 +1718,17 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + @Override + public CompoundTag readSync(ChunkPos chunkcoordintpair) throws IOException { + if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) { +- CompoundTag ret = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE +- .loadChunkDataAsyncFuture(this.level, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), +- false, true, true).join().chunkData; ++ // MultiPaper start - don't block the main thread, run tasks in the meantime ++ CompletableFuture completablefuture = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE ++ .loadChunkDataAsyncFuture(this.level, chunkcoordintpair.x, chunkcoordintpair.z, com.destroystokyo.paper.io.IOUtil.getPriorityForCurrentThread(), ++ false, true, true); ++ ++ if (!completablefuture.isDone()) { ++ level.chunkSource.mainThreadProcessor.managedBlock(completablefuture::isDone); ++ } ++ ++ CompoundTag ret = completablefuture.join().chunkData; ++ // MultiPaper end + + if (ret == com.destroystokyo.paper.io.PaperFileIOThread.FAILURE_VALUE) { + throw new IOException("See logs for further detail"); diff --git a/patches/server/0113-Run-tasks-while-we-wait-for-the-entity-storage-worke.patch b/patches/server/0113-Run-tasks-while-we-wait-for-the-entity-storage-worke.patch new file mode 100644 index 0000000..6b69eb8 --- /dev/null +++ b/patches/server/0113-Run-tasks-while-we-wait-for-the-entity-storage-worke.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PureGero +Date: Thu, 27 Jan 2022 22:43:56 +1000 +Subject: [PATCH] Run tasks while we wait for the entity storage worker to + close + +Original license: GPLv3 +Original project: https://github.com/MultiPaper/MultiPaper + +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +index 2bc0384728f89b7c64a8beec78a1b77dc063d37b..513ba9199a1361e678e0146e1ca36af9e42ce3dd 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java +@@ -122,7 +122,12 @@ public class EntityStorage implements EntityPersistentStorage { + + @Override + public void flush(boolean sync) { +- this.worker.synchronize(sync).join(); ++ // MultiPaper start - Run tasks while we wait for the entity storage worker to close ++ CompletableFuture completableFuture = this.worker.synchronize(sync); ++ if (!completableFuture.isDone()) { ++ level.chunkSource.mainThreadProcessor.managedBlock(completableFuture::isDone); ++ } ++ // MultiPaper end + this.entityDeserializerQueue.runAll(); + } + diff --git a/patches/server/0114-Don-t-double-save-the-json-lists.patch b/patches/server/0114-Don-t-double-save-the-json-lists.patch new file mode 100644 index 0000000..cf35c4b --- /dev/null +++ b/patches/server/0114-Don-t-double-save-the-json-lists.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PureGero +Date: Sun, 27 Feb 2022 19:21:10 +1000 +Subject: [PATCH] Don't double save the json lists + +Original license: GPLv3 +Original project: https://github.com/MultiPaper/MultiPaper + +diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +index dc96b30c70cd79d7b2a0322f32b9399a0f2faa41..db0b69f227ab388fa1335471313200f072cca2f3 100644 +--- a/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java ++++ b/src/main/java/net/minecraft/server/dedicated/DedicatedPlayerList.java +@@ -44,13 +44,13 @@ public class DedicatedPlayerList extends PlayerList { + @Override + public void op(GameProfile profile) { + super.op(profile); +- this.saveOps(); ++ // this.saveOps(); // MultiPaper - don't double save the op list + } + + @Override + public void deop(GameProfile profile) { + super.deop(profile); +- this.saveOps(); ++ // this.saveOps(); // MultiPaper - don't double save the op list + } + + @Override +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftIpBanList.java b/src/main/java/org/bukkit/craftbukkit/CraftIpBanList.java +index 61cb647b2aa590303402e6652bd37b5bca0e0b1d..1f3f373d59b1c72aa05136d3279aec17d1c5ed51 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftIpBanList.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftIpBanList.java +@@ -41,11 +41,13 @@ public class CraftIpBanList implements org.bukkit.BanList { + + this.list.add(entry); + +- try { +- this.list.save(); +- } catch (IOException ex) { +- Bukkit.getLogger().log(Level.SEVERE, "Failed to save banned-ips.json, {0}", ex.getMessage()); +- } ++ // MultiPaper start - Don't double save the ban list ++ // try { ++ // this.list.save(); ++ // } catch (IOException ex) { ++ // Bukkit.getLogger().log(Level.SEVERE, "Failed to save banned-ips.json, {0}", ex.getMessage()); ++ // } ++ // MultiPaper end + + return new CraftIpBanEntry(target, entry, this.list); + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftProfileBanEntry.java b/src/main/java/org/bukkit/craftbukkit/CraftProfileBanEntry.java +index 126968d557263b3efddc9d53d0f8f436a401cf78..b7425e88609efe31112426c8c86dc85d0496d6e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftProfileBanEntry.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftProfileBanEntry.java +@@ -78,10 +78,12 @@ public final class CraftProfileBanEntry implements org.bukkit.BanEntry { + public void save() { + UserBanListEntry entry = new UserBanListEntry(this.profile, this.created, this.source, this.expiration, this.reason); + this.list.add(entry); +- try { +- this.list.save(); +- } catch (IOException ex) { +- Bukkit.getLogger().log(Level.SEVERE, "Failed to save banned-players.json, {0}", ex.getMessage()); +- } ++ // MultiPaper start - Don't double save the ban list ++ // try { ++ // this.list.save(); ++ // } catch (IOException ex) { ++ // Bukkit.getLogger().log(Level.SEVERE, "Failed to save banned-players.json, {0}", ex.getMessage()); ++ // } ++ // MultiPaper end + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java b/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java +index 6e2047f1b45799c7a1ddfdcd24d76e6e12f91e4b..66e693404478b33819531a95b55978bb3a1c6860 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java +@@ -54,11 +54,13 @@ public class CraftProfileBanList implements org.bukkit.BanList { + + this.list.add(entry); + +- try { +- this.list.save(); +- } catch (IOException ex) { +- Bukkit.getLogger().log(Level.SEVERE, "Failed to save banned-players.json, {0}", ex.getMessage()); +- } ++ // MultiPaper start - Don't double save the ban list ++ // try { ++ // this.list.save(); ++ // } catch (IOException ex) { ++ // Bukkit.getLogger().log(Level.SEVERE, "Failed to save banned-players.json, {0}", ex.getMessage()); ++ // } ++ // MultiPaper end + + return new CraftProfileBanEntry(profile, entry, this.list); + } diff --git a/patches/server/0116-Don-t-wander-into-non-ticking-chunks.patch b/patches/server/0116-Don-t-wander-into-non-ticking-chunks.patch new file mode 100644 index 0000000..d891c98 --- /dev/null +++ b/patches/server/0116-Don-t-wander-into-non-ticking-chunks.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PureGero +Date: Thu, 14 Apr 2022 10:58:25 +1000 +Subject: [PATCH] Don't wander into non-ticking chunks + +Original license: GPLv3 +Original project: https://github.com/MultiPaper/MultiPaper + +diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/RandomStrollGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/RandomStrollGoal.java +index 216929c838446c3c14d9b9906ffa625ef35fcbc8..331adba3220e2e47335459a1cdd23221b3ba83b5 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/goal/RandomStrollGoal.java ++++ b/src/main/java/net/minecraft/world/entity/ai/goal/RandomStrollGoal.java +@@ -2,6 +2,9 @@ package net.minecraft.world.entity.ai.goal; + + import java.util.EnumSet; + import javax.annotation.Nullable; ++ ++import net.minecraft.core.BlockPos; ++import net.minecraft.server.level.ServerLevel; + import net.minecraft.world.entity.PathfinderMob; + import net.minecraft.world.entity.ai.util.DefaultRandomPos; + import net.minecraft.world.phys.Vec3; +@@ -49,7 +52,7 @@ public class RandomStrollGoal extends Goal { + } + + Vec3 vec3 = this.getPosition(); +- if (vec3 == null) { ++ if (vec3 == null || !((ServerLevel) this.mob.level).isPositionEntityTicking(new BlockPos(vec3))) { // MultiPaper - don't wander into non-ticking chunks + return false; + } else { + this.wantedX = vec3.x; +diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java +index a51424d29ac353cf1bec4d1484db0acb63bebba5..abfaf2e12757b5607a3ac08dc5acebccdbea6770 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java +@@ -138,6 +138,7 @@ public class Squid extends WaterAnimal { + } + + if (!this.level.isClientSide) { ++ if ((tx != 0 || ty != 0 || tz != 0) && !((ServerLevel) this.level).isPositionEntityTicking(new BlockPos(position().add(tx, ty, tz)))) tx = ty = tz = 0; // MultiPaper - don't allow squids to wander into non-ticking chunks + this.setDeltaMovement((double) (this.tx * this.speed), (double) (this.ty * this.speed), (double) (this.tz * this.speed)); + } + diff --git a/patches/server/0117-Optimize-CraftServer.getWorld-UUID.patch b/patches/server/0117-Optimize-CraftServer.getWorld-UUID.patch new file mode 100644 index 0000000..5ef9d6a --- /dev/null +++ b/patches/server/0117-Optimize-CraftServer.getWorld-UUID.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: PureGero +Date: Sun, 26 Jun 2022 11:17:27 +1000 +Subject: [PATCH] Optimize CraftServer.getWorld(UUID) + +Original license: GPLv3 +Original project: https://github.com/MultiPaper/MultiPaper + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 8fb33258a4949f210eaaadb10effea01b1545ea8..65a8bb881720da73136a26e5031c9972b3cc03c2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -45,6 +45,8 @@ import java.util.logging.Level; + import java.util.logging.Logger; + import java.util.stream.Collectors; + import javax.imageio.ImageIO; ++ ++import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; + import net.minecraft.advancements.Advancement; + import net.minecraft.commands.CommandSourceStack; + import net.minecraft.commands.Commands; +@@ -270,6 +272,7 @@ public final class CraftServer implements Server { + protected final DedicatedServer console; + protected final DedicatedPlayerList playerList; + private final Map worlds = new LinkedHashMap(); ++ private final Map worldsByUUID = new Object2ObjectLinkedOpenHashMap<>(); // MultiPaper - optimize getWorld(UUID) + private final Map, Registry> registries = new HashMap<>(); + private YamlConfiguration configuration; + private YamlConfiguration commandsConfiguration; +@@ -1377,6 +1380,7 @@ public final class CraftServer implements Server { + this.getLogger().log(Level.SEVERE, null, ex); + } + ++ this.worldsByUUID.remove(world.getUID()); // MultiPaper - optimize getWorld(UUID) + this.worlds.remove(world.getName().toLowerCase(java.util.Locale.ENGLISH)); + this.console.removeLevel(handle); + return true; +@@ -1395,6 +1399,7 @@ public final class CraftServer implements Server { + + @Override + public World getWorld(UUID uid) { ++ if (true) return this.worldsByUUID.get(uid); // MultiPaper - optimize getWorld(UUID) + for (World world : this.worlds.values()) { + if (world.getUID().equals(uid)) { + return world; +@@ -1418,6 +1423,7 @@ public final class CraftServer implements Server { + System.out.println("World " + world.getName() + " is a duplicate of another world and has been prevented from loading. Please delete the uid.dat file from " + world.getName() + "'s world directory if you want to be able to load the duplicate world."); + return; + } ++ this.worldsByUUID.put(world.getUID(), world); // MultiPaper - optimize getWorld(UUID) + this.worlds.put(world.getName().toLowerCase(java.util.Locale.ENGLISH), world); + MultiPaper.broadcastPacketToExternalServers(new SubscribeToWorldPacket(world.getName())); // MultiPaper + }