diff --git a/build-data/leaf.at b/build-data/leaf.at index 227aec3d..b04d590a 100644 --- a/build-data/leaf.at +++ b/build-data/leaf.at @@ -4,6 +4,7 @@ protected net.minecraft.world.entity.Entity dimensions protected net.minecraft.world.entity.ai.goal.RemoveBlockGoal blockToRemove protected net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal getTargetConditions()Lnet/minecraft/world/entity/ai/targeting/TargetingConditions; protected-f net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase$Cache largeCollisionShape +public net.minecraft.server.level.ServerEntity sendDirtyEntityData()V public net.minecraft.util.Mth SIN public net.minecraft.world.entity.Entity updateInWaterStateAndDoWaterCurrentPushing()V public net.minecraft.world.entity.LivingEntity canGlide()Z diff --git a/leaf-server/minecraft-patches/features/0079-Hide-specified-item-components.patch b/leaf-server/minecraft-patches/features/0079-Hide-specified-item-components.patch index 5745ed27..59eb1838 100644 --- a/leaf-server/minecraft-patches/features/0079-Hide-specified-item-components.patch +++ b/leaf-server/minecraft-patches/features/0079-Hide-specified-item-components.patch @@ -33,7 +33,7 @@ index c1130f596cf3443eeb62eb1b12587172fe0859ee..18590e0b1d94ee3266637c5f3ab65ead @Override diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index 3dcd8df0b395a8fed8bc0cbe0ff78f4ae0056fd3..f4c4998a4913358e5164b44eb78b4f3df04778d2 100644 +index 3dcd8df0b395a8fed8bc0cbe0ff78f4ae0056fd3..cee7daa4908efde754442bf7ef0932b94cf5ebca 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -306,7 +306,12 @@ public abstract class AbstractContainerMenu { @@ -44,7 +44,7 @@ index 3dcd8df0b395a8fed8bc0cbe0ff78f4ae0056fd3..f4c4998a4913358e5164b44eb78b4f3d + // Leaf start - Hide specified item components - Avoid some frequent client animations + final boolean matchResult = org.dreeam.leaf.config.modules.gameplay.HideItemComponent.enabled + ? !org.dreeam.leaf.util.item.ItemStackStripper.matchesStripped(this.getCarried(), this.remoteCarried) -+ : !ItemStack.matches(this.getCarried(), this.remoteCarried); // Paper - add flag to simplify remote matching logic ++ : !ItemStack.matches(this.getCarried(), this.remoteCarried); + if (matchResult) { + // Leaf end - Hide specified item components - Avoid some frequent client animations this.remoteCarried = this.getCarried().copy(); diff --git a/leaf-server/minecraft-patches/features/0085-Multithreaded-Tracker.patch b/leaf-server/minecraft-patches/features/0085-Multithreaded-Tracker.patch index 8fa0a7e1..a15a8293 100644 --- a/leaf-server/minecraft-patches/features/0085-Multithreaded-Tracker.patch +++ b/leaf-server/minecraft-patches/features/0085-Multithreaded-Tracker.patch @@ -37,7 +37,7 @@ index dd2509996bfd08e8c3f9f2be042229eac6d7692d..a35e9fae8f8da0c42f0616c4f78dc396 private static final byte CHUNK_TICKET_STAGE_NONE = 0; private static final byte CHUNK_TICKET_STAGE_LOADING = 1; diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542d50e7a98 100644 +index 5d9d233e3a568aa6297ed9c703fa450f98158602..24765ca23899b2eec049bf539c1f9eafc8b48d1b 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java @@ -248,6 +248,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -70,21 +70,16 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 // Paper start - optimise entity tracker if (true) { this.newTrackerTick(); -@@ -1073,12 +1089,24 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1073,7 +1089,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider final Entity entity; private final int range; SectionPos lastSectionPos; - public final Set seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl -+ public final Set seenBy = org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled ? it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>()) : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl // Leaf - petal - Multithreaded tracker -+ public volatile ServerPlayerConnection[] seenByArray = EMPTY_OBJECT_ARRAY; // Leaf - - // Paper start - optimise entity tracker - private long lastChunkUpdate = -1L; - private ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk lastTrackedChunk; - -+ public final Object sync = new Object(); // Leaf - Multithreaded tracker + // Leaf start - Multithreaded tracker + public static final ServerPlayerConnection[] EMPTY_OBJECT_ARRAY = new ServerPlayerConnection[0]; ++ public final Object sync = new Object(); ++ public final Set seenBy = org.dreeam.leaf.config.modules.async.MultithreadedTracker.enabled ? it.unimi.dsi.fastutil.objects.ReferenceSets.synchronize(new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>()) : new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl ++ private volatile ServerPlayerConnection[] seenByArray = EMPTY_OBJECT_ARRAY; + public ServerPlayerConnection[] seenBy() { + return seenByArray; + } @@ -92,11 +87,10 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 + this.seenByArray = this.seenBy.toArray(EMPTY_OBJECT_ARRAY); + } + // Leaf end - Multithreaded tracker -+ - @Override - public final void moonrise$tick(final ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk chunk) { - if (chunk == null) { -@@ -1100,27 +1128,95 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + + // Paper start - optimise entity tracker + private long lastChunkUpdate = -1L; +@@ -1100,27 +1127,95 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.lastTrackedChunk = chunk; final ServerPlayer[] playersRaw = players.getRawDataUnchecked(); @@ -111,21 +105,21 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 if (lastChunkUpdate != currChunkUpdate || lastTrackedChunk != chunk) { // need to purge any players possible not in the chunk list - for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) { -+ // Leaf start ++ // Leaf start - Multithreaded tracker + boolean removed = false; + for (final ServerPlayerConnection conn : this.seenBy()) { final ServerPlayer player = conn.getPlayer(); if (!players.contains(player)) { - this.removePlayer(player); + removed |= this.removePlayerMulti(player); -+ } -+ } + } + } + if (removed) { + this.seenByUpdated(); + } -+ // Leaf end -+ } -+ } + } + } ++ // Leaf end - Multithreaded tracker + + // Leaf start - Multithreaded tracker + public final @Nullable Runnable leafTickCompact(final ca.spottedleaf.moonrise.common.misc.NearbyPlayers.TrackedChunk chunk) { @@ -172,8 +166,8 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 + } + if (removed) { + this.seenByUpdated(); - } - } ++ } ++ } + }; + + // Only update asynchronously for real player, and sync update for fake players @@ -185,49 +179,49 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 + } else { + updatePlayerTasks.run(); + return null; - } - } ++ } ++ } + // Leaf end - Multithreaded tracker @Override public final void moonrise$removeNonTickThreadPlayers() { boolean foundToRemove = false; - for (final ServerPlayerConnection conn : this.seenBy) { -+ for (final ServerPlayerConnection conn : this.seenBy()) { // Leaf ++ for (final ServerPlayerConnection conn : this.seenBy()) { // Leaf - Multithreaded tracker if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(conn.getPlayer())) { foundToRemove = true; break; -@@ -1131,12 +1227,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1131,12 +1226,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return; } - for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) { -+ for (final ServerPlayerConnection conn : this.seenBy()) { // Leaf ++ for (final ServerPlayerConnection conn : this.seenBy()) { // Leaf - Multithreaded tracker ServerPlayer player = conn.getPlayer(); if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(player)) { - this.removePlayer(player); -+ this.removePlayerMulti(player); // Leaf ++ this.removePlayerMulti(player); // Leaf - Multithreaded tracker } } -+ this.seenByUpdated(); // Leaf ++ this.seenByUpdated(); // Leaf - Multithreaded tracker } @Override -@@ -1146,10 +1243,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1146,10 +1242,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (this.seenBy.isEmpty()) { return; } - for (final ServerPlayerConnection conn : new java.util.ArrayList<>(this.seenBy)) { -+ for (final ServerPlayerConnection conn : this.seenBy()) { // Leaf ++ for (final ServerPlayerConnection conn : this.seenBy()) { // Leaf - Multithreaded tracker ServerPlayer player = conn.getPlayer(); - this.removePlayer(player); -+ this.removePlayerMulti(player); // Leaf ++ this.removePlayerMulti(player); // Leaf - Multithreaded tracker } -+ this.seenByUpdated(); // Leaf ++ this.seenByUpdated(); // Leaf - Multithreaded tracker } @Override -@@ -1176,7 +1274,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1176,7 +1273,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void broadcast(Packet packet) { @@ -236,7 +230,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 serverPlayerConnection.send(packet); } } -@@ -1189,21 +1287,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1189,21 +1286,34 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void broadcastRemoved() { @@ -246,7 +240,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 } } -+ // Leaf start ++ // Leaf start - Multithreaded tracker + public boolean removePlayerMulti(ServerPlayer player) { + if (this.seenBy.remove(player.connection)) { + this.serverEntity.removePairing(player); @@ -255,7 +249,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 + return false; + } + } -+ // Leaf end ++ // Leaf end - Multithreaded tracker + public void removePlayer(ServerPlayer player) { - org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot @@ -263,7 +257,7 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); } -+ this.seenByUpdated(); // Leaf ++ this.seenByUpdated(); // Leaf - Multithreaded tracker } public void updatePlayer(ServerPlayer player) { @@ -274,19 +268,19 @@ index 5d9d233e3a568aa6297ed9c703fa450f98158602..fa11526bf799910da9193ae6e3366542 // Paper start - remove allocation of Vec3D here // Vec3 vec3 = player.position().subtract(this.entity.position()); double vec3_dx = player.getX() - this.entity.getX(); -@@ -1231,6 +1342,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1231,6 +1341,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // CraftBukkit end if (flag) { if (this.seenBy.add(player.connection)) { -+ this.seenByUpdated(); // Leaf ++ this.seenByUpdated(); // Leaf - Multithreaded tracker // Paper start - entity tracking events if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) { this.serverEntity.addPairing(player); -@@ -1239,6 +1351,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1239,6 +1350,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.serverEntity.onPlayerAdd(); // Paper - fix desync when a player is added to the tracker } } else if (this.seenBy.remove(player.connection)) { -+ this.seenByUpdated(); // Leaf ++ this.seenByUpdated(); // Leaf - Multithreaded tracker this.serverEntity.removePairing(player); } } @@ -304,7 +298,7 @@ index f106373ef3ac4a8685c2939c9e8361688a285913..51ae390c68e7a3aa193329cc3bc47ca6 public boolean visible = true; diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index d8298c7925e3bcea07ead4d438478cc51abcfa16..e67d87b3043b381d27f75f37e3b7f922e18dcc2d 100644 +index 1dee20436fc29537319ee456756a8e8f7b6fe66a..1f3e030cea42a0c9e27425cb18c232f482ef8608 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java @@ -70,6 +70,7 @@ public class ServerEntity { @@ -339,16 +333,14 @@ index d8298c7925e3bcea07ead4d438478cc51abcfa16..e67d87b3043b381d27f75f37e3b7f922 MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level); if (savedData != null) { - for (final net.minecraft.server.network.ServerPlayerConnection connection : this.trackedPlayers) { // Paper -+ for (final net.minecraft.server.network.ServerPlayerConnection connection : this.trackedPlayers.toArray(ChunkMap.TrackedEntity.EMPTY_OBJECT_ARRAY)) { // Paper // Leaf ++ for (final net.minecraft.server.network.ServerPlayerConnection connection : this.trackedPlayers.toArray(ChunkMap.TrackedEntity.EMPTY_OBJECT_ARRAY)) { // Paper // Leaf - Multithreaded tracker final ServerPlayer serverPlayer = connection.getPlayer(); // Paper savedData.tickCarriedBy(serverPlayer, item); Packet updatePacket = savedData.getUpdatePacket(mapId, serverPlayer); -@@ -424,7 +433,13 @@ public class ServerEntity { - return Mth.unpackDegrees(this.lastSentYHeadRot); +@@ -425,6 +434,12 @@ public class ServerEntity { } -- private void sendDirtyEntityData() { -+ public void sendDirtyEntityData() { // Leaf - public + public void sendDirtyEntityData() { + // Leaf start - Multithreaded tracker + if (Thread.currentThread() instanceof org.dreeam.leaf.async.tracker.MultithreadedTracker.MultithreadedTrackerThread) { + wantSendDirtyEntityData = true; @@ -394,7 +386,7 @@ index 04bf8bba0d8c0d5459605253dcc3f135bf43fd95..abe79d07196de0a10a382d4c37161c7e if (this.player.isRemoved()) { LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java -index c96f458994818392857642282ec3d492124885da..1caf6846c5057f2c9bcd56ba9f217cc2863cd41b 100644 +index c96f458994818392857642282ec3d492124885da..d345afd14ef6fe2f0a584df5dfa080fd7ab3f47e 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java @@ -142,12 +142,14 @@ public class PrimedTnt extends Entity implements TraceableEntity { @@ -404,7 +396,7 @@ index c96f458994818392857642282ec3d492124885da..1caf6846c5057f2c9bcd56ba9f217cc2 - ete.seenBy.stream() - .filter(viewer -> (viewer.getPlayer().getX() - this.getX()) * (viewer.getPlayer().getY() - this.getY()) * (viewer.getPlayer().getZ() - this.getZ()) < 16 * 16) - .forEach(viewer -> { -+ // Leaf start ++ // Leaf start - Multithreaded tracker + for (var viewer : ete.seenBy()) { + if ((viewer.getPlayer().getX() - this.getX()) * (viewer.getPlayer().getY() - this.getY()) * (viewer.getPlayer().getZ() - this.getZ()) < 16 * 16) { viewer.send(velocityPacket); @@ -412,7 +404,7 @@ index c96f458994818392857642282ec3d492124885da..1caf6846c5057f2c9bcd56ba9f217cc2 - }); + } + } -+ // Leaf end ++ // Leaf end - Multithreaded tracker } } // Paper end - Option to prevent TNT from moving in water diff --git a/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch b/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch index 87c4d127..96454dc8 100644 --- a/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch +++ b/leaf-server/minecraft-patches/features/0090-Smart-sort-entities-in-NearestLivingEntitySensor.patch @@ -12,17 +12,16 @@ In non-strict test, this can give ~60-110% improvement (524ms on Paper, 204ms on under 625 villagers situation. diff --git a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..d4d75a3f5d03533626417aaa3b0457ab98acea1c 100644 +index b0c5e41fefc7c9adf1a61bd5b52861736657d37e..ef87b95d53e5ea2555778e6020ea07a11c474961 100644 --- a/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java +++ b/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java -@@ -13,17 +13,28 @@ import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; +@@ -13,17 +13,27 @@ import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities; import net.minecraft.world.phys.AABB; public class NearestLivingEntitySensor extends Sensor { + + // Leaf start - Smart sort entities in NearestLivingEntitySensor + private final org.dreeam.leaf.util.FastBitRadixSort sorter; -+ + public NearestLivingEntitySensor() { + this.sorter = new org.dreeam.leaf.util.FastBitRadixSort(); + } diff --git a/leaf-server/minecraft-patches/features/0134-SparklyPaper-Parallel-world-ticking.patch b/leaf-server/minecraft-patches/features/0134-SparklyPaper-Parallel-world-ticking.patch index 122f15f4..ff920aca 100644 --- a/leaf-server/minecraft-patches/features/0134-SparklyPaper-Parallel-world-ticking.patch +++ b/leaf-server/minecraft-patches/features/0134-SparklyPaper-Parallel-world-ticking.patch @@ -869,18 +869,10 @@ index 88b07fbb96b20124777889830afa480673629d43..f8bb32840129e57b7799f883cb4570d2 + // Leaf end - SparklyPaper - parallel world ticking mod (prevent clearing portal process) } diff --git a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java -index 3614551856c594f3c0cfee984fcf03fad672b007..f39e2e4b6a3b18a3fbfbd58c99560b9378b7a031 100644 +index 3614551856c594f3c0cfee984fcf03fad672b007..f4577f908ca9f279b72d89e5b0822d34b6fb7dd1 100644 --- a/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java +++ b/net/minecraft/world/entity/ai/behavior/GoToPotentialJobSite.java -@@ -3,6 +3,7 @@ package net.minecraft.world.entity.ai.behavior; - import com.google.common.collect.ImmutableMap; - import java.util.Optional; - import net.minecraft.core.BlockPos; -+import net.minecraft.core.SectionPos; - import net.minecraft.core.GlobalPos; - import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.server.level.ServerLevel; -@@ -44,14 +45,32 @@ public class GoToPotentialJobSite extends Behavior { +@@ -44,14 +44,34 @@ public class GoToPotentialJobSite extends Behavior { Optional memory = entity.getBrain().getMemory(MemoryModuleType.POTENTIAL_JOB_SITE); memory.ifPresent(globalPos -> { BlockPos blockPos = globalPos.pos(); @@ -890,6 +882,7 @@ index 3614551856c594f3c0cfee984fcf03fad672b007..f39e2e4b6a3b18a3fbfbd58c99560b93 - if (poiManager.exists(blockPos, holder -> true)) { - poiManager.release(blockPos); - } ++ // Leaf start - SparklyPaper - parallel world ticking + ServerLevel entityLevel = level; // Villager's current level + ServerLevel poiLevel = entityLevel.getServer().getLevel(globalPos.dimension()); // POI's actual level + @@ -909,7 +902,7 @@ index 3614551856c594f3c0cfee984fcf03fad672b007..f39e2e4b6a3b18a3fbfbd58c99560b93 - DebugPackets.sendPoiTicketCountPacket(level, blockPos); + if (org.dreeam.leaf.config.modules.async.SparklyPaperParallelWorldTicking.enabled) { // Added curly braces here + // Schedule POI operations on the POI's level thread, using POI's chunk coordinates for locality -+ poiLevel.moonrise$getChunkTaskScheduler().scheduleChunkTask(SectionPos.blockToSectionCoord(blockPos.getX()), SectionPos.blockToSectionCoord(blockPos.getZ()), poiOperationsTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING); ++ poiLevel.moonrise$getChunkTaskScheduler().scheduleChunkTask(blockPos.getX() >> 4, blockPos.getZ() >> 4, poiOperationsTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING); + // Schedule debug packet on the entity's level thread, using entity's chunk coordinates for locality + entityLevel.moonrise$getChunkTaskScheduler().scheduleChunkTask(entity.chunkPosition().x, entity.chunkPosition().z, debugPacketTask, ca.spottedleaf.concurrentutil.util.Priority.BLOCKING); + } @@ -917,6 +910,7 @@ index 3614551856c594f3c0cfee984fcf03fad672b007..f39e2e4b6a3b18a3fbfbd58c99560b93 + poiOperationsTask.run(); // This will use poiLevel's PoiManager but thread checks are permissive + debugPacketTask.run(); // This will use entityLevel's PoiManager + } ++ // Leaf end - SparklyPaper - parallel world ticking } }); entity.getBrain().eraseMemory(MemoryModuleType.POTENTIAL_JOB_SITE); @@ -1037,7 +1031,7 @@ index d212f57c8c0b2086f567fd30237b110203d9e8cb..ed4df82581b5411e54068ccc59ea85a7 } else { Entity entity = owner.teleport( diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index f4c4998a4913358e5164b44eb78b4f3df04778d2..cb0a064a41f4f72f4f1a8768b6a1961b903e7708 100644 +index cee7daa4908efde754442bf7ef0932b94cf5ebca..ff2ff95ec9d94e2e31e8174196b384c37d56f38a 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -92,8 +92,14 @@ public abstract class AbstractContainerMenu { diff --git a/leaf-server/minecraft-patches/features/0164-reduce-PlayerChunk-Updates.patch b/leaf-server/minecraft-patches/features/0164-Reduce-PlayerChunk-Updates.patch similarity index 98% rename from leaf-server/minecraft-patches/features/0164-reduce-PlayerChunk-Updates.patch rename to leaf-server/minecraft-patches/features/0164-Reduce-PlayerChunk-Updates.patch index ec87ac5d..8a4ce281 100644 --- a/leaf-server/minecraft-patches/features/0164-reduce-PlayerChunk-Updates.patch +++ b/leaf-server/minecraft-patches/features/0164-Reduce-PlayerChunk-Updates.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Thu, 8 May 2025 10:08:54 +0200 -Subject: [PATCH] reduce PlayerChunk Updates +Subject: [PATCH] Reduce PlayerChunk Updates diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java diff --git a/leaf-server/minecraft-patches/features/0165-async-switch-connection-state.patch b/leaf-server/minecraft-patches/features/0165-Async-switch-connection-state.patch similarity index 84% rename from leaf-server/minecraft-patches/features/0165-async-switch-connection-state.patch rename to leaf-server/minecraft-patches/features/0165-Async-switch-connection-state.patch index 03b4f3b5..d02cdc9f 100644 --- a/leaf-server/minecraft-patches/features/0165-async-switch-connection-state.patch +++ b/leaf-server/minecraft-patches/features/0165-Async-switch-connection-state.patch @@ -1,22 +1,22 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Fri, 9 May 2025 16:55:34 +0900 -Subject: [PATCH] async switch connection state +Subject: [PATCH] Async switch connection state diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java -index f3e9de8716f5e1a72ec465ee897c8f0413f7b1c3..3a82e1e510029576485427af9fd705b37c5f6e20 100644 +index f3e9de8716f5e1a72ec465ee897c8f0413f7b1c3..c83ee2137a57e62003b1d20c3ceea9f569350a53 100644 --- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java @@ -342,6 +342,11 @@ public class Connection extends SimpleChannelInboundHandler> { if (protocolInfo.flow() != this.getReceiving()) { throw new IllegalStateException("Invalid inbound protocol: " + protocolInfo.id()); } else { -+ // Leaf start ++ // Leaf start - Async switch connection state + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { + this.channel.config().setAutoRead(false); + } -+ // Leaf end ++ // Leaf end - Async switch connection state this.packetListener = packetInfo; this.disconnectListener = null; UnconfiguredPipelineHandler.InboundConfigurationTask inboundConfigurationTask = UnconfiguredPipelineHandler.setupInboundProtocol(protocolInfo); @@ -25,34 +25,33 @@ index f3e9de8716f5e1a72ec465ee897c8f0413f7b1c3..3a82e1e510029576485427af9fd705b3 } - syncAfterConfigurationChange(this.channel.writeAndFlush(inboundConfigurationTask)); -+ // Leaf start ++ // Leaf start - Async switch connection state + var cf = this.channel.writeAndFlush(inboundConfigurationTask); + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { + cf.addListener((ChannelFutureListener) Connection::syncAfterConfigurationChange); + return; + } + syncAfterConfigurationChange(cf); -+ // Leaf end ++ // Leaf end - Async switch connection state } } -@@ -369,9 +381,41 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -369,7 +381,38 @@ public class Connection extends SimpleChannelInboundHandler> { } boolean flag = protocolInfo.id() == ConnectionProtocol.LOGIN; - syncAfterConfigurationChange(this.channel.writeAndFlush(outboundConfigurationTask.andThen(context -> this.sendLoginDisconnect = flag))); + var cf = this.channel.writeAndFlush(outboundConfigurationTask.andThen(context -> this.sendLoginDisconnect = flag)); -+ // Leaf start ++ // Leaf start - Async switch connection state + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) { + if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()) { + throw new IllegalStateException("Thread failed netty thread check: Switching outbound protocol state use setupOutboundProtocolAsync instead"); + } + } -+ // Leaf end + syncAfterConfigurationChange(cf); + } + } -+ // Leaf start ++ + public @Nullable ChannelFuture setupOutboundProtocolAsync(ProtocolInfo protocolInfo) { + if (protocolInfo.flow() != this.getSending()) { + throw new IllegalStateException("Invalid outbound protocol: " + protocolInfo.id()); @@ -73,24 +72,22 @@ index f3e9de8716f5e1a72ec465ee897c8f0413f7b1c3..3a82e1e510029576485427af9fd705b3 + return cf; + } + return null; ++ // Leaf end - Async switch connection state } } -+ // Leaf end - public void setListenerForServerboundHandshake(PacketListener packetListener) { - if (this.packetListener != null) { diff --git a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java -index 2e9eb04c7c4342393c05339906c267bca9ff29b1..c70d5a0db1dfd01eab323aefd07d6e81dd188927 100644 +index 2e9eb04c7c4342393c05339906c267bca9ff29b1..53b9daa909c2b89046d5af515e17afe09ea7015a 100644 --- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java -@@ -140,11 +140,32 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis +@@ -140,11 +140,34 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis } } -+ private volatile boolean changingState = false; // Leaf ++ private volatile boolean changingState = false; // Leaf - Async switch connection state @Override public void handleConfigurationFinished(ServerboundFinishConfigurationPacket packet) { -+ // Leaf start ++ // Leaf start - Async switch connection state + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && !changingState) { + changingState = true; + this.finishCurrentTask(JoinWorldTask.TYPE); @@ -109,27 +106,29 @@ index 2e9eb04c7c4342393c05339906c267bca9ff29b1..c70d5a0db1dfd01eab323aefd07d6e81 + }); + return; + } -+ // Leaf end PacketUtils.ensureRunningOnSameThread(packet, this, this.server); - this.finishCurrentTask(JoinWorldTask.TYPE); - this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()))); -+ if (!org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) { this.finishCurrentTask(JoinWorldTask.TYPE); } // Leaf -+ if (!org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) { this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()))); } // Leaf ++ if (!org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) { ++ this.finishCurrentTask(JoinWorldTask.TYPE); ++ this.connection.setupOutboundProtocol(GameProtocols.CLIENTBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess()))); ++ } ++ // Leaf end - Async switch connection state try { PlayerList playerList = this.server.getPlayerList(); diff --git a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 49f1743db193be1f10bfe6419231eb682e1068f7..b0ffd2077747b2325ab795eef457b9a0fa44754b 100644 +index 49f1743db193be1f10bfe6419231eb682e1068f7..8cbfe4abca6a3962376f723b94de86b4cab9d9e2 100644 --- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -472,11 +472,32 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, +@@ -472,11 +472,31 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, this.disconnect(ServerCommonPacketListenerImpl.DISCONNECT_UNEXPECTED_QUERY); } -+ private volatile boolean changingState = false; // Leaf ++ private volatile boolean changingState = false; // Leaf - Async switch connection state @Override public void handleLoginAcknowledgement(ServerboundLoginAcknowledgedPacket packet) { -+ // Leaf start ++ // Leaf start - Async switch connection state + if (org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled && !changingState) { + changingState = true; + this.connection.setupOutboundProtocolAsync(ConfigurationProtocols.CLIENTBOUND).addListener(l -> { @@ -147,12 +146,11 @@ index 49f1743db193be1f10bfe6419231eb682e1068f7..b0ffd2077747b2325ab795eef457b9a0 + }); + return; + } -+ // Leaf end -+ ++ // Leaf end - Async switch connection state PacketUtils.ensureRunningOnSameThread(packet, this, this.server); // CraftBukkit Validate.validState(this.state == ServerLoginPacketListenerImpl.State.PROTOCOL_SWITCHING, "Unexpected login acknowledgement packet"); - this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); -+ if (!org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) { this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); } // Leaf ++ if (!org.dreeam.leaf.config.modules.network.AlternativeJoin.enabled) this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); // Leaf - Async switch connection state CommonListenerCookie commonListenerCookie = CommonListenerCookie.createInitial(Objects.requireNonNull(this.authenticatedProfile), this.transferred); ServerConfigurationPacketListenerImpl serverConfigurationPacketListenerImpl = new ServerConfigurationPacketListenerImpl( this.server, this.connection, commonListenerCookie, this.player // CraftBukkit diff --git a/leaf-server/minecraft-patches/features/0166-Optimise-BlockEntities-tickersInLevel.patch b/leaf-server/minecraft-patches/features/0166-Optimise-BlockEntities-tickersInLevel.patch index 0f09babb..1ad19b8d 100644 --- a/leaf-server/minecraft-patches/features/0166-Optimise-BlockEntities-tickersInLevel.patch +++ b/leaf-server/minecraft-patches/features/0166-Optimise-BlockEntities-tickersInLevel.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Optimise BlockEntities tickersInLevel diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 546fb78339c005ed71142cb3c894f816b8c72d08..22ccc6bc8444f2dba1db8a0e06d5018b6631c442 100644 +index 546fb78339c005ed71142cb3c894f816b8c72d08..e6eab6929b08503c49debbbd25497ffedad438e1 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java @@ -72,7 +72,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @@ -13,7 +13,7 @@ index 546fb78339c005ed71142cb3c894f816b8c72d08..22ccc6bc8444f2dba1db8a0e06d5018b } }; - private final Map tickersInLevel = Maps.newHashMap(); -+ private final Map tickersInLevel = org.dreeam.leaf.config.modules.opt.OptimiseBlockEntities.enabled ? new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>() : Maps.newHashMap(); ++ private final Map tickersInLevel = org.dreeam.leaf.config.modules.opt.OptimiseBlockEntities.enabled ? new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>() : Maps.newHashMap(); // Leaf - Optimise BlockEntities tickersInLevel public boolean loaded; public final ServerLevel level; // CraftBukkit - type @Nullable diff --git a/leaf-server/minecraft-patches/features/0167-Pluto-Check-if-the-cactus-can-even-survive-being-pla.patch b/leaf-server/minecraft-patches/features/0167-Pluto-Check-if-the-cactus-can-even-survive-being-pla.patch index a985202f..b465fe70 100644 --- a/leaf-server/minecraft-patches/features/0167-Pluto-Check-if-the-cactus-can-even-survive-being-pla.patch +++ b/leaf-server/minecraft-patches/features/0167-Pluto-Check-if-the-cactus-can-even-survive-being-pla.patch @@ -1,8 +1,21 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Taiyou06 -Date: Thu, 8 May 2025 21:24:48 +0200 +From: Yive <6853318+Yive@users.noreply.github.com> +Date: Tue, 11 Jul 2023 13:27:01 -0700 Subject: [PATCH] Pluto: Check if the cactus can even survive being placed +Original license: GPLv3 +Original project: https://github.com/Yive/Pluto + +Results at 3,000 randomTickSpeed and 24,448 cacti: + +check-survival-before-growth - false & doTileDrop - true: 48mspt +check-survival-before-growth - true & doTileDrop - true: 25mspt +check-survival-before-growth - false & doTileDrop - false: 18mspt +check-survival-before-growth - true & doTileDrop - false: 6mspt + +Setting the gamerule "doTileDrop" to false was to simulate a server that has chunk collectors. + +Note: This might increase the item output of a cacti farm, though in theory it should act the same as vanilla. diff --git a/net/minecraft/world/level/block/CactusBlock.java b/net/minecraft/world/level/block/CactusBlock.java index 079b4c95cf81119ca99daeb159aefca389afed74..8fe29455d7ae44f43c663718d38ea2d8cf639797 100644 diff --git a/leaf-server/minecraft-patches/features/0168-flush-location-while-knockback.patch b/leaf-server/minecraft-patches/features/0168-Flush-location-while-knockback.patch similarity index 84% rename from leaf-server/minecraft-patches/features/0168-flush-location-while-knockback.patch rename to leaf-server/minecraft-patches/features/0168-Flush-location-while-knockback.patch index 27a24946..79ccc1cc 100644 --- a/leaf-server/minecraft-patches/features/0168-flush-location-while-knockback.patch +++ b/leaf-server/minecraft-patches/features/0168-Flush-location-while-knockback.patch @@ -1,24 +1,24 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Sun, 11 May 2025 19:45:58 +0200 -Subject: [PATCH] flush location while knockback +Subject: [PATCH] Flush location while knockback diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 477455fdfcc591a89823e88983eb12dabb078d9b..67c4cbb8ed6131b639b01e4fc0cbf56057a3fe03 100644 +index 477455fdfcc591a89823e88983eb12dabb078d9b..8469cf9cacebea3fdd855f6c3e9e2cf61c78b8ac 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -1412,6 +1412,13 @@ public abstract class Player extends LivingEntity { } if (!cancelled) { -+ // Leaf start ++ // Leaf start - Flush location while knockback + if (org.dreeam.leaf.config.modules.gameplay.Knockback.flushKnockback && target instanceof ServerPlayer targetPlayer && this instanceof ServerPlayer player1) { + targetPlayer.connection.send(net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket.of(this)); + player1.connection.send(new net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket(targetPlayer)); + player1.connection.send(net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket.of(targetPlayer)); + } -+ // Leaf end ++ // Leaf end - Flush location while knockback ((ServerPlayer)target).connection.send(new ClientboundSetEntityMotionPacket(target)); target.hurtMarked = false; target.setDeltaMovement(deltaMovement); @@ -26,12 +26,12 @@ index 477455fdfcc591a89823e88983eb12dabb078d9b..67c4cbb8ed6131b639b01e4fc0cbf560 } this.causeFoodExhaustion(this.level().spigotConfig.combatExhaustion, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value -+ // Leaf start ++ // Leaf start - Flush location while knockback + if (org.dreeam.leaf.config.modules.gameplay.Knockback.flushKnockback && this instanceof ServerPlayer player1 && target instanceof ServerPlayer target1) { + target1.connection.connection.flushChannel(); + player1.connection.connection.flushChannel(); + } -+ // Leaf end ++ // Leaf end - Flush location while knockback } else { this.sendSoundEffect(this, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F); // Paper - send while respecting visibility // CraftBukkit start - resync on cancelled event diff --git a/leaf-server/minecraft-patches/features/0169-Only-tick-items-at-hand.patch b/leaf-server/minecraft-patches/features/0169-Only-tick-items-at-hand.patch index c2917c5d..0adbe382 100644 --- a/leaf-server/minecraft-patches/features/0169-Only-tick-items-at-hand.patch +++ b/leaf-server/minecraft-patches/features/0169-Only-tick-items-at-hand.patch @@ -5,41 +5,45 @@ Subject: [PATCH] Only tick items at hand diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 50cf63666071f5d01a85dfc6c6c45c19b05d8ec2..f5afaaa8db28295425ff3c6db73917210eadc3ca 100644 +index 50cf63666071f5d01a85dfc6c6c45c19b05d8ec2..ef53b9f307572dd5dc99d02e017d6b2dafb04e3f 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -888,9 +888,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -888,12 +888,19 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc super.tick(); } -- for (int i = 0; i < this.getInventory().getContainerSize(); i++) { -- ItemStack item = this.getInventory().getItem(i); -- if (!item.isEmpty()) { ++ // Leaf start - Only tick items at hand + if (org.dreeam.leaf.config.modules.opt.OptimizeItemTicking.onlyTickItemsInHand) { + this.synchronizeSpecialItemUpdates(this.getMainHandItem()); + this.synchronizeSpecialItemUpdates(this.getOffhandItem()); + } else { -+ for (int i = 0; i < this.getInventory().getContainerSize(); ++i) { -+ ItemStack item = this.getInventory().getItem(i); -+ if (item.isEmpty()) continue; + for (int i = 0; i < this.getInventory().getContainerSize(); i++) { + ItemStack item = this.getInventory().getItem(i); + if (!item.isEmpty()) { this.synchronizeSpecialItemUpdates(item); } } ++ } ++ // Leaf end - Only tick items at hand + + if (this.getHealth() != this.lastSentHealth + || this.lastSentFood != this.foodData.getFoodLevel() diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 67c4cbb8ed6131b639b01e4fc0cbf56057a3fe03..8bab487a1d77d8227bf9426d0218e906db034982 100644 +index 8469cf9cacebea3fdd855f6c3e9e2cf61c78b8ac..d39757fae68580abcb13804e01587e542f1e087d 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -631,7 +631,12 @@ public abstract class Player extends LivingEntity { +@@ -631,7 +631,14 @@ public abstract class Player extends LivingEntity { } this.tickRegeneration(); -- this.inventory.tick(); ++ // Leaf start - Only tick items at hand + if (org.dreeam.leaf.config.modules.opt.OptimizeItemTicking.onlyTickItemsInHand) { + this.getMainHandItem().inventoryTick(this.level(), this, 0, true); + this.getOffhandItem().inventoryTick(this.level(), this, 0, true); + } else { -+ this.inventory.tick(); + this.inventory.tick(); + } ++ // Leaf end - Only tick items at hand this.oBob = this.bob; if (this.abilities.flying && !this.isPassenger()) { this.resetFallDistance(); diff --git a/leaf-server/minecraft-patches/features/0170-Smart-sort-items-in-NearestItemSensor.patch b/leaf-server/minecraft-patches/features/0170-Smart-sort-items-in-NearestItemSensor.patch index 3f02bbde..0907f553 100644 --- a/leaf-server/minecraft-patches/features/0170-Smart-sort-items-in-NearestItemSensor.patch +++ b/leaf-server/minecraft-patches/features/0170-Smart-sort-items-in-NearestItemSensor.patch @@ -5,41 +5,32 @@ Subject: [PATCH] Smart sort items in NearestItemSensor diff --git a/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -index 09fd13e2d958da8326276c4dadf25bf488aff5ac..a6268791efba64aa21957b7883a5691b5a07cc1a 100644 +index 09fd13e2d958da8326276c4dadf25bf488aff5ac..651797720f7fc6ff9dc614f4de56053c304b1170 100644 --- a/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java +++ b/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java -@@ -6,6 +6,7 @@ import java.util.List; - import java.util.Optional; - import java.util.Set; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.Mob; - import net.minecraft.world.entity.ai.Brain; - import net.minecraft.world.entity.ai.memory.MemoryModuleType; -@@ -16,6 +17,8 @@ public class NearestItemSensor extends Sensor { +@@ -16,6 +16,12 @@ public class NearestItemSensor extends Sensor { private static final long Y_RANGE = 16L; public static final int MAX_DISTANCE_TO_WANTED_ITEM = 32; ++ // Leaf start - Smart sort items in NearestItemSensor + private final org.dreeam.leaf.util.FastBitRadixSort itemSorter; -+ public NearestItemSensor() {this.itemSorter = new org.dreeam.leaf.util.FastBitRadixSort();} ++ public NearestItemSensor() { ++ this.itemSorter = new org.dreeam.leaf.util.FastBitRadixSort(); ++ } ++ // Leaf end - Smart sort items in NearestItemSensor @Override public Set> requires() { return ImmutableSet.of(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM); -@@ -24,12 +27,13 @@ public class NearestItemSensor extends Sensor { - @Override +@@ -25,10 +31,10 @@ public class NearestItemSensor extends Sensor { protected void doTick(ServerLevel level, Mob entity) { Brain brain = entity.getBrain(); -- List entitiesOfClass = level.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(32.0, 16.0, 32.0), itemEntity -> itemEntity.closerThan(entity, MAX_DISTANCE_TO_WANTED_ITEM) && entity.wantsToPickUp(level, itemEntity.getItem())); // Paper - Perf: Move predicate into getEntities + List entitiesOfClass = level.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(32.0, 16.0, 32.0), itemEntity -> itemEntity.closerThan(entity, MAX_DISTANCE_TO_WANTED_ITEM) && entity.wantsToPickUp(level, itemEntity.getItem())); // Paper - Perf: Move predicate into getEntities - entitiesOfClass.sort(Comparator.comparingDouble(entity::distanceToSqr)); -+ List entitiesOfClass = level.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(32.0, 16.0, 32.0), itemEntity -> itemEntity.closerThan(entity, MAX_DISTANCE_TO_WANTED_ITEM) && entity.wantsToPickUp(level, itemEntity.getItem())); -+ ItemEntity[] sortedItems = this.itemSorter.sort(entitiesOfClass, entity, ItemEntity.class); -+ ++ ItemEntity[] sortedItems = this.itemSorter.sort(entitiesOfClass, entity, ItemEntity.class); // Leaf - Smart sort items in NearestItemSensor // Paper start - Perf: remove streams from hot code ItemEntity nearest = null; - for (final ItemEntity itemEntity : entitiesOfClass) { -- if (entity.hasLineOfSight(itemEntity)) { // Paper - Perf: Move predicate into getEntities -+ for (final ItemEntity itemEntity : sortedItems) { -+ if (entity.hasLineOfSight(itemEntity)) { ++ for (final ItemEntity itemEntity : sortedItems) { // Leaf - Smart sort items in NearestItemSensor + if (entity.hasLineOfSight(itemEntity)) { // Paper - Perf: Move predicate into getEntities nearest = itemEntity; break; - } diff --git a/leaf-server/minecraft-patches/features/0172-Remove-streams-in-MobSensor.patch b/leaf-server/minecraft-patches/features/0172-Remove-streams-in-MobSensor.patch index 40643cb2..3c2dcbd5 100644 --- a/leaf-server/minecraft-patches/features/0172-Remove-streams-in-MobSensor.patch +++ b/leaf-server/minecraft-patches/features/0172-Remove-streams-in-MobSensor.patch @@ -5,22 +5,25 @@ Subject: [PATCH] Remove streams in MobSensor diff --git a/net/minecraft/world/entity/ai/sensing/MobSensor.java b/net/minecraft/world/entity/ai/sensing/MobSensor.java -index bda210b4809a5aade7ab4d0f26fdda4d5f53f619..18c7fe0b39b366d3ac4fd83415953c063e5c562f 100644 +index bda210b4809a5aade7ab4d0f26fdda4d5f53f619..2271196768bfc90626e007a70602f818c832e348 100644 --- a/net/minecraft/world/entity/ai/sensing/MobSensor.java +++ b/net/minecraft/world/entity/ai/sensing/MobSensor.java -@@ -40,7 +40,14 @@ public class MobSensor extends Sensor { +@@ -40,10 +40,15 @@ public class MobSensor extends Sensor { public void checkForMobsNearby(T sensingEntity) { Optional> memory = sensingEntity.getBrain().getMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES); if (!memory.isEmpty()) { - boolean flag = memory.get().stream().anyMatch(livingEntity -> this.mobTest.test(sensingEntity, livingEntity)); -+ boolean flag = false; +- if (flag) { +- this.mobDetected(sensingEntity); ++ // Leaf start - Remove streams in MobSensor + List entities = memory.get(); + for (LivingEntity livingEntity : entities) { + if (this.mobTest.test(sensingEntity, livingEntity)) { -+ flag = true; ++ this.mobDetected(sensingEntity); + break; + } -+ } - if (flag) { - this.mobDetected(sensingEntity); } ++ // Leaf end - Remove streams in MobSensor + } + } + diff --git a/leaf-server/minecraft-patches/features/0173-Remove-streams-in-TemptingSensor.patch b/leaf-server/minecraft-patches/features/0173-Remove-streams-in-TemptingSensor.patch index f6ec76a7..22bd01c0 100644 --- a/leaf-server/minecraft-patches/features/0173-Remove-streams-in-TemptingSensor.patch +++ b/leaf-server/minecraft-patches/features/0173-Remove-streams-in-TemptingSensor.patch @@ -5,25 +5,10 @@ Subject: [PATCH] Remove streams in TemptingSensor diff --git a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java -index 4b3ba795bc18417f983600f1edbc1895ccb7deab..48fef89a7a3286c17a56a842fa44b80797971d2f 100644 +index 4b3ba795bc18417f983600f1edbc1895ccb7deab..16bec10543419b3010af414f1b6d12068c3a4ea7 100644 --- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java +++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java -@@ -1,12 +1,13 @@ - package net.minecraft.world.entity.ai.sensing; - - import com.google.common.collect.ImmutableSet; -+import java.util.ArrayList; - import java.util.Comparator; - import java.util.List; - import java.util.Set; - import java.util.function.Predicate; --import java.util.stream.Collectors; - import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; - import net.minecraft.world.entity.EntitySelector; - import net.minecraft.world.entity.PathfinderMob; - import net.minecraft.world.entity.ai.Brain; -@@ -36,14 +37,21 @@ public class TemptingSensor extends Sensor { +@@ -36,15 +36,21 @@ public class TemptingSensor extends Sensor { protected void doTick(ServerLevel level, PathfinderMob entity) { Brain brain = entity.getBrain(); TargetingConditions targetingConditions = TEMPT_TARGETING.copy().range((float)entity.getAttributeValue(Attributes.TEMPT_RANGE)); @@ -35,10 +20,9 @@ index 4b3ba795bc18417f983600f1edbc1895ccb7deab..48fef89a7a3286c17a56a842fa44b807 - .filter(serverPlayer -> !entity.hasPassenger(serverPlayer)) - .sorted(Comparator.comparingDouble(entity::distanceToSqr)) - .collect(Collectors.toList()); -+ -+ List allPlayers = level.players(); -+ List list = new ArrayList<>(); -+ ++ // Leaf start - Remove streams in TemptingSensor ++ List allPlayers = level.players(); ++ List list = new java.util.ArrayList<>(); + for (Player serverPlayer : allPlayers) { + if (EntitySelector.NO_SPECTATORS.test(serverPlayer) && + targetingConditions.test(level, entity, serverPlayer) && @@ -47,9 +31,10 @@ index 4b3ba795bc18417f983600f1edbc1895ccb7deab..48fef89a7a3286c17a56a842fa44b807 + list.add(serverPlayer); + } + } -+ -+ list.sort(Comparator.comparingDouble(entity::distanceToSqr)); ++ // Leaf end - Remove streams in TemptingSensor + if (!list.isEmpty()) { ++ list.sort(Comparator.comparingDouble(entity::distanceToSqr)); // Leaf - Remove streams in TemptingSensor Player player = list.get(0); // CraftBukkit start + EntityTargetLivingEntityEvent event = CraftEventFactory.callEntityTargetLivingEvent(entity, player, EntityTargetEvent.TargetReason.TEMPT); diff --git a/leaf-server/minecraft-patches/features/0175-Use-HashedList-on-WeightedRandomList.patch b/leaf-server/minecraft-patches/features/0174-Use-HashedList-on-WeightedRandomList.patch similarity index 56% rename from leaf-server/minecraft-patches/features/0175-Use-HashedList-on-WeightedRandomList.patch rename to leaf-server/minecraft-patches/features/0174-Use-HashedList-on-WeightedRandomList.patch index 4508b07c..9e32b823 100644 --- a/leaf-server/minecraft-patches/features/0175-Use-HashedList-on-WeightedRandomList.patch +++ b/leaf-server/minecraft-patches/features/0174-Use-HashedList-on-WeightedRandomList.patch @@ -5,39 +5,28 @@ Subject: [PATCH] Use HashedList on WeightedRandomList diff --git a/net/minecraft/util/random/WeightedRandomList.java b/net/minecraft/util/random/WeightedRandomList.java -index d81648b9159b765ea3ff99abd46c065ac7f08d6b..76678beea53dac2fa7c394e97a6616a32ac08a64 100644 +index d81648b9159b765ea3ff99abd46c065ac7f08d6b..dc141f55f2df22b49b7db034cad9a2f57f6b8731 100644 --- a/net/minecraft/util/random/WeightedRandomList.java +++ b/net/minecraft/util/random/WeightedRandomList.java -@@ -2,6 +2,8 @@ package net.minecraft.util.random; - - import com.google.common.collect.ImmutableList; - import com.mojang.serialization.Codec; -+ -+import java.util.Collections; - import java.util.List; - import java.util.Objects; - import java.util.Optional; -@@ -11,10 +13,12 @@ import net.minecraft.util.RandomSource; +@@ -11,10 +11,12 @@ import net.minecraft.util.RandomSource; public class WeightedRandomList { private final int totalWeight; private final ImmutableList items; -+ private List entryHashList; ++ private List entryHashList; // Leaf - Use HashedList on WeightedRandomList WeightedRandomList(List items) { this.items = ImmutableList.copyOf(items); this.totalWeight = WeightedRandom.getTotalWeight(items); -+ this.entryHashList = this.items.size() > 4 ? this.items : Collections.unmodifiableList(new org.dreeam.leaf.util.list.HashedReferenceList(this.items)); ++ this.entryHashList = this.items.size() > 4 ? this.items : java.util.Collections.unmodifiableList(new org.dreeam.leaf.util.list.HashedReferenceList<>(this.items)); // Leaf - Use HashedList on WeightedRandomList } public static WeightedRandomList create() { -@@ -43,9 +47,7 @@ public class WeightedRandomList { - } +@@ -44,7 +46,7 @@ public class WeightedRandomList { } -- public List unwrap() { + public List unwrap() { - return this.items; -- } -+ public List unwrap() {return this.entryHashList;} ++ return this.entryHashList; // Leaf - Use HashedList on WeightedRandomList + } public static Codec> codec(Codec elementCodec) { - return elementCodec.listOf().xmap(WeightedRandomList::create, WeightedRandomList::unwrap); diff --git a/leaf-server/minecraft-patches/features/0176-Add-configurable-death-item-drop-knockback-settings.patch b/leaf-server/minecraft-patches/features/0175-Add-configurable-death-item-drop-knockback-settings.patch similarity index 80% rename from leaf-server/minecraft-patches/features/0176-Add-configurable-death-item-drop-knockback-settings.patch rename to leaf-server/minecraft-patches/features/0175-Add-configurable-death-item-drop-knockback-settings.patch index 4dfe585c..3e1c19dd 100644 --- a/leaf-server/minecraft-patches/features/0176-Add-configurable-death-item-drop-knockback-settings.patch +++ b/leaf-server/minecraft-patches/features/0175-Add-configurable-death-item-drop-knockback-settings.patch @@ -5,27 +5,27 @@ Subject: [PATCH] Add configurable death item drop knockback settings diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index f5afaaa8db28295425ff3c6db73917210eadc3ca..84d105c714c7cf2c015fb847740e25bb51f6d177 100644 +index 4275caa2b4d636f646f185d67e1cdbc194bd68aa..cacceac0ee28fc045e97c0d062729390b51c4794 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1096,7 +1096,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1099,7 +1099,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc if (!keepInventory) { for (ItemStack item : this.getInventory().getContents()) { if (!item.isEmpty() && !EnchantmentHelper.has(item, net.minecraft.world.item.enchantment.EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)) { - loot.add(new DefaultDrop(item, stack -> this.drop(stack, true, false, false))); // Paper - Restore vanilla drops behavior; drop function taken from Inventory#dropAll (don't fire drop event) -+ loot.add(new DefaultDrop(item, stack -> this.drop(stack, org.dreeam.leaf.config.modules.gameplay.DeathItemDropKnockback.dropAround, false, false))); // Paper - Restore vanilla drops behavior; drop function taken from Inventory#dropAll (don't fire drop event) ++ loot.add(new DefaultDrop(item, stack -> this.drop(stack, org.dreeam.leaf.config.modules.gameplay.DeathItemDropKnockback.dropAround, false, false))); // Paper - Restore vanilla drops behavior; drop function taken from Inventory#dropAll (don't fire drop event) // Leaf - Add configurable death item drop knockback settings } } } -@@ -2849,9 +2849,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -2852,9 +2852,9 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc } if (dropAround) { - float f = this.random.nextFloat() * 0.5F; -+ float f = this.random.nextFloat() * (float) org.dreeam.leaf.config.modules.gameplay.DeathItemDropKnockback.horizontalForce; ++ float f = this.random.nextFloat() * (float) org.dreeam.leaf.config.modules.gameplay.DeathItemDropKnockback.horizontalForce; // Leaf - Add configurable death item drop knockback settings float f1 = this.random.nextFloat() * (float) (Math.PI * 2); - itemEntity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f); -+ itemEntity.setDeltaMovement(-Mth.sin(f1) * f, (float) org.dreeam.leaf.config.modules.gameplay.DeathItemDropKnockback.verticalForce, Mth.cos(f1) * f); ++ itemEntity.setDeltaMovement(-Mth.sin(f1) * f, (float) org.dreeam.leaf.config.modules.gameplay.DeathItemDropKnockback.verticalForce, Mth.cos(f1) * f); // Leaf - Add configurable death item drop knockback settings } else { float f = 0.3F; float f1 = Mth.sin(this.getXRot() * (float) (Math.PI / 180.0)); diff --git a/leaf-server/minecraft-patches/features/0177-optimize-AttributeMap.patch b/leaf-server/minecraft-patches/features/0176-Optimize-AttributeMap.patch similarity index 80% rename from leaf-server/minecraft-patches/features/0177-optimize-AttributeMap.patch rename to leaf-server/minecraft-patches/features/0176-Optimize-AttributeMap.patch index 4c3257d5..da4562d9 100644 --- a/leaf-server/minecraft-patches/features/0177-optimize-AttributeMap.patch +++ b/leaf-server/minecraft-patches/features/0176-Optimize-AttributeMap.patch @@ -1,31 +1,31 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Thu, 15 May 2025 21:11:18 +0900 -Subject: [PATCH] optimize AttributeMap +Subject: [PATCH] Optimize AttributeMap diff --git a/net/minecraft/world/entity/ai/attributes/Attribute.java b/net/minecraft/world/entity/ai/attributes/Attribute.java -index f8419dde44ebc7324e783f8bee42132d5ec973c3..1c52a118bad6b4b8abdf2527347ef66888b71f54 100644 +index f8419dde44ebc7324e783f8bee42132d5ec973c3..406767c60ec1a324faaf5d3658b161647497f99b 100644 --- a/net/minecraft/world/entity/ai/attributes/Attribute.java +++ b/net/minecraft/world/entity/ai/attributes/Attribute.java @@ -16,10 +16,15 @@ public class Attribute { private boolean syncable; private final String descriptionId; private Attribute.Sentiment sentiment = Attribute.Sentiment.POSITIVE; -+ // Leaf start - optimize AttributeMap ++ // Leaf start - Optimize AttributeMap + public final int uid; + private static final java.util.concurrent.atomic.AtomicInteger SIZE = new java.util.concurrent.atomic.AtomicInteger(); -+ // Leaf end - optimize AttributeMap ++ // Leaf end - Optimize AttributeMap protected Attribute(String descriptionId, double defaultValue) { this.defaultValue = defaultValue; this.descriptionId = descriptionId; -+ this.uid = SIZE.getAndAdd(1); // Leaf - optimize AttributeMap ++ this.uid = SIZE.getAndAdd(1); // Leaf - Optimize AttributeMap } public double getDefaultValue() { diff --git a/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/net/minecraft/world/entity/ai/attributes/AttributeMap.java -index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..19f7119256ac50ba8db961f179d3fabb9263944e 100644 +index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..51a5a3a804a1cbb0e1d23be432043552b102d837 100644 --- a/net/minecraft/world/entity/ai/attributes/AttributeMap.java +++ b/net/minecraft/world/entity/ai/attributes/AttributeMap.java @@ -20,12 +20,12 @@ import org.slf4j.Logger; @@ -33,13 +33,13 @@ index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..19f7119256ac50ba8db961f179d3fabb private static final Logger LOGGER = LogUtils.getLogger(); // Gale start - Lithium - replace AI attributes with optimized collections - private final Map, AttributeInstance> attributes = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0); -+ private final Map, AttributeInstance> attributes = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(); // Leaf - optimize AttributeMap ++ private final Map, AttributeInstance> attributes = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(); // Leaf - Optimize AttributeMap private final Set attributesToSync = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0); private final Set attributesToUpdate = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0); // Gale end - Lithium - replace AI attributes with optimized collections private final AttributeSupplier supplier; - private final java.util.function.Function, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations -+ // private final java.util.function.Function, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations ++ //private final java.util.function.Function, AttributeInstance> createInstance; // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap private final net.minecraft.world.entity.LivingEntity entity; // Purpur - Ridables public AttributeMap(AttributeSupplier supplier) { @@ -48,7 +48,7 @@ index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..19f7119256ac50ba8db961f179d3fabb // Purpur end - Ridables this.supplier = defaultAttributes; - this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations -+ // this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations ++ //this.createInstance = holder -> this.supplier.createInstance(this::onAttributeModified, holder); // Gale - Airplane - reduce entity allocations // Leaf - Optimize AttributeMap } private void onAttributeModified(AttributeInstance instance) { @@ -57,7 +57,7 @@ index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..19f7119256ac50ba8db961f179d3fabb @Nullable public AttributeInstance getInstance(Holder attribute) { - return this.attributes.computeIfAbsent(attribute, this.createInstance); // Gale - Airplane - reduce entity allocations - cache lambda, as for some reason java allocates it anyways -+ // Leaf start - optimize AttributeMap ++ // Leaf start - Optimize AttributeMap + AttributeInstance v; + if ((v = this.attributes.get(attribute)) == null) { + AttributeInstance newValue; @@ -67,12 +67,12 @@ index 89f4c5b2d61e27acd48063f9f24ce9ea91898b8b..19f7119256ac50ba8db961f179d3fabb + } + } + return v; -+ // Leaf end - optimize AttributeMap ++ // Leaf end - Optimize AttributeMap } public boolean hasAttribute(Holder attribute) { diff --git a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java -index 24710041ccbc70e5506d8d89ae34f0141977f209..608edf272735d356215cf0147e65dcef391e1638 100644 +index 24710041ccbc70e5506d8d89ae34f0141977f209..09341ef6c651150aba223689badbead490162b2b 100644 --- a/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java +++ b/net/minecraft/world/entity/ai/attributes/AttributeSupplier.java @@ -11,7 +11,7 @@ public class AttributeSupplier { @@ -80,7 +80,7 @@ index 24710041ccbc70e5506d8d89ae34f0141977f209..608edf272735d356215cf0147e65dcef AttributeSupplier(Map, AttributeInstance> instances) { - this.instances = instances; -+ this.instances = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(instances); // Leaf - optimize AttributeMap ++ this.instances = new org.dreeam.leaf.util.map.AttributeInstanceArrayMap(instances); // Leaf - Optimize AttributeMap } public AttributeInstance getAttributeInstance(Holder attribute) { diff --git a/leaf-server/minecraft-patches/features/0178-optimize-getScaledTrackingDistance.patch b/leaf-server/minecraft-patches/features/0177-Optimize-getScaledTrackingDistance.patch similarity index 76% rename from leaf-server/minecraft-patches/features/0178-optimize-getScaledTrackingDistance.patch rename to leaf-server/minecraft-patches/features/0177-Optimize-getScaledTrackingDistance.patch index be9b6476..7f8ac17e 100644 --- a/leaf-server/minecraft-patches/features/0178-optimize-getScaledTrackingDistance.patch +++ b/leaf-server/minecraft-patches/features/0177-Optimize-getScaledTrackingDistance.patch @@ -1,11 +1,11 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 17 May 2025 19:01:50 +0900 -Subject: [PATCH] optimize getScaledTrackingDistance +Subject: [PATCH] Optimize getScaledTrackingDistance diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index eb0589b203bcf72cd24bb37f2c448c23cb8d6f2b..a1ec070b8620ba34bae9103f19307f42e6ed2a7c 100644 +index eb0589b203bcf72cd24bb37f2c448c23cb8d6f2b..a54f9030c81a2eb36f4dae951b09a9a6057be936 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java @@ -838,7 +838,13 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @@ -13,13 +13,13 @@ index eb0589b203bcf72cd24bb37f2c448c23cb8d6f2b..a1ec070b8620ba34bae9103f19307f42 @Override public int getScaledTrackingDistance(int trackingDistance) { - return this.getProperties().entityBroadcastRangePercentage * trackingDistance / 100; -+ // Leaf start ++ // Leaf start - Optimize getScaledTrackingDistance + int p = this.getProperties().entityBroadcastRangePercentage; + if (p == 100) { + return trackingDistance; + } + return p * trackingDistance / 100; -+ // Leaf end ++ // Leaf end - Optimize getScaledTrackingDistance } @Override diff --git a/leaf-server/minecraft-patches/features/0179-optimize-SynchedEntityData-packDirty.patch b/leaf-server/minecraft-patches/features/0178-Optimize-SynchedEntityData-packDirty.patch similarity index 78% rename from leaf-server/minecraft-patches/features/0179-optimize-SynchedEntityData-packDirty.patch rename to leaf-server/minecraft-patches/features/0178-Optimize-SynchedEntityData-packDirty.patch index bbfe075e..324a6646 100644 --- a/leaf-server/minecraft-patches/features/0179-optimize-SynchedEntityData-packDirty.patch +++ b/leaf-server/minecraft-patches/features/0178-Optimize-SynchedEntityData-packDirty.patch @@ -1,11 +1,11 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Sat, 17 May 2025 19:03:31 +0900 -Subject: [PATCH] optimize SynchedEntityData#packDirty +Subject: [PATCH] Optimize SynchedEntityData#packDirty diff --git a/net/minecraft/network/syncher/SynchedEntityData.java b/net/minecraft/network/syncher/SynchedEntityData.java -index 3d90f9f1ac1bd281edf6bb0f93ea821657d5bd2f..546c36d0bc14b8db49245ff162be3dbc4d680da6 100644 +index 3d90f9f1ac1bd281edf6bb0f93ea821657d5bd2f..f0b8d44009ebfaf7a45f9cbaea5dc3ff157815fc 100644 --- a/net/minecraft/network/syncher/SynchedEntityData.java +++ b/net/minecraft/network/syncher/SynchedEntityData.java @@ -84,7 +84,15 @@ public class SynchedEntityData { @@ -13,7 +13,7 @@ index 3d90f9f1ac1bd281edf6bb0f93ea821657d5bd2f..546c36d0bc14b8db49245ff162be3dbc } else { this.isDirty = false; - List> list = new ArrayList<>(); -+ // Leaf start ++ // Leaf start - Optimize SynchedEntityData#packDirty + int cap = 0; + for (SynchedEntityData.DataItem dataItem : this.itemsById) { + if (dataItem.isDirty()) { @@ -21,7 +21,7 @@ index 3d90f9f1ac1bd281edf6bb0f93ea821657d5bd2f..546c36d0bc14b8db49245ff162be3dbc + } + } + ArrayList> list = new ArrayList<>(cap); -+ // Leaf end ++ // Leaf end - Optimize SynchedEntityData#packDirty for (SynchedEntityData.DataItem dataItem : this.itemsById) { if (dataItem.isDirty()) { diff --git a/leaf-server/minecraft-patches/features/0174-paw-optimization.patch b/leaf-server/minecraft-patches/features/0179-Paw-optimization.patch similarity index 98% rename from leaf-server/minecraft-patches/features/0174-paw-optimization.patch rename to leaf-server/minecraft-patches/features/0179-Paw-optimization.patch index 48fb02b4..f64e4834 100644 --- a/leaf-server/minecraft-patches/features/0174-paw-optimization.patch +++ b/leaf-server/minecraft-patches/features/0179-Paw-optimization.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Thu, 24 Apr 2025 16:36:16 -0400 -Subject: [PATCH] paw optimization +Subject: [PATCH] Paw optimization Some random optimizations @@ -10,10 +10,10 @@ Some random optimizations - Secret patches (WIP) diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java -index 3a82e1e510029576485427af9fd705b37c5f6e20..32f26640664135c9f7f45f8b204b7ff412fe343e 100644 +index c83ee2137a57e62003b1d20c3ceea9f569350a53..de1f271d36c7daa10c398e146386b51e2622df9a 100644 --- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java -@@ -661,13 +661,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -660,13 +660,7 @@ public class Connection extends SimpleChannelInboundHandler> { if (!(this.packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener) || loginPacketListener.state != net.minecraft.server.network.ServerLoginPacketListenerImpl.State.VERIFYING || Connection.joinAttemptsThisTick++ < MAX_PER_TICK) { diff --git a/leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch b/leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch index 832c367a..2d96ec10 100644 --- a/leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch +++ b/leaf-server/paper-patches/features/0024-Multithreaded-Tracker.patch @@ -49,7 +49,7 @@ index edcd209798740f31cb302f36d7864a0d8ea1d561..e2444cc9e28dd432bf3351066b140810 if (entityTracker != null) { - for (ServerPlayerConnection connection : entityTracker.seenBy) { -+ for (ServerPlayerConnection connection : entityTracker.seenBy()) { // Leaf ++ for (ServerPlayerConnection connection : entityTracker.seenBy()) { // Leaf - Multithreaded tracker players.add(connection.getPlayer().getBukkitEntity()); } } @@ -58,7 +58,7 @@ index edcd209798740f31cb302f36d7864a0d8ea1d561..e2444cc9e28dd432bf3351066b140810 // Paper start - resend possibly desynced entity instead of add entity packet - for (final ServerPlayerConnection connection : entityTracker.seenBy) { -+ for (final ServerPlayerConnection connection : entityTracker.seenBy()) { // Leaf ++ for (final ServerPlayerConnection connection : entityTracker.seenBy()) { // Leaf - Multithreaded tracker this.getHandle().resendPossiblyDesyncedEntityData(connection.getPlayer()); } // Paper end - resend possibly desynced entity instead of add entity packet @@ -67,7 +67,7 @@ index edcd209798740f31cb302f36d7864a0d8ea1d561..e2444cc9e28dd432bf3351066b140810 Set set = new java.util.HashSet<>(tracker.seenBy.size()); - for (net.minecraft.server.network.ServerPlayerConnection connection : tracker.seenBy) { -+ for (net.minecraft.server.network.ServerPlayerConnection connection : tracker.seenBy()) { // Leaf ++ for (net.minecraft.server.network.ServerPlayerConnection connection : tracker.seenBy()) { // Leaf - Multithreaded tracker set.add(connection.getPlayer().getBukkitEntity().getPlayer()); } return set; diff --git a/leaf-server/paper-patches/features/0036-async-chunk-send.patch b/leaf-server/paper-patches/features/0036-Async-chunk-send.patch similarity index 96% rename from leaf-server/paper-patches/features/0036-async-chunk-send.patch rename to leaf-server/paper-patches/features/0036-Async-chunk-send.patch index a0008705..68e26cf6 100644 --- a/leaf-server/paper-patches/features/0036-async-chunk-send.patch +++ b/leaf-server/paper-patches/features/0036-Async-chunk-send.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: hayanesuru Date: Fri, 2 May 2025 18:22:24 -0700 -Subject: [PATCH] async chunk send +Subject: [PATCH] Async chunk send diff --git a/src/main/java/io/papermc/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/io/papermc/paper/antixray/ChunkPacketBlockControllerAntiXray.java diff --git a/leaf-server/paper-patches/features/0037-Optimise-player-movement-checks.patch b/leaf-server/paper-patches/features/0037-Optimise-player-movement-checks.patch index e28034f5..ead9dd25 100644 --- a/leaf-server/paper-patches/features/0037-Optimise-player-movement-checks.patch +++ b/leaf-server/paper-patches/features/0037-Optimise-player-movement-checks.patch @@ -5,16 +5,18 @@ Subject: [PATCH] Optimise player movement checks diff --git a/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java b/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java -index 94689e0342cf95dbedec955d67c95fa07a219678..26e4fe123c84e63ae4808facc33d6bbe94fc3133 100644 +index 94689e0342cf95dbedec955d67c95fa07a219678..8a888d52495bd6f447b8d767ca80de20dfee66b9 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/misc/SingleUserAreaMap.java -@@ -88,6 +88,9 @@ public abstract class SingleUserAreaMap { +@@ -88,6 +88,11 @@ public abstract class SingleUserAreaMap { if (fromX == NOT_SET) { return false; } ++ // Leaf start - Optimise player movement checks + if (org.dreeam.leaf.config.modules.opt.OptimizePlayerMovementProcessing.enabled && fromX == toX && fromZ == toZ && oldViewDistance == newViewDistance) { + return true; + } ++ // Leaf end - Optimise player movement checks this.lastChunkX = toX; this.lastChunkZ = toZ; diff --git a/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSend.java b/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSend.java index d64f225d..d5fcecaf 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSend.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSend.java @@ -10,6 +10,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class AsyncChunkSend { + public static final ExecutorService POOL = new ThreadPoolExecutor( 1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), diff --git a/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSendThread.java b/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSendThread.java index 7e9f8bcb..4dae48a5 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSendThread.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/async/chunk/AsyncChunkSendThread.java @@ -1,6 +1,7 @@ package org.dreeam.leaf.async.chunk; public class AsyncChunkSendThread extends Thread { + protected AsyncChunkSendThread(Runnable task) { super(task); } diff --git a/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/MultithreadedTracker.java b/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/MultithreadedTracker.java index 9d78ac41..851067ab 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/MultithreadedTracker.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/async/tracker/MultithreadedTracker.java @@ -19,7 +19,6 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; @@ -191,11 +190,11 @@ public class MultithreadedTracker { private static @NotNull ThreadFactory getThreadFactory() { return new ThreadFactoryBuilder() - .setThreadFactory(MultithreadedTrackerThread::new) - .setNameFormat(THREAD_PREFIX + " Thread - %d") - .setPriority(Thread.NORM_PRIORITY - 2) - .setUncaughtExceptionHandler(Util::onThreadException) - .build(); + .setThreadFactory(MultithreadedTrackerThread::new) + .setNameFormat(THREAD_PREFIX + " Thread - %d") + .setPriority(Thread.NORM_PRIORITY - 2) + .setUncaughtExceptionHandler(Util::onThreadException) + .build(); } private static @NotNull RejectedExecutionHandler getRejectedPolicy() { diff --git a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/network/AlternativeJoin.java b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/network/AlternativeJoin.java index 46f1154a..8176ce30 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/network/AlternativeJoin.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/network/AlternativeJoin.java @@ -14,7 +14,7 @@ public class AlternativeJoin extends ConfigModules { @Override public void onLoaded() { enabled = config.getBoolean(getBasePath() + ".async-switch-state", enabled, config.pickStringRegionBased( - "Async switch connection state", - "...")); + "Async switch connection state.", + "异步切换连接状态.")); } } diff --git a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeItemTicking.java b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeItemTicking.java index 5de82881..ea153f1f 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeItemTicking.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeItemTicking.java @@ -14,8 +14,8 @@ public class OptimizeItemTicking extends ConfigModules { @Override public void onLoaded() { onlyTickItemsInHand = config.getBoolean(getBasePath() + ".only-tick-items-in-hand", onlyTickItemsInHand, config.pickStringRegionBased(""" - Whether to only tick/update items in main hand and offhand instead of the entire inventory.""", + Whether to only tick / update items in main hand and offhand instead of the entire inventory.""", """ - 是否只对主手和副手中的物品进行tick/更新,而不是整个物品栏中的所有物品。""")); + 是否只对主手和副手中的物品进行 tick / 更新,而不是整个物品栏中的所有物品。""")); } } diff --git a/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollPackets.java b/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollPackets.java index 458f12c2..7aebf5b6 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollPackets.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollPackets.java @@ -8,6 +8,7 @@ import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.NotNull; public class DoABarrelRollPackets { + private static LeafCustomPayload.@NotNull Type createType(String path) { return new LeafCustomPayload.Type<>(ResourceLocation.fromNamespaceAndPath(DoABarrelRollProtocol.NAMESPACE, path)); } diff --git a/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollProtocol.java b/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollProtocol.java index 48c2a35d..af88f866 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollProtocol.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/protocol/DoABarrelRollProtocol.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.OptionalInt; public class DoABarrelRollProtocol implements Protocol { + protected static final String NAMESPACE = "do_a_barrel_roll"; private static final Logger LOGGER = LogManager.getLogger(NAMESPACE); private static final int PROTOCOL_VERSION = 4; diff --git a/leaf-server/src/main/java/org/dreeam/leaf/protocol/LeafCustomPayload.java b/leaf-server/src/main/java/org/dreeam/leaf/protocol/LeafCustomPayload.java index 54ca72eb..3894dfa8 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/protocol/LeafCustomPayload.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/protocol/LeafCustomPayload.java @@ -4,6 +4,7 @@ import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import org.jetbrains.annotations.NotNull; public interface LeafCustomPayload extends CustomPacketPayload { + @NotNull @Override Type type(); diff --git a/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocol.java b/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocol.java index fdedc410..61c5c529 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocol.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocol.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.NotNull; import java.util.List; interface Protocol { + String namespace(); List> c2s(); diff --git a/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocols.java b/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocols.java index 4a54b998..000b6f93 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocols.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/protocol/Protocols.java @@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class Protocols { + private static final ObjectArrayList PROTOCOLS = new ObjectArrayList<>(); static void register(Protocol protocol) { diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/list/HashedReferenceList.java b/leaf-server/src/main/java/org/dreeam/leaf/util/list/HashedReferenceList.java index 9887bd89..3a905e30 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/list/HashedReferenceList.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/list/HashedReferenceList.java @@ -15,8 +15,8 @@ import java.util.NoSuchElementException; * A List implementation that maintains a hash-based counter for O(1) element lookup. * Combines an array-based list for order with a hash map for fast containment checks. */ -public class HashedReferenceList - implements List { +public class HashedReferenceList implements List { + // The actual ordered storage of elements private final ReferenceArrayList list = new ReferenceArrayList<>(); // Tracks occurrence count of each element for O(1) contains checks diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java b/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java index b1fa9212..9d4619c2 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java @@ -10,8 +10,9 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.AbstractMap.SimpleEntry; -/// fast array backend map with O(1) get & put & remove +// fast array backend map with O(1) get & put & remove public class AttributeInstanceArrayMap implements Map, AttributeInstance>, Cloneable { + private int size = 0; private transient AttributeInstance[] a = new AttributeInstance[32]; private transient KeySet keys;