diff --git a/patches/server/0007-Pufferfish-Dynamic-Activation-of-Brain.patch b/patches/server/0006-Pufferfish-Dynamic-Activation-of-Brain.patch similarity index 100% rename from patches/server/0007-Pufferfish-Dynamic-Activation-of-Brain.patch rename to patches/server/0006-Pufferfish-Dynamic-Activation-of-Brain.patch diff --git a/patches/server/0008-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch b/patches/server/0007-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch similarity index 100% rename from patches/server/0008-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch rename to patches/server/0007-Pufferfish-Throttle-goal-selector-during-inactive-ti.patch diff --git a/patches/server/0009-Pufferfish-Entity-TTL.patch b/patches/server/0008-Pufferfish-Entity-TTL.patch similarity index 97% rename from patches/server/0009-Pufferfish-Entity-TTL.patch rename to patches/server/0008-Pufferfish-Entity-TTL.patch index 1b3385fe..6354499b 100644 --- a/patches/server/0009-Pufferfish-Entity-TTL.patch +++ b/patches/server/0008-Pufferfish-Entity-TTL.patch @@ -7,7 +7,7 @@ Original license: GPL v3 Original project: https://github.com/pufferfish-gg/Pufferfish diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index bdd61610c9f1c380a8e5e068a5ad85dea86c26b9..109106fb93dd2b05363a1d89d38a9ccf09ae5195 100644 +index e4081783fb55ee1d804af3947be76d400f2834d4..e8b651e628e8ab2033dbf2ee3eb5d38ff22c9f45 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -849,6 +849,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess diff --git a/patches/server/0010-Purpur-Server-Changes.patch b/patches/server/0009-Purpur-Server-Changes.patch similarity index 99% rename from patches/server/0010-Purpur-Server-Changes.patch rename to patches/server/0009-Purpur-Server-Changes.patch index 61064a68..e57f5297 100644 --- a/patches/server/0010-Purpur-Server-Changes.patch +++ b/patches/server/0009-Purpur-Server-Changes.patch @@ -699,7 +699,7 @@ index d2ea951c7e5899d0e2edb52064e35c23965c4230..b929842514a97ca993ead608d355a4af Bootstrap.bootStrap(); Bootstrap.validate(); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e2f2bc175d94110e32b412b73528686661b79809..a94cb6810de2a7c9f1425d421e77f84c9471805a 100644 +index 208b9558d9019cd00f7ed270d2a36f9a28464e65..7f12e6fc9ff0c6f0e2659886f2cf1efb117f78d6 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -289,6 +289,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - Add EntityMoveEvent net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers worldserver.updateLagCompensationTick(); // Paper - lag compensation @@ -868,7 +868,7 @@ index 0d9de4c61c7b26a6ff37c12fde629161fd0c3d5a..2f7897744f4aea718170698881773e90 entityitem = entityplayer.drop(itemstack, false, false, false); // CraftBukkit - SPIGOT-2942: Add boolean to call event if (entityitem != null) { diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 944ada1e0f4e4a8460ec3c8e1d9a0de7469d395b..e9d6f0cdb5b1f15e1536844b6a8637f3e7d21c6f 100644 +index 42ac2efb4c84c5f15c10934f928183962f179626..ca31ceb08099324df560bfc4f7888a509ad75307 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -118,6 +118,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @@ -926,10 +926,10 @@ index 944ada1e0f4e4a8460ec3c8e1d9a0de7469d395b..e9d6f0cdb5b1f15e1536844b6a8637f3 // CraftBukkit start // this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); // Spigot - moved up -@@ -374,6 +408,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -373,6 +407,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + DedicatedServer.LOGGER.info("JMX monitoring enabled"); } - if (org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled) mobSpawnExecutor.start(); // Pufferfish + org.purpurmc.purpur.task.BossBarTask.startAll(); // Purpur + if (org.purpurmc.purpur.PurpurConfig.beeCountPayload) org.purpurmc.purpur.task.BeehiveTask.instance().register(); // Purpur return true; diff --git a/patches/server/0011-Fix-Pufferfish-and-Purpur-patches.patch b/patches/server/0010-Fix-Pufferfish-and-Purpur-patches.patch similarity index 95% rename from patches/server/0011-Fix-Pufferfish-and-Purpur-patches.patch rename to patches/server/0010-Fix-Pufferfish-and-Purpur-patches.patch index 9ac424b1..99cc5d6d 100644 --- a/patches/server/0011-Fix-Pufferfish-and-Purpur-patches.patch +++ b/patches/server/0010-Fix-Pufferfish-and-Purpur-patches.patch @@ -27,7 +27,7 @@ index e94224ed280247ee69dfdff8dc960f2b8729be33..5b9725a9a81c0850dc2809c150529e5f for (Component component : formatProviders(spigotPlugins, sender)) { // Purpur diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index a94cb6810de2a7c9f1425d421e77f84c9471805a..dfe1b32ff274f8620a953303873e046c4eeea4ec 100644 +index 7f12e6fc9ff0c6f0e2659886f2cf1efb117f78d6..ff2e76176e0c49aae4115d5c2f764dbf2926e33c 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -300,7 +300,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); -@@ -1047,6 +1047,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - rewrite chunk system +@@ -1045,6 +1047,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop list = Lists.newArrayListWithCapacity(this.chunkMap.size()); Iterator iterator = this.chunkMap.getChunks().iterator(); @@ -1182,7 +1182,7 @@ index 7cf2a31b6becffe971a2c078958f4193f322101d..58866bd00890f10f781675e636952609 while (iterator.hasNext()) { ChunkHolder playerchunk = (ChunkHolder) iterator.next(); -@@ -440,7 +431,6 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -437,7 +428,6 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon boolean flagAndHasNaturalSpawn = flag && this.anySpawnCategoryIsSpawnedThisTick(); if (flagAndHasNaturalSpawn) { // Gale end - MultiPaper - skip unnecessary mob spawning computations @@ -1190,15 +1190,15 @@ index 7cf2a31b6becffe971a2c078958f4193f322101d..58866bd00890f10f781675e636952609 int k = this.distanceManager.getNaturalSpawnChunkCount(); // Paper start - Optional per player mob spawns int naturalSpawnChunkCount = k; -@@ -469,7 +459,6 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - // Pufferfish end +@@ -461,7 +451,6 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); } // Paper end - Optional per player mob spawns - this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings - //this.lastSpawnState = spawnercreature_d; // Pufferfish - this is managed asynchronously + this.lastSpawnState = spawnercreature_d; // Gale start - MultiPaper - skip unnecessary mob spawning computations -@@ -513,19 +502,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -506,19 +495,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } } } @@ -1217,7 +1217,7 @@ index 7cf2a31b6becffe971a2c078958f4193f322101d..58866bd00890f10f781675e636952609 - this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing }); } - + } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index cb3e583ae2f5a7619455932ad1d8ee5c9e131ac1..86af09319462b58f2ec97caf7a1033b2a3ae961d 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server/0015-Bump-Dependencies.patch b/patches/server/0014-Bump-Dependencies.patch similarity index 100% rename from patches/server/0015-Bump-Dependencies.patch rename to patches/server/0014-Bump-Dependencies.patch diff --git a/patches/server/0016-Remove-vanilla-username-check.patch b/patches/server/0015-Remove-vanilla-username-check.patch similarity index 100% rename from patches/server/0016-Remove-vanilla-username-check.patch rename to patches/server/0015-Remove-vanilla-username-check.patch diff --git a/patches/server/0017-Remove-Spigot-Check-for-Broken-BungeeCord-Configurat.patch b/patches/server/0016-Remove-Spigot-Check-for-Broken-BungeeCord-Configurat.patch similarity index 100% rename from patches/server/0017-Remove-Spigot-Check-for-Broken-BungeeCord-Configurat.patch rename to patches/server/0016-Remove-Spigot-Check-for-Broken-BungeeCord-Configurat.patch diff --git a/patches/server/0018-Remove-UseItemOnPacket-Too-Far-Check.patch b/patches/server/0017-Remove-UseItemOnPacket-Too-Far-Check.patch similarity index 100% rename from patches/server/0018-Remove-UseItemOnPacket-Too-Far-Check.patch rename to patches/server/0017-Remove-UseItemOnPacket-Too-Far-Check.patch diff --git a/patches/server/0019-KTP-Allow-unknown-event-thread-execution.patch b/patches/server/0018-KTP-Allow-unknown-event-thread-execution.patch similarity index 100% rename from patches/server/0019-KTP-Allow-unknown-event-thread-execution.patch rename to patches/server/0018-KTP-Allow-unknown-event-thread-execution.patch diff --git a/patches/server/0020-KeYi-Player-Skull-API.patch b/patches/server/0019-KeYi-Player-Skull-API.patch similarity index 100% rename from patches/server/0020-KeYi-Player-Skull-API.patch rename to patches/server/0019-KeYi-Player-Skull-API.patch diff --git a/patches/server/0021-KeYi-Disable-arrow-despawn-counter-by-default.patch b/patches/server/0020-KeYi-Disable-arrow-despawn-counter-by-default.patch similarity index 100% rename from patches/server/0021-KeYi-Disable-arrow-despawn-counter-by-default.patch rename to patches/server/0020-KeYi-Disable-arrow-despawn-counter-by-default.patch diff --git a/patches/server/0022-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch b/patches/server/0021-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch similarity index 100% rename from patches/server/0022-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch rename to patches/server/0021-KeYi-Add-an-option-for-spigot-item-merging-mechanism.patch diff --git a/patches/server/0023-Carpet-Fixes-Optimized-getBiome-method.patch b/patches/server/0022-Carpet-Fixes-Optimized-getBiome-method.patch similarity index 100% rename from patches/server/0023-Carpet-Fixes-Optimized-getBiome-method.patch rename to patches/server/0022-Carpet-Fixes-Optimized-getBiome-method.patch diff --git a/patches/server/0024-Carpet-Fixes-Use-optimized-RecipeManager.patch b/patches/server/0023-Carpet-Fixes-Use-optimized-RecipeManager.patch similarity index 100% rename from patches/server/0024-Carpet-Fixes-Use-optimized-RecipeManager.patch rename to patches/server/0023-Carpet-Fixes-Use-optimized-RecipeManager.patch diff --git a/patches/server/0025-Rail-Optimization-optimized-PoweredRailBlock-logic.patch b/patches/server/0024-Rail-Optimization-optimized-PoweredRailBlock-logic.patch similarity index 100% rename from patches/server/0025-Rail-Optimization-optimized-PoweredRailBlock-logic.patch rename to patches/server/0024-Rail-Optimization-optimized-PoweredRailBlock-logic.patch diff --git a/patches/server/0026-Akarin-Save-Json-list-asynchronously.patch b/patches/server/0025-Akarin-Save-Json-list-asynchronously.patch similarity index 100% rename from patches/server/0026-Akarin-Save-Json-list-asynchronously.patch rename to patches/server/0025-Akarin-Save-Json-list-asynchronously.patch diff --git a/patches/server/0027-Slice-Smooth-Teleports.patch b/patches/server/0026-Slice-Smooth-Teleports.patch similarity index 95% rename from patches/server/0027-Slice-Smooth-Teleports.patch rename to patches/server/0026-Slice-Smooth-Teleports.patch index 4b8f8650..c56438fe 100644 --- a/patches/server/0027-Slice-Smooth-Teleports.patch +++ b/patches/server/0026-Slice-Smooth-Teleports.patch @@ -7,7 +7,7 @@ Original license: MIT Original project: https://github.com/Cryptite/Slice diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 250b23672ff509f9972ad6c91112d161b3068933..3926782762ecd3003138d8792a144b0353d4991c 100644 +index d573ae3fee994614bcc6c699bcbe8210874ca414..30f984553e823b3c928b0e2181baf5d2058c2d84 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -306,6 +306,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple @@ -36,7 +36,7 @@ index 75728fe1e02cc7042e30d954bc913fefd107ef94..5a46f2b5f2903adbb5410c509aac62a5 entityplayer1.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); entityplayer1.connection.send(new ClientboundSetExperiencePacket(entityplayer1.experienceProgress, entityplayer1.totalExperience, entityplayer1.experienceLevel)); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ee1d4d83b856b9a7eba28a6f72256bb5dc33b67b..9325d2c676899fcedc360ea9183339c91af026dc 100644 +index 7a7a2acca5980ab3d79346f47e4153dd6c98939b..cf85b3af38258fa34e8f67d1f002a521cc59c81b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1361,6 +1361,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0028-Parchment-Make-FixLight-use-action-bar.patch b/patches/server/0027-Parchment-Make-FixLight-use-action-bar.patch similarity index 100% rename from patches/server/0028-Parchment-Make-FixLight-use-action-bar.patch rename to patches/server/0027-Parchment-Make-FixLight-use-action-bar.patch diff --git a/patches/server/0029-Leaves-Server-Utils.patch b/patches/server/0028-Leaves-Server-Utils.patch similarity index 100% rename from patches/server/0029-Leaves-Server-Utils.patch rename to patches/server/0028-Leaves-Server-Utils.patch diff --git a/patches/server/0030-Leaves-Protocol-Core.patch b/patches/server/0029-Leaves-Protocol-Core.patch similarity index 99% rename from patches/server/0030-Leaves-Protocol-Core.patch rename to patches/server/0029-Leaves-Protocol-Core.patch index bad4ca71..0d649049 100644 --- a/patches/server/0030-Leaves-Protocol-Core.patch +++ b/patches/server/0029-Leaves-Protocol-Core.patch @@ -51,7 +51,7 @@ index 1967c43ee3a12e63365cc40ee6565307e2fd73cf..6e376d0db5321d8e9b6e0b54617ffd17 assert isValidPath(path); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4468ec76c0b12726313add26c2abdaaaea2691c0..8bfb77148aab03a4d031d700ee03483e125017f2 100644 +index 65d89562f96c20e20649c049370dca0ef3f059b5..36940bc192088233842d8fa7a37b84657552ceff 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1806,6 +1806,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) public static S spin(Function serverFactory) { diff --git a/patches/server/0054-SparklyPaper-Optimize-canSee-checks.patch b/patches/server/0053-SparklyPaper-Optimize-canSee-checks.patch similarity index 100% rename from patches/server/0054-SparklyPaper-Optimize-canSee-checks.patch rename to patches/server/0053-SparklyPaper-Optimize-canSee-checks.patch diff --git a/patches/server/0055-Polpot-Make-egg-and-snowball-can-knockback-player.patch b/patches/server/0054-Polpot-Make-egg-and-snowball-can-knockback-player.patch similarity index 100% rename from patches/server/0055-Polpot-Make-egg-and-snowball-can-knockback-player.patch rename to patches/server/0054-Polpot-Make-egg-and-snowball-can-knockback-player.patch diff --git a/patches/server/0056-Redirect-vanilla-getProfiler-in-PathNavigationRegion.patch b/patches/server/0055-Redirect-vanilla-getProfiler-in-PathNavigationRegion.patch similarity index 100% rename from patches/server/0056-Redirect-vanilla-getProfiler-in-PathNavigationRegion.patch rename to patches/server/0055-Redirect-vanilla-getProfiler-in-PathNavigationRegion.patch diff --git a/patches/server/0057-Fix-MC-65198.patch b/patches/server/0056-Fix-MC-65198.patch similarity index 100% rename from patches/server/0057-Fix-MC-65198.patch rename to patches/server/0056-Fix-MC-65198.patch diff --git a/patches/server/0058-Including-5s-in-getTPS.patch b/patches/server/0057-Including-5s-in-getTPS.patch similarity index 100% rename from patches/server/0058-Including-5s-in-getTPS.patch rename to patches/server/0057-Including-5s-in-getTPS.patch diff --git a/patches/server/0059-Remove-useless-creating-stats-json-bases-on-player-n.patch b/patches/server/0058-Remove-useless-creating-stats-json-bases-on-player-n.patch similarity index 100% rename from patches/server/0059-Remove-useless-creating-stats-json-bases-on-player-n.patch rename to patches/server/0058-Remove-useless-creating-stats-json-bases-on-player-n.patch diff --git a/patches/server/0060-Fix-NPE-during-creating-GUI-graph.patch b/patches/server/0059-Fix-NPE-during-creating-GUI-graph.patch similarity index 100% rename from patches/server/0060-Fix-NPE-during-creating-GUI-graph.patch rename to patches/server/0059-Fix-NPE-during-creating-GUI-graph.patch diff --git a/patches/server/0061-Don-t-throw-exception-on-missing-ResourceKey-value.patch b/patches/server/0060-Don-t-throw-exception-on-missing-ResourceKey-value.patch similarity index 100% rename from patches/server/0061-Don-t-throw-exception-on-missing-ResourceKey-value.patch rename to patches/server/0060-Don-t-throw-exception-on-missing-ResourceKey-value.patch diff --git a/patches/server/0062-Improve-Purpur-AFK-system.patch b/patches/server/0061-Improve-Purpur-AFK-system.patch similarity index 100% rename from patches/server/0062-Improve-Purpur-AFK-system.patch rename to patches/server/0061-Improve-Purpur-AFK-system.patch diff --git a/patches/server/0063-Virtual-Thread-for-async-scheduler.patch b/patches/server/0062-Virtual-Thread-for-async-scheduler.patch similarity index 100% rename from patches/server/0063-Virtual-Thread-for-async-scheduler.patch rename to patches/server/0062-Virtual-Thread-for-async-scheduler.patch diff --git a/patches/server/0064-Mirai-Configurable-chat-message-signatures.patch b/patches/server/0063-Mirai-Configurable-chat-message-signatures.patch similarity index 98% rename from patches/server/0064-Mirai-Configurable-chat-message-signatures.patch rename to patches/server/0063-Mirai-Configurable-chat-message-signatures.patch index 50420b12..4ba28a16 100644 --- a/patches/server/0064-Mirai-Configurable-chat-message-signatures.patch +++ b/patches/server/0063-Mirai-Configurable-chat-message-signatures.patch @@ -71,10 +71,10 @@ index 50dc68a005490415b88780397ef6c26859596dd5..162115048cffc824376e54b7f60ae071 public static record Favicon(byte[] iconBytes) { private static final String PREFIX = "data:image/png;base64,"; diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 020a0f033f64875bb04d1dead332d471d480935f..f26cec20aa9f52b5dd090107fa76fcd390fc1067 100644 +index b38470108f0842ee65cb55ff7e376105cc7ba2f6..9bf4b58f056172d88365197352b1d434b7170769 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -709,6 +709,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -708,6 +708,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @Override public boolean enforceSecureProfile() { diff --git a/patches/server/0065-Block-log4j-rce-exploit-in-chat.patch b/patches/server/0064-Block-log4j-rce-exploit-in-chat.patch similarity index 100% rename from patches/server/0065-Block-log4j-rce-exploit-in-chat.patch rename to patches/server/0064-Block-log4j-rce-exploit-in-chat.patch diff --git a/patches/server/0066-Cache-player-profileResult.patch b/patches/server/0065-Cache-player-profileResult.patch similarity index 100% rename from patches/server/0066-Cache-player-profileResult.patch rename to patches/server/0065-Cache-player-profileResult.patch diff --git a/patches/server/0067-Prevent-change-non-editable-sign-warning-spam-in-con.patch b/patches/server/0066-Prevent-change-non-editable-sign-warning-spam-in-con.patch similarity index 100% rename from patches/server/0067-Prevent-change-non-editable-sign-warning-spam-in-con.patch rename to patches/server/0066-Prevent-change-non-editable-sign-warning-spam-in-con.patch diff --git a/patches/server/0068-Ignore-terminal-provider-warning.patch b/patches/server/0067-Ignore-terminal-provider-warning.patch similarity index 100% rename from patches/server/0068-Ignore-terminal-provider-warning.patch rename to patches/server/0067-Ignore-terminal-provider-warning.patch diff --git a/patches/server/0069-Fix-console-freeze-above-JAVA-22.patch b/patches/server/0068-Fix-console-freeze-above-JAVA-22.patch similarity index 100% rename from patches/server/0069-Fix-console-freeze-above-JAVA-22.patch rename to patches/server/0068-Fix-console-freeze-above-JAVA-22.patch diff --git a/patches/server/0070-Fix-console-output-display-on-Pterodactyl-panel.patch b/patches/server/0069-Fix-console-output-display-on-Pterodactyl-panel.patch similarity index 100% rename from patches/server/0070-Fix-console-output-display-on-Pterodactyl-panel.patch rename to patches/server/0069-Fix-console-output-display-on-Pterodactyl-panel.patch diff --git a/patches/server/0071-Faster-Random-Generator.patch b/patches/server/0070-Faster-Random-Generator.patch similarity index 100% rename from patches/server/0071-Faster-Random-Generator.patch rename to patches/server/0070-Faster-Random-Generator.patch diff --git a/patches/server/0072-Don-t-save-primed-tnt-entity.patch b/patches/server/0071-Don-t-save-primed-tnt-entity.patch similarity index 100% rename from patches/server/0072-Don-t-save-primed-tnt-entity.patch rename to patches/server/0071-Don-t-save-primed-tnt-entity.patch diff --git a/patches/server/0073-Don-t-save-falling-block-entity.patch b/patches/server/0072-Don-t-save-falling-block-entity.patch similarity index 100% rename from patches/server/0073-Don-t-save-falling-block-entity.patch rename to patches/server/0072-Don-t-save-falling-block-entity.patch diff --git a/patches/server/0074-Configurable-connection-message.patch b/patches/server/0073-Configurable-connection-message.patch similarity index 100% rename from patches/server/0074-Configurable-connection-message.patch rename to patches/server/0073-Configurable-connection-message.patch diff --git a/patches/server/0075-Remove-stream-in-BlockBehaviour-cache-blockstate.patch b/patches/server/0074-Remove-stream-in-BlockBehaviour-cache-blockstate.patch similarity index 100% rename from patches/server/0075-Remove-stream-in-BlockBehaviour-cache-blockstate.patch rename to patches/server/0074-Remove-stream-in-BlockBehaviour-cache-blockstate.patch diff --git a/patches/server/0076-Reduce-worldgen-allocations.patch b/patches/server/0075-Reduce-worldgen-allocations.patch similarity index 100% rename from patches/server/0076-Reduce-worldgen-allocations.patch rename to patches/server/0075-Reduce-worldgen-allocations.patch diff --git a/patches/server/0077-Fix-MC-183518.patch b/patches/server/0076-Fix-MC-183518.patch similarity index 100% rename from patches/server/0077-Fix-MC-183518.patch rename to patches/server/0076-Fix-MC-183518.patch diff --git a/patches/server/0078-Use-caffeine-cache-kickPermission-instead-of-using-g.patch b/patches/server/0077-Use-caffeine-cache-kickPermission-instead-of-using-g.patch similarity index 100% rename from patches/server/0078-Use-caffeine-cache-kickPermission-instead-of-using-g.patch rename to patches/server/0077-Use-caffeine-cache-kickPermission-instead-of-using-g.patch diff --git a/patches/server/0079-Do-not-place-player-if-the-server-is-full.patch b/patches/server/0078-Do-not-place-player-if-the-server-is-full.patch similarity index 100% rename from patches/server/0079-Do-not-place-player-if-the-server-is-full.patch rename to patches/server/0078-Do-not-place-player-if-the-server-is-full.patch diff --git a/patches/server/0080-Fix-MC-200418.patch b/patches/server/0079-Fix-MC-200418.patch similarity index 100% rename from patches/server/0080-Fix-MC-200418.patch rename to patches/server/0079-Fix-MC-200418.patch diff --git a/patches/server/0081-Fix-MC-119417.patch b/patches/server/0080-Fix-MC-119417.patch similarity index 100% rename from patches/server/0081-Fix-MC-119417.patch rename to patches/server/0080-Fix-MC-119417.patch diff --git a/patches/server/0082-Fix-MC-223153.patch b/patches/server/0081-Fix-MC-223153.patch similarity index 100% rename from patches/server/0082-Fix-MC-223153.patch rename to patches/server/0081-Fix-MC-223153.patch diff --git a/patches/server/0006-Pufferfish-Optimize-mob-spawning.patch b/patches/work/server/0007-Pufferfish-Optimize-mob-spawning.patch similarity index 65% rename from patches/server/0006-Pufferfish-Optimize-mob-spawning.patch rename to patches/work/server/0007-Pufferfish-Optimize-mob-spawning.patch index c47a7a08..1f870a36 100644 --- a/patches/server/0006-Pufferfish-Optimize-mob-spawning.patch +++ b/patches/work/server/0007-Pufferfish-Optimize-mob-spawning.patch @@ -20,10 +20,10 @@ and, in my opinion, worth the low risk of minor mob-spawning-related inconsistencies. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 208b9558d9019cd00f7ed270d2a36f9a28464e65..e2f2bc175d94110e32b412b73528686661b79809 100644 +index 17af0e5be9245573bfcd2ead2be3b6434cd8f576..a976002437a5d9c761835691213e11b14d9a7d45 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -310,6 +310,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop atomicreference = new AtomicReference(); Thread thread = new io.papermc.paper.util.TickThread(() -> { // Paper - rewrite chunk system diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 42ac2efb4c84c5f15c10934f928183962f179626..944ada1e0f4e4a8460ec3c8e1d9a0de7469d395b 100644 +index 8c74652ffa2c1263c835381bc27ffdc6d272dbf7..05e214ca14240ba635927c9f2a71d19ba1e9aa45 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -373,6 +373,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -364,6 +364,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface DedicatedServer.LOGGER.info("JMX monitoring enabled"); } @@ -44,13 +44,26 @@ index 42ac2efb4c84c5f15c10934f928183962f179626..944ada1e0f4e4a8460ec3c8e1d9a0de7 return true; } } +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +index 7bac7112b520286ebe9e8d36dc0932900e76eb52..54c3e32c7ae869d55408d77ea2aa1635f980a39b 100644 +--- a/src/main/java/net/minecraft/server/level/ChunkMap.java ++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +@@ -246,7 +246,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end + // Paper start - optimise chunk tick iteration + public final it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet needsChangeBroadcasting = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); +- public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets); ++ public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap = new gg.pufferfish.pufferfish.util.AsyncPlayerAreaMap(this.pooledLinkedPlayerHashSets); // Pufferfish + // Paper end - optimise chunk tick iteration + + public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index fe96ee6b36d38a7da61c80715716365d2a33f07d..e59f0957b664c0ae3c4c7ce7d9ab68b038985870 100644 +index 94689992b4d159ab996e00ae20afa8fef0e84db2..af4fe64e190e73dcc5f2495d0b533547d8f57f1d 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -128,6 +128,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } - // Paper end - rewrite chunk system +@@ -74,6 +74,9 @@ public class ServerChunkCache extends ChunkSource { + private final LevelChunk[] lastLoadedChunks = new LevelChunk[4 * 4]; + // Paper end + public boolean firstRunSpawnCounts = true; // Pufferfish + public final java.util.concurrent.atomic.AtomicBoolean _pufferfish_spawnCountsReady = new java.util.concurrent.atomic.AtomicBoolean(false); // Pufferfish - optimize countmobs @@ -58,7 +71,7 @@ index fe96ee6b36d38a7da61c80715716365d2a33f07d..e59f0957b664c0ae3c4c7ce7d9ab68b0 public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory) { this.level = world; this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(world); -@@ -442,6 +445,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -508,6 +511,7 @@ public class ServerChunkCache extends ChunkSource { // Paper start - Optional per player mob spawns int naturalSpawnChunkCount = k; if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled @@ -66,7 +79,7 @@ index fe96ee6b36d38a7da61c80715716365d2a33f07d..e59f0957b664c0ae3c4c7ce7d9ab68b0 // re-set mob counts for (ServerPlayer player : this.level.players) { // Paper start - per player mob spawning backoff -@@ -456,14 +460,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -522,14 +526,18 @@ public class ServerChunkCache extends ChunkSource { } // Paper end - per player mob spawning backoff } @@ -88,20 +101,20 @@ index fe96ee6b36d38a7da61c80715716365d2a33f07d..e59f0957b664c0ae3c4c7ce7d9ab68b0 // Gale start - MultiPaper - skip unnecessary mob spawning computations } else { spawnercreature_d = null; -@@ -491,8 +499,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - - if (this.level.isNaturalSpawningAllowed(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { +@@ -622,8 +630,8 @@ public class ServerChunkCache extends ChunkSource { + if (tick && chunk1.chunkStatus.isOrAfter(net.minecraft.server.level.FullChunkStatus.ENTITY_TICKING)) { + // Paper end - optimise chunk tick iteration chunk1.incrementInhabitedTime(j); -- if (flagAndHasNaturalSpawn && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot // Gale - MultiPaper - skip unnecessary mob spawning computations +- if (spawn && flagAndHasNaturalSpawn && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration // Gale - MultiPaper - skip unnecessary mob spawning computations - NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); -+ if (flagAndHasNaturalSpawn && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot // Gale - MultiPaper - skip unnecessary mob spawning computations // Pufferfish ++ if (spawn && flagAndHasNaturalSpawn && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair)) { // Spigot // Paper - optimise chunk tick iteration // Gale - MultiPaper - skip unnecessary mob spawning computations // Pufferfish + NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1); // Pufferfish } - if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { -@@ -520,6 +528,40 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration +@@ -666,6 +674,40 @@ public class ServerChunkCache extends ChunkSource { this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing - }); + // Paper - optimise chunk tick iteration } + + // Pufferfish start - optimize mob spawning @@ -126,7 +139,7 @@ index fe96ee6b36d38a7da61c80715716365d2a33f07d..e59f0957b664c0ae3c4c7ce7d9ab68b0 + if (_pufferfish_spawnCountsReady.getAndSet(false)) { + net.minecraft.server.MinecraftServer.getServer().mobSpawnExecutor.submit(() -> { + int mapped = distanceManager.getNaturalSpawnChunkCount(); -+ ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet.Iterator objectiterator = ++ io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator objectiterator = + level.entityTickList.entities.iterator(io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); + gg.pufferfish.pufferfish.util.IterableWrapper wrappedIterator = + new gg.pufferfish.pufferfish.util.IterableWrapper<>(objectiterator); @@ -141,41 +154,52 @@ index fe96ee6b36d38a7da61c80715716365d2a33f07d..e59f0957b664c0ae3c4c7ce7d9ab68b0 // Gale start - MultiPaper - skip unnecessary mob spawning computations diff --git a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java -index d8b4196adf955f8d414688dc451caac2d9c609d9..80a43def4912a3228cd95117d5c2aac68798b4ec 100644 +index 83a39f900551e39d5af6f17a339a386ddee4feef..0c8c534fc69172387f188af5282accfed7597ac7 100644 --- a/src/main/java/net/minecraft/world/level/entity/EntityTickList.java +++ b/src/main/java/net/minecraft/world/level/entity/EntityTickList.java @@ -9,7 +9,7 @@ import javax.annotation.Nullable; import net.minecraft.world.entity.Entity; public class EntityTickList { -- private final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system -+ public final ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet entities = new ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet<>(); // Paper - rewrite chunk system // Pufferfish - private->public +- private final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet entities = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(true); // Paper - rewrite this, always keep this updated - why would we EVER tick an entity that's not ticking? ++ public final io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet entities = new io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet<>(true); // Paper - rewrite this, always keep this updated - why would we EVER tick an entity that's not ticking? // Pufferfish - private->public private void ensureActiveIsNotIterated() { - // Paper - rewrite chunk system + // Paper - replace with better logic, do not delay removals diff --git a/src/main/java/org/dreeam/leaf/config/modules/async/AsyncMobSpawning.java b/src/main/java/org/dreeam/leaf/config/modules/async/AsyncMobSpawning.java new file mode 100644 -index 0000000000000000000000000000000000000000..8a3726a747ff4640f9936a9eae1dca34e5203029 +index 0000000000000000000000000000000000000000..67c575439f7d60046586972dfc3212bb36a3d033 --- /dev/null +++ b/src/main/java/org/dreeam/leaf/config/modules/async/AsyncMobSpawning.java -@@ -0,0 +1,30 @@ +@@ -0,0 +1,41 @@ +package org.dreeam.leaf.config.modules.async; + -+import org.dreeam.leaf.config.ConfigModules; ++import com.electronwill.nightconfig.core.file.CommentedFileConfig; ++import org.dreeam.leaf.config.ConfigInfo; ++import org.dreeam.leaf.config.DoNotLoad; +import org.dreeam.leaf.config.EnumConfigCategory; ++import org.dreeam.leaf.config.IConfigModule; + -+public class AsyncMobSpawning extends ConfigModules { ++public class AsyncMobSpawning implements IConfigModule { + -+ public String getBasePath() { -+ return EnumConfigCategory.ASYNC.getBaseKeyName() + ".async-mob-spawning"; ++ @Override ++ public EnumConfigCategory getCategory() { ++ return EnumConfigCategory.ASYNC; + } + ++ @Override ++ public String getBaseName() { ++ return "async_mob_spawning"; ++ } ++ ++ @ConfigInfo(baseName = "enabled") + public static boolean enabled = true; ++ @DoNotLoad + public static boolean asyncMobSpawningInitialized; + + @Override -+ public void onLoaded() { -+ config.addComment(getBasePath(), """ ++ public void onLoaded(CommentedFileConfig config) { ++ config.setComment("async.async_mob_spawning", """ + Whether or not asynchronous mob spawning should be enabled. + On servers with many entities, this can improve performance by up to 15%. You must have + paper's per-player-mob-spawns setting set to true for this to work. @@ -185,7 +209,7 @@ index 0000000000000000000000000000000000000000..8a3726a747ff4640f9936a9eae1dca34 + // This prevents us from changing the value during a reload. + if (!asyncMobSpawningInitialized) { + asyncMobSpawningInitialized = true; -+ enabled = config.getBoolean(getBasePath() + ".enabled", enabled); ++ this.get("async.async_mob_spawning.enabled", enabled, config); + } + } +} diff --git a/patches/work/server/0083-Optimize-Leaves-ProtocolManager-structure.patch b/patches/work/server/0083-Optimize-Leaves-ProtocolManager-structure.patch new file mode 100644 index 00000000..f8458b99 --- /dev/null +++ b/patches/work/server/0083-Optimize-Leaves-ProtocolManager-structure.patch @@ -0,0 +1,545 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> +Date: Sat, 13 Jul 2024 21:23:12 +0800 +Subject: [PATCH] Optimize Leaves ProtocolManager structure + + +diff --git a/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java +index c496c97c99cd352c2566731d3017cf1b14ee74ec..9b54e24bd094465625dca12f6ac5724f51775adb 100644 +--- a/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java ++++ b/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java +@@ -31,6 +31,10 @@ public class AppleSkinProtocol { + + private static final Set players = new HashSet<>(); + ++ public static boolean shouldEnable() { ++ return org.dreeam.leaf.config.modules.network.ProtocolSupport.appleskinProtocol; ++ } ++ + @Contract("_ -> new") + public static @NotNull ResourceLocation id(String path) { + return new ResourceLocation(PROTOCOL_ID, path); +@@ -38,49 +42,41 @@ public class AppleSkinProtocol { + + @ProtocolHandler.PlayerJoin + public static void onPlayerLoggedIn(@NotNull ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.appleskinProtocol) { +- resetPlayerData(player); +- } ++ resetPlayerData(player); + } + + @ProtocolHandler.PlayerLeave + public static void onPlayerLoggedOut(@NotNull ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.appleskinProtocol) { +- players.remove(player); +- resetPlayerData(player); +- } ++ players.remove(player); ++ resetPlayerData(player); + } + + @ProtocolHandler.MinecraftRegister(ignoreId = true) + public static void onPlayerSubscribed(@NotNull ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.appleskinProtocol) { +- players.add(player); +- } ++ players.add(player); + } + + @ProtocolHandler.Ticker + public static void tick() { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.appleskinProtocol) { +- for (ServerPlayer player : players) { +- FoodData data = player.getFoodData(); +- +- float saturation = data.getSaturationLevel(); +- Float previousSaturation = previousSaturationLevels.get(player.getUUID()); +- if (previousSaturation == null || saturation != previousSaturation) { +- ProtocolUtils.sendPayloadPacket(player, SATURATION_KEY, buf -> { +- buf.writeFloat(saturation); +- }); +- previousSaturationLevels.put(player.getUUID(), saturation); +- } +- +- float exhaustion = data.getExhaustionLevel(); +- Float previousExhaustion = previousExhaustionLevels.get(player.getUUID()); +- if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= MINIMUM_EXHAUSTION_CHANGE_THRESHOLD) { +- ProtocolUtils.sendPayloadPacket(player, EXHAUSTION_KEY, buf -> { +- buf.writeFloat(exhaustion); +- }); +- previousExhaustionLevels.put(player.getUUID(), exhaustion); +- } ++ for (ServerPlayer player : players) { ++ FoodData data = player.getFoodData(); ++ ++ float saturation = data.getSaturationLevel(); ++ Float previousSaturation = previousSaturationLevels.get(player.getUUID()); ++ if (previousSaturation == null || saturation != previousSaturation) { ++ ProtocolUtils.sendPayloadPacket(player, SATURATION_KEY, buf -> { ++ buf.writeFloat(saturation); ++ }); ++ previousSaturationLevels.put(player.getUUID(), saturation); ++ } ++ ++ float exhaustion = data.getExhaustionLevel(); ++ Float previousExhaustion = previousExhaustionLevels.get(player.getUUID()); ++ if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= MINIMUM_EXHAUSTION_CHANGE_THRESHOLD) { ++ ProtocolUtils.sendPayloadPacket(player, EXHAUSTION_KEY, buf -> { ++ buf.writeFloat(exhaustion); ++ }); ++ previousExhaustionLevels.put(player.getUUID(), exhaustion); + } + } + } +diff --git a/src/main/java/org/leavesmc/leaves/protocol/AsteorBarProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/AsteorBarProtocol.java +index ed8d9888a24d3ae6cf8fe2f8b269554102e451df..1bdd77078c7345db1a675fbdc26b37e96bf468b0 100644 +--- a/src/main/java/org/leavesmc/leaves/protocol/AsteorBarProtocol.java ++++ b/src/main/java/org/leavesmc/leaves/protocol/AsteorBarProtocol.java +@@ -30,6 +30,10 @@ public class AsteorBarProtocol { + + private static final Set players = new HashSet<>(); + ++ public static boolean shouldEnable() { ++ return org.dreeam.leaf.config.modules.network.ProtocolSupport.asteorBarProtocol; ++ } ++ + @Contract("_ -> new") + public static @NotNull ResourceLocation id(String path) { + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID, path); +@@ -37,51 +41,43 @@ public class AsteorBarProtocol { + + @ProtocolHandler.PlayerJoin + public static void onPlayerLoggedIn(@NotNull ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.asteorBarProtocol) { +- resetPlayerData(player); +- } ++ resetPlayerData(player); + } + + @ProtocolHandler.PlayerLeave + public static void onPlayerLoggedOut(@NotNull ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.asteorBarProtocol) { +- players.remove(player); +- resetPlayerData(player); +- } ++ players.remove(player); ++ resetPlayerData(player); + } + + @ProtocolHandler.MinecraftRegister(ignoreId = true) + public static void onPlayerSubscribed(@NotNull ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.asteorBarProtocol) { +- players.add(player); +- } ++ players.add(player); + } + + @ProtocolHandler.Ticker + public static void tick() { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.asteorBarProtocol) { +- for (ServerPlayer player : players) { +- FoodData data = player.getFoodData(); +- +- float saturation = data.getSaturationLevel(); +- Float previousSaturation = previousSaturationLevels.get(player.getUUID()); +- if (previousSaturation == null || saturation != previousSaturation) { +- ProtocolUtils.sendPayloadPacket(player, NETWORK_KEY, buf -> { +- buf.writeByte(1); +- buf.writeFloat(saturation); +- }); +- previousSaturationLevels.put(player.getUUID(), saturation); +- } +- +- float exhaustion = data.getExhaustionLevel(); +- Float previousExhaustion = previousExhaustionLevels.get(player.getUUID()); +- if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= THRESHOLD) { +- ProtocolUtils.sendPayloadPacket(player, NETWORK_KEY, buf -> { +- buf.writeByte(0); +- buf.writeFloat(exhaustion); +- }); +- previousExhaustionLevels.put(player.getUUID(), exhaustion); +- } ++ for (ServerPlayer player : players) { ++ FoodData data = player.getFoodData(); ++ ++ float saturation = data.getSaturationLevel(); ++ Float previousSaturation = previousSaturationLevels.get(player.getUUID()); ++ if (previousSaturation == null || saturation != previousSaturation) { ++ ProtocolUtils.sendPayloadPacket(player, NETWORK_KEY, buf -> { ++ buf.writeByte(1); ++ buf.writeFloat(saturation); ++ }); ++ previousSaturationLevels.put(player.getUUID(), saturation); ++ } ++ ++ float exhaustion = data.getExhaustionLevel(); ++ Float previousExhaustion = previousExhaustionLevels.get(player.getUUID()); ++ if (previousExhaustion == null || Math.abs(exhaustion - previousExhaustion) >= THRESHOLD) { ++ ProtocolUtils.sendPayloadPacket(player, NETWORK_KEY, buf -> { ++ buf.writeByte(0); ++ buf.writeFloat(exhaustion); ++ }); ++ previousExhaustionLevels.put(player.getUUID(), exhaustion); + } + } + } +diff --git a/src/main/java/org/leavesmc/leaves/protocol/ChatImageProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/ChatImageProtocol.java +index 87ffe8a81a8bab7d20ff9551b105487d47616ee1..b026b9fefd85d16b0294738034bfae1220d47eac 100644 +--- a/src/main/java/org/leavesmc/leaves/protocol/ChatImageProtocol.java ++++ b/src/main/java/org/leavesmc/leaves/protocol/ChatImageProtocol.java +@@ -7,7 +7,6 @@ import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.common.custom.CustomPacketPayload; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerPlayer; +-import org.dreeam.leaf.config.modules.network.ProtocolSupport; + import org.jetbrains.annotations.Contract; + import org.jetbrains.annotations.NotNull; + import org.leavesmc.leaves.protocol.chatimage.ChatImageIndex; +@@ -30,7 +29,12 @@ public class ChatImageProtocol { + public static int MAX_STRING = 532767; + private static final Gson gson = new Gson(); + +- public record FileInfoChannelPacket(String message) implements LeavesCustomPayload { ++ public static boolean shouldEnable() { ++ return org.dreeam.leaf.config.modules.network.ProtocolSupport.chatImageProtocol; ++ } ++ ++ public record FileInfoChannelPacket( ++ String message) implements LeavesCustomPayload { + private static final ResourceLocation FILE_INFO = ChatImageProtocol.id("file_info"); + + @New +@@ -49,7 +53,8 @@ public class ChatImageProtocol { + } + } + +- public record DownloadFileChannelPacket(String message) implements LeavesCustomPayload { ++ public record DownloadFileChannelPacket( ++ String message) implements LeavesCustomPayload { + /** + * 发送文件分块到客户端通道(Map) + */ +@@ -72,7 +77,8 @@ public class ChatImageProtocol { + + } + +- public record FileChannelPacket(String message) implements LeavesCustomPayload { ++ public record FileChannelPacket( ++ String message) implements LeavesCustomPayload { + /** + * 客户端发送文件分块到服务器通道(Map) + */ +@@ -97,7 +103,6 @@ public class ChatImageProtocol { + + @ProtocolHandler.PayloadReceiver(payload = FileChannelPacket.class, payloadId = "file_channel") + public static void serverFileChannelReceived(ServerPlayer player, String res) { +- if (!ProtocolSupport.chatImageProtocol) return; + ChatImageIndex title = gson.fromJson(res, ChatImageIndex.class); + HashMap blocks = SERVER_BLOCK_CACHE.containsKey(title.url) ? SERVER_BLOCK_CACHE.get(title.url) : new HashMap<>(); + blocks.put(title.index, res); +@@ -123,7 +128,6 @@ public class ChatImageProtocol { + + @ProtocolHandler.PayloadReceiver(payload = FileInfoChannelPacket.class, payloadId = "file_info") + public static void serverFileInfoChannelReceived(ServerPlayer player, String url) { +- if (!ProtocolSupport.chatImageProtocol) return; + if (SERVER_BLOCK_CACHE.containsKey(url) && FILE_COUNT_MAP.containsKey(url)) { + HashMap list = SERVER_BLOCK_CACHE.get(url); + Integer total = FILE_COUNT_MAP.get(url); +diff --git a/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java +index 9e35dfaf8bb5511b4cd0a71175d7ecb6d835042f..5ef19098512ae8a070dea270a68c27695c34624b 100644 +--- a/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java ++++ b/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java +@@ -16,6 +16,10 @@ public class XaeroMapProtocol { + private static final ResourceLocation MINIMAP_KEY = idMini("main"); + private static final ResourceLocation WORLDMAP_KEY = idWorld("main"); + ++ public static boolean shouldEnable() { ++ return org.dreeam.leaf.config.modules.network.ProtocolSupport.xaeroMapProtocol; ++ } ++ + @Contract("_ -> new") + public static @NotNull ResourceLocation idMini(String path) { + return new ResourceLocation(PROTOCOL_ID_MINI, path); +@@ -27,7 +31,7 @@ public class XaeroMapProtocol { + } + + public static void onSendWorldInfo(@NotNull ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.xaeroMapProtocol) { ++ if (shouldEnable()) { + ProtocolUtils.sendPayloadPacket(player, MINIMAP_KEY, buf -> { + buf.writeByte(0); + buf.writeInt(org.dreeam.leaf.config.modules.network.ProtocolSupport.xaeroMapServerID); +diff --git a/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java b/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java +index e7ce2e7a1686f1775c0a2e0cd731294025d2833b..54e7d12492eefbd4ae0d5c01f447381cde8a607a 100644 +--- a/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java ++++ b/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java +@@ -6,33 +6,23 @@ import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerPlayer; + import org.apache.commons.lang.ArrayUtils; + import org.bukkit.event.player.PlayerKickEvent; ++import org.dreeam.leaf.config.LeafConfig; + import org.jetbrains.annotations.NotNull; + import org.leavesmc.leaves.LeavesLogger; + +-import java.io.File; +-import java.io.IOException; + import java.lang.reflect.Constructor; + import java.lang.reflect.Executable; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; +-import java.net.JarURLConnection; +-import java.net.URL; +-import java.net.URLDecoder; +-import java.nio.charset.StandardCharsets; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collections; +-import java.util.Enumeration; + import java.util.HashMap; + import java.util.HashSet; +-import java.util.LinkedHashSet; + import java.util.List; + import java.util.Map; + import java.util.Set; +-import java.util.jar.JarEntry; +-import java.util.jar.JarFile; +- + public class LeavesProtocolManager { + + private static final Class[] PAYLOAD_PARAMETER_TYPES = {ResourceLocation.class, FriendlyByteBuf.class}; +@@ -49,9 +39,23 @@ public class LeavesProtocolManager { + private static final Map> MINECRAFT_REGISTER = new HashMap<>(); + + public static void init() { +- for (Class clazz : getClasses("org.leavesmc.leaves.protocol")) { ++ LeavesProtocolManager.cleanProtocols(); // Do cleanup ++ ++ for (Class clazz : LeafConfig.getClasses("org.leavesmc.leaves.protocol")) { + final LeavesProtocol protocol = clazz.getAnnotation(LeavesProtocol.class); + if (protocol != null) { ++ ++ try { ++ Object instance = clazz.getConstructor().newInstance(); ++ Method method = clazz.getMethod("shouldEnable"); ++ ++ if (!(boolean) method.invoke(instance)) continue; ++ } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | ++ InvocationTargetException e) { ++ LOGGER.severe("Failed to load class " + clazz.getName() + " due to missing dependencies, " + e.getCause() + ": " + e.getMessage()); ++ return; ++ } ++ + Set methods; + try { + Method[] publicMethods = clazz.getMethods(); +@@ -155,6 +159,16 @@ public class LeavesProtocolManager { + } + } + ++ private static void cleanProtocols() { ++ KNOWN_TYPES.clear(); ++ KNOW_RECEIVERS.clear(); ++ TICKERS.clear(); ++ PLAYER_JOIN.clear(); ++ PLAYER_LEAVE.clear(); ++ RELOAD_SERVER.clear(); ++ MINECRAFT_REGISTER.clear(); ++ } ++ + public static LeavesCustomPayload decode(ResourceLocation id, FriendlyByteBuf buf) { + for (LeavesProtocol protocol : KNOWN_TYPES.keySet()) { + if (!ArrayUtils.contains(protocol.namespace(), id.getNamespace())) { +@@ -276,81 +290,6 @@ public class LeavesProtocolManager { + } + } + +- public static Set> getClasses(String pack) { +- Set> classes = new LinkedHashSet<>(); +- String packageDirName = pack.replace('.', '/'); +- Enumeration dirs; +- try { +- dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); +- while (dirs.hasMoreElements()) { +- URL url = dirs.nextElement(); +- String protocol = url.getProtocol(); +- if ("file".equals(protocol)) { +- String filePath = URLDecoder.decode(url.getFile(), StandardCharsets.UTF_8); +- findClassesInPackageByFile(pack, filePath, classes); +- } else if ("jar".equals(protocol)) { +- JarFile jar; +- try { +- jar = ((JarURLConnection) url.openConnection()).getJarFile(); +- Enumeration entries = jar.entries(); +- findClassesInPackageByJar(pack, entries, packageDirName, classes); +- } catch (IOException exception) { +- LOGGER.warning("Failed to load jar file, " + exception.getCause() + ": " + exception.getMessage()); +- } +- } +- } +- } catch (IOException exception) { +- LOGGER.warning("Failed to load classes, " + exception.getCause() + ": " + exception.getMessage()); +- } +- return classes; +- } +- +- private static void findClassesInPackageByFile(String packageName, String packagePath, Set> classes) { +- File dir = new File(packagePath); +- if (!dir.exists() || !dir.isDirectory()) { +- return; +- } +- File[] dirfiles = dir.listFiles((file) -> file.isDirectory() || file.getName().endsWith(".class")); +- if (dirfiles != null) { +- for (File file : dirfiles) { +- if (file.isDirectory()) { +- findClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), classes); +- } else { +- String className = file.getName().substring(0, file.getName().length() - 6); +- try { +- classes.add(Class.forName(packageName + '.' + className)); +- } catch (ClassNotFoundException exception) { +- LOGGER.warning("Failed to load class " + className + ", " + exception.getCause() + ": " + exception.getMessage()); +- } +- } +- } +- } +- } +- +- private static void findClassesInPackageByJar(String packageName, Enumeration entries, String packageDirName, Set> classes) { +- while (entries.hasMoreElements()) { +- JarEntry entry = entries.nextElement(); +- String name = entry.getName(); +- if (name.charAt(0) == '/') { +- name = name.substring(1); +- } +- if (name.startsWith(packageDirName)) { +- int idx = name.lastIndexOf('/'); +- if (idx != -1) { +- packageName = name.substring(0, idx).replace('/', '.'); +- } +- if (name.endsWith(".class") && !entry.isDirectory()) { +- String className = name.substring(packageName.length() + 1, name.length() - 6); +- try { +- classes.add(Class.forName(packageName + '.' + className)); +- } catch (ClassNotFoundException exception) { +- LOGGER.warning("Failed to load class " + className + ", " + exception.getCause() + ": " + exception.getMessage()); +- } +- } +- } +- } +- } +- + public record ErrorPayload(ResourceLocation id, String[] protocolID, String[] packetID) implements LeavesCustomPayload { + @Override + public void write(@NotNull FriendlyByteBuf buf) { +diff --git a/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java b/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java +index 43ad624bbe334384de4e79d0075e67389648c014..b418b705be48950587e24bb2dfb8751e7d459ff4 100644 +--- a/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java ++++ b/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java +@@ -103,6 +103,10 @@ public class JadeProtocol { + + public static final WrappedHierarchyLookup> itemStorageProviders = new WrappedHierarchyLookup<>(); + ++ public static boolean shouldEnable() { ++ return org.dreeam.leaf.config.modules.network.ProtocolSupport.jadeProtocol; ++ } ++ + @Contract("_ -> new") + public static @NotNull ResourceLocation id(String path) { + return new ResourceLocation(PROTOCOL_ID, path); +@@ -126,9 +130,9 @@ public class JadeProtocol { + priorities = new PriorityStore<>(IJadeProvider::getDefaultPriority, IJadeProvider::getUid); + priorities.setSortingFunction((store, allKeys) -> { + List keys = allKeys.stream() +- .filter(JadeProtocol::isPrimaryKey) +- .sorted(Comparator.comparingInt(store::byKey)) +- .collect(Collectors.toCollection(ArrayList::new)); ++ .filter(JadeProtocol::isPrimaryKey) ++ .sorted(Comparator.comparingInt(store::byKey)) ++ .collect(Collectors.toCollection(ArrayList::new)); + allKeys.stream().filter(Predicate.not(JadeProtocol::isPrimaryKey)).forEach($ -> { + int index = keys.indexOf(JadeProtocol.getPrimaryKey($)); + keys.add(index + 1, $); +@@ -177,8 +181,8 @@ public class JadeProtocol { + + try { + shearableBlocks = Collections.unmodifiableList(LootTableMineableCollector.execute( +- MinecraftServer.getServer().registryAccess().registryOrThrow(Registries.LOOT_TABLE), +- Items.SHEARS.getDefaultInstance())); ++ MinecraftServer.getServer().registryAccess().registryOrThrow(Registries.LOOT_TABLE), ++ Items.SHEARS.getDefaultInstance())); + } catch (Throwable ignore) { + LeavesLogger.LOGGER.severe("Failed to collect shearable blocks"); + } +@@ -186,17 +190,11 @@ public class JadeProtocol { + + @ProtocolHandler.PlayerJoin + public static void onPlayerJoin(ServerPlayer player) { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.jadeProtocol) { +- ProtocolUtils.sendPayloadPacket(player, new ServerPingPayload("", shearableBlocks)); +- } ++ ProtocolUtils.sendPayloadPacket(player, new ServerPingPayload("", shearableBlocks)); + } + + @ProtocolHandler.PayloadReceiver(payload = RequestEntityPayload.class, payloadId = "request_entity") + public static void requestEntityData(ServerPlayer player, RequestEntityPayload payload) { +- if (!org.dreeam.leaf.config.modules.network.ProtocolSupport.jadeProtocol) { +- return; +- } +- + MinecraftServer server = MinecraftServer.getServer(); + server.execute(() -> { + Level world = player.level(); +@@ -237,10 +235,6 @@ public class JadeProtocol { + + @ProtocolHandler.PayloadReceiver(payload = RequestBlockPayload.class, payloadId = "request_block") + public static void requestBlockData(ServerPlayer player, RequestBlockPayload payload) { +- if (!org.dreeam.leaf.config.modules.network.ProtocolSupport.jadeProtocol) { +- return; +- } +- + MinecraftServer server = MinecraftServer.getServer(); + server.execute(() -> { + Level world = player.level(); +@@ -291,9 +285,7 @@ public class JadeProtocol { + + @ProtocolHandler.ReloadServer + public static void onServerReload() { +- if (org.dreeam.leaf.config.modules.network.ProtocolSupport.jadeProtocol) { +- enableAllPlayer(); +- } ++ enableAllPlayer(); + } + + public static void enableAllPlayer() { +@@ -302,7 +294,8 @@ public class JadeProtocol { + } + } + +- public record RequestEntityPayload(boolean showDetails, int entityId, int partIndex, Vec3 hitVec) implements LeavesCustomPayload { ++ public record RequestEntityPayload(boolean showDetails, int entityId, int partIndex, ++ Vec3 hitVec) implements LeavesCustomPayload { + + private static final ResourceLocation PACKET_REQUEST_ENTITY = JadeProtocol.id("request_entity"); + +@@ -326,7 +319,8 @@ public class JadeProtocol { + } + } + +- public record RequestBlockPayload(boolean showDetails, BlockHitResult hitResult, BlockState blockState, ItemStack fakeBlock) implements LeavesCustomPayload { ++ public record RequestBlockPayload(boolean showDetails, BlockHitResult hitResult, BlockState blockState, ++ ItemStack fakeBlock) implements LeavesCustomPayload { + + private static final ResourceLocation PACKET_REQUEST_BLOCK = JadeProtocol.id("request_block"); + private static final StreamCodec ITEM_STACK_CODEC = ItemStack.OPTIONAL_STREAM_CODEC; +@@ -352,7 +346,8 @@ public class JadeProtocol { + } + } + +- public record ServerPingPayload(String serverConfig, List shearableBlocks) implements LeavesCustomPayload { ++ public record ServerPingPayload(String serverConfig, ++ List shearableBlocks) implements LeavesCustomPayload { + + private static final ResourceLocation PACKET_SERVER_PING = JadeProtocol.id("server_ping_v1"); + private static final StreamCodec> SHEARABLE_BLOCKS_CODEC = ByteBufCodecs.registry(Registries.BLOCK).apply(ByteBufCodecs.list());