From da839bc17cf7e6ef78040187e6d3c4a03db03f13 Mon Sep 17 00:00:00 2001 From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Thu, 14 Sep 2023 16:28:26 -0400 Subject: [PATCH] Add some optimization from upstream paper --- .../0039-Paper-Upstream-Optimization.patch | 335 ++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 patches/server/0039-Paper-Upstream-Optimization.patch diff --git a/patches/server/0039-Paper-Upstream-Optimization.patch b/patches/server/0039-Paper-Upstream-Optimization.patch new file mode 100644 index 000000000..96a1a4d52 --- /dev/null +++ b/patches/server/0039-Paper-Upstream-Optimization.patch @@ -0,0 +1,335 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Thu, 14 Sep 2023 16:20:03 -0400 +Subject: [PATCH] Paper: Upstream Optimization + +Original code by PaperMC, licensed under GPL v3 +You can find the original code on https://github.com/PaperMC/Paper + +Optimise multiple block updates occurring in the same chunk | https://github.com/PaperMC/Paper/commit/fb06829845db10be0405966f874a16f135f73229 +Copy NBT in legacy dragon fight converter | https://github.com/PaperMC/Paper/commit/fb06829845db10be0405966f874a16f135f73229 +Copy NBT in upgrade data neighbor ticks | https://github.com/PaperMC/Paper/commit/471f4de9c46ab27df060989a2d49c25b1d8793a2 +Add missing slot sanity checks for container clicks | https://github.com/PaperMC/Paper/commit/e2b197132d00833a82cbbb57930842a6b896d626 + +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2843.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2843.java +index 6333eabb123f13495f7a828fe79c204aff9dcedd..69783c4ca366e4895d4f1c5909656b4f41fee3a1 100644 +--- a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2843.java ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2843.java +@@ -35,7 +35,7 @@ public final class V2843 { + if (outOfBounds == null) { + outOfBounds = Types.NBT.createEmptyList(); + } +- outOfBounds.addMap(tick); ++ outOfBounds.addMap(tick.copy()); + } + } + +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3459.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3459.java +index 21cd3a4252ba57f088105b6fdf2ebb659c00afd3..86509b2fa3c83dc485776d36b7bc2944b1f9a0b5 100644 +--- a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3459.java ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3459.java +@@ -24,7 +24,7 @@ public final class V3459 { + + final MapType endData = dimensionData.getMap("1"); + if (endData != null) { +- data.setMap("DragonFight", endData.getMap("DragonFight", endData.getTypeUtil().createEmptyMap())); ++ data.setMap("DragonFight", endData.getMap("DragonFight", endData.getTypeUtil().createEmptyMap()).copy()); + } + + return null; +diff --git a/src/main/java/ca/spottedleaf/starlight/common/light/StarLightInterface.java b/src/main/java/ca/spottedleaf/starlight/common/light/StarLightInterface.java +index 691239e65b0870ceb0d071b57793cff9b2593f62..4200a028c8dec73f7b821506519a91c00c101587 100644 +--- a/src/main/java/ca/spottedleaf/starlight/common/light/StarLightInterface.java ++++ b/src/main/java/ca/spottedleaf/starlight/common/light/StarLightInterface.java +@@ -193,7 +193,7 @@ public final class StarLightInterface { + return this.hasBlockLight; + } + +- protected int getSkyLightValue(final BlockPos blockPos, final ChunkAccess chunk) { ++ public int getSkyLightValue(final BlockPos blockPos, final ChunkAccess chunk) { + if (!this.hasSkyLight) { + return 0; + } +@@ -263,7 +263,7 @@ public final class StarLightInterface { + return 15; + } + +- protected int getBlockLightValue(final BlockPos blockPos, final ChunkAccess chunk) { ++ public int getBlockLightValue(final BlockPos blockPos, final ChunkAccess chunk) { + if (!this.hasBlockLight) { + return 0; + } +@@ -382,7 +382,7 @@ public final class StarLightInterface { + } + } + +- public CompletableFuture blockChange(final BlockPos pos) { ++ public io.papermc.paper.chunk.system.light.LightQueue.ChunkTasks blockChange(final BlockPos pos) { // Paper - rewrite chunk system + if (this.world == null || pos.getY() < WorldUtil.getMinBlockY(this.world) || pos.getY() > WorldUtil.getMaxBlockY(this.world)) { // empty world + return null; + } +@@ -390,7 +390,7 @@ public final class StarLightInterface { + return this.lightQueue.queueBlockChange(pos); + } + +- public CompletableFuture sectionChange(final SectionPos pos, final boolean newEmptyValue) { ++ public io.papermc.paper.chunk.system.light.LightQueue.ChunkTasks sectionChange(final SectionPos pos, final boolean newEmptyValue) { // Paper - rewrite chunk system + if (this.world == null) { // empty world + return null; + } +@@ -531,7 +531,7 @@ public final class StarLightInterface { + throw new UnsupportedOperationException("No longer implemented, task draining is now performed by the light thread"); // Paper - replace light queue + } + +- protected static final class LightQueue { ++ public static final class LightQueue { + + protected final Long2ObjectLinkedOpenHashMap chunkTasks = new Long2ObjectLinkedOpenHashMap<>(); + protected final StarLightInterface manager; +@@ -544,13 +544,13 @@ public final class StarLightInterface { + return this.chunkTasks.isEmpty(); + } + +- public synchronized CompletableFuture queueBlockChange(final BlockPos pos) { ++ public synchronized LightQueue.ChunkTasks queueBlockChange(final BlockPos pos) { + final ChunkTasks tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), ChunkTasks::new); + tasks.changedPositions.add(pos.immutable()); +- return tasks.onComplete; ++ return tasks; + } + +- public synchronized CompletableFuture queueSectionChange(final SectionPos pos, final boolean newEmptyValue) { ++ public synchronized LightQueue.ChunkTasks queueSectionChange(final SectionPos pos, final boolean newEmptyValue) { + final ChunkTasks tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), ChunkTasks::new); + + if (tasks.changedSectionSet == null) { +@@ -558,20 +558,20 @@ public final class StarLightInterface { + } + tasks.changedSectionSet[pos.getY() - this.manager.minSection] = Boolean.valueOf(newEmptyValue); + +- return tasks.onComplete; ++ return tasks; + } + +- public synchronized CompletableFuture queueChunkLighting(final ChunkPos pos, final Runnable lightTask) { ++ public synchronized LightQueue.ChunkTasks queueChunkLighting(final ChunkPos pos, final Runnable lightTask) { + final ChunkTasks tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), ChunkTasks::new); + if (tasks.lightTasks == null) { + tasks.lightTasks = new ArrayList<>(); + } + tasks.lightTasks.add(lightTask); + +- return tasks.onComplete; ++ return tasks; + } + +- public synchronized CompletableFuture queueChunkSkylightEdgeCheck(final SectionPos pos, final ShortCollection sections) { ++ public synchronized LightQueue.ChunkTasks queueChunkSkylightEdgeCheck(final SectionPos pos, final ShortCollection sections) { + final ChunkTasks tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), ChunkTasks::new); + + ShortOpenHashSet queuedEdges = tasks.queuedEdgeChecksSky; +@@ -580,10 +580,10 @@ public final class StarLightInterface { + } + queuedEdges.addAll(sections); + +- return tasks.onComplete; ++ return tasks; + } + +- public synchronized CompletableFuture queueChunkBlocklightEdgeCheck(final SectionPos pos, final ShortCollection sections) { ++ public synchronized LightQueue.ChunkTasks queueChunkBlocklightEdgeCheck(final SectionPos pos, final ShortCollection sections) { + final ChunkTasks tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), ChunkTasks::new); + + ShortOpenHashSet queuedEdges = tasks.queuedEdgeChecksBlock; +@@ -592,7 +592,7 @@ public final class StarLightInterface { + } + queuedEdges.addAll(sections); + +- return tasks.onComplete; ++ return tasks; + } + + public void removeChunk(final ChunkPos pos) { +@@ -612,13 +612,14 @@ public final class StarLightInterface { + return this.chunkTasks.removeFirst(); + } + +- protected static final class ChunkTasks { ++ public static final class ChunkTasks { + + public final Set changedPositions = new ObjectOpenHashSet<>(); + public Boolean[] changedSectionSet; + public ShortOpenHashSet queuedEdgeChecksSky; + public ShortOpenHashSet queuedEdgeChecksBlock; + public List lightTasks; ++ public boolean isTicketAdded = false; + + public final CompletableFuture onComplete = new CompletableFuture<>(); + +diff --git a/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java b/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java +index 36e93fefdfbebddce4c153974c7cd81af3cb92e9..de28d6ee71990da74d9deb360fac8bde5adbc918 100644 +--- a/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java ++++ b/src/main/java/io/papermc/paper/chunk/system/light/LightQueue.java +@@ -79,7 +79,7 @@ public final class LightQueue { + } + } + +- public CompletableFuture queueBlockChange(final BlockPos pos) { ++ public ChunkTasks queueBlockChange(final BlockPos pos) { + final ChunkTasks tasks; + synchronized (this) { + tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), (final long keyInMap) -> { +@@ -90,10 +90,10 @@ public final class LightQueue { + + tasks.schedule(); + +- return tasks.onComplete; ++ return tasks; + } + +- public CompletableFuture queueSectionChange(final SectionPos pos, final boolean newEmptyValue) { ++ public ChunkTasks queueSectionChange(final SectionPos pos, final boolean newEmptyValue) { + final ChunkTasks tasks; + synchronized (this) { + tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), (final long keyInMap) -> { +@@ -108,10 +108,10 @@ public final class LightQueue { + + tasks.schedule(); + +- return tasks.onComplete; ++ return tasks; + } + +- public CompletableFuture queueChunkLightTask(final ChunkPos pos, final BooleanSupplier lightTask, final PrioritisedExecutor.Priority priority) { ++ public ChunkTasks queueChunkLightTask(final ChunkPos pos, final BooleanSupplier lightTask, final PrioritisedExecutor.Priority priority) { + final ChunkTasks tasks; + synchronized (this) { + tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), (final long keyInMap) -> { +@@ -125,10 +125,10 @@ public final class LightQueue { + + tasks.schedule(); + +- return tasks.onComplete; ++ return tasks; + } + +- public CompletableFuture queueChunkSkylightEdgeCheck(final SectionPos pos, final ShortCollection sections) { ++ public ChunkTasks queueChunkSkylightEdgeCheck(final SectionPos pos, final ShortCollection sections) { + final ChunkTasks tasks; + synchronized (this) { + tasks = this.chunkTasks.computeIfAbsent(CoordinateUtils.getChunkKey(pos), (final long keyInMap) -> { +@@ -144,10 +144,10 @@ public final class LightQueue { + + tasks.schedule(); + +- return tasks.onComplete; ++ return tasks; + } + +- public CompletableFuture queueChunkBlocklightEdgeCheck(final SectionPos pos, final ShortCollection sections) { ++ public ChunkTasks queueChunkBlocklightEdgeCheck(final SectionPos pos, final ShortCollection sections) { + final ChunkTasks tasks; + + synchronized (this) { +@@ -164,7 +164,7 @@ public final class LightQueue { + + tasks.schedule(); + +- return tasks.onComplete; ++ return tasks; + } + + public void removeChunk(final ChunkPos pos) { +@@ -177,20 +177,20 @@ public final class LightQueue { + } + } + +- protected static final class ChunkTasks implements Runnable { +- +- final Set changedPositions = new HashSet<>(); +- Boolean[] changedSectionSet; +- ShortOpenHashSet queuedEdgeChecksSky; +- ShortOpenHashSet queuedEdgeChecksBlock; +- List lightTasks; +- +- final CompletableFuture onComplete = new CompletableFuture<>(); ++ public static final class ChunkTasks implements Runnable { + ++ public final CompletableFuture onComplete = new CompletableFuture<>(); ++ public boolean isTicketAdded; + public final long chunkCoordinate; ++ + private final StarLightInterface lightEngine; + private final LightQueue queue; + private final PrioritisedExecutor.PrioritisedTask task; ++ private final Set changedPositions = new HashSet<>(); ++ private Boolean[] changedSectionSet; ++ private ShortOpenHashSet queuedEdgeChecksSky; ++ private ShortOpenHashSet queuedEdgeChecksBlock; ++ private List lightTasks; + + public ChunkTasks(final long chunkCoordinate, final StarLightInterface lightEngine, final LightQueue queue) { + this(chunkCoordinate, lightEngine, queue, PrioritisedExecutor.Priority.NORMAL); +diff --git a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +index b4be02ec4bb77059f79d3e4d6a6f1ee4843a01f9..76bd323f25d7c2f4e12dd13baa53995fa4f8b27a 100644 +--- a/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java ++++ b/src/main/java/net/minecraft/server/level/ThreadedLevelLightEngine.java +@@ -110,7 +110,8 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + + private final Long2IntOpenHashMap chunksBeingWorkedOn = new Long2IntOpenHashMap(); + +- private void queueTaskForSection(final int chunkX, final int chunkY, final int chunkZ, final Supplier> runnable) { ++ private void queueTaskForSection(final int chunkX, final int chunkY, final int chunkZ, ++ final Supplier runnable) { // Paper - rewrite chunk system + final ServerLevel world = (ServerLevel)this.theLightEngine.getWorld(); + + final ChunkAccess center = this.theLightEngine.getAnyChunkNow(chunkX, chunkZ); +@@ -137,20 +138,26 @@ public class ThreadedLevelLightEngine extends LevelLightEngine implements AutoCl + + final long key = CoordinateUtils.getChunkKey(chunkX, chunkZ); + +- final CompletableFuture updateFuture = runnable.get(); ++ final io.papermc.paper.chunk.system.light.LightQueue.ChunkTasks updateFuture = runnable.get(); // Paper - rewrite chunk system + + if (updateFuture == null) { + // not scheduled + return; + } + ++ if (updateFuture.isTicketAdded) { ++ // ticket already added ++ return; ++ } ++ updateFuture.isTicketAdded = true; ++ + final int references = this.chunksBeingWorkedOn.addTo(key, 1); + 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.thenAcceptAsync((final Void ignore) -> { ++ updateFuture.onComplete.thenAcceptAsync((final Void ignore) -> { + final int newReferences = this.chunksBeingWorkedOn.get(key); + if (newReferences == 1) { + this.chunksBeingWorkedOn.remove(key); +diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +index 9ca261c9f21279558961649cb4849ac379d67573..9614a0b5b32d88a5b212e33af649ca1aa2a22dfd 100644 +--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java ++++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +@@ -424,6 +424,7 @@ public abstract class AbstractContainerMenu { + this.resetQuickCraft(); + } + } else if (this.quickcraftStatus == 1) { ++ if (slotIndex < 0) return; // Paper + slot = (Slot) this.slots.get(slotIndex); + itemstack = this.getCarried(); + if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) { +@@ -599,6 +600,7 @@ public abstract class AbstractContainerMenu { + int j2; + + if (actionType == ClickType.SWAP) { ++ if (slotIndex < 0) return; // Paper + slot2 = (Slot) this.slots.get(slotIndex); + itemstack1 = playerinventory.getItem(button); + itemstack = slot2.getItem();