diff --git a/README.md b/README.md index 78f0464b..90fc4ab6 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ maven { } dependencies { - compileOnly("org.leavesmc.leaves:leaves-api:1.21.8-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves-api:1.21.10-R0.1-SNAPSHOT") } ``` @@ -40,7 +40,7 @@ Each time you want to update your dependency, you must re-build Leaves. Leaves-Server: ```kotlin dependencies { - compileOnly("org.leavesmc.leaves:leaves:1.21.8-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves:1.21.10-R0.1-SNAPSHOT") } ``` diff --git a/README_cn.md b/README_cn.md index d7269b4f..a3c3f9d9 100644 --- a/README_cn.md +++ b/README_cn.md @@ -30,7 +30,7 @@ maven { } dependencies { - compileOnly("org.leavesmc.leaves:leaves-api:1.21.8-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves-api:1.21.10-R0.1-SNAPSHOT") } ``` @@ -39,7 +39,7 @@ dependencies { Leaves-Server: ```kotlin dependencies { - compileOnly("org.leavesmc.leaves:leaves:1.21.8-R0.1-SNAPSHOT") + compileOnly("org.leavesmc.leaves:leaves:1.21.10-R0.1-SNAPSHOT") } ``` diff --git a/build.gradle.kts b/build.gradle.kts index 797981d2..22dfcf54 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ import java.util.Locale plugins { java - id("org.leavesmc.leavesweight.patcher") version "2.0.0-SNAPSHOT" + id("org.leavesmc.leavesweight.patcher") version "2.1.0-SNAPSHOT" } subprojects { diff --git a/gradle.properties b/gradle.properties index f197da43..2e26bff5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,11 @@ group=org.leavesmc.leaves -version=1.21.8-R0.1-SNAPSHOT -mcVersion=1.21.8 -paperRef=29c8822d90899c89d2689338e81a98f690bcba12 +version=1.21.10-R0.1-SNAPSHOT +mcVersion=1.21.10 +paperRef=af06383701d3c02e3e3cbd2ef5c5b55e2bbd0742 +preVersion=true +paper.runDisableWatchdog=true -preVersion=false +org.gradle.configuration-cache=false org.gradle.caching=true org.gradle.parallel=true - -paper.runDisableWatchdog=true +org.gradle.vfs.watch=false diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ff23a68d..2e111328 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/leaves-api/build.gradle.kts.patch b/leaves-api/build.gradle.kts.patch index 867175e7..0fcd25ba 100644 --- a/leaves-api/build.gradle.kts.patch +++ b/leaves-api/build.gradle.kts.patch @@ -1,6 +1,6 @@ --- a/paper-api/build.gradle.kts +++ b/paper-api/build.gradle.kts -@@ -90,19 +_,33 @@ +@@ -89,19 +_,33 @@ testRuntimeOnly("org.junit.platform:junit-platform-launcher") } @@ -35,7 +35,7 @@ val outgoingVariants = arrayOf("runtimeElements", "apiElements", "sourcesElements", "javadocElements") val mainCapability = "${project.group}:${project.name}:${project.version}" -@@ -147,6 +_,16 @@ +@@ -146,6 +_,16 @@ } } @@ -52,7 +52,7 @@ tasks.jar { from(generateApiVersioningFile.map { it.outputs.files.singleFile }) { into("META-INF/maven/${project.group}/${project.name}") -@@ -166,7 +_,7 @@ +@@ -165,7 +_,7 @@ tasks.withType().configureEach { val options = options as StandardJavadocDocletOptions @@ -61,7 +61,7 @@ options.use() options.isDocFilesSubDirs = true options.links( -@@ -199,16 +_,18 @@ +@@ -198,16 +_,18 @@ } // workaround for https://github.com/gradle/gradle/issues/4046 diff --git a/leaves-api/paper-patches/features/0001-Delete-Timings.patch b/leaves-api/paper-patches/features/0001-Delete-Timings.patch index 663897de..b5244432 100644 --- a/leaves-api/paper-patches/features/0001-Delete-Timings.patch +++ b/leaves-api/paper-patches/features/0001-Delete-Timings.patch @@ -730,10 +730,10 @@ index 199789d56d22fcb1b77ebd56805cc28aa5a5ab0a..00000000000000000000000000000000 -} diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java deleted file mode 100644 -index c8287776ad585d04fb4fa3290cd73d7097035ea0..0000000000000000000000000000000000000000 +index 143fb3623a3fcf4be2d30dafb330584cb61ffe50..0000000000000000000000000000000000000000 --- a/src/main/java/co/aikar/timings/TimingHistory.java +++ /dev/null -@@ -1,357 +0,0 @@ +@@ -1,356 +0,0 @@ -/* - * This file is licensed under the MIT License (MIT). - * @@ -787,8 +787,7 @@ index c8287776ad585d04fb4fa3290cd73d7097035ea0..00000000000000000000000000000000 -import static co.aikar.util.JSONUtil.*; - -/** -- * Internal. -- * +- * @hidden - * @deprecated Timings will be removed in the future - */ -@Deprecated(forRemoval = true) @@ -2368,7 +2367,7 @@ index 5753b9bce89db2ac378ec41f1b61907cc2e23335..00000000000000000000000000000000 -} diff --git a/src/main/java/co/aikar/util/LoadingMap.java b/src/main/java/co/aikar/util/LoadingMap.java deleted file mode 100644 -index 1786eeb5cbeaad75602c9c5649bbcd9b2af5cf81..0000000000000000000000000000000000000000 +index 207b6853a0cb0185492b62c0c5d9602d48b7959c..0000000000000000000000000000000000000000 --- a/src/main/java/co/aikar/util/LoadingMap.java +++ /dev/null @@ -1,369 +0,0 @@ @@ -2456,9 +2455,9 @@ index 1786eeb5cbeaad75602c9c5649bbcd9b2af5cf81..00000000000000000000000000000000 - /** - * Creates a LoadingMap with an auto instantiating loader. - * -- * Will auto construct class of of Value when not found +- * Will auto construct class of Value when not found - * -- * Since this uses Reflection, It is more effecient to define your own static loader +- * Since this uses Reflection, It is more efficient to define your own static loader - * than using this helper, but if performance is not critical, this is easier. - * - * @param backingMap Actual map being used. @@ -2476,9 +2475,9 @@ index 1786eeb5cbeaad75602c9c5649bbcd9b2af5cf81..00000000000000000000000000000000 - /** - * Creates a LoadingMap with an auto instantiating loader. - * -- * Will auto construct class of of Value when not found +- * Will auto construct class of Value when not found - * -- * Since this uses Reflection, It is more effecient to define your own static loader +- * Since this uses Reflection, It is more efficient to define your own static loader - * than using this helper, but if performance is not critical, this is easier. - * - * @param backingMap Actual map being used. @@ -2860,7 +2859,7 @@ index 3e61a926620a67daec3af54b72a1b911eaef2ed4..00000000000000000000000000000000 - } -} diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 27a7c69f23084e821d945d5e97e51a94ddd94e58..d645ee8470a2dd9f7b8eff2b7ff2211aba9c342f 100644 +index e387ba67f0b6cde8ee2be7acba8f791792802ad4..06402e9d811b62ea59c67ecbffe9272c73f2040d 100644 --- a/src/main/java/org/bukkit/command/Command.java +++ b/src/main/java/org/bukkit/command/Command.java @@ -32,16 +32,6 @@ public abstract class Command { diff --git a/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch b/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch index 40d5d1d3..8ad1b2da 100644 --- a/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch +++ b/leaves-api/paper-patches/features/0003-Add-fakeplayer-api.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add fakeplayer api diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 3bde4ad79ade5aae18e9073307f637717e8dd9e3..9971ed1347f0f37800911c6cd9d0f8ae1a4f100c 100644 +index 14d81c7b138ebf999d5812d26fbf869209c100f3..3b0513fbbf46e7cbb1790264eebaed9862d48eb5 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3016,4 +3016,15 @@ public final class Bukkit { +@@ -3003,4 +3003,15 @@ public final class Bukkit { public static void restart() { server.restart(); } @@ -25,10 +25,10 @@ index 3bde4ad79ade5aae18e9073307f637717e8dd9e3..9971ed1347f0f37800911c6cd9d0f8ae + // Leaves end - Bot API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9bab00ab10c78908090c8a1a12d4c84e9324b08b..3e7aad4ddf573f7c868b7824c4f0f34fa08cb1fe 100644 +index 964b57bb240151ddf4f11c203b67e8be6469e473..865842a857e5371bd82133a018582c7b88566403 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2723,4 +2723,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2760,4 +2760,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ void allowPausing(@NotNull org.bukkit.plugin.Plugin plugin, boolean value); // Paper end - API to check if the server is sleeping diff --git a/leaves-api/paper-patches/features/0004-Replay-Mod-API.patch b/leaves-api/paper-patches/features/0004-Replay-Mod-API.patch index c19bfac3..11cd9e02 100644 --- a/leaves-api/paper-patches/features/0004-Replay-Mod-API.patch +++ b/leaves-api/paper-patches/features/0004-Replay-Mod-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Replay Mod API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 9971ed1347f0f37800911c6cd9d0f8ae1a4f100c..803611b793daed2d51ef6ab34d01fc8b0a3ecd23 100644 +index 3b0513fbbf46e7cbb1790264eebaed9862d48eb5..44ee8036e2f813e947c2c166e1876030cabf86ff 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3027,4 +3027,10 @@ public final class Bukkit { +@@ -3014,4 +3014,10 @@ public final class Bukkit { return server.getBotManager(); } // Leaves end - Bot API @@ -20,10 +20,10 @@ index 9971ed1347f0f37800911c6cd9d0f8ae1a4f100c..803611b793daed2d51ef6ab34d01fc8b + // Leaves end - Photographer API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 3e7aad4ddf573f7c868b7824c4f0f34fa08cb1fe..ce128dd8120b75884cb208d7ba7d316ee110333b 100644 +index 865842a857e5371bd82133a018582c7b88566403..74f704d4245199205afff5a992805f40a365cc81 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2732,4 +2732,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2769,4 +2769,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ @NotNull org.leavesmc.leaves.entity.bot.BotManager getBotManager(); // Leaves end - Bot API diff --git a/leaves-api/paper-patches/features/0005-Bytebuf-API.patch b/leaves-api/paper-patches/features/0005-Bytebuf-API.patch index 54357505..ebea3a33 100644 --- a/leaves-api/paper-patches/features/0005-Bytebuf-API.patch +++ b/leaves-api/paper-patches/features/0005-Bytebuf-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Bytebuf API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 803611b793daed2d51ef6ab34d01fc8b0a3ecd23..0149af5bd4234f925e12d78251766be5a16e5060 100644 +index 44ee8036e2f813e947c2c166e1876030cabf86ff..c25729882f87a904e59680967f3d20b02df50eae 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3033,4 +3033,10 @@ public final class Bukkit { +@@ -3020,4 +3020,10 @@ public final class Bukkit { return server.getPhotographerManager(); } // Leaves end - Photographer API @@ -20,10 +20,10 @@ index 803611b793daed2d51ef6ab34d01fc8b0a3ecd23..0149af5bd4234f925e12d78251766be5 + // Leaves end - Bytebuf API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index ce128dd8120b75884cb208d7ba7d316ee110333b..e63fb4e0c55929f2721e16f69e0c0a4b455477fa 100644 +index 74f704d4245199205afff5a992805f40a365cc81..9f9051214c81e1fc4a6f1a0b0d18ea98bdf2fe92 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2736,4 +2736,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2773,4 +2773,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi // Leaves start - Photographer API @NotNull org.leavesmc.leaves.entity.photographer.PhotographerManager getPhotographerManager(); // Leaves end - Photographer API @@ -33,10 +33,10 @@ index ce128dd8120b75884cb208d7ba7d316ee110333b..e63fb4e0c55929f2721e16f69e0c0a4b + // Leaves end - Bytebuf API } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 3584ca0a89f59e391ab6d5be8f2274a6801d025f..4171ac88c491c071af9def920084292e108587f0 100644 +index 3eef8d533c2aa65d66fbd58f2260b4764a964ebe..73285735653a3aec90df4866b3f97f8ca38a5394 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java -@@ -3859,6 +3859,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -3931,6 +3931,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM boolean isChunkSent(long chunkKey); // Paper end diff --git a/leaves-api/paper-patches/features/0008-Leaves-Config-API.patch b/leaves-api/paper-patches/features/0008-Leaves-Config-API.patch index f3781937..170f6c93 100644 --- a/leaves-api/paper-patches/features/0008-Leaves-Config-API.patch +++ b/leaves-api/paper-patches/features/0008-Leaves-Config-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaves Config API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 0149af5bd4234f925e12d78251766be5a16e5060..3c019280bc751e0710f1d34478b56986bc6000fc 100644 +index c25729882f87a904e59680967f3d20b02df50eae..5cc913f9e903ea5ef51c2e2b8cc18fdad8838c1e 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3039,4 +3039,10 @@ public final class Bukkit { +@@ -3026,4 +3026,10 @@ public final class Bukkit { return server.getBytebufManager(); } // Leaves end - Bytebuf API @@ -20,10 +20,10 @@ index 0149af5bd4234f925e12d78251766be5a16e5060..3c019280bc751e0710f1d34478b56986 + // Leaves end - Config API } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index e63fb4e0c55929f2721e16f69e0c0a4b455477fa..37ff5eabaf0fd3ab72eb37a1f21904b5a1adebe0 100644 +index 9f9051214c81e1fc4a6f1a0b0d18ea98bdf2fe92..95621c3b4279f4d1b7786772cc035f3747e9d84f 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2740,4 +2740,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2777,4 +2777,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi // Leaves start - Bytebuf API org.leavesmc.leaves.bytebuf.BytebufManager getBytebufManager(); // Leaves end - Bytebuf API diff --git a/leaves-api/paper-patches/features/0009-Leaves-Plugin.patch b/leaves-api/paper-patches/features/0009-Leaves-Plugin.patch index ca6e2c59..8b209602 100644 --- a/leaves-api/paper-patches/features/0009-Leaves-Plugin.patch +++ b/leaves-api/paper-patches/features/0009-Leaves-Plugin.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Leaves Plugin This patch is licensed under the MIT license. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 6c7a84baee27bd1e1ab95fe3a84057b8109c78d1..195a63c86c565ea0a1672138b9d217abaa0258ad 100644 +index 5cc913f9e903ea5ef51c2e2b8cc18fdad8838c1e..554b8977c9b358f177e29907bcebaed8ab2100fc 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -3017,6 +3017,12 @@ public final class Bukkit { +@@ -3004,6 +3004,12 @@ public final class Bukkit { server.restart(); } @@ -23,10 +23,10 @@ index 6c7a84baee27bd1e1ab95fe3a84057b8109c78d1..195a63c86c565ea0a1672138b9d217ab /** * Returns a bot manager. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 8aa35daa8c80d90c4e863902a4db85175885cfe8..6e0d00d3d7220cacac781b010dac4212c64d5b08 100644 +index 95621c3b4279f4d1b7786772cc035f3747e9d84f..cdc5295db1dbbd4b20a0acc99fdcc9013d6a5489 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2724,6 +2724,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2761,6 +2761,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi void allowPausing(@NotNull org.bukkit.plugin.Plugin plugin, boolean value); // Paper end - API to check if the server is sleeping diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/Bot.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/Bot.java index df7dbdd0..f49d18aa 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/Bot.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/Bot.java @@ -22,9 +22,9 @@ public interface Bot extends Player { /** * Gets the fakeplayer name without prefix and suffix * - * @return fakeplayer real name + * @return fakeplayer raw name */ - @NotNull String getRealName(); + @NotNull String getRawName(); /** * Gets the creator's UUID of the fakeplayer @@ -74,4 +74,13 @@ public interface Bot extends Player { * @return success */ boolean remove(boolean save); + + /** + * Remove the fakeplayer + * + * @param save should save + * @param resume should resume at next server start + * @return success + */ + boolean remove(boolean save, boolean resume); } diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotCreator.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotCreator.java index e70b1f33..1bb6f48f 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotCreator.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotCreator.java @@ -10,8 +10,8 @@ import java.util.function.Consumer; public interface BotCreator { - static BotCreator of(String realName, Location location) { - return Bukkit.getBotManager().botCreator(realName, location); + static BotCreator of(String rawName, Location location) { + return Bukkit.getBotManager().botCreator(rawName, location); } BotCreator name(String name); diff --git a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java index c434364f..8271673a 100644 --- a/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java +++ b/leaves-api/src/main/java/org/leavesmc/leaves/entity/bot/BotManager.java @@ -44,5 +44,5 @@ public interface BotManager { */ > T newAction(@NotNull Class type); - BotCreator botCreator(@NotNull String realName, @NotNull Location location); + BotCreator botCreator(@NotNull String rawName, @NotNull Location location); } diff --git a/leaves-server/build.gradle.kts.patch b/leaves-server/build.gradle.kts.patch index 10814803..f2701cf0 100644 --- a/leaves-server/build.gradle.kts.patch +++ b/leaves-server/build.gradle.kts.patch @@ -4,13 +4,13 @@ -import io.papermc.fill.model.BuildChannel import io.papermc.paperweight.attribute.DevBundleOutput import io.papermc.paperweight.util.* - import io.papermc.paperweight.util.data.FileEntry -@@ -10,24 +_,36 @@ + import java.time.Instant +@@ -7,22 +_,34 @@ `java-library` `maven-publish` idea - id("io.papermc.paperweight.core") -- id("io.papermc.fill.gradle") version "1.0.7" +- id("io.papermc.fill.gradle") version "1.0.9" + id("org.leavesmc.leavesweight.core") // Leaves - build change } @@ -18,9 +18,9 @@ +val leavesMavenPublicUrl = "https://repo.leavesmc.com/snapshots/" // Leaves - build change dependencies { - mache("io.papermc:mache:1.21.8+build.2") + mache("io.papermc:mache:1.21.10+build.9") - paperclip("io.papermc:paperclip:3.0.3") -+ leavesclip("org.leavesmc:leavesclip:3.0.7") // Leaves - build change ++ leavesclip("org.leavesmc:leavesclip:3.0.8") // Leaves - build change testRuntimeOnly("org.junit.platform:junit-platform-launcher") } @@ -42,12 +42,9 @@ + // Leaves end - build change + spigot { -- enabled = true -+ // enabled = true // Leaves - disable - buildDataRef = "436eac9815c211be1a2a6ca0702615f995e81c44" - packageVersion = "v1_21_R5" // also needs to be updated in MappingEnvironment - } -@@ -49,6 +_,7 @@ + enabled = true + buildDataRef = "42d18d4c4653ffc549778dbe223f6994a031d69e" +@@ -46,6 +_,7 @@ libraryRepositories.addAll( "https://repo.maven.apache.org/maven2/", paperMavenPublicUrl, @@ -55,7 +52,7 @@ ) } -@@ -107,7 +_,22 @@ +@@ -104,7 +_,22 @@ } } @@ -79,7 +76,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { extendsFrom(configurations.compileClasspath.get()) } -@@ -129,7 +_,19 @@ +@@ -127,7 +_,19 @@ } dependencies { @@ -97,10 +94,10 @@ + exclude(group = "com.google.guava", module = "guava") + } + // Leaves end - leaves plugin - implementation("ca.spottedleaf:concurrentutil:0.0.3") + implementation("ca.spottedleaf:concurrentutil:0.0.7") implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 -@@ -157,7 +_,6 @@ +@@ -154,7 +_,6 @@ implementation("org.spongepowered:configurate-yaml:4.2.0") // Deps that were previously in the API but have now been moved here for backwards compat, eventually to be removed @@ -108,8 +105,8 @@ runtimeOnly("org.xerial:sqlite-jdbc:3.49.1.0") runtimeOnly("com.mysql:mysql-connector-j:9.2.0") runtimeOnly("com.lmax:disruptor:3.4.4") -@@ -188,26 +_,36 @@ - implementation("me.lucko:spark-paper:1.10.133-20250413.112336-1") +@@ -185,26 +_,36 @@ + implementation("me.lucko:spark-paper:1.10.152") } +// Leaves start - hide irrelevant compilation warnings @@ -127,7 +124,7 @@ val git = Git(rootProject.layout.projectDirectory.path) val mcVersion = rootProject.providers.gradleProperty("mcVersion").get() val build = System.getenv("BUILD_NUMBER") ?: null -- val buildTime = if (build != null) Instant.now() else Instant.EPOCH +- val buildTime = providers.environmentVariable("BUILD_STARTED_AT").map(Instant::parse).orElse(Instant.EPOCH).get() + val buildTime = Instant.now() // Leaves - always use build time val gitHash = git.exec(providers, "rev-parse", "--short=7", "HEAD").get().trim() val implementationVersion = "$mcVersion-${build ?: "DEV"}-$gitHash" @@ -151,7 +148,7 @@ "Build-Number" to (build ?: ""), "Build-Time" to buildTime.toString(), "Git-Branch" to gitBranch, -@@ -266,7 +_,7 @@ +@@ -263,7 +_,7 @@ jvmArgumentProviders.add(provider) } @@ -160,7 +157,7 @@ idea { module { generatedSourceDirs.add(generatedDir.toFile()) -@@ -315,6 +_,10 @@ +@@ -300,6 +_,10 @@ } args("--nogui") @@ -171,7 +168,7 @@ systemProperty("net.kyori.adventure.text.warnWhenLegacyFormattingDetected", true) if (providers.gradleProperty("paper.runDisableWatchdog").getOrElse("false") == "true") { systemProperty("disable.watchdog", true) -@@ -359,30 +_,26 @@ +@@ -344,30 +_,26 @@ classpath(tasks.createReobfBundlerJar.flatMap { it.outputZip }) mainClass.set(null as String?) } diff --git a/leaves-server/minecraft-patches/features/0001-Build-changes.patch b/leaves-server/minecraft-patches/features/0001-Build-changes.patch index 6a7d78cd..a521d1bb 100644 --- a/leaves-server/minecraft-patches/features/0001-Build-changes.patch +++ b/leaves-server/minecraft-patches/features/0001-Build-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Build changes diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java -index 42899a91b9061b85985fbbd0de4032c757f4aa8f..a93f00d1a64e4deb9b89435bab258f3bad487e2f 100644 +index 4b87e48309323faee2bf5cc65428a28d8646ef7a..d129f160acf0da81cadeacab9587d86dcc49dc6a 100644 --- a/ca/spottedleaf/moonrise/paper/PaperHooks.java +++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java @@ -29,7 +29,7 @@ import net.minecraft.world.phys.AABB; @@ -18,10 +18,10 @@ index 42899a91b9061b85985fbbd0de4032c757f4aa8f..a93f00d1a64e4deb9b89435bab258f3b private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 9243bb11e3f968d0bf0eb2e3dc9295c0232bc15d..9ba90e9e1c6dae13579337edb5a5bede0daa4098 100644 +index f63a5567a2e845de904c2dacfbb875049e3e0c65..e82584a516af3b08ca4b11ed2aaf28cfbf345825 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1194,7 +1194,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Sat, 1 Feb 2025 14:21:05 +0800 -Subject: [PATCH] Leaves Server Config And Command +Subject: [PATCH] Leaves Server Config diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index c22234df51a61954d1728b8406545f753dd8a3c2..d4775a33ee63a61e15ec3c1051261c01f2af28e0 100644 +index 4693330ebbd1540559caa4ef5494e75b69351c24..ecdb937f08a437a1d2398e49ca835071015844f2 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -184,6 +184,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -277,6 +277,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now @@ -16,4 +16,4 @@ index c22234df51a61954d1728b8406545f753dd8a3c2..d4775a33ee63a61e15ec3c1051261c01 + com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics // Leaves - down - this.setPvpAllowed(properties.pvp); + // this.worldData.setGameType(properties.gameMode.get()); // CraftBukkit - moved to world loading diff --git a/leaves-server/minecraft-patches/features/0003-Leaves-Utils.patch b/leaves-server/minecraft-patches/features/0003-Leaves-Utils.patch index 2869a2e8..8c096dd6 100644 --- a/leaves-server/minecraft-patches/features/0003-Leaves-Utils.patch +++ b/leaves-server/minecraft-patches/features/0003-Leaves-Utils.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaves Utils diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 70b6ea8ab35e88989b5b1f5ffd64490a9d743b56..ea616ff83c14dd582bdb49442bc0b9103fc8f1b3 100644 +index 2e3e038874757049445a91bf590d5a1a427a3f6d..9b122a3dc18c6dbc84683ab54e5a503d0a5b7e4b 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -372,6 +372,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -373,6 +373,8 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name public boolean isTemporarilyActive; public long activatedImmunityTick = Integer.MIN_VALUE; @@ -17,7 +17,7 @@ index 70b6ea8ab35e88989b5b1f5ffd64490a9d743b56..ea616ff83c14dd582bdb49442bc0b910 public void inactiveTick() { } // Paper end - EAR 2 -@@ -2585,6 +2587,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2634,6 +2636,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name output.putBoolean("Paper.FreezeLock", true); } // Paper end @@ -25,7 +25,7 @@ index 70b6ea8ab35e88989b5b1f5ffd64490a9d743b56..ea616ff83c14dd582bdb49442bc0b910 } catch (Throwable var7) { CrashReport crashReport = CrashReport.forThrowable(var7, "Saving entity NBT"); CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being saved"); -@@ -2705,6 +2708,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2754,6 +2757,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name } freezeLocked = input.getBooleanOr("Paper.FreezeLock", false); // Paper end @@ -33,16 +33,16 @@ index 70b6ea8ab35e88989b5b1f5ffd64490a9d743b56..ea616ff83c14dd582bdb49442bc0b910 } catch (Throwable var7) { CrashReport crashReport = CrashReport.forThrowable(var7, "Loading entity NBT"); CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded"); -@@ -4422,7 +4426,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - return SlotAccess.NULL; +@@ -4512,7 +4516,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + return this.getType().is(EntityTypeTags.DEFLECTS_PROJECTILES) ? ProjectileDeflection.REVERSE : ProjectileDeflection.NONE; } - @Nullable + @org.jetbrains.annotations.NotNull // Leaves - notnull - public MinecraftServer getServer() { - return this.level().getServer(); + public net.minecraft.world.entity.LivingEntity getControllingPassenger() { + return null; } -@@ -5364,4 +5368,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5402,4 +5406,9 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name return ((ServerLevel) this.level()).isPositionEntityTicking(this.blockPosition()); } // Paper end - Expose entity id counter @@ -53,10 +53,10 @@ index 70b6ea8ab35e88989b5b1f5ffd64490a9d743b56..ea616ff83c14dd582bdb49442bc0b910 + // Leaves end - leaves ex data } diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index c41df4b1fff1f65532256e835dc30fadbb4f8c8b..9383d9f940163f42db8802f0a260925a83119160 100644 +index d225267b1b07854b76c88ce461d7817a86d023a0..01e0dc28ef63456a45b800e72d76180b40811a72 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -962,7 +962,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -916,7 +916,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl return this.isClientSide; } @@ -66,7 +66,7 @@ index c41df4b1fff1f65532256e835dc30fadbb4f8c8b..9383d9f940163f42db8802f0a260925a public MinecraftServer getServer() { return null; diff --git a/net/minecraft/world/level/LevelAccessor.java b/net/minecraft/world/level/LevelAccessor.java -index 5f28df24876f93866312c3c7d19cb6bcaf5e2f8b..049133cba588612127b45c1489f80d2fe6d6e330 100644 +index e4a9e59661f5b51caf5b4fb12b0c90b14c1f9647..f5e9e395f04d5335d5d9a220f94962a72e38577d 100644 --- a/net/minecraft/world/level/LevelAccessor.java +++ b/net/minecraft/world/level/LevelAccessor.java @@ -46,7 +46,7 @@ public interface LevelAccessor extends CommonLevelAccessor, LevelTimeAccess, Sch @@ -79,10 +79,10 @@ index 5f28df24876f93866312c3c7d19cb6bcaf5e2f8b..049133cba588612127b45c1489f80d2f default Difficulty getDifficulty() { diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java -index be6f37f91569c659c609e5e8d38671ca86f8cd95..958914e40fceda5d67a98154817b4c5ce478a62d 100644 +index 572fcb33b14d16334e2ab92ddf8699f1ba975aff..c431d0c45e71e0c8b880784181c92967e40779bd 100644 --- a/net/minecraft/world/level/block/Block.java +++ b/net/minecraft/world/level/block/Block.java -@@ -610,6 +610,13 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -649,6 +649,13 @@ public class Block extends BlockBehaviour implements ItemLike { } // CraftBukkit end @@ -97,10 +97,10 @@ index be6f37f91569c659c609e5e8d38671ca86f8cd95..958914e40fceda5d67a98154817b4c5c @Override public boolean equals(Object other) { diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java -index 834e27ef2f7b342b074ff9e1e390e02f3ca1c399..be66f0f1cb1b0bcec8f9489a1fdd8777df1adb6b 100644 +index d31da50baeb7f47f0e1d81ee3c05023370df8cd3..a38618c28819405f0fb35aa686d1f3f0e94e5da2 100644 --- a/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -763,7 +763,7 @@ public abstract class BlockBehaviour implements FeatureElement { +@@ -766,7 +766,7 @@ public abstract class BlockBehaviour implements FeatureElement { } public PushReaction getPistonPushReaction() { diff --git a/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch b/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch index 877d4e3a..9cd8e843 100644 --- a/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch +++ b/leaves-server/minecraft-patches/features/0004-Leaves-Protocol-Core.patch @@ -33,10 +33,10 @@ index fb263fa1f30a7dfcb7ec2656abfb38e5fe88eac9..56fd1ed7ccaf96e7eedea60fbdbf7f93 }; } diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 9ba90e9e1c6dae13579337edb5a5bede0daa4098..eb6d5e82b6a2576af14c0c080a05a87022f90c93 100644 +index e82584a516af3b08ca4b11ed2aaf28cfbf345825..2493722c47b92cbcd13c08af0caf38a543ac7e37 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1745,6 +1745,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginMessagerChannels; // Paper end - retain certain values @@ -57,7 +57,7 @@ index f02800e4e941b05bde6f0d5fac76e2b6ec5b9832..7a7090a2a7b41762d94cebf847cc6a79 public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie) { this.server = server; -@@ -70,6 +71,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -71,6 +72,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack this.pluginMessagerChannels = cookie.channels(); this.keepAlive = cookie.keepAlive(); // Paper end @@ -65,7 +65,7 @@ index f02800e4e941b05bde6f0d5fac76e2b6ec5b9832..7a7090a2a7b41762d94cebf847cc6a79 } // Paper start - configuration phase API -@@ -149,6 +151,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -150,6 +152,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @Override public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { @@ -84,7 +84,7 @@ index f02800e4e941b05bde6f0d5fac76e2b6ec5b9832..7a7090a2a7b41762d94cebf847cc6a79 // Paper start if (!(packet.payload() instanceof final net.minecraft.network.protocol.common.custom.DiscardedPayload discardedPayload)) { return; -@@ -208,10 +222,11 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -209,10 +223,11 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack final String channel = new String(data, from, length, java.nio.charset.StandardCharsets.US_ASCII); if (register) { bridge.addChannel(channel); @@ -97,7 +97,7 @@ index f02800e4e941b05bde6f0d5fac76e2b6ec5b9832..7a7090a2a7b41762d94cebf847cc6a79 } @Override -@@ -379,9 +394,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -380,9 +395,9 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack net.minecraft.server.level.ServerPlayer player = serverGamePacketListener.player; org.bukkit.event.player.PlayerKickEvent.Cause cause = disconnectionDetails.disconnectionReason().orElseThrow().game().orElse(org.bukkit.event.player.PlayerKickEvent.Cause.UNKNOWN); org.bukkit.event.player.PlayerKickEvent event = new org.bukkit.event.player.PlayerKickEvent( @@ -110,7 +110,7 @@ index f02800e4e941b05bde6f0d5fac76e2b6ec5b9832..7a7090a2a7b41762d94cebf847cc6a79 ); -@@ -414,10 +429,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -415,10 +430,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack private void disconnect0(DisconnectionDetails disconnectionDetails) { this.connection @@ -126,19 +126,19 @@ index f02800e4e941b05bde6f0d5fac76e2b6ec5b9832..7a7090a2a7b41762d94cebf847cc6a79 this.connection.setReadOnly(); // CraftBukkit - Don't wait diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index e1fd699b33832c0f01b14023db7cc2b9d6797227..e064fd73a3904bf6aeb6ba38978cfea81e79e5dc 100644 +index cc5d1e8007e2ea32605bd68d0a73683e8fb6886e..d9fbc5dc6665fd13cc2aa9978ea6edef4c736548 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -335,6 +335,8 @@ public abstract class PlayerList { - return; - } +@@ -239,6 +239,8 @@ public abstract class PlayerList { + return; + } + org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); + - final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); + final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -@@ -507,6 +509,7 @@ public abstract class PlayerList { + if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure +@@ -424,6 +426,7 @@ public abstract class PlayerList { return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName()))); } public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) { @@ -146,7 +146,7 @@ index e1fd699b33832c0f01b14023db7cc2b9d6797227..e064fd73a3904bf6aeb6ba38978cfea8 // Paper end - Fix kick event leave message not being sent ServerLevel serverLevel = player.level(); player.awardStat(Stats.LEAVE_GAME); -@@ -1396,6 +1399,7 @@ public abstract class PlayerList { +@@ -1279,6 +1282,7 @@ public abstract class PlayerList { serverPlayer.connection.send(clientboundUpdateRecipesPacket); serverPlayer.getRecipeBook().sendInitialRecipeBook(serverPlayer); } diff --git a/leaves-server/minecraft-patches/features/0005-Configurable-trading-with-the-void.patch b/leaves-server/minecraft-patches/features/0005-Configurable-trading-with-the-void.patch index 65b248f2..ccd88a45 100644 --- a/leaves-server/minecraft-patches/features/0005-Configurable-trading-with-the-void.patch +++ b/leaves-server/minecraft-patches/features/0005-Configurable-trading-with-the-void.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable trading with the void diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index dda8d38ef61672cc714d9e5a475f9b0412ed5ff9..364d5e28646ea341034921622354c7b19644b343 100644 +index c0ed4e023b35a076b554fa387e9a2324166b2fae..0c9002b6ceaf5f11a059db356976215d5acf5cce 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2727,7 +2727,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2794,7 +2794,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Spigot start if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message // Paper start - Fix merchant inventory not closing on entity removal @@ -18,10 +18,10 @@ index dda8d38ef61672cc714d9e5a475f9b0412ed5ff9..364d5e28646ea341034921622354c7b1 } // Paper end - Fix merchant inventory not closing on entity removal diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 91f505c9d84aba773d237664c2aaaf9750cadadf..184d116320f0cd3e9fba47a86e94e0a8424c913f 100644 +index d9fbc5dc6665fd13cc2aa9978ea6edef4c736548..4abf4ea7f86955351b5e4da2c89a707003802d2e 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -551,7 +551,7 @@ public abstract class PlayerList { +@@ -468,7 +468,7 @@ public abstract class PlayerList { player.stopRiding(); rootVehicle.getPassengersAndSelf().forEach(entity -> { // Paper start - Fix villager boat exploit @@ -31,7 +31,7 @@ index 91f505c9d84aba773d237664c2aaaf9750cadadf..184d116320f0cd3e9fba47a86e94e0a8 if (human != null) { villager.setTradingPlayer(null); diff --git a/net/minecraft/world/inventory/MerchantMenu.java b/net/minecraft/world/inventory/MerchantMenu.java -index d59f67ffe34201c63e3d9706a4434f33b6732edb..1bf2a015fa35981328c098f2fec363c84b85b2a7 100644 +index 6dfee62a46a5882df7f405e59d762647289d7866..ade7732b638b30ad0ae50605793cbf75754aad0e 100644 --- a/net/minecraft/world/inventory/MerchantMenu.java +++ b/net/minecraft/world/inventory/MerchantMenu.java @@ -74,6 +74,7 @@ public class MerchantMenu extends AbstractContainerMenu { diff --git a/leaves-server/minecraft-patches/features/0006-Make-snowball-and-egg-can-knockback-player.patch b/leaves-server/minecraft-patches/features/0006-Make-snowball-and-egg-can-knockback-player.patch index eb2a4d1a..c2b8bf2c 100644 --- a/leaves-server/minecraft-patches/features/0006-Make-snowball-and-egg-can-knockback-player.patch +++ b/leaves-server/minecraft-patches/features/0006-Make-snowball-and-egg-can-knockback-player.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make snowball and egg can knockback player diff --git a/net/minecraft/world/entity/projectile/Snowball.java b/net/minecraft/world/entity/projectile/Snowball.java -index 677b4b681f9c2c09a8ae3cfdec72102265547a7b..1474cf208019cd46ca767374bceb3c9c31fdeab2 100644 +index cd36d3a988ae871fe93157c24c26f36308c71fbf..f8da22e77547916076056ea7202dd499fefd8f9f 100644 --- a/net/minecraft/world/entity/projectile/Snowball.java +++ b/net/minecraft/world/entity/projectile/Snowball.java -@@ -54,6 +54,12 @@ public class Snowball extends ThrowableItemProjectile { +@@ -55,6 +55,12 @@ public class Snowball extends ThrowableItemProjectile { Entity entity = result.getEntity(); int i = entity instanceof Blaze ? 3 : 0; entity.hurt(this.damageSources().thrown(this, this.getOwner()), i); @@ -22,10 +22,10 @@ index 677b4b681f9c2c09a8ae3cfdec72102265547a7b..1474cf208019cd46ca767374bceb3c9c @Override diff --git a/net/minecraft/world/entity/projectile/ThrownEgg.java b/net/minecraft/world/entity/projectile/ThrownEgg.java -index 73ec34b43f3fb2aa3edc3f1cb48a923d1fa32036..6583f983129b2a90bd44104de9f4f992fa21a00c 100644 +index bbb364be2af16a3c200d2197166bb3ad28e5e35d..34deb006b1a81e8c6f65150ac7ab80f037ffa0c7 100644 --- a/net/minecraft/world/entity/projectile/ThrownEgg.java +++ b/net/minecraft/world/entity/projectile/ThrownEgg.java -@@ -55,6 +55,12 @@ public class ThrownEgg extends ThrowableItemProjectile { +@@ -56,6 +56,12 @@ public class ThrownEgg extends ThrowableItemProjectile { protected void onHitEntity(EntityHitResult result) { super.onHitEntity(result); result.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F); diff --git a/leaves-server/minecraft-patches/features/0007-Leaves-Fakeplayer.patch b/leaves-server/minecraft-patches/features/0007-Leaves-Fakeplayer.patch index 62d18af5..13f92ccb 100644 --- a/leaves-server/minecraft-patches/features/0007-Leaves-Fakeplayer.patch +++ b/leaves-server/minecraft-patches/features/0007-Leaves-Fakeplayer.patch @@ -17,10 +17,10 @@ index a82d84283632342bd30bc3449983431ba43583e0..f59526f6bfa1b4af5b474f0b438513c9 Set> set = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak if (set != null && !set.isEmpty()) { diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java -index 41005f6b9f53a9c1125ad5e08538d9f5aacb3571..3e9b8c5fb2157f767de8bddc3e767512c5f7651f 100644 +index 14addbaf68b7ad80490187d12d9c9b00891e2ce1..b186b5e0d3b32d7b51b2f58f0ef4b2bf36ae5c13 100644 --- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java -@@ -96,7 +96,7 @@ public class Connection extends SimpleChannelInboundHandler> { +@@ -95,7 +95,7 @@ public class Connection extends SimpleChannelInboundHandler> { @Nullable private volatile PacketListener disconnectListener; @Nullable @@ -30,19 +30,19 @@ index 41005f6b9f53a9c1125ad5e08538d9f5aacb3571..3e9b8c5fb2157f767de8bddc3e767512 private DisconnectionDetails disconnectionDetails; private boolean encrypted; diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index eb6d5e82b6a2576af14c0c080a05a87022f90c93..5c49816db8241694eed640a34c056effbf382934 100644 +index 2493722c47b92cbcd13c08af0caf38a543ac7e37..309ff4c55b2a4ccf3d18951b51c2e10d0ff39bfc 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -304,6 +304,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping - public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation +@@ -378,6 +378,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function threadFunction) { ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system AtomicReference atomicReference = new AtomicReference<>(); -@@ -996,6 +998,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { - if (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping @@ -59,7 +59,7 @@ index eb6d5e82b6a2576af14c0c080a05a87022f90c93..5c49816db8241694eed640a34c056eff this.emptyTicks++; } else { this.emptyTicks = 0; -@@ -1763,6 +1766,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop gameProfiles, @Nullable Component reason) throws CommandSyntaxException { +@@ -44,8 +44,15 @@ public class BanPlayerCommands { + private static int banPlayers(CommandSourceStack source, Collection players, @Nullable Component reason) throws CommandSyntaxException { UserBanList bans = source.getServer().getPlayerList().getBans(); int i = 0; - + boolean hasBot = false; // Leaves - disable kick - for (GameProfile gameProfile : gameProfiles) { + for (NameAndId nameAndId : players) { + // Leaves start - disable ban -+ if (gameProfile instanceof org.leavesmc.leaves.bot.BotList.CustomGameProfile) { ++ if (nameAndId.isBot()) { + source.sendFailure(Component.literal("Permission denied")); + hasBot = true; + continue; + } + // Leaves end - disable ban -+ ServerPlayer player = source.getServer().getPlayerList().getPlayer(gameProfile.getId()); - if (!bans.isBanned(gameProfile)) { + if (!bans.isBanned(nameAndId)) { UserBanListEntry userBanListEntry = new UserBanListEntry( - gameProfile, null, source.getTextName(), null, reason == null ? null : reason.getString() -@@ -55,7 +63,6 @@ public class BanPlayerCommands { - source.sendSuccess( - () -> Component.translatable("commands.ban.success", Component.literal(gameProfile.getName()), userBanListEntry.getReason()), true - ); -- ServerPlayer player = source.getServer().getPlayerList().getPlayer(gameProfile.getId()); - if (player != null) { - player.connection.disconnect(Component.translatable("multiplayer.disconnect.banned"), org.bukkit.event.player.PlayerKickEvent.Cause.BANNED); // Paper - kick event cause - } + nameAndId, null, source.getTextName(), null, reason == null ? null : reason.getString() @@ -63,7 +70,13 @@ public class BanPlayerCommands { } @@ -163,7 +154,7 @@ index ac3ba9d0ea344fa189912d359b718fbe05e7aa49..61a4db144f721b47ac1000df72263bce return i; } diff --git a/net/minecraft/server/commands/KickCommand.java b/net/minecraft/server/commands/KickCommand.java -index 14e2e0fcf20c8fa875bbefb97a673be4928d099a..8af40a77dc3da1599da2793168488f88686b8785 100644 +index a5e5b0e0cd67a65b9fe3f69416070429196c5fa8..1a756a09cd281e60e8802a4111f71b0be1c70dcf 100644 --- a/net/minecraft/server/commands/KickCommand.java +++ b/net/minecraft/server/commands/KickCommand.java @@ -46,9 +46,17 @@ public class KickCommand { @@ -181,7 +172,7 @@ index 14e2e0fcf20c8fa875bbefb97a673be4928d099a..8af40a77dc3da1599da2793168488f88 + continue; + } + // Leaves end - disable kick - if (!source.getServer().isSingleplayerOwner(serverPlayer.getGameProfile())) { + if (!source.getServer().isSingleplayerOwner(serverPlayer.nameAndId())) { serverPlayer.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause source.sendSuccess(() -> Component.translatable("commands.kick.success", serverPlayer.getDisplayName(), reason), true); @@ -57,7 +65,13 @@ public class KickCommand { @@ -200,22 +191,22 @@ index 14e2e0fcf20c8fa875bbefb97a673be4928d099a..8af40a77dc3da1599da2793168488f88 return i; } diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java -index f2286b96b8f40b4588f817913c42ae7b4a92340f..e6c7bbb023000b9de90c1256274ff5aba4a6478a 100644 +index 4c7bccc00b9e84c4744f6cdc2c2e574a33ffe324..065af7f615711d7830002cd8f3046fab706082c1 100644 --- a/net/minecraft/server/commands/OpCommand.java +++ b/net/minecraft/server/commands/OpCommand.java @@ -43,6 +43,7 @@ public class OpCommand { int i = 0; - for (GameProfile gameProfile : gameProfiles) { -+ if (gameProfile instanceof org.leavesmc.leaves.bot.BotList.CustomGameProfile) continue; // Leaves - disable op - if (!playerList.isOp(gameProfile)) { - playerList.op(gameProfile); + for (NameAndId nameAndId : players) { ++ if (nameAndId.isBot()) continue; // Leaves - disable op + if (!playerList.isOp(nameAndId)) { + playerList.op(nameAndId); i++; diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 414a8357a7498c69341fa634ada2e664e18ca03a..f85993fc507d699728e058b12bb49dcb7aaea44b 100644 +index 361034289bb5e4241f3313581ddbc4e33823a9eb..8d73fffb41346851d088ca0dee206661ff85ec29 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -162,6 +162,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -255,6 +255,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } // Spigot start @@ -223,22 +214,22 @@ index 414a8357a7498c69341fa634ada2e664e18ca03a..f85993fc507d699728e058b12bb49dcb this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); org.spigotmc.SpigotConfig.init((java.io.File) this.options.valueOf("spigot-settings")); org.spigotmc.SpigotConfig.registerCommands(); -@@ -185,6 +186,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -278,6 +279,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now org.leavesmc.leaves.LeavesConfig.init((java.io.File) options.valueOf("leaves-settings")); // Leaves - Server Config -+ this.getBotList().loadBotInfo(); // Leaves - load resident bot info ++ this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics // Leaves - down diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index eb352aa4296abc3ed4cf31c590bc0be66daf4de3..019886669966c69936ae6591598c97a8afbfd3db 100644 +index ce53eb1e966e07b04e6a13785a858a3318b2c573..1993907c606b231b879a7279d3880876f5307b1c 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java -@@ -1317,6 +1317,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1365,6 +1365,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } - } else if (this.seenBy.remove(player.connection)) { - this.serverEntity.removePairing(player); + } else { + this.removePlayer(player); + // Leaves start - render bot + if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) { + if (bot.needSendFakeData(player)) { @@ -250,10 +241,10 @@ index eb352aa4296abc3ed4cf31c590bc0be66daf4de3..019886669966c69936ae6591598c97a8 } } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 364d5e28646ea341034921622354c7b19644b343..c61c0b6d58f96955bfbdad0caaeb56f073a95181 100644 +index 0c9002b6ceaf5f11a059db356976215d5acf5cce..2bab1246cf658508228c7f662175692bfd82cad4 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -214,6 +214,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -222,6 +222,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) @@ -261,7 +252,7 @@ index 364d5e28646ea341034921622354c7b19644b343..c61c0b6d58f96955bfbdad0caaeb56f0 @Override public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { -@@ -675,6 +676,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -699,6 +700,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit @@ -269,7 +260,7 @@ index 364d5e28646ea341034921622354c7b19644b343..c61c0b6d58f96955bfbdad0caaeb56f0 } // Paper start -@@ -2226,6 +2228,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2279,6 +2281,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return this.players; } @@ -282,7 +273,7 @@ index 364d5e28646ea341034921622354c7b19644b343..c61c0b6d58f96955bfbdad0caaeb56f0 @Override public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { Optional> optional = PoiTypes.forState(oldState); -@@ -2661,6 +2669,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2728,6 +2736,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.add(serverPlayer); @@ -294,7 +285,7 @@ index 364d5e28646ea341034921622354c7b19644b343..c61c0b6d58f96955bfbdad0caaeb56f0 if (serverPlayer.isReceivingWaypoints()) { ServerLevel.this.getWaypointManager().addPlayer(serverPlayer); } -@@ -2739,6 +2752,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2806,6 +2819,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe ServerLevel.this.getChunkSource().removeEntity(entity); if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.remove(serverPlayer); @@ -307,10 +298,10 @@ index 364d5e28646ea341034921622354c7b19644b343..c61c0b6d58f96955bfbdad0caaeb56f0 ServerLevel.this.updateSleepingPlayerList(); } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 8f94c963f2c59668d72d162f46f7505d6a6b06a5..87c8c4c7ca52f7d804ddaff87aaf381552e1aee2 100644 +index b4a996ac6c570e988b38237a32f90ec5042cbc17..04ea4e33504703c4074aef6e74ec06dc772b1bb9 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -219,7 +219,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -228,7 +228,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false; public ServerGamePacketListenerImpl connection; private final MinecraftServer server; @@ -319,7 +310,7 @@ index 8f94c963f2c59668d72d162f46f7505d6a6b06a5..87c8c4c7ca52f7d804ddaff87aaf3815 private final PlayerAdvancements advancements; private final ServerStatsCounter stats; private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE; -@@ -240,7 +240,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -249,7 +249,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc private Entity camera; public boolean isChangingDimension; public boolean seenCredits = false; @@ -328,7 +319,16 @@ index 8f94c963f2c59668d72d162f46f7505d6a6b06a5..87c8c4c7ca52f7d804ddaff87aaf3815 @Nullable private Vec3 levitationStartPos; private int levitationStartTime; -@@ -1454,6 +1454,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1250,7 +1250,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + this.setClientLoaded(false); + } + +- private void tellNeutralMobsThatIDied() { ++ protected void tellNeutralMobsThatIDied() { // Leaves private -> protected + AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0); + this.level() + .getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS) +@@ -1562,6 +1562,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.lastSentHealth = -1.0F; this.lastSentFood = -1; this.teleportSpectators(teleportTransition, serverLevel); @@ -340,61 +340,109 @@ index 8f94c963f2c59668d72d162f46f7505d6a6b06a5..87c8c4c7ca52f7d804ddaff87aaf3815 // CraftBukkit start org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld()); this.level().getCraftServer().getPluginManager().callEvent(changeEvent); -diff --git a/net/minecraft/server/players/GameProfileCache.java b/net/minecraft/server/players/GameProfileCache.java -index 066f84df5c31242ab542932f1e243369d0e766e2..52706e843923666940e679a83a302db7a243dd11 100644 ---- a/net/minecraft/server/players/GameProfileCache.java -+++ b/net/minecraft/server/players/GameProfileCache.java -@@ -125,6 +125,12 @@ public class GameProfileCache { - // Paper end +diff --git a/net/minecraft/server/players/CachedUserNameToIdResolver.java b/net/minecraft/server/players/CachedUserNameToIdResolver.java +index 3dc78b91cc853cfa6dce69979273b5f35b5f87f1..0625ebf19b5c514e096e6a91539c807ccf0b3f87 100644 +--- a/net/minecraft/server/players/CachedUserNameToIdResolver.java ++++ b/net/minecraft/server/players/CachedUserNameToIdResolver.java +@@ -121,6 +121,12 @@ public class CachedUserNameToIdResolver implements UserNameToIdResolver { - public Optional get(String name) { + @Override + public Optional get(String name) { + // Leaves start - fix bot + org.leavesmc.leaves.bot.ServerBot bot = org.leavesmc.leaves.bot.BotList.INSTANCE.getBotByName(name); + if (bot != null) { -+ return Optional.of(bot.getGameProfile()); ++ return Optional.of(bot.nameAndId()); + } + // Leaves end - fix bot String string = name.toLowerCase(Locale.ROOT); boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency - GameProfileCache.GameProfileInfo gameProfileInfo = this.profilesByName.get(string); + CachedUserNameToIdResolver.GameProfileInfo gameProfileInfo = this.profilesByName.get(string); +diff --git a/net/minecraft/server/players/NameAndId.java b/net/minecraft/server/players/NameAndId.java +index fdcc23c618b5db59e384a38f9ef91b6d2e922a8a..ccb56f29e79805f3286bbb80ce6c4d4b36a6e9e8 100644 +--- a/net/minecraft/server/players/NameAndId.java ++++ b/net/minecraft/server/players/NameAndId.java +@@ -8,18 +8,22 @@ import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.core.UUIDUtil; + +-public record NameAndId(UUID id, String name) { ++public record NameAndId(UUID id, String name, boolean isBot) { // Leaves - fakeplayer + public static final Codec CODEC = RecordCodecBuilder.create( + instance -> instance.group(UUIDUtil.STRING_CODEC.fieldOf("id").forGetter(NameAndId::id), Codec.STRING.fieldOf("name").forGetter(NameAndId::name)) + .apply(instance, NameAndId::new) + ); + + public NameAndId(GameProfile profile) { +- this(profile.id(), profile.name()); ++ this(profile.id(), profile.name(), com.google.common.collect.Iterables.getFirst(profile.properties().get("is_bot"), "false").equals("true")); // Leaves - fakeplayer + } + + public NameAndId(com.mojang.authlib.yggdrasil.response.NameAndId nameAndId) { +- this(nameAndId.id(), nameAndId.name()); ++ this(nameAndId.id(), nameAndId.name(), false); // Leaves - fakeplayer ++ } ++ ++ public NameAndId(UUID uuid, String name) { ++ this(uuid, name, false); // Leaves - fakeplayer + } + + @Nullable +@@ -34,7 +38,7 @@ public record NameAndId(UUID id, String name) { + return null; + } + +- return new NameAndId(uuid, json.get("name").getAsString()); ++ return new NameAndId(uuid, json.get("name").getAsString(), false); // Leaves - fakeplayer + } else { + return null; + } +@@ -47,7 +51,7 @@ public record NameAndId(UUID id, String name) { + + public static NameAndId createOffline(String name) { + UUID uuid = UUIDUtil.createOfflinePlayerUUID(name); +- return new NameAndId(uuid, name); ++ return new NameAndId(uuid, name, false); // Leaves - fakeplayer + } + + // Paper start - utility method for common conversion back to the game profile diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 2dffdc770529e048c4e8df7d70de59c94d3a77be..1135d32f1f275306792b95d10f76ac233e265e0d 100644 +index 4abf4ea7f86955351b5e4da2c89a707003802d2e..6dec8565e9d290302ce7766357a56b8c2295c163 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -337,6 +337,19 @@ public abstract class PlayerList { +@@ -241,6 +241,19 @@ public abstract class PlayerList { org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); -+ // Leaves start - bot support -+ if (org.leavesmc.leaves.LeavesConfig.modify.fakeplayer.enable) { -+ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName()); -+ if (bot != null) { -+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false); -+ } -+ this.server.getBotList().bots.forEach(bot1 -> { -+ bot1.sendPlayerInfo(player); -+ bot1.sendFakeDataIfNeed(player, true); -+ }); // Leaves - render bot ++ // Leaves start - bot support ++ if (org.leavesmc.leaves.LeavesConfig.modify.fakeplayer.enable) { ++ org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName()); ++ if (bot != null) { ++ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false); + } -+ // Leaves end - bot support ++ this.server.getBotList().bots.forEach(bot1 -> { ++ bot1.sendPlayerInfo(player); ++ bot1.sendFakeDataIfNeed(player, true); ++ }); // Leaves - render bot ++ } ++ // Leaves end - bot support + - final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); - - if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure -@@ -827,6 +840,12 @@ public abstract class PlayerList { - } - // Paper end - Add PlayerPostRespawnEvent + final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); + if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure +@@ -700,6 +713,12 @@ public abstract class PlayerList { + respawnReason + ).callEvent(); + // Paper end + // Leaves start - bot support + if (org.leavesmc.leaves.LeavesConfig.modify.fakeplayer.enable) { + this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(serverPlayer, true)); // Leaves - render bot + } + // Leaves end - bot support + - // CraftBukkit end return serverPlayer; -@@ -931,11 +950,16 @@ public abstract class PlayerList { + } +@@ -802,11 +821,16 @@ public abstract class PlayerList { } public String[] getPlayerNamesArray() { @@ -402,7 +450,7 @@ index 2dffdc770529e048c4e8df7d70de59c94d3a77be..1135d32f1f275306792b95d10f76ac23 + String[] strings = new String[this.players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support for (int i = 0; i < this.players.size(); i++) { - strings[i] = this.players.get(i).getGameProfile().getName(); + strings[i] = this.players.get(i).getGameProfile().name(); } + // Leaves start - fakeplayer support + for (int i = this.players.size(); i < strings.length; ++i) { @@ -412,7 +460,7 @@ index 2dffdc770529e048c4e8df7d70de59c94d3a77be..1135d32f1f275306792b95d10f76ac23 return strings; } -@@ -1038,7 +1062,14 @@ public abstract class PlayerList { +@@ -919,7 +943,14 @@ public abstract class PlayerList { @Nullable public ServerPlayer getPlayerByName(String username) { @@ -428,7 +476,15 @@ index 2dffdc770529e048c4e8df7d70de59c94d3a77be..1135d32f1f275306792b95d10f76ac23 } public void broadcast(@Nullable Player except, double x, double y, double z, double radius, ResourceKey dimension, Packet packet) { -@@ -1354,7 +1385,13 @@ public abstract class PlayerList { +@@ -960,6 +991,7 @@ public abstract class PlayerList { + } + // Paper end - Incremental chunk and player saving + } ++ org.leavesmc.leaves.bot.BotList.INSTANCE.saveAllResumeBots(); // Leaves - resident fakeplayer + return null; }); // Paper - ensure main + } + +@@ -1226,7 +1258,13 @@ public abstract class PlayerList { @Nullable public ServerPlayer getPlayer(UUID playerUUID) { @@ -442,7 +498,7 @@ index 2dffdc770529e048c4e8df7d70de59c94d3a77be..1135d32f1f275306792b95d10f76ac23 + // Leaves start - fakeplayer support } - public boolean canBypassPlayerLimit(GameProfile profile) { + @Nullable diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java index f9e7532f86122a379692561a639a209a126e8bba..2412f46837e967694222730e68e7d25ac32225cf 100644 --- a/net/minecraft/server/waypoints/ServerWaypointManager.java @@ -472,10 +528,10 @@ index f9e7532f86122a379692561a639a209a126e8bba..2412f46837e967694222730e68e7d25a for (WaypointTransmitter waypointTransmitter : this.waypoints) { diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 541bd2361b094f04dc2705979204930c564f8323..05730869d237439d3988635d4c8b048a7b654ca7 100644 +index 9b122a3dc18c6dbc84683ab54e5a503d0a5b7e4b..c6815ffef7fb2fd2e5ef2769c2c93135b52558f5 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -1173,7 +1173,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1185,7 +1185,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name BlockPos onPosLegacy = this.getOnPosLegacy(); BlockState blockState = this.level().getBlockState(onPosLegacy); @@ -484,7 +540,7 @@ index 541bd2361b094f04dc2705979204930c564f8323..05730869d237439d3988635d4c8b048a this.checkFallDamage(vec3.y, this.onGround(), blockState, onPosLegacy); } -@@ -1487,7 +1487,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1506,7 +1506,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name } // Paper start - optimise collisions @@ -494,10 +550,10 @@ index 541bd2361b094f04dc2705979204930c564f8323..05730869d237439d3988635d4c8b048a final boolean yZero = movement.y == 0.0; final boolean zZero = movement.z == 0.0; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 0268e02d2ef2cb3d699644a804e23a6da4521f4c..cc17fa4aa24d9fa258d61a74ba49c08979774698 100644 +index 025ef0b83e5d481c8b2ef25206cafd30897caabd..c18b0155edd695524246e5c2134de94008d8a023 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -3117,7 +3117,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3157,7 +3157,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin private void travelRidden(Player player, Vec3 travelVector) { Vec3 riddenInput = this.getRiddenInput(player, travelVector); this.tickRidden(player, riddenInput); @@ -506,16 +562,16 @@ index 0268e02d2ef2cb3d699644a804e23a6da4521f4c..cc17fa4aa24d9fa258d61a74ba49c089 this.setSpeed(this.getRiddenSpeed(player)); this.travel(riddenInput); } else { -@@ -3971,7 +3971,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -4006,7 +4006,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin // Paper start - lag compensate eating // we add 1 to the expected time to avoid lag compensating when we should not final boolean shouldLagCompensate = this.useItem.has(DataComponents.FOOD) && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1L + this.totalEatTimeTicks) * 50L * (1000L * 1000L)); -- if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide && !usingItem.useOnRelease()) { -+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !(this instanceof org.leavesmc.leaves.bot.ServerBot) && !this.level().isClientSide && !usingItem.useOnRelease()) { // Leaves - Fakeplayer skip this check +- if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide() && !usingItem.useOnRelease()) { ++ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !(this instanceof org.leavesmc.leaves.bot.ServerBot) && !this.level().isClientSide() && !usingItem.useOnRelease()) { this.useItemRemaining = 0; // Paper end - lag compensate eating this.completeUsingItem(); -@@ -4148,6 +4148,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -4183,6 +4183,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.stopUsingItem(); } @@ -537,13 +593,13 @@ index 0268e02d2ef2cb3d699644a804e23a6da4521f4c..cc17fa4aa24d9fa258d61a74ba49c089 + // Leaves end - Fakeplayer + public void stopUsingItem() { - if (!this.level().isClientSide) { + if (!this.level().isClientSide()) { boolean isUsingItem = this.isUsingItem(); diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 8f4c45fbea2d7c1317aff36031bb834b07b23a82..8ec6f52f58bcc985fdc758a692798a35d6c86378 100644 +index e95e259e5be5bb14a4ba2473d6ce850ebbedcb6d..e4c7262ded690e56ba2eef71bb7d46f9cd99b8b7 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -205,7 +205,7 @@ public abstract class Player extends LivingEntity { +@@ -167,7 +167,7 @@ public abstract class Player extends Avatar implements ContainerUser { private int lastLevelUpTime; public GameProfile gameProfile; private boolean reducedDebugInfo; @@ -552,7 +608,7 @@ index 8f4c45fbea2d7c1317aff36031bb834b07b23a82..8ec6f52f58bcc985fdc758a692798a35 private final ItemCooldowns cooldowns = this.createItemCooldowns(); private Optional lastDeathLocation = Optional.empty(); @Nullable -@@ -372,6 +372,12 @@ public abstract class Player extends LivingEntity { +@@ -309,6 +309,12 @@ public abstract class Player extends Avatar implements ContainerUser { } } @@ -565,8 +621,8 @@ index 8f4c45fbea2d7c1317aff36031bb834b07b23a82..8ec6f52f58bcc985fdc758a692798a35 @Override protected float getMaxHeadRotationRelativeToBody() { return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody(); -@@ -674,7 +680,7 @@ public abstract class Player extends LivingEntity { - } +@@ -537,7 +543,7 @@ public abstract class Player extends Avatar implements ContainerUser { + public void removeEntitiesOnShoulder() { } - private void touch(Entity entity) { @@ -574,7 +630,7 @@ index 8f4c45fbea2d7c1317aff36031bb834b07b23a82..8ec6f52f58bcc985fdc758a692798a35 entity.playerTouch(this); } -@@ -1299,7 +1305,7 @@ public abstract class Player extends LivingEntity { +@@ -1148,7 +1154,7 @@ public abstract class Player extends Avatar implements ContainerUser { this.sweepAttack(); } @@ -584,10 +640,10 @@ index 8f4c45fbea2d7c1317aff36031bb834b07b23a82..8ec6f52f58bcc985fdc758a692798a35 boolean cancelled = false; org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java -index 5f3abbe943be394e9cb987945a238208940b5015..8c139d572bd3c44b8e2b6205e28ab09f82c9abfe 100644 +index 207e30f822f286a6358055fcd5bc3af6ee7a553d..2c79332e148375c2f277df94b16ce7dd2422c004 100644 --- a/net/minecraft/world/entity/projectile/FishingHook.java +++ b/net/minecraft/world/entity/projectile/FishingHook.java -@@ -58,7 +58,7 @@ public class FishingHook extends Projectile { +@@ -59,7 +59,7 @@ public class FishingHook extends Projectile { public static final EntityDataAccessor DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT); private static final EntityDataAccessor DATA_BITING = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.BOOLEAN); private int life; @@ -597,10 +653,10 @@ index 5f3abbe943be394e9cb987945a238208940b5015..8c139d572bd3c44b8e2b6205e28ab09f public int timeUntilHooked; public float fishAngle; diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java -index df360ff06d10fc7f996055dce5148825539e9261..b67ae301db4ed3c45a08941f036dc48078a9f12a 100644 +index adab5dc640a7a0299c04020225a68317282aebe9..e127a670935186ba3d96a8d85640cf465ef52b7e 100644 --- a/net/minecraft/world/entity/vehicle/AbstractBoat.java +++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java -@@ -271,6 +271,11 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { +@@ -269,6 +269,11 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { } this.move(MoverType.SELF, this.getDeltaMovement()); @@ -612,7 +668,7 @@ index df360ff06d10fc7f996055dce5148825539e9261..b67ae301db4ed3c45a08941f036dc480 } else { this.setDeltaMovement(Vec3.ZERO); } -@@ -381,6 +386,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { +@@ -377,6 +382,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { } } @@ -627,14 +683,14 @@ index df360ff06d10fc7f996055dce5148825539e9261..b67ae301db4ed3c45a08941f036dc480 protected SoundEvent getPaddleSound() { return switch (this.getStatus()) { diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index 06846950348954328c07f64cd9b3359e79a1a468..e1783ad0adbb791b2ff7441243c9f0aeaf37c7f6 100644 +index 670090c4466d6472a83263e1769f19e3e491c927..4e53e7c05af11cae2ce8cf313c69a83336e22ba6 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -400,6 +400,7 @@ public abstract class AbstractContainerMenu { - private void doClick(int slotId, int button, ClickType clickType, Player player) { + private void doClick(int slotIndex, int button, ClickType clickType, Player player) { Inventory inventory = player.getInventory(); -+ if (!doClickCheck(slotId, button, clickType, player)) return; // Leaves - doClick check ++ if (!doClickCheck(slotIndex, button, clickType, player)) return; // Leaves - doClick check if (clickType == ClickType.QUICK_CRAFT) { int i = this.quickcraftStatus; this.quickcraftStatus = getQuickcraftHeader(button); @@ -662,10 +718,10 @@ index 06846950348954328c07f64cd9b3359e79a1a468..e1783ad0adbb791b2ff7441243c9f0ae FeatureFlagSet featureFlagSet = player.level().enabledFeatures(); return carriedItem.isItemEnabled(featureFlagSet) && carriedItem.overrideStackedOnOther(slot, action, player) diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index da16f4831c875e07c25d7ed041bed493db614658..462e2e4173ea07811022838e4fb592ab5f65e653 100644 +index 47862c00e9e01c7cdd5fcd808cc1b76740b85a57..14c74eb71b5bfb67d0fcf9d660f748c7b1dba63d 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -442,7 +442,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -443,7 +443,7 @@ public final class ItemStack implements DataComponentHolder { placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(serverLevel, player, hand, blocks.getFirst(), clickedPos); } @@ -674,7 +730,7 @@ index da16f4831c875e07c25d7ed041bed493db614658..462e2e4173ea07811022838e4fb592ab interactionResult = InteractionResult.FAIL; // cancel placement // PAIL: Remove this when MC-99075 fixed player.containerMenu.forceHeldSlot(hand); -@@ -938,6 +938,20 @@ public final class ItemStack implements DataComponentHolder { +@@ -939,6 +939,20 @@ public final class ItemStack implements DataComponentHolder { } } @@ -696,7 +752,7 @@ index da16f4831c875e07c25d7ed041bed493db614658..462e2e4173ea07811022838e4fb592ab return this.getItem().useOnRelease(this); } diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index f1ce4cff1c03a0037ade2c8ef989cf327c973a7e..0976aef81b950a062152094501372d00c20bb2b7 100644 +index 59a002711531f8337a86d85b6e8b11b5fad8ced7..0a76cf42aaaaf210a4e43ed9bd3d177f0003ba57 100644 --- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java @@ -135,7 +135,7 @@ public class PistonMovingBlockEntity extends BlockEntity { @@ -709,7 +765,7 @@ index f1ce4cff1c03a0037ade2c8ef989cf327c973a7e..0976aef81b950a062152094501372d00 double d1 = deltaMovement.x; double d2 = deltaMovement.y; diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java -index b3cfab9c82fe12694f5d2f56bd922828e51df680..3d5f64f67c402d7a86fd8a8e79b9fc90e61548a8 100644 +index 801a50ba4d202df0289339f26968e7f6bb9ca767..196f5dd260701d520cc8a037a896f34c87f74934 100644 --- a/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -48,6 +48,11 @@ public class PhantomSpawner implements CustomSpawner { @@ -737,16 +793,3 @@ index bef794c3f58c41d910aa0bcc63fbdeea7225fddf..a601da588e6973cc5b87d3e3eeba49b5 this.id = id; } -diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java -index fe44d8d17d2622b3d6021c11579af85ef96737bb..0aae211dc2048f8cd14213c2a868394d1ed16070 100644 ---- a/net/minecraft/world/level/storage/PlayerDataStorage.java -+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java -@@ -19,7 +19,7 @@ import net.minecraft.util.datafix.DataFixTypes; - import net.minecraft.world.entity.player.Player; - import org.slf4j.Logger; - --public class PlayerDataStorage { -+public class PlayerDataStorage implements org.leavesmc.leaves.bot.IPlayerDataStorage { - private static final Logger LOGGER = LogUtils.getLogger(); - private final File playerDir; - protected final DataFixer fixerUpper; diff --git a/leaves-server/minecraft-patches/features/0008-Make-shears-in-dispenser-can-unlimited-use.patch b/leaves-server/minecraft-patches/features/0008-Make-shears-in-dispenser-can-unlimited-use.patch index b4cf29a7..b27ab73a 100644 --- a/leaves-server/minecraft-patches/features/0008-Make-shears-in-dispenser-can-unlimited-use.patch +++ b/leaves-server/minecraft-patches/features/0008-Make-shears-in-dispenser-can-unlimited-use.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Make shears in dispenser can unlimited use diff --git a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index b4a9be09452a889c228612a466b8925cb3768102..38442a054bbe87db8dcfab20147d19b2c758d225 100644 +index 7d8f8ab3657e4a872e64176f89eca54d09c71ef1..6d3c6506ed82f24090496189402ff8946b960325 100644 --- a/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java @@ -45,7 +45,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING)); - this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearEntity(serverLevel, blockPos, item, bukkitBlock, craftItem)); // CraftBukkit + this.setSuccess(tryShearBeehive(serverLevel, item, blockPos) || tryShearEntity(serverLevel, blockPos, item, bukkitBlock, craftItem)); // CraftBukkit if (this.isSuccess()) { - item.hurtAndBreak(1, serverLevel, null, item1 -> {}); + item.hurtAndBreak(1, serverLevel, null, item1 -> { if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.shearsInDispenserCanZeroAmount) item.grow(1); }); // Leaves - Make shears in dispenser can unlimited use diff --git a/leaves-server/minecraft-patches/features/0010-Add-isShrink-to-EntityResurrectEvent.patch b/leaves-server/minecraft-patches/features/0010-Add-isShrink-to-EntityResurrectEvent.patch index 150b5c91..c06998f9 100644 --- a/leaves-server/minecraft-patches/features/0010-Add-isShrink-to-EntityResurrectEvent.patch +++ b/leaves-server/minecraft-patches/features/0010-Add-isShrink-to-EntityResurrectEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add isShrink to EntityResurrectEvent diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 1ba342a1a60951f828034d3ed535b577b3990bf6..7a7971ec03fcdf72ecaa1e934d5ab3c62113c251 100644 +index c18b0155edd695524246e5c2134de94008d8a023..f4a45a39afae0befa5c6048bb5f2001395d5cbfc 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -1733,14 +1733,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -1741,14 +1741,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin } final org.bukkit.inventory.EquipmentSlot handSlot = (hand != null) ? org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand) : null; diff --git a/leaves-server/minecraft-patches/features/0013-Stick-can-change-ArmorStand-arm-status.patch b/leaves-server/minecraft-patches/features/0013-Stick-can-change-ArmorStand-arm-status.patch index 5fe1b057..a380eaa2 100644 --- a/leaves-server/minecraft-patches/features/0013-Stick-can-change-ArmorStand-arm-status.patch +++ b/leaves-server/minecraft-patches/features/0013-Stick-can-change-ArmorStand-arm-status.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Stick can change ArmorStand arm status diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java -index 46369e554be8c72e6fc2e6d58374dbfc77d94879..d7725b5ca689e3d5b512baab04e113be77c0b2ee 100644 +index 15479a9fc47cca3d6627b42c31ba8ff114bbe362..9420ca7e32ae71ce9cecf8afd808ae6e9f8f4258 100644 --- a/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -228,6 +228,13 @@ public class ArmorStand extends LivingEntity { +@@ -229,6 +229,13 @@ public class ArmorStand extends LivingEntity { return InteractionResult.SUCCESS_SERVER; } } else { diff --git a/leaves-server/minecraft-patches/features/0015-No-chat-sign.patch b/leaves-server/minecraft-patches/features/0015-No-chat-sign.patch index 65d0af7e..5702d95a 100644 --- a/leaves-server/minecraft-patches/features/0015-No-chat-sign.patch +++ b/leaves-server/minecraft-patches/features/0015-No-chat-sign.patch @@ -72,10 +72,10 @@ index 1df628ac0b414511aaed6e09d78f884c4170f730..b92081d70ffeec47c304e553ce1aea0a } } diff --git a/net/minecraft/network/protocol/status/ServerStatus.java b/net/minecraft/network/protocol/status/ServerStatus.java -index a491be4250de3199c3e1aa9e5482b568692bd2f5..9844b19020ef6e4fa5a3008dcd768bb674657d2f 100644 +index 88447fc2108126ccfad2fb7eb79ac94537f132d3..1bca4150c63da064bd2d1ee8f504f2ebbc9d96a0 100644 --- a/net/minecraft/network/protocol/status/ServerStatus.java +++ b/net/minecraft/network/protocol/status/ServerStatus.java -@@ -20,7 +20,8 @@ public record ServerStatus( +@@ -19,7 +19,8 @@ public record ServerStatus( Optional players, Optional version, Optional favicon, @@ -85,7 +85,7 @@ index a491be4250de3199c3e1aa9e5482b568692bd2f5..9844b19020ef6e4fa5a3008dcd768bb6 ) { public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( -@@ -28,11 +29,18 @@ public record ServerStatus( +@@ -27,11 +28,18 @@ public record ServerStatus( ServerStatus.Players.CODEC.lenientOptionalFieldOf("players").forGetter(ServerStatus::players), ServerStatus.Version.CODEC.lenientOptionalFieldOf("version").forGetter(ServerStatus::version), ServerStatus.Favicon.CODEC.lenientOptionalFieldOf("favicon").forGetter(ServerStatus::favicon), @@ -106,10 +106,10 @@ index a491be4250de3199c3e1aa9e5482b568692bd2f5..9844b19020ef6e4fa5a3008dcd768bb6 private static final String PREFIX = "data:image/png;base64,"; public static final Codec CODEC = Codec.STRING.comapFlatMap(string -> { diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index f85993fc507d699728e058b12bb49dcb7aaea44b..91babab6152bb12768399ef6f2ea6afcb5e644b7 100644 +index 8d73fffb41346851d088ca0dee206661ff85ec29..4fdc743f56cdc4f92bfa8004c33e2f34cc9e9c70 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -573,7 +573,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -781,7 +781,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface // Paper start - Add setting for proxy online mode status return properties.enforceSecureProfile && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() @@ -119,10 +119,10 @@ index f85993fc507d699728e058b12bb49dcb7aaea44b..91babab6152bb12768399ef6f2ea6afc } diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index 2dd95aca955f19ce48be35b1ca9bcc94c3a1984d..e9d328dacdc23eea792ab350ec2ea9f8337ae008 100644 +index adb26ae4dfd5dc111cc55000b71c15f95239b090..20b9dfe68dfbcd5bb999ee4ec0500bdf6bc7fdd5 100644 --- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -@@ -322,10 +322,24 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -323,10 +323,24 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } public void send(Packet packet) { @@ -136,11 +136,11 @@ index 2dd95aca955f19ce48be35b1ca9bcc94c3a1984d..e9d328dacdc23eea792ab350ec2ea9f8 this.send(packet, null); } - public void send(Packet packet, @Nullable ChannelFutureListener channelFutureListener) { + public void send(Packet packet, @Nullable ChannelFutureListener sendListener) { + // Leaves start - no ClientboundPlayerChatHeaderPacket and rebuild ClientboundPlayerChatPacket + if (org.leavesmc.leaves.LeavesConfig.mics.noChatSign) { -+ if (packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerChatPacket && channelFutureListener != null) { -+ channelFutureListener = null; ++ if (packet instanceof net.minecraft.network.protocol.game.ClientboundPlayerChatPacket && sendListener != null) { ++ sendListener = null; + } + } + // Leaves end - no ClientboundPlayerChatHeaderPacket and rebuild ClientboundPlayerChatPacket @@ -148,10 +148,10 @@ index 2dd95aca955f19ce48be35b1ca9bcc94c3a1984d..e9d328dacdc23eea792ab350ec2ea9f8 if (packet == null || this.processedDisconnect) { // Spigot return; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 1135d32f1f275306792b95d10f76ac233e265e0d..e59a4178100532a2a52b4242409a270ed62498f6 100644 +index 6dec8565e9d290302ce7766357a56b8c2295c163..bf5d8fe260aaca48a73d6ffe9d1312f5161f9365 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1313,7 +1313,7 @@ public abstract class PlayerList { +@@ -1186,7 +1186,7 @@ public abstract class PlayerList { } public boolean verifyChatTrusted(PlayerChatMessage message) { diff --git a/leaves-server/minecraft-patches/features/0016-Dont-send-useless-entity-packets.patch b/leaves-server/minecraft-patches/features/0016-Dont-send-useless-entity-packets.patch index 5f580054..3c6cdcd7 100644 --- a/leaves-server/minecraft-patches/features/0016-Dont-send-useless-entity-packets.patch +++ b/leaves-server/minecraft-patches/features/0016-Dont-send-useless-entity-packets.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Dont send useless entity packets This patch is Powered by Purpur(https://github.com/PurpurMC/Purpur) diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index e96d4dee14c05f2fa329bfb1588ec795d4e3d730..f6b2d541fdfd11c6ff6033fbf4cd5153796634e3 100644 +index 638432a2e6506d3db6a25c068a33eeafb13cf0d6..1099280bd8e28c167702b74041928f260695ba7c 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java -@@ -200,6 +200,11 @@ public class ServerEntity { +@@ -188,6 +188,11 @@ public class ServerEntity { } else if (flag) { packet = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), b, b1, this.entity.onGround()); flag4 = true; @@ -21,7 +21,7 @@ index e96d4dee14c05f2fa329bfb1588ec795d4e3d730..f6b2d541fdfd11c6ff6033fbf4cd5153 } } else { packet = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short)l, (short)l1, (short)l2, b, b1, this.entity.onGround()); -@@ -319,6 +324,21 @@ public class ServerEntity { +@@ -300,6 +305,21 @@ public class ServerEntity { this.positionCodec.setBase(this.entity.position()); } diff --git a/leaves-server/minecraft-patches/features/0017-Optimize-suffocation.patch b/leaves-server/minecraft-patches/features/0017-Optimize-suffocation.patch index 731a9247..5616a405 100644 --- a/leaves-server/minecraft-patches/features/0017-Optimize-suffocation.patch +++ b/leaves-server/minecraft-patches/features/0017-Optimize-suffocation.patch @@ -6,19 +6,19 @@ Subject: [PATCH] Optimize suffocation This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 7a7971ec03fcdf72ecaa1e934d5ab3c62113c251..f0ff74a4f2831ead191bc12cb4873162a470c71f 100644 +index f4a45a39afae0befa5c6048bb5f2001395d5cbfc..ccc6900644f666729dc47cc0cfcdef66dd65b90a 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -437,7 +437,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin - +@@ -440,7 +440,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + profilerFiller.push("livingEntityBaseTick"); if (this.isAlive() && this.level() instanceof ServerLevel serverLevel1) { boolean flag = this instanceof Player; - if (this.isInWall()) { + if ((!org.leavesmc.leaves.LeavesConfig.performance.enableSuffocationOptimization || this instanceof WitherBoss || (tickCount % 10 == 0 && couldPossiblyBeHurt(1.0F))) && this.isInWall()) { // Leaves - optimize suffocation this.hurtServer(serverLevel1, this.damageSources().inWall(), 1.0F); } else if (flag && !serverLevel1.getWorldBorder().isWithinBounds(this.getBoundingBox())) { - double d = serverLevel1.getWorldBorder().getDistanceToBorder(this) + serverLevel1.getWorldBorder().getDamageSafeZone(); -@@ -1404,6 +1404,12 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + double d = serverLevel1.getWorldBorder().getDistanceToBorder(this) + serverLevel1.getWorldBorder().getSafeZone(); +@@ -1411,6 +1411,12 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin return this.getHealth() <= 0.0F; } diff --git a/leaves-server/minecraft-patches/features/0018-Only-check-for-spooky-season-once-an-hour.patch b/leaves-server/minecraft-patches/features/0018-Only-check-for-spooky-season-once-an-hour.patch index fded8ce8..0325f7d1 100644 --- a/leaves-server/minecraft-patches/features/0018-Only-check-for-spooky-season-once-an-hour.patch +++ b/leaves-server/minecraft-patches/features/0018-Only-check-for-spooky-season-once-an-hour.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Only check for spooky season once an hour This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/world/entity/ambient/Bat.java b/net/minecraft/world/entity/ambient/Bat.java -index 912b099a51269f92f250c7d6094ad41817749f93..af661d572d2bab00a392f858dd910c8be5e16e81 100644 +index c0198c0b6d00667c9591a5cd254b0bfedc3fb627..ec713dd16a842119c02b760ed45f7de2a839cb3b 100644 --- a/net/minecraft/world/entity/ambient/Bat.java +++ b/net/minecraft/world/entity/ambient/Bat.java -@@ -245,12 +245,30 @@ public class Bat extends AmbientCreature { +@@ -246,12 +246,30 @@ public class Bat extends AmbientCreature { } } diff --git a/leaves-server/minecraft-patches/features/0019-Config-to-disable-method-profiler.patch b/leaves-server/minecraft-patches/features/0019-Config-to-disable-method-profiler.patch index d19662fb..68712766 100644 --- a/leaves-server/minecraft-patches/features/0019-Config-to-disable-method-profiler.patch +++ b/leaves-server/minecraft-patches/features/0019-Config-to-disable-method-profiler.patch @@ -6,12 +6,12 @@ Subject: [PATCH] Config to disable method profiler This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 5c49816db8241694eed640a34c056effbf382934..af5fde7121211887672045c00aa404e2f68c43c1 100644 +index 309ff4c55b2a4ccf3d18951b51c2e10d0ff39bfc..19b89c3d0a21c0223bac1844081099d2bf8296ab 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1249,7 +1249,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos)); +- } else { +- this.neighborUpdater.setDebugListener(null); +- } ++ if (this.neighborUpdater instanceof net.minecraft.world.level.redstone.CollectingNeighborUpdater cnu) { // Leaves start - instantBlockUpdaterReintroduced ++ if (this.debugSynchronizers.hasAnySubscriberFor(DebugSubscriptions.NEIGHBOR_UPDATES)) { ++ cnu.setDebugListener(blockPos -> this.debugSynchronizers.broadcastEventToTracking(blockPos, DebugSubscriptions.NEIGHBOR_UPDATES, blockPos)); ++ } else { ++ cnu.setDebugListener(null); ++ } ++ } // Leaves end - instantBlockUpdaterReintroduced ++ + + this.debugSynchronizers.tick(this.server.debugSubscribers()); + profilerFiller.pop(); diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index c41df4b1fff1f65532256e835dc30fadbb4f8c8b..ef8a072838558caab19e8a85f4b59cac570c2635 100644 +index 01e0dc28ef63456a45b800e72d76180b40811a72..feafaaeca7ffa6fda5af9897c448b61ee1760290 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -873,7 +873,13 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -113,7 +113,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + .add(new ExplosionParticleInfo(ParticleTypes.SMOKE, 1.0F, 1.0F)) + .build(); + public final List blockEntityTickers = Lists.newArrayList(); +- protected final CollectingNeighborUpdater neighborUpdater; ++ protected final net.minecraft.world.level.redstone.NeighborUpdater neighborUpdater; // Leaves - instantBlockUpdaterReintroduced + private final List pendingBlockEntityTickers = Lists.newArrayList(); + private boolean tickingBlockEntities; + public final Thread thread; +@@ -863,7 +863,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl this.thread = Thread.currentThread(); this.biomeManager = new BiomeManager(this, biomeZoomSeed); this.isDebug = isDebug; @@ -22,5 +56,5 @@ index c41df4b1fff1f65532256e835dc30fadbb4f8c8b..ef8a072838558caab19e8a85f4b59cac + } + // Leaves end - instantBlockUpdaterReintroduced this.registryAccess = registryAccess; + this.palettedContainerFactory = PalettedContainerFactory.create(registryAccess); this.damageSources = new DamageSources(registryAccess); - diff --git a/leaves-server/minecraft-patches/features/0026-Random-flatten-triangular-distribution.patch b/leaves-server/minecraft-patches/features/0026-Random-flatten-triangular-distribution.patch index 4e0ddd6e..4643919e 100644 --- a/leaves-server/minecraft-patches/features/0026-Random-flatten-triangular-distribution.patch +++ b/leaves-server/minecraft-patches/features/0026-Random-flatten-triangular-distribution.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Random flatten triangular distribution This patch is Powered by Carpet-TIS-Addition(https://github.com/plusls/Carpet-TIS-Addition) diff --git a/net/minecraft/util/RandomSource.java b/net/minecraft/util/RandomSource.java -index 8516d47b0ba79d91638837199e7ae0fb6cb44a79..49a70e860eafdeca28ca3684a75bd3c8c4668b9c 100644 +index 98a54bc4de251014342cda6d0951b7fea79ce553..17a79cef7dac1b407e4e62883b4a943d172fa6b9 100644 --- a/net/minecraft/util/RandomSource.java +++ b/net/minecraft/util/RandomSource.java @@ -52,13 +52,25 @@ public interface RandomSource { @@ -14,23 +14,23 @@ index 8516d47b0ba79d91638837199e7ae0fb6cb44a79..49a70e860eafdeca28ca3684a75bd3c8 double nextGaussian(); + // Leaves start - flattenTriangularDistribution - default double triangle(double min, double max) { -- return min + max * (this.nextDouble() - this.nextDouble()); + default double triangle(double center, double maxDeviation) { +- return center + maxDeviation * (this.nextDouble() - this.nextDouble()); + if (org.leavesmc.leaves.LeavesConfig.modify.flattenTriangularDistribution) { + this.nextDouble(); -+ return min + max * (-1 + this.nextDouble() * 2); ++ return center + maxDeviation * (-1 + this.nextDouble() * 2); + } else { -+ return min + max * (this.nextDouble() - this.nextDouble()); ++ return center + maxDeviation * (this.nextDouble() - this.nextDouble()); + } } - default float triangle(float min, float max) { -- return min + max * (this.nextFloat() - this.nextFloat()); + default float triangle(float center, float maxDeviation) { +- return center + maxDeviation * (this.nextFloat() - this.nextFloat()); + if (org.leavesmc.leaves.LeavesConfig.modify.flattenTriangularDistribution) { + this.nextFloat(); -+ return min + max * (-1 + this.nextFloat() * 2); ++ return center + maxDeviation * (-1 + this.nextFloat() * 2); + } else { -+ return min + max * (this.nextFloat() - this.nextFloat()); ++ return center + maxDeviation * (this.nextFloat() - this.nextFloat()); + } } + // Leaves end - flattenTriangularDistribution diff --git a/leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch b/leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch index 68b359b4..6f11c44b 100644 --- a/leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0027-BBOR-Protocol.patch @@ -5,10 +5,10 @@ Subject: [PATCH] BBOR Protocol diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 75578e6ed7233a03d9b6cd3c6d3997f1c6148392..f24db919989bc2e5768e18b4fda68c38d6cde7e0 100644 +index de59760d27280555a334bda4f436164568cffbd6..bdc564c24982c196f151121fb769c7cfad4a08b0 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -749,6 +749,11 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -759,6 +759,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot public void setLoaded(boolean loaded) { this.loaded = loaded; diff --git a/leaves-server/minecraft-patches/features/0028-PCA-sync-protocol.patch b/leaves-server/minecraft-patches/features/0028-PCA-sync-protocol.patch index d17a0820..b64ee089 100644 --- a/leaves-server/minecraft-patches/features/0028-PCA-sync-protocol.patch +++ b/leaves-server/minecraft-patches/features/0028-PCA-sync-protocol.patch @@ -6,10 +6,10 @@ Subject: [PATCH] PCA sync protocol This patch is Powered by plusls-carpet-addition(https://github.com/plusls/plusls-carpet-addition) diff --git a/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -index 31ed5d7cfbda1a1f98ebfc89f5cbc65332cabdae..18c683f7d7e18200a24cfc8d26e83f578681f7f5 100644 +index c87a1a5e3696e40f9f0d6f4d93e102e73325d4f8..b01f53af58afdde22f062e6d16888bf09ee98805 100644 --- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java +++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java -@@ -305,6 +305,13 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory +@@ -306,6 +306,13 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory public void createInventory() { SimpleContainer simpleContainer = this.inventory; this.inventory = new SimpleContainer(this.getInventorySize(), (org.bukkit.entity.AbstractHorse) this.getBukkitEntity()); // CraftBukkit @@ -24,11 +24,11 @@ index 31ed5d7cfbda1a1f98ebfc89f5cbc65332cabdae..18c683f7d7e18200a24cfc8d26e83f57 int min = Math.min(simpleContainer.getContainerSize(), this.inventory.getContainerSize()); diff --git a/net/minecraft/world/entity/npc/AbstractVillager.java b/net/minecraft/world/entity/npc/AbstractVillager.java -index f8782cdcf3015cad2693663a3c222bd60822f45b..38572ecba568072b132b9e7fc12e6c0c38edd2e2 100644 +index 6bb17ecbd93f6ced5436cf75f3695f44eedd4bd9..ea7364f3cc9f339578232ba1103008a9ed50234a 100644 --- a/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/net/minecraft/world/entity/npc/AbstractVillager.java @@ -48,6 +48,15 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa - super(entityType, level); + super(type, level); this.setPathfindingMalus(PathType.DANGER_FIRE, 16.0F); this.setPathfindingMalus(PathType.DAMAGE_FIRE, -1.0F); + // Leaves start - pca @@ -44,7 +44,7 @@ index f8782cdcf3015cad2693663a3c222bd60822f45b..38572ecba568072b132b9e7fc12e6c0c @Override diff --git a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -index 6a008c86f4e360c916b93f0e3a62a9d8b43e74e6..7781ca07a0c8fe1140f341b695e66de95802ee2e 100644 +index 0f9bfcd1eab023c1772e9fafcda85d110904bd1c..8fdde0cc090c80b65b4c0d679bf4b412b6b761ee 100644 --- a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +++ b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java @@ -65,6 +65,11 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme @@ -60,10 +60,10 @@ index 6a008c86f4e360c916b93f0e3a62a9d8b43e74e6..7781ca07a0c8fe1140f341b695e66de9 @Override diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 36a72a11d28f99bfe85868461925b778cc01478e..bebe8737b71fc37336342f14b6ea4cfab12d3f34 100644 +index d8176f1f36f12fe179b5a63e6bf8f290a7a7461d..37bbd8d2cf412983fc4eb89737b3343f17364cae 100644 --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -429,6 +429,16 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -430,6 +430,16 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit } } @@ -81,10 +81,10 @@ index 36a72a11d28f99bfe85868461925b778cc01478e..bebe8737b71fc37336342f14b6ea4cfa public void setRecipeUsed(@Nullable RecipeHolder recipe) { if (recipe != null) { diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -index d679ab599dfd0bdbdc3ab5530d7fcd1c38baf7fa..f0ba09c0edc598dfc4e501ba69016e8a2f8d3a7c 100644 +index 75c09a2079c89f9346391abdd01ef8790b9cbb13..6741fe3abc4396236dc0ca31074e36d66e42c39a 100644 --- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -@@ -121,6 +121,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -124,6 +124,16 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { this.items = items; } @@ -100,12 +100,12 @@ index d679ab599dfd0bdbdc3ab5530d7fcd1c38baf7fa..f0ba09c0edc598dfc4e501ba69016e8a + @Override protected Component getDefaultName() { - return Component.translatable("container.barrel"); + return DEFAULT_NAME; diff --git a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index 91f7ee163107d846e7f6a5783be6eff96e783886..cbbe3dee3dda06d0e2451597dae0ac03009330e0 100644 +index f0673167d6273c7689cd58ac8f51e51649cb3ad0..03c9a2d253ba6fec39a0322eb74ac611fdc8b7f0 100644 --- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -147,6 +147,11 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -149,6 +149,11 @@ public class BeehiveBlockEntity extends BlockEntity { super.setChanged(); } @@ -117,7 +117,7 @@ index 91f7ee163107d846e7f6a5783be6eff96e783886..cbbe3dee3dda06d0e2451597dae0ac03 return list; } -@@ -204,6 +209,11 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -206,6 +211,11 @@ public class BeehiveBlockEntity extends BlockEntity { this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(bee, this.getBlockState())); } @@ -129,7 +129,7 @@ index 91f7ee163107d846e7f6a5783be6eff96e783886..cbbe3dee3dda06d0e2451597dae0ac03 bee.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause super.setChanged(); } -@@ -325,6 +335,11 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -327,6 +337,11 @@ public class BeehiveBlockEntity extends BlockEntity { if (releaseOccupant(level, pos, state, beeData.toOccupant(), null, beeReleaseStatus, savedFlowerPos)) { flag = true; iterator.remove(); @@ -154,10 +154,10 @@ index 91f7ee163107d846e7f6a5783be6eff96e783886..cbbe3dee3dda06d0e2451597dae0ac03 @Override diff --git a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java -index 79a9f1c87de30cda479b55cf70fbc3219a3dcad4..7eac2188a38fff2ecfa4082b5d023b111cf7d8f6 100644 +index 5b28e257982c911f4d8ffe286dc125b3f9b64ee4..a4d3d5b6830d156c76e381c5437867c0ed104016 100644 --- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java -@@ -331,4 +331,14 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -334,4 +334,14 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements protected AbstractContainerMenu createMenu(int id, Inventory player) { return new BrewingStandMenu(id, player, this, this.dataAccess); } @@ -173,10 +173,10 @@ index 79a9f1c87de30cda479b55cf70fbc3219a3dcad4..7eac2188a38fff2ecfa4082b5d023b11 + // Leaves end - pca } diff --git a/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/net/minecraft/world/level/block/entity/ChestBlockEntity.java -index b7d94ebe0ee995392c355c4237da8443dcc79b21..784e146b28370dc2dac094d5f2ac654a5bc47e01 100644 +index 6b1299c20573ca009f6bffce829a4a593f548fce..5b209de34bd425bf6c209a5317603f1c6d7280bf 100644 --- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java -@@ -202,6 +202,16 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement +@@ -214,6 +214,16 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement otherChest.setItems(items); } @@ -215,10 +215,10 @@ index 6b5179ae4269829b1e356840c9a8c33153334c32..b78ee57634471bc6e5308fb30c8f974f return this.output; } diff --git a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java -index ae52dc75335799e55e403e3d3f11e9f1d67e4305..36b9362e1ce31b63c100ec65921e095fb7871e82 100644 +index b4a155cc914092dad83977df714fbbc033c69d19..2fbfe925c81126cb99a4330a232d7d1b1f035973 100644 --- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java +++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java -@@ -104,6 +104,16 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity { +@@ -105,6 +105,16 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity { return stack; } @@ -234,12 +234,12 @@ index ae52dc75335799e55e403e3d3f11e9f1d67e4305..36b9362e1ce31b63c100ec65921e095f + @Override protected Component getDefaultName() { - return Component.translatable("container.dispenser"); + return DEFAULT_NAME; diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 800b7e78ae989868ed0b9e060c80dcd002759412..5f42af7c6fc82d6672ed06a2315254c9c5886ce4 100644 +index 28348e3881c3c8591053a01b193fb2a956f79726..ab88bca97fe275528a2feb22e5da89252be683c3 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -122,6 +122,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -123,6 +123,16 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen this.facing = blockState.getValue(HopperBlock.FACING); } @@ -255,8 +255,8 @@ index 800b7e78ae989868ed0b9e060c80dcd002759412..5f42af7c6fc82d6672ed06a2315254c9 + @Override protected Component getDefaultName() { - return Component.translatable("container.hopper"); -@@ -198,6 +208,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return DEFAULT_NAME; +@@ -199,6 +209,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (flag) { blockEntity.setCooldown(level.spigotConfig.hopperTransfer); // Spigot setChanged(level, pos, state); @@ -269,10 +269,10 @@ index 800b7e78ae989868ed0b9e060c80dcd002759412..5f42af7c6fc82d6672ed06a2315254c9 } } diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -index ebea67223ce1d350087c73dff0cc3fe6d7b47ca0..a820ab9a2b6dc6b95d4de61aaaad4e79c521efe4 100644 +index 4d268864656ad67e6971b74534e25ac47d922cbd..68fcb64d13bbd61ad78137f101ab20264f402df8 100644 --- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -@@ -267,6 +267,16 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -268,6 +268,16 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl this.itemStacks = items; } diff --git a/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch b/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch index c2c5ef80..c786b868 100644 --- a/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0029-Alternative-block-placement-Protocol.patch @@ -9,10 +9,10 @@ MasaGadget(https://github.com/plusls/MasaGadget) litematica(https://github.com/maruohon/litematica) diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index 6db566adf2d0df1d26221eda04aa01738df6d3d2..8f112f382190d606a87f38da8bcdf8dd5f31d1c5 100644 +index dceb2b683064bbf4286c3fe71e0fd0c5a644cb07..19649f75889d1c4243519eb8ccb46f4b9abd0f68 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -149,7 +149,7 @@ public class BlockItem extends Item { +@@ -148,7 +148,7 @@ public class BlockItem extends Item { @Nullable protected BlockState getPlacementState(BlockPlaceContext context) { @@ -43,10 +43,10 @@ index 12c6c8aeec89a0a55633c62fe98f5a3aa75fd476..1f0e7c391d02b18e2c89700025713ec3 blockState = blockState1; break; diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java -index 958914e40fceda5d67a98154817b4c5ce478a62d..3c5fd8efbe577c9b262870444984ad249097b8c2 100644 +index 57574f93763ab98a4bc109f56cfc3af08962a878..c9318bda7ea2cb25939516fb1c3cc90488bb8e6c 100644 --- a/net/minecraft/world/level/block/Block.java +++ b/net/minecraft/world/level/block/Block.java -@@ -439,6 +439,33 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -478,6 +478,33 @@ public class Block extends BlockBehaviour implements ItemLike { public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) { } diff --git a/leaves-server/minecraft-patches/features/0030-Jade-Protocol.patch b/leaves-server/minecraft-patches/features/0030-Jade-Protocol.patch index 01b6bbda..07a108b2 100644 --- a/leaves-server/minecraft-patches/features/0030-Jade-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0030-Jade-Protocol.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Jade Protocol This patch is Powered by Jade(https://github.com/Snownee/Jade) diff --git a/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -index c1798db2972c8f2a343cf6e16fd9354ff212d906..a8d617b16ab2b2c0cdb289a0aa05fa171940cd7e 100644 +index b5ce8de41b087812b02f22d538d5ca18eee60694..7b63c9aa70f070208e9a161fbee8d913204a2394 100644 --- a/net/minecraft/world/entity/animal/armadillo/Armadillo.java +++ b/net/minecraft/world/entity/animal/armadillo/Armadillo.java -@@ -63,7 +63,7 @@ public class Armadillo extends Animal { +@@ -64,7 +64,7 @@ public class Armadillo extends Animal { public final AnimationState rollOutAnimationState = new AnimationState(); public final AnimationState rollUpAnimationState = new AnimationState(); public final AnimationState peekAnimationState = new AnimationState(); @@ -17,12 +17,12 @@ index c1798db2972c8f2a343cf6e16fd9354ff212d906..a8d617b16ab2b2c0cdb289a0aa05fa17 + public int scuteTime; // Leaves - private -> public private boolean peekReceivedClient = false; - public Armadillo(EntityType entityType, Level level) { + public Armadillo(EntityType type, Level level) { diff --git a/net/minecraft/world/entity/animal/frog/Tadpole.java b/net/minecraft/world/entity/animal/frog/Tadpole.java -index 17f58246849ed407821a987b200cc765eb7943f9..ac27df3ba0ce9bbdf2f32ea87171fbb9407008d6 100644 +index 3ce172c1bdaf8b8a8ad774dd37498e8e379c68bb..5736d20494d2aaad1d5ac3403d4a923199bdbf13 100644 --- a/net/minecraft/world/entity/animal/frog/Tadpole.java +++ b/net/minecraft/world/entity/animal/frog/Tadpole.java -@@ -254,7 +254,7 @@ public class Tadpole extends AbstractFish { +@@ -247,7 +247,7 @@ public class Tadpole extends AbstractFish { } } diff --git a/leaves-server/minecraft-patches/features/0031-Player-operation-limiter.patch b/leaves-server/minecraft-patches/features/0031-Player-operation-limiter.patch index c259c03f..58a6d28b 100644 --- a/leaves-server/minecraft-patches/features/0031-Player-operation-limiter.patch +++ b/leaves-server/minecraft-patches/features/0031-Player-operation-limiter.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Player operation limiter This patch is Powered by plusls-carpet-addition(https://github.com/plusls/plusls-carpet-addition) diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 87c8c4c7ca52f7d804ddaff87aaf381552e1aee2..29b8e7b6d96ff7ca2dd53f00ea2010e6aad83a52 100644 +index 04ea4e33504703c4074aef6e74ec06dc772b1bb9..0110db0b1002b2007892e5c57b74de567d901d7b 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -429,6 +429,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -443,6 +443,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public boolean isRealPlayer; // Paper public @Nullable com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper - PlayerNaturallySpawnCreaturesEvent public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event @@ -20,7 +20,7 @@ index 87c8c4c7ca52f7d804ddaff87aaf381552e1aee2..29b8e7b6d96ff7ca2dd53f00ea2010e6 // Paper start - rewrite chunk system private ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.PlayerChunkLoaderData chunkLoader; -@@ -745,6 +749,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -723,6 +727,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc } // CraftBukkit end this.tickClientLoadTimeout(); @@ -28,7 +28,7 @@ index 87c8c4c7ca52f7d804ddaff87aaf381552e1aee2..29b8e7b6d96ff7ca2dd53f00ea2010e6 this.gameMode.tick(); this.wardenSpawnTracker.tick(); if (this.invulnerableTime > 0) { -@@ -2981,4 +2986,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -3103,4 +3108,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end @@ -61,10 +61,10 @@ index 87c8c4c7ca52f7d804ddaff87aaf381552e1aee2..29b8e7b6d96ff7ca2dd53f00ea2010e6 + // Leaves end - player operation limiter } diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java -index cfbf34964288526e93d0a5b212c1b60296c10430..9cce442c16ced8d9320a5760580ff13f02cbf8f1 100644 +index 7166889bce8065508030ecd5b1400ee9be031bf3..65e2edf39857b2e03c5a32dfb3b822b5cb4ce93c 100644 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -300,6 +300,19 @@ public class ServerPlayerGameMode { +@@ -320,6 +320,19 @@ public class ServerPlayerGameMode { } public void destroyAndAck(BlockPos pos, int sequence, String message) { @@ -85,10 +85,10 @@ index cfbf34964288526e93d0a5b212c1b60296c10430..9cce442c16ced8d9320a5760580ff13f this.debugLogging(pos, true, sequence, message); } else { diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index 8f112f382190d606a87f38da8bcdf8dd5f31d1c5..a46a50d1385897cc7fcf0d6976f0de7e8078d260 100644 +index 7bca36dd26afb02524022df74147f628edf51460..58ec8a43265ebf50fdd71f2cbb7dedf4762bc5b4 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -65,6 +65,21 @@ public class BlockItem extends Item { +@@ -64,6 +64,21 @@ public class BlockItem extends Item { final org.bukkit.block.BlockState oldBukkitState = bukkitState != null ? bukkitState : org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockPlaceContext.getLevel(), blockPlaceContext.getClickedPos()); // Paper - Reset placed block on exception // CraftBukkit end diff --git a/leaves-server/minecraft-patches/features/0032-Renewable-Elytra.patch b/leaves-server/minecraft-patches/features/0032-Renewable-Elytra.patch index 6b913faf..31f0e3c2 100644 --- a/leaves-server/minecraft-patches/features/0032-Renewable-Elytra.patch +++ b/leaves-server/minecraft-patches/features/0032-Renewable-Elytra.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Renewable Elytra This patch is Powered by Carpet-TIS-Addition(https://github.com/plusls/Carpet-TIS-Addition) diff --git a/net/minecraft/world/entity/monster/Phantom.java b/net/minecraft/world/entity/monster/Phantom.java -index ffcfdbc80df2a9e6c546348b86e7615e6109eb49..d985f224f06f5a823f74b276477ededdbe77596a 100644 +index b0f0a70ef6d708917ac8278c7eebd81d1fd7df6a..25c02ce8a613adae374bf85ed282399d44fba2ef 100644 --- a/net/minecraft/world/entity/monster/Phantom.java +++ b/net/minecraft/world/entity/monster/Phantom.java -@@ -246,6 +246,20 @@ public class Phantom extends Mob implements Enemy { +@@ -242,6 +242,20 @@ public class Phantom extends Mob implements Enemy { return targetingConditions.test(level, this, entity); } diff --git a/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch b/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch index b6b9823e..ee11ad67 100644 --- a/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch +++ b/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch @@ -6,10 +6,10 @@ Subject: [PATCH] MC Technical Survival Mode Will automatically overwrite some configuration after startup diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 29b8e7b6d96ff7ca2dd53f00ea2010e6aad83a52..217bcd7f9aab84b9bff82af0f3cab95818ba51a2 100644 +index 0110db0b1002b2007892e5c57b74de567d901d7b..d4df6ca7360d4bc605a51061444191d7929c7778 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1654,7 +1654,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1747,7 +1747,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public boolean isInvulnerableTo(ServerLevel level, DamageSource damageSource) { return (super.isInvulnerableTo(level, damageSource) // Paper - disable player cramming; || this.isChangingDimension() && !damageSource.is(DamageTypes.ENDER_PEARL) @@ -19,10 +19,10 @@ index 29b8e7b6d96ff7ca2dd53f00ea2010e6aad83a52..217bcd7f9aab84b9bff82af0f3cab958 @Override diff --git a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java -index 57befff1f0675e889304a6258258384d8de02c87..36be5f1e3547d29fd85e3b3f0c39e8f5ec1adf4e 100644 +index ffc960a4e66ed03a358b363a4ce1dcee0b29ac36..c1671664618428d5b82df721b559ce7280b9e8b7 100644 --- a/net/minecraft/world/entity/ai/behavior/AcquirePoi.java +++ b/net/minecraft/world/entity/ai/behavior/AcquirePoi.java -@@ -70,7 +70,7 @@ public class AcquirePoi { +@@ -69,7 +69,7 @@ public class AcquirePoi { return false; } else { mutableLong.setValue(time + 20L + level.getRandom().nextInt(20)); @@ -32,7 +32,7 @@ index 57befff1f0675e889304a6258258384d8de02c87..36be5f1e3547d29fd85e3b3f0c39e8f5 map.long2ObjectEntrySet().removeIf(entry -> !entry.getValue().isStillValid(time)); Predicate predicate1 = pos -> { diff --git a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -index a0e0fad40838fa7d835f31e5ce4ae3ab40e0bfa4..d8effc3a9773d29319b8e2bd15abbf03f0996ce5 100644 +index 4fc773a0cb9d68e22e4d6cc7d819196a6cabf4f1..af87a79c58b41e625a83665ff0893c9a29386a35 100644 --- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java @@ -65,7 +65,7 @@ public class EndCrystal extends Entity { @@ -45,7 +45,7 @@ index a0e0fad40838fa7d835f31e5ce4ae3ab40e0bfa4..d8effc3a9773d29319b8e2bd15abbf03 || ((ServerLevel) this.level()).getDragonFight() == null || ((ServerLevel) this.level()).getDragonFight().respawnStage == null diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java -index 17d54d38dcec39eefeb989cd576cc640a36e82f5..1d7a1739d6a3a55aacb33d57a58712350b150f64 100644 +index c685b5123c88fc73c26a3ba31225ab1226e52702..d36ce16724e9f5a79960f0aa265a0354f5240abc 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java @@ -100,7 +100,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { @@ -58,10 +58,10 @@ index 17d54d38dcec39eefeb989cd576cc640a36e82f5..1d7a1739d6a3a55aacb33d57a5871235 this.applyGravity(); this.move(MoverType.SELF, this.getDeltaMovement()); diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index 4f647507d06d45a65b4b1793219d90c65e110225..dac4646902a93eaaa287f5b6da324eea81ea3150 100644 +index 911c5099a2bbb3e955c9314219114873642c7355..74d5ef7e0a63661f8b314846b8985c5f04cae87e 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java -@@ -82,7 +82,7 @@ public final class NaturalSpawner { +@@ -84,7 +84,7 @@ public final class NaturalSpawner { MobCategory category = entity.getType().getCategory(); if (category != MobCategory.MISC) { // Paper start - Only count natural spawns @@ -71,10 +71,10 @@ index 4f647507d06d45a65b4b1793219d90c65e110225..dac4646902a93eaaa287f5b6da324eea entity.spawnReason == org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN)) { continue; diff --git a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -index cbbe3dee3dda06d0e2451597dae0ac03009330e0..aa94abe106ae0f47f61e6c431f1abcbdbf945dfa 100644 +index 03c9a2d253ba6fec39a0322eb74ac611fdc8b7f0..7ffcc21a6c4d679e860e845492429af838491444 100644 --- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java -@@ -342,7 +342,7 @@ public class BeehiveBlockEntity extends BlockEntity { +@@ -344,7 +344,7 @@ public class BeehiveBlockEntity extends BlockEntity { // Leaves end - pca } // Paper start - Fix bees aging inside; use exitTickCounter to keep actual bee life @@ -84,10 +84,10 @@ index cbbe3dee3dda06d0e2451597dae0ac03009330e0..aa94abe106ae0f47f61e6c431f1abcbd } // Paper end - Fix bees aging inside; use exitTickCounter to keep actual bee life diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index d7755e6a4641b5463eb39885bf53b6950c09bfc9..52ef2891eb9b6c8c8db763c9836fc6470746c68f 100644 +index ab88bca97fe275528a2feb22e5da89252be683c3..ca5707060e415a32fdb50509c24e79494d3ad28f 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -275,7 +275,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -276,7 +276,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen origItemStack.setCount(originalItemCount); } } @@ -96,7 +96,7 @@ index d7755e6a4641b5463eb39885bf53b6950c09bfc9..52ef2891eb9b6c8c8db763c9836fc647 hopper.setCooldown(level.spigotConfig.hopperTransfer); } return false; -@@ -316,7 +316,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -317,7 +317,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } origItemStack.setCount(originalItemCount); diff --git a/leaves-server/minecraft-patches/features/0034-Item-overstack-util.patch b/leaves-server/minecraft-patches/features/0034-Item-overstack-util.patch index b014afb7..1625fe64 100644 --- a/leaves-server/minecraft-patches/features/0034-Item-overstack-util.patch +++ b/leaves-server/minecraft-patches/features/0034-Item-overstack-util.patch @@ -26,7 +26,7 @@ index 643797124fe5a4489d0b7419b7e600c04f283ef2..04b4100da96aad50f08e8c59200eec93 public String serialize(HolderLookup.Provider levelRegistry) { diff --git a/net/minecraft/server/commands/GiveCommand.java b/net/minecraft/server/commands/GiveCommand.java -index adba92a9ebef64561147427d1339f70e2701d93c..fc367026ca84b125bf3ccd261ef43a3833c1da5c 100644 +index 4f56cdcf658234b1ca92d38c3df3d31e9be34a15..f6e18d62db18616a422ae74d6f329d1b3a96300b 100644 --- a/net/minecraft/server/commands/GiveCommand.java +++ b/net/minecraft/server/commands/GiveCommand.java @@ -55,7 +55,7 @@ public class GiveCommand { @@ -39,10 +39,10 @@ index adba92a9ebef64561147427d1339f70e2701d93c..fc367026ca84b125bf3ccd261ef43a38 if (count > i) { source.sendFailure(Component.translatable("commands.give.failed.toomanyitems", i, itemStack.getDisplayName())); diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ca13dd72f173be6714965c506f2d48dcd3c9e569..87201eca6bbcb0dbf2612b59219d97960db29d01 100644 +index ef7d44ea1c1582bbf1d544819825778c414fe40d..a77a7b77c27a0d1257f4eaa071b1c5934aff0f47 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2987,7 +2987,7 @@ public class ServerGamePacketListenerImpl +@@ -2998,7 +2998,7 @@ public class ServerGamePacketListenerImpl } else if (slot.mayPlace(cursor)) { if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) { int toPlace = packet.buttonNum() == 0 ? cursor.getCount() : 1; @@ -51,7 +51,7 @@ index ca13dd72f173be6714965c506f2d48dcd3c9e569..87201eca6bbcb0dbf2612b59219d9796 toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); if (toPlace == 1) { action = InventoryAction.PLACE_ONE; -@@ -3023,7 +3023,7 @@ public class ServerGamePacketListenerImpl +@@ -3034,7 +3034,7 @@ public class ServerGamePacketListenerImpl } } else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) { if (clickedItem.getCount() >= 0) { @@ -60,7 +60,7 @@ index ca13dd72f173be6714965c506f2d48dcd3c9e569..87201eca6bbcb0dbf2612b59219d9796 // As of 1.5, this is result slots only action = InventoryAction.PICKUP_ALL; } -@@ -3234,6 +3234,7 @@ public class ServerGamePacketListenerImpl +@@ -3251,6 +3251,7 @@ public class ServerGamePacketListenerImpl this.player.containerMenu.broadcastFullState(); } else { this.player.containerMenu.broadcastChanges(); @@ -68,7 +68,7 @@ index ca13dd72f173be6714965c506f2d48dcd3c9e569..87201eca6bbcb0dbf2612b59219d9796 } if (packet.buttonNum() == Inventory.SLOT_OFFHAND && this.player.containerMenu != this.player.inventoryMenu) this.player.containerSynchronizer.sendOffHandSlotChange(); // Paper - update offhand data when the player is clicking in an inventory not their own as the sychronizer does not include offhand slots if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes. -@@ -3345,7 +3346,7 @@ public class ServerGamePacketListenerImpl +@@ -3362,7 +3363,7 @@ public class ServerGamePacketListenerImpl } boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45; @@ -77,7 +77,7 @@ index ca13dd72f173be6714965c506f2d48dcd3c9e569..87201eca6bbcb0dbf2612b59219d9796 if (flag || (flag1 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packet.slotNum()).getItem(), packet.itemStack()))) { // Insist on valid slot // CraftBukkit start - Call click event org.bukkit.inventory.InventoryView inventory = this.player.inventoryMenu.getBukkitView(); -@@ -3387,6 +3388,7 @@ public class ServerGamePacketListenerImpl +@@ -3404,6 +3405,7 @@ public class ServerGamePacketListenerImpl this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack); this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack); this.player.inventoryMenu.broadcastChanges(); @@ -86,10 +86,10 @@ index ca13dd72f173be6714965c506f2d48dcd3c9e569..87201eca6bbcb0dbf2612b59219d9796 } else if (flag && flag2) { if (this.dropSpamThrottler.isUnderThreshold()) { diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java -index b382665cc125b8b5c0938e5e55984e4bf91d37ff..86cac164a2bf0e76528396e6aabbfd64cfc29559 100644 +index 8e6f097b4d17aaaf8eccc16e11ce2bd01ad63322..5493576c54e87823f68bbf8a18441b373aae0461 100644 --- a/net/minecraft/world/Container.java +++ b/net/minecraft/world/Container.java -@@ -32,6 +32,12 @@ public interface Container extends Clearable, Iterable { +@@ -34,6 +34,12 @@ public interface Container extends Clearable, Iterable { return Math.min(this.getMaxStackSize(), stack.getMaxStackSize()); } @@ -125,10 +125,10 @@ index d907e24d563e27acab2f2bf9711b1755ea9afd19..75170c8d3be477a6ea2a1d62018a6ab6 if (min > 0) { other.grow(min); diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index 51804b611f469f2ab53e455e8c633b867b00cc88..df24938d5136948b151d3c1c72ccb2ec97640478 100644 +index 6be576368695c902a0d6da74b1d77d3018b4585a..e198e4c1ee267c6738117959e71cf4018bf6ef1d 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java -@@ -279,10 +279,15 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -270,10 +270,15 @@ public class ItemEntity extends Entity implements TraceableEntity { private boolean isMergable() { ItemStack item = this.getItem(); @@ -146,10 +146,10 @@ index 51804b611f469f2ab53e455e8c633b867b00cc88..df24938d5136948b151d3c1c72ccb2ec ItemStack item1 = itemEntity.getItem(); if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) { diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java -index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0c59f7654 100644 +index 41e59f3739945ca7f6ab710c993b5c0f15fcd529..b849b04f227b43d036f4f6b3ae7accfafc389d9f 100644 --- a/net/minecraft/world/entity/player/Inventory.java +++ b/net/minecraft/world/entity/player/Inventory.java -@@ -165,10 +165,12 @@ public class Inventory implements Container, Nameable { +@@ -166,10 +166,12 @@ public class Inventory implements Container, Nameable { } private boolean hasRemainingSpaceForItem(ItemStack destination, ItemStack origin) { @@ -164,7 +164,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0 } // CraftBukkit start - Watch method above! :D -@@ -181,7 +183,7 @@ public class Inventory implements Container, Nameable { +@@ -182,7 +184,7 @@ public class Inventory implements Container, Nameable { } if (this.hasRemainingSpaceForItem(itemInSlot, itemStack)) { @@ -173,7 +173,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0 } if (remains <= 0) { return itemStack.getCount(); -@@ -190,7 +192,7 @@ public class Inventory implements Container, Nameable { +@@ -191,7 +193,7 @@ public class Inventory implements Container, Nameable { ItemStack itemInOffhand = this.equipment.get(EquipmentSlot.OFFHAND); if (this.hasRemainingSpaceForItem(itemInOffhand, itemStack)) { @@ -182,7 +182,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0 } if (remains <= 0) { return itemStack.getCount(); -@@ -314,7 +316,7 @@ public class Inventory implements Container, Nameable { +@@ -315,7 +317,7 @@ public class Inventory implements Container, Nameable { this.setItem(slot, item); } @@ -191,7 +191,7 @@ index a6bb436dc80daf6901dc027a6011ead4b3ed27e2..71df58ae26325a2d28b6679733c474c0 int min = Math.min(count, i); if (min == 0) { return count; -@@ -420,7 +422,7 @@ public class Inventory implements Container, Nameable { +@@ -421,7 +423,7 @@ public class Inventory implements Container, Nameable { break; } @@ -214,7 +214,7 @@ index 83ccde54c625d40dc595e000c533f60aa929bd5a..6779503888e6d311758cffde582b0efb public void accountStack(ItemStack stack, int maxStackSize) { diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java -index 02d2efef2dc0f0e12eac0c71fa290af706f7694d..99f109e2653eff10c011f380694bd77a76381cee 100644 +index 6e756ed4a811d9fe7d78d7dc89b3b5a735e0e857..358de981544b220bde770410c24e5f6b10520d91 100644 --- a/net/minecraft/world/entity/vehicle/ContainerEntity.java +++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java @@ -163,7 +163,7 @@ public interface ContainerEntity extends Container, MenuProvider { @@ -225,9 +225,9 @@ index 02d2efef2dc0f0e12eac0c71fa290af706f7694d..99f109e2653eff10c011f380694bd77a + stack.limitSize(this.getMaxStackLeaves(stack)); // Leaves - item over-stack util } - default SlotAccess getChestVehicleSlot(final int index) { + default SlotAccess getChestVehicleSlot(final int slot) { diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index e1783ad0adbb791b2ff7441243c9f0aeaf37c7f6..47963968763cbee60016853d617f159c0761d282 100644 +index 4e53e7c05af11cae2ce8cf313c69a83336e22ba6..e78baa9433b6f5cb32142fe583fe95831b173d5a 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -295,6 +295,13 @@ public abstract class AbstractContainerMenu { @@ -263,14 +263,14 @@ index e1783ad0adbb791b2ff7441243c9f0aeaf37c7f6..47963968763cbee60016853d617f159c carried2.grow(itemStack2.getCount()); slot.onTake(player, itemStack2); @@ -626,7 +633,7 @@ public abstract class AbstractContainerMenu { - Slot slot2 = this.slots.get(slotId); + Slot slot2 = this.slots.get(slotIndex); if (slot2.hasItem()) { ItemStack itemStack = slot2.getItem(); - this.setCarried(itemStack.copyWithCount(itemStack.getMaxStackSize())); + this.setCarried(itemStack.copyWithCount(org.leavesmc.leaves.util.ItemOverstackUtils.getItemStackMaxCount(itemStack))); // Leaves - item over-stack util } - } else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) { - Slot slot2 = this.slots.get(slotId); + } else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotIndex >= 0) { + Slot slot2 = this.slots.get(slotIndex); @@ -657,15 +664,15 @@ public abstract class AbstractContainerMenu { int maxStackSize = button == 0 ? 1 : -1; @@ -353,10 +353,10 @@ index 5ceb8964476b40db4511bec91ff13c4f522a1357..f416d7976e41a06b5a8be93485eaa233 @Nullable diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index da16f4831c875e07c25d7ed041bed493db614658..3ba64f91883b88f3131d4582c771b511bbccfcd9 100644 +index 14c74eb71b5bfb67d0fcf9d660f748c7b1dba63d..695f377155018d2b919086f0c29bdfb0abe1a2b2 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -162,7 +162,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -164,7 +164,7 @@ public final class ItemStack implements DataComponentHolder { @Deprecated @Nullable private Item item; @@ -365,7 +365,7 @@ index da16f4831c875e07c25d7ed041bed493db614658..3ba64f91883b88f3131d4582c771b511 @Nullable private Entity entityRepresentation; -@@ -189,7 +189,8 @@ public final class ItemStack implements DataComponentHolder { +@@ -191,7 +191,8 @@ public final class ItemStack implements DataComponentHolder { } else { Holder holder = Item.STREAM_CODEC.decode(buffer); DataComponentPatch dataComponentPatch = codec.decode(buffer); @@ -375,7 +375,7 @@ index da16f4831c875e07c25d7ed041bed493db614658..3ba64f91883b88f3131d4582c771b511 } } -@@ -198,13 +199,15 @@ public final class ItemStack implements DataComponentHolder { +@@ -200,13 +201,15 @@ public final class ItemStack implements DataComponentHolder { if (value.isEmpty() || value.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem() buffer.writeVarInt(0); } else { @@ -395,7 +395,7 @@ index da16f4831c875e07c25d7ed041bed493db614658..3ba64f91883b88f3131d4582c771b511 } finally { net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev); } -@@ -299,7 +302,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -300,7 +303,7 @@ public final class ItemStack implements DataComponentHolder { for (ItemStack itemStack : itemContainerContents.nonEmptyItems()) { int count = itemStack.getCount(); @@ -405,7 +405,7 @@ index da16f4831c875e07c25d7ed041bed493db614658..3ba64f91883b88f3131d4582c771b511 return DataResult.error(() -> "Item stack with count of " + count + " was larger than maximum: " + maxStackSize); } diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java -index 38b03c7b02bdfc579e5e126c12de3d878e26d188..caf31218a1aff84367da126ee1dc46b8c8a1e5d1 100644 +index a132883d85d515edb131049714915902444e4c3e..59cea0d226829267e9a5dff9f81789673bd3f062 100644 --- a/net/minecraft/world/level/block/CrafterBlock.java +++ b/net/minecraft/world/level/block/CrafterBlock.java @@ -192,7 +192,7 @@ public class CrafterBlock extends BaseEntityBlock { @@ -418,10 +418,10 @@ index 38b03c7b02bdfc579e5e126c12de3d878e26d188..caf31218a1aff84367da126ee1dc46b8 org.bukkit.craftbukkit.inventory.CraftItemStack oitemstack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack); diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index bebe8737b71fc37336342f14b6ea4cfab12d3f34..4fdb3c36b39213f01f86ba281c7b62af99f5dcce 100644 +index 37bbd8d2cf412983fc4eb89737b3343f17364cae..8a93c4b9571b3088dc92317544d209603880d3fa 100644 --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -409,7 +409,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -410,7 +410,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit ItemStack itemStack = this.items.get(index); boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameComponents(itemStack, stack); this.items.set(index, stack); @@ -431,10 +431,10 @@ index bebe8737b71fc37336342f14b6ea4cfab12d3f34..4fdb3c36b39213f01f86ba281c7b62af this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API this.cookingTimer = 0; diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index 5a094257a31f0500278a706a418e1697f8810ffb..63d6a43dab067aa4c8fb67095c455130196eef9f 100644 +index 1b2f8c4e1e362dc63fde2c7139039f0ce7eb762f..701a12db0c342c9ff2c974e581b112182dec2ea6 100644 --- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -@@ -145,7 +145,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co +@@ -149,7 +149,7 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co @Override public void setItem(int slot, ItemStack stack) { this.getItems().set(slot, stack); @@ -444,10 +444,10 @@ index 5a094257a31f0500278a706a418e1697f8810ffb..63d6a43dab067aa4c8fb67095c455130 } diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index e53b40c70c0a61cbe14a236a99725daa28512b0b..d152ad88e8e873a0164b2394516bd10f23c7b263 100644 +index ca5707060e415a32fdb50509c24e79494d3ad28f..a1799e2646569bf9db4fcdd3a9758f486f96f56e 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -113,7 +113,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -114,7 +114,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen public void setItem(int index, ItemStack stack) { this.unpackLootTable(null); this.getItems().set(index, stack); @@ -456,7 +456,7 @@ index e53b40c70c0a61cbe14a236a99725daa28512b0b..d152ad88e8e873a0164b2394516bd10f } @Override -@@ -692,9 +692,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -693,9 +693,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (item.isEmpty()) { // Spigot start - SPIGOT-6693, SimpleContainer#setItem ItemStack leftover = ItemStack.EMPTY; // Paper - Make hoppers respect inventory max stack size diff --git a/leaves-server/minecraft-patches/features/0035-Return-nether-portal-fix.patch b/leaves-server/minecraft-patches/features/0035-Return-nether-portal-fix.patch index 6f4c408c..774819ad 100644 --- a/leaves-server/minecraft-patches/features/0035-Return-nether-portal-fix.patch +++ b/leaves-server/minecraft-patches/features/0035-Return-nether-portal-fix.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Return nether portal fix This patch is powered by NetherPortalFix(https://github.com/TwelveIterationMods/NetherPortalFix) diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 51fd9298a931501ee15401b64f3194c72c00b00f..c356a88667c9fe0e8b0aca564f976043dfb83b39 100644 +index d4df6ca7360d4bc605a51061444191d7929c7778..134f6eba6655b7294ebcdf5cf5d9e2183e2ecf5b 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1468,6 +1468,21 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1576,6 +1576,21 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld()); this.level().getCraftServer().getPluginManager().callEvent(changeEvent); // CraftBukkit end @@ -32,13 +32,13 @@ index 51fd9298a931501ee15401b64f3194c72c00b00f..c356a88667c9fe0e8b0aca564f976043 if (this.isBlocking()) { this.stopUsingItem(); diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index e59a4178100532a2a52b4242409a270ed62498f6..7a0d36b9c6a633919a116fc4d47e500b2c6cbc28 100644 +index bf5d8fe260aaca48a73d6ffe9d1312f5161f9365..7977a0cfe18c99c4c6ba8c5b56387b690ede554d 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -820,6 +820,20 @@ public abstract class PlayerList { - if (fromWorld != level) { - org.bukkit.event.player.PlayerChangedWorldEvent event = new org.bukkit.event.player.PlayerChangedWorldEvent(player.getBukkitEntity(), fromWorld.getWorld()); - this.server.server.getPluginManager().callEvent(event); +@@ -700,6 +700,20 @@ public abstract class PlayerList { + // It's possible for respawn to be in a diff dimension + if (fromLevel != level) { + new org.bukkit.event.player.PlayerChangedWorldEvent(serverPlayer.getBukkitEntity(), fromLevel.getWorld()).callEvent(); + // Leaves start - nether portal fix + if (org.leavesmc.leaves.LeavesConfig.modify.netherPortalFix) { + final ResourceKey fromDim = player.level().dimension(); @@ -53,14 +53,14 @@ index e59a4178100532a2a52b4242409a270ed62498f6..7a0d36b9c6a633919a116fc4d47e500b + } + } + // Leaves end - nether portal fix + serverPlayer.triggerDimensionChangeTriggers(level); } - // Save player file again if they were disconnected diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 942be06bebe8c3fca0b0c33fa387e30deda8dd7c..bc19f0bf079d6a7fa2fc8aaed6477da5e57d32da 100644 +index ce4c8e14d3d7b5837dcce006fa67722f3f430fa4..759c320fc331704efe5df10d3f1f33aa87262290 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -257,7 +257,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -259,7 +259,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin protected ItemStack useItem = ItemStack.EMPTY; public int useItemRemaining; protected int fallFlyTicks; @@ -70,14 +70,14 @@ index 942be06bebe8c3fca0b0c33fa387e30deda8dd7c..bc19f0bf079d6a7fa2fc8aaed6477da5 @Nullable private DamageSource lastDamageSource; diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java -index 6c5629a6f5f91496a55eb0bf281ceae1567915b1..3aabae6e27e692aa65cc931e57306426e0f4d645 100644 +index d3f0a61c0c91d3a6a1dc4e59d57743ba89a9c19a..1ad863dc255a7b91d0b163000b6bb5d43e2ad204 100644 --- a/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/net/minecraft/world/level/block/NetherPortalBlock.java @@ -179,7 +179,18 @@ public class NetherPortalBlock extends Block implements Portal { @Nullable - private TeleportTransition getExitPortal(ServerLevel level, Entity entity, BlockPos pos, BlockPos exitPos, boolean isNether, WorldBorder worldBorder, int searchRadius, boolean canCreatePortal, int createRadius) { // CraftBukkit -- Optional optional = level.getPortalForcer().findClosestPortalPosition(exitPos, worldBorder, searchRadius); // CraftBukkit + private TeleportTransition getExitPortal(ServerLevel level, Entity entity, BlockPos pos, BlockPos exitPos, WorldBorder worldBorder, org.bukkit.craftbukkit.event.PortalEventResult result) { // CraftBukkit +- Optional optional = level.getPortalForcer().findClosestPortalPosition(exitPos, worldBorder, result.searchRadius()); // CraftBukkit + // Leaves start - fix return portal + Optional optional = Optional.empty(); + if (org.leavesmc.leaves.LeavesConfig.modify.netherPortalFix && entity instanceof net.minecraft.server.level.ServerPlayer player) { @@ -87,7 +87,7 @@ index 6c5629a6f5f91496a55eb0bf281ceae1567915b1..3aabae6e27e692aa65cc931e57306426 + } + } + if (optional.isEmpty()) { -+ optional = level.getPortalForcer().findClosestPortalPosition(exitPos, worldBorder, searchRadius); // CraftBukkit ++ level.getPortalForcer().findClosestPortalPosition(exitPos, worldBorder, result.searchRadius()); // CraftBukkit + } + // Leaves end - fix return portal BlockUtil.FoundRectangle largestRectangleAround; diff --git a/leaves-server/minecraft-patches/features/0036-Leaves-Extra-Yggdrasil-Service.patch b/leaves-server/minecraft-patches/features/0036-Leaves-Extra-Yggdrasil-Service.patch index 7fa34772..83a46233 100644 --- a/leaves-server/minecraft-patches/features/0036-Leaves-Extra-Yggdrasil-Service.patch +++ b/leaves-server/minecraft-patches/features/0036-Leaves-Extra-Yggdrasil-Service.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaves Extra Yggdrasil Service diff --git a/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java b/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java -index 8c3151c25c172b846f0d028b5100718ada2d09d7..d59d05f8894481fb5ebe1aeb8ee7a162b3dc6f1c 100644 +index 9e5757391ea32e37b2aac52cc1bb38259a2cc497..b85593aea7a347a5c2c50464d2146f96f4fa317e 100644 --- a/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java +++ b/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java -@@ -46,7 +46,7 @@ import java.util.stream.Collectors; +@@ -48,7 +48,7 @@ import java.util.stream.Collectors; public class YggdrasilMinecraftSessionService implements MinecraftSessionService { private static final Logger LOGGER = LoggerFactory.getLogger(YggdrasilMinecraftSessionService.class); @@ -18,10 +18,10 @@ index 8c3151c25c172b846f0d028b5100718ada2d09d7..d59d05f8894481fb5ebe1aeb8ee7a162 private final String baseUrl; private final URL joinUrl; diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index fd3553bdc1c3cdbf6aa3dc00e0a4987f8eaa4fb8..e673df664b06c654a7be0622874b9b27ad7ef20f 100644 +index 8d299a75c80fddc61a2aa4dc5b0dc5948aef5a0d..30b681bc234eac8dc44ce3bf6e228171f5a71a7a 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java -@@ -178,7 +178,7 @@ public class Main { +@@ -176,7 +176,7 @@ public class Main { file = new File(bukkitConfiguration.getString("settings.world-container", ".")); } // Paper end - fix SPIGOT-5824 @@ -31,15 +31,15 @@ index fd3553bdc1c3cdbf6aa3dc00e0a4987f8eaa4fb8..e673df664b06c654a7be0622874b9b27 String string = Optional.ofNullable((String) optionSet.valueOf("world")).orElse(dedicatedServerSettings.getProperties().levelName); LevelStorageSource levelStorageSource = LevelStorageSource.createDefault(file.toPath()); diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 11728fa48bb144bbe933eb8fa2df22b52ac1b5a5..7e339cb26a132487ac0ab91d3db7e4885bacd545 100644 +index 5ad76e6483b589d6695ad086755cc9dc0edd9235..c3c93caab5981d509dd5471419f3d79cdd045f1d 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -245,7 +245,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop public + private final NotificationManager notificationManager; private long lastServerStatus; public final Thread serverThread; - private long lastTickNanos = Util.getNanos(); diff --git a/leaves-server/minecraft-patches/features/0037-Configurable-vanilla-random.patch b/leaves-server/minecraft-patches/features/0037-Configurable-vanilla-random.patch index b1088ee2..f5a05e14 100644 --- a/leaves-server/minecraft-patches/features/0037-Configurable-vanilla-random.patch +++ b/leaves-server/minecraft-patches/features/0037-Configurable-vanilla-random.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable vanilla random diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index d5051d8a2b0af5d8b63a0d10987c0a7ee7114ff0..e6457e07e7e8e7690d160020b92fbc6874c1ec82 100644 +index c6815ffef7fb2fd2e5ef2769c2c93135b52558f5..f6dd8e81f6881400c3278ea53e2ed248625744e1 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -281,7 +281,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -282,7 +282,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name public double yOld; public double zOld; public boolean noPhysics; @@ -18,10 +18,10 @@ index d5051d8a2b0af5d8b63a0d10987c0a7ee7114ff0..e6457e07e7e8e7690d160020b92fbc68 private int remainingFireTicks; public boolean wasTouchingWater; diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java -index 13f24836649790a34b988e2d63accb043e6ff080..d991660c990ca280a422154d4b3bde8dc0cdfd49 100644 +index e94c6c1ee969a7d0953b933fb0633cebb510a68c..97fbdb90db218c6f2f81487cc30430d7c90afa8e 100644 --- a/net/minecraft/world/entity/animal/Bee.java +++ b/net/minecraft/world/entity/animal/Bee.java -@@ -802,7 +802,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -808,7 +808,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @VisibleForDebug public class BeeGoToHiveGoal extends Bee.BaseBeeGoal { public static final int MAX_TRAVELLING_TICKS = 2400; @@ -30,7 +30,7 @@ index 13f24836649790a34b988e2d63accb043e6ff080..d991660c990ca280a422154d4b3bde8d private static final int MAX_BLACKLISTED_TARGETS = 3; final List blacklistedTargets = Lists.newArrayList(); @Nullable -@@ -918,7 +918,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -924,7 +924,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { public class BeeGoToKnownFlowerGoal extends Bee.BaseBeeGoal { private static final int MAX_TRAVELLING_TICKS = 2400; @@ -40,23 +40,23 @@ index 13f24836649790a34b988e2d63accb043e6ff080..d991660c990ca280a422154d4b3bde8d BeeGoToKnownFlowerGoal() { this.setFlags(EnumSet.of(Goal.Flag.MOVE)); diff --git a/net/minecraft/world/entity/animal/Squid.java b/net/minecraft/world/entity/animal/Squid.java -index 58e1bc90cbc32669fa6c66d214119f0c459ff38c..ea41360af5e5d49c96ca24e9c36bd52cfdd7d40c 100644 +index 8313ea146ba6910d92653c29887c94b75f68cce4..9b8775a9069db99605ac5367804923d537320d68 100644 --- a/net/minecraft/world/entity/animal/Squid.java +++ b/net/minecraft/world/entity/animal/Squid.java -@@ -46,7 +46,7 @@ public class Squid extends AgeableWaterCreature { +@@ -47,7 +47,7 @@ public class Squid extends AgeableWaterCreature { - public Squid(EntityType entityType, Level level) { - super(entityType, level); -- //this.random.setSeed(this.getId()); // Paper - Share random for entities to make them more random + public Squid(EntityType type, Level level) { + super(type, level); +- // this.random.setSeed(this.getId()); // Paper - Share random for entities to make them more random + if (org.leavesmc.leaves.LeavesConfig.modify.useVanillaRandom) this.random.setSeed(this.getId()); // Paper - Share random for entities to make them more random // Leaves - vanilla plz this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F; } diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index df24938d5136948b151d3c1c72ccb2ec97640478..af0467f60e5a873eeed7b741717c327272746a9a 100644 +index e198e4c1ee267c6738117959e71cf4018bf6ef1d..671ae6195c86b44dfb2df4414a35287e3acd954f 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java -@@ -67,7 +67,13 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -66,7 +66,13 @@ public class ItemEntity extends Entity implements TraceableEntity { // Paper start - Don't use level random in entity constructors (to make them thread-safe) this(EntityType.ITEM, level); this.setPos(posX, posY, posZ); @@ -68,11 +68,11 @@ index df24938d5136948b151d3c1c72ccb2ec97640478..af0467f60e5a873eeed7b741717c3272 + this.setDeltaMovement(this.random.nextDouble() * 0.2 - 0.1, 0.2, this.random.nextDouble() * 0.2 - 0.1); + } + // Leaves end - vanilla yes, safe no - this.setItem(itemStack); + this.setItem(stack); // Paper end - Don't use level random in entity constructors } diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java -index 1d7a1739d6a3a55aacb33d57a58712350b150f64..87dff2fb5246d730feca82396a68b41150e2d383 100644 +index d36ce16724e9f5a79960f0aa265a0354f5240abc..8230b42919bd8888acf656c5846601bead39598f 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java @@ -68,7 +68,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { diff --git a/leaves-server/minecraft-patches/features/0038-Catch-update-suppression-crash.patch b/leaves-server/minecraft-patches/features/0038-Catch-update-suppression-crash.patch index a1b0a66b..b6922099 100644 --- a/leaves-server/minecraft-patches/features/0038-Catch-update-suppression-crash.patch +++ b/leaves-server/minecraft-patches/features/0038-Catch-update-suppression-crash.patch @@ -4,36 +4,36 @@ Date: Fri, 17 Mar 2023 15:57:08 +0800 Subject: [PATCH] Catch update suppression crash -diff --git a/net/minecraft/network/protocol/PacketUtils.java b/net/minecraft/network/protocol/PacketUtils.java -index 4535858701b2bb232b9d2feb2af6551526232ddc..03e70445dfe14c119284f7c301127075c009e915 100644 ---- a/net/minecraft/network/protocol/PacketUtils.java -+++ b/net/minecraft/network/protocol/PacketUtils.java -@@ -27,7 +27,20 @@ public class PacketUtils { - if (processor.shouldHandleMessage(packet)) { - try { - packet.handle(processor); +diff --git a/net/minecraft/network/PacketProcessor.java b/net/minecraft/network/PacketProcessor.java +index 3e4241976fdfe65bc0aae90a9097770745c0ddf1..8e3e9a8aaee8fd4fbe986f9f079945179017c4f3 100644 +--- a/net/minecraft/network/PacketProcessor.java ++++ b/net/minecraft/network/PacketProcessor.java +@@ -97,7 +97,20 @@ public class PacketProcessor implements AutoCloseable { + if (this.listener.shouldHandleMessage(this.packet)) { + try { + this.packet.handle(this.listener); + // Leaves start - update suppression crash fix -+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) { -+ if (processor instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) { ++ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) { ++ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) { ++ exception.providePlayer(gamePacketListener.player); ++ } ++ exception.consume(); + } catch (Exception var3) { ++ if (var3.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) { ++ if (this.listener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) { + exception.providePlayer(gamePacketListener.player); + } + exception.consume(); - } catch (Exception var4) { -+ if (var4.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) { -+ if (processor instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) { -+ exception.providePlayer(gamePacketListener.player); -+ } -+ exception.consume(); -+ } -+ // Leaves end - update suppression crash fix - if (var4 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError) { - throw makeReportedException(var4, packet, processor); - } ++ } ++ // Leaves end - update suppression crash fix + if (var3 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError) { + throw PacketUtils.makeReportedException(var3, this.packet, this.listener); + } diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 4cc0bb9c612986934bf44f933aa402b3787394ba..2545c7ebbe4bab45ea22d3843d42c7e55941387e 100644 +index c8135525666da2cedc134025327e240fbe6cd63c..bd9d83675d40b383678c6066b73b9e053b5ea6a6 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1726,7 +1726,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ca.spottedleaf.moonrise.patch @@ -154,10 +154,10 @@ index 9b9842462b210b0407279ee8a8e9ccecf3ead005..ba9c8a677c1759e75392344df7877c5f } diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index f24db919989bc2e5768e18b4fda68c38d6cde7e0..0e22116fefcbdbf2049b7ec285b35fd03c723dc5 100644 +index bdc564c24982c196f151121fb769c7cfad4a08b0..7c5f827134e0fa81031660a78d4d404c21840cb6 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -373,7 +373,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -380,7 +380,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot if (blockState == state) { return null; } else { @@ -166,7 +166,7 @@ index f24db919989bc2e5768e18b4fda68c38d6cde7e0..0e22116fefcbdbf2049b7ec285b35fd0 this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state); this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state); this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(i, y, i2, state); -@@ -445,6 +445,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -454,6 +454,7 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot this.markUnsaved(); return blockState; } @@ -175,7 +175,7 @@ index f24db919989bc2e5768e18b4fda68c38d6cde7e0..0e22116fefcbdbf2049b7ec285b35fd0 } } diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java -index 332b33a004ab11150cca0cc2cefc26d0286648f5..8942aa2ca4796c7c36c0955141627ea905e0ec64 100644 +index f45cf0136e77ed5a903d033a7b0611e5edc23db9..77ed7a6a4bea3dfc77d060c49f77f4e080da200b 100644 --- a/net/minecraft/world/level/redstone/NeighborUpdater.java +++ b/net/minecraft/world/level/redstone/NeighborUpdater.java @@ -60,9 +60,22 @@ public interface NeighborUpdater { diff --git a/leaves-server/minecraft-patches/features/0039-Bedrock-break-list.patch b/leaves-server/minecraft-patches/features/0039-Bedrock-break-list.patch index b22605c5..072246f0 100644 --- a/leaves-server/minecraft-patches/features/0039-Bedrock-break-list.patch +++ b/leaves-server/minecraft-patches/features/0039-Bedrock-break-list.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Bedrock break list diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 2545c7ebbe4bab45ea22d3843d42c7e55941387e..cbc9f4fbad0a88bc324111a7ce80c2880ed1d3be 100644 +index bd9d83675d40b383678c6066b73b9e053b5ea6a6..fa2ae16481541308d525d0ac70a8bbc2c66a8851 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1758,6 +1758,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> { @@ -20,19 +20,19 @@ index 3e9b8c5fb2157f767de8bddc3e767512c5f7651f..ce65b531ec2b8a5dd1955ee8d826520f synchronized (PACKET_LIMIT_LOCK) { if (this.allPacketCounts != null) { diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index e4ea337185ed33b04fff0ea0974619bb27fa83bf..4b91a75e10161e69771a2779d3531e386a3fbde2 100644 +index 28fe3e0c8bb743237ddf324f633e986fb91bb405..55374283f8cb1e7f3485eae7dc1da2db3cc98a0c 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -821,7 +821,7 @@ public class ServerGamePacketListenerImpl +@@ -828,7 +828,7 @@ public class ServerGamePacketListenerImpl public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) { // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); // Paper - AsyncTabCompleteEvent; run this async // CraftBukkit start -- if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits -+ if (!org.leavesmc.leaves.LeavesConfig.modify.disablePacketLimit && !this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits // Leaves - can disable +- if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.nameAndId()) && !this.server.isSingleplayerOwner(this.player.nameAndId())) { // Paper - configurable tab spam limits ++ if (!org.leavesmc.leaves.LeavesConfig.modify.disablePacketLimit && !this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.nameAndId()) && !this.server.isSingleplayerOwner(this.player.nameAndId())) { // Paper - configurable tab spam limits // Leaves - can disable this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Paper - add proper async disconnect return; } -@@ -2002,6 +2002,7 @@ public class ServerGamePacketListenerImpl +@@ -2010,6 +2010,7 @@ public class ServerGamePacketListenerImpl private static int getSpamThreshold() { return io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.incomingPacketThreshold; } // Paper - Configurable threshold private boolean checkLimit(long timestamp) { @@ -40,7 +40,7 @@ index e4ea337185ed33b04fff0ea0974619bb27fa83bf..4b91a75e10161e69771a2779d3531e38 if (this.lastLimitedPacket != -1 && timestamp - this.lastLimitedPacket < getSpamThreshold() && this.limitedPackets++ >= 8) { // Paper - Configurable threshold; raise packet limit to 8 return false; } -@@ -2536,6 +2537,7 @@ public class ServerGamePacketListenerImpl +@@ -2544,6 +2545,7 @@ public class ServerGamePacketListenerImpl // Spigot start - spam exclusions private void detectRateSpam(String message) { @@ -48,7 +48,7 @@ index e4ea337185ed33b04fff0ea0974619bb27fa83bf..4b91a75e10161e69771a2779d3531e38 // CraftBukkit start - replaced with thread safe throttle if (org.spigotmc.SpigotConfig.enableSpamExclusions) { for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) { -@@ -3246,7 +3248,7 @@ public class ServerGamePacketListenerImpl +@@ -3263,7 +3265,7 @@ public class ServerGamePacketListenerImpl @Override public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) { // Paper start - auto recipe limit diff --git a/leaves-server/minecraft-patches/features/0044-Syncmatica-Protocol.patch b/leaves-server/minecraft-patches/features/0044-Syncmatica-Protocol.patch index 9365a7e3..3ffa8ada 100644 --- a/leaves-server/minecraft-patches/features/0044-Syncmatica-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0044-Syncmatica-Protocol.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Syncmatica Protocol This patch is Powered by Syncmatica(https://github.com/End-Tech/syncmatica) diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 3c7b691a60f355ebaeb96f7ba07955f5be7fd09b..6e8e4b009a4dd52047bc8d8f8e2e27558e0d8dff 100644 +index 55374283f8cb1e7f3485eae7dc1da2db3cc98a0c..ea9e98313c25e7ce94b011f5bc74a4318145c6f6 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -323,9 +323,12 @@ public class ServerGamePacketListenerImpl +@@ -326,9 +326,12 @@ public class ServerGamePacketListenerImpl this.signedMessageDecoder = SignedMessageChain.Decoder.unsigned(player.getUUID(), server::enforceSecureProfile); this.chatMessageChain = new FutureChain(server.chatExecutor); // CraftBukkit - async chat this.tickEndEvent = new io.papermc.paper.event.packet.ClientTickEndEvent(player.getBukkitEntity()); // Paper - add client tick end event diff --git a/leaves-server/minecraft-patches/features/0048-Despawn-enderman-with-block.patch b/leaves-server/minecraft-patches/features/0048-Despawn-enderman-with-block.patch index 3d107087..4c862c67 100644 --- a/leaves-server/minecraft-patches/features/0048-Despawn-enderman-with-block.patch +++ b/leaves-server/minecraft-patches/features/0048-Despawn-enderman-with-block.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Despawn enderman with block diff --git a/net/minecraft/world/entity/monster/EnderMan.java b/net/minecraft/world/entity/monster/EnderMan.java -index 6760bfd91f59139922768db5e5d362c5e7e4e473..33d4025ac997f46b7bf129c4dd3ba457c6fc9da2 100644 +index 0732709d0ca78f59ad6b7f8ac5e7bfbe5506f60b..b314fb8819388facf664060fc0d1a091543aac68 100644 --- a/net/minecraft/world/entity/monster/EnderMan.java +++ b/net/minecraft/world/entity/monster/EnderMan.java -@@ -448,7 +448,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -454,7 +454,7 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean requiresCustomPersistence() { diff --git a/leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch b/leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch index 20da66ef..a1dfb6e0 100644 --- a/leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch +++ b/leaves-server/minecraft-patches/features/0049-Optimized-dragon-respawn.patch @@ -18,10 +18,10 @@ index f7bb979f08634a7e1b77c59040f59fb5e11aafa5..3cad7d6bca9af77bace18bfd7cc013ac for (int i1 = 0; i1 < this.height; i1++) { for (int i2 = 0; i2 < this.depth; i2++) { diff --git a/net/minecraft/world/level/dimension/end/EndDragonFight.java b/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 8ccd40c70e150bd5a8d89818c229258642f2349e..18a567b676f0bfcd725f19c5ed9e3fdbc8e65573 100644 +index fcb0fb9ca663ec40e1541d099bc3d710963f6c9d..d2e49f8490bff739a3726e73a303b2c24c47617f 100644 --- a/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -273,8 +273,68 @@ public class EndDragonFight { +@@ -274,8 +274,68 @@ public class EndDragonFight { return false; } @@ -90,7 +90,7 @@ index 8ccd40c70e150bd5a8d89818c229258642f2349e..18a567b676f0bfcd725f19c5ed9e3fdb ChunkPos chunkPos = new ChunkPos(this.origin); for (int i = -8 + chunkPos.x; i <= 8 + chunkPos.x; i++) { -@@ -572,6 +632,11 @@ public class EndDragonFight { +@@ -573,6 +633,11 @@ public class EndDragonFight { } public boolean respawnDragon(List crystals) { // CraftBukkit - return boolean diff --git a/leaves-server/minecraft-patches/features/0050-Creative-fly-no-clip.patch b/leaves-server/minecraft-patches/features/0050-Creative-fly-no-clip.patch index 2641864a..bfc3162a 100644 --- a/leaves-server/minecraft-patches/features/0050-Creative-fly-no-clip.patch +++ b/leaves-server/minecraft-patches/features/0050-Creative-fly-no-clip.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Creative fly no clip diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java -index a62edee768c30c99213baa6bd736d67ae52b558c..cfd9d63f55e73c1777055d13a802b29e151cc0d4 100644 +index 85c5a8497ee45de232a87c3f152e7ca67c1821ee..47bdbf9c73f19ff85ae93f3e31e45d35fe8c0a92 100644 --- a/net/minecraft/world/entity/ExperienceOrb.java +++ b/net/minecraft/world/entity/ExperienceOrb.java @@ -202,7 +202,7 @@ public class ExperienceOrb extends Entity { @@ -18,10 +18,10 @@ index a62edee768c30c99213baa6bd736d67ae52b558c..cfd9d63f55e73c1777055d13a802b29e } else { this.followingPlayer = null; diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 8ec6f52f58bcc985fdc758a692798a35d6c86378..61baebc707cb6afcaf8c7f56fd906813d309a2cf 100644 +index e4c7262ded690e56ba2eef71bb7d46f9cd99b8b7..7b0fdecf7ca4a5b6dd910369d6546a909926dff2 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -287,8 +287,8 @@ public abstract class Player extends LivingEntity { +@@ -247,8 +247,8 @@ public abstract class Player extends Avatar implements ContainerUser { @Override public void tick() { @@ -32,7 +32,7 @@ index 8ec6f52f58bcc985fdc758a692798a35d6c86378..61baebc707cb6afcaf8c7f56fd906813 this.setOnGround(false); } -@@ -481,7 +481,7 @@ public abstract class Player extends LivingEntity { +@@ -375,7 +375,7 @@ public abstract class Player extends Avatar implements ContainerUser { if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) { Pose desiredPose = this.getDesiredPose(); Pose pose; @@ -41,16 +41,16 @@ index 8ec6f52f58bcc985fdc758a692798a35d6c86378..61baebc707cb6afcaf8c7f56fd906813 pose = desiredPose; } else if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) { pose = Pose.CROUCHING; -@@ -624,7 +624,7 @@ public abstract class Player extends LivingEntity { - } - - this.bob = this.bob + (f - this.bob) * 0.4F; +@@ -507,7 +507,7 @@ public abstract class Player extends Avatar implements ContainerUser { + this.updateSwingTime(); + this.yHeadRot = this.getYRot(); + this.setSpeed((float)this.getAttributeValue(Attributes.MOVEMENT_SPEED)); - if (this.getHealth() > 0.0F && !this.isSpectator()) { + if (this.getHealth() > 0.0F && !this.isCreativeFlyOrSpectator()) { // Leaves - creative no clip AABB aabb; if (this.isPassenger() && !this.getVehicle().isRemoved()) { aabb = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0); -@@ -1949,9 +1949,29 @@ public abstract class Player extends LivingEntity { +@@ -1733,9 +1733,29 @@ public abstract class Player extends Avatar implements ContainerUser { return this.gameMode() == GameType.SPECTATOR; } @@ -82,10 +82,10 @@ index 8ec6f52f58bcc985fdc758a692798a35d6c86378..61baebc707cb6afcaf8c7f56fd906813 @Override diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index a46a50d1385897cc7fcf0d6976f0de7e8078d260..593e65ef3a768d4039047e42e666c8382a5d38eb 100644 +index 58ec8a43265ebf50fdd71f2cbb7dedf4762bc5b4..c269fd74bb2157f5c5f38d9dd6e1a0a032c9f29c 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -185,8 +185,9 @@ public class BlockItem extends Item { +@@ -184,8 +184,9 @@ public class BlockItem extends Item { protected boolean canPlace(BlockPlaceContext context, BlockState state) { Player player = context.getPlayer(); // CraftBukkit start @@ -110,20 +110,20 @@ index 1f0e7c391d02b18e2c89700025713ec3d759f2ea..300ee12ca9584e53e9d72e3ebfd039be org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(org.bukkit.craftbukkit.block.CraftBlock.at(context.getLevel(), clickedPos), player, org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(blockState), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -index a820ab9a2b6dc6b95d4de61aaaad4e79c521efe4..c1d1e28daa3b4d2a0bb359af08670f5d071e51ed 100644 +index 68fcb64d13bbd61ad78137f101ab20264f402df8..7e8ca373a48f89d30d4efdfcfe2acdc903a1fed9 100644 --- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -@@ -152,7 +152,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -153,7 +153,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl List entities = level.getEntities(null, progressDeltaAabb); if (!entities.isEmpty()) { for (Entity entity : entities) { - if (entity.getPistonPushReaction() != PushReaction.IGNORE) { -+ if (entity.getPistonPushReaction() != PushReaction.IGNORE && !(entity instanceof Player player && player.isCreativeFlyOrSpectator())) { // Leaves - creative no clip ++ if (entity.getPistonPushReaction() != PushReaction.IGNORE && !(entity instanceof net.minecraft.world.entity.player.Player player && player.isCreativeFlyOrSpectator())) { // Leaves - creative no clip entity.move( MoverType.SHULKER_BOX, new Vec3( diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index 0976aef81b950a062152094501372d00c20bb2b7..2841dd4896ee15d8d7ea1105d0f78b7fe41937fb 100644 +index 0a76cf42aaaaf210a4e43ed9bd3d177f0003ba57..13bd8dc66ad1a6f882d13dc0cbc3f6ae710fab90 100644 --- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java @@ -151,7 +151,7 @@ public class PistonMovingBlockEntity extends BlockEntity { diff --git a/leaves-server/minecraft-patches/features/0051-Shave-snow-layers.patch b/leaves-server/minecraft-patches/features/0051-Shave-snow-layers.patch index 9164594c..3c63c103 100644 --- a/leaves-server/minecraft-patches/features/0051-Shave-snow-layers.patch +++ b/leaves-server/minecraft-patches/features/0051-Shave-snow-layers.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Shave snow layers diff --git a/net/minecraft/world/item/ShovelItem.java b/net/minecraft/world/item/ShovelItem.java -index 887ac9f547ceaf76fd533ae47239a64c29a64b18..29b272ff2e4fe686a0e12b33f6edbe1a412b1590 100644 +index ba0609f4d9166e66599f9d4430885ab03d53ef41..c50ea91c477a9b59222faab629cdf32049899519 100644 --- a/net/minecraft/world/item/ShovelItem.java +++ b/net/minecraft/world/item/ShovelItem.java @@ -43,6 +43,26 @@ public class ShovelItem extends Item { @@ -26,7 +26,7 @@ index 887ac9f547ceaf76fd533ae47239a64c29a64b18..29b272ff2e4fe686a0e12b33f6edbe1a + level.playSound(player, clickedPos, SoundEvents.SNOW_BREAK, SoundSource.BLOCKS, 1.0F, 1.0F); + + if (player != null) { -+ tool.hurtAndBreak(1, player, LivingEntity.getSlotForHand(context.getHand())); ++ tool.hurtAndBreak(1, player, context.getHand()); + } + + return InteractionResult.SUCCESS; diff --git a/leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch b/leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch index bd18ba5b..a53cc38a 100644 --- a/leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch +++ b/leaves-server/minecraft-patches/features/0052-Elytra-aeronautics-no-chunk-load.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Elytra aeronautics no chunk load diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java -index 019886669966c69936ae6591598c97a8afbfd3db..b6fb1f2ba8622d9d319210ea7cf0a984349444e6 100644 +index 1993907c606b231b879a7279d3880876f5307b1c..85c957c547b8a90157308dccbcfb961caa0b9201 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java -@@ -854,7 +854,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -862,7 +862,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } private boolean skipPlayer(ServerPlayer player) { @@ -18,7 +18,7 @@ index 019886669966c69936ae6591598c97a8afbfd3db..b6fb1f2ba8622d9d319210ea7cf0a984 } void updatePlayerStatus(ServerPlayer player, boolean track) { -@@ -888,6 +889,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -896,6 +897,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } public void move(ServerPlayer player) { @@ -27,24 +27,24 @@ index 019886669966c69936ae6591598c97a8afbfd3db..b6fb1f2ba8622d9d319210ea7cf0a984 SectionPos lastSectionPos = player.getLastSectionPos(); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 400cb6f7fb05d4e69a7c5bfb960480eef13f15c5..d64292ebe3ed40655720ea112f7cbc2fb2108d9e 100644 +index b4000881962db5fe9c6de38f406647d95a395ec3..b4edd659a77139c1771b0714eaa35b6810d96d78 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -839,6 +839,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } +@@ -868,6 +868,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } ); + profilerFiller.popPush("blockEntities"); + if (org.leavesmc.leaves.LeavesConfig.modify.elytraAeronautics.enableNoChunkLoad) { + org.leavesmc.leaves.util.ElytraAeronauticsHelper.tick(this); + } - profilerFiller.pop(); this.tickBlockEntities(); + profilerFiller.pop(); } diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 6d9e8cb2ffe24568854a3681b8fdce76f21612c9..cbd4b3a909eab280aebcb959d86abcc66e12d633 100644 +index ea9e98313c25e7ce94b011f5bc74a4318145c6f6..8d3151a6cc4d3a53601d41abce9d61323ce86a8c 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -582,7 +582,7 @@ public class ServerGamePacketListenerImpl +@@ -591,7 +591,7 @@ public class ServerGamePacketListenerImpl speed *= 2f; // TODO: Get the speed of the vehicle instead of the player // Paper start - Prevent moving into unloaded chunks @@ -53,7 +53,7 @@ index 6d9e8cb2ffe24568854a3681b8fdce76f21612c9..cbd4b3a909eab280aebcb959d86abcc6 !serverLevel.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position()))) || !serverLevel.areChunksLoadedForMove(rootVehicle.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(rootVehicle.position()))) )) { -@@ -1597,6 +1597,7 @@ public class ServerGamePacketListenerImpl +@@ -1603,6 +1603,7 @@ public class ServerGamePacketListenerImpl allowMovement = !this.hasNewCollision(serverLevel, this.player, boundingBox, newBox); } // else: no collision at all detected, why do we care? } @@ -62,10 +62,10 @@ index 6d9e8cb2ffe24568854a3681b8fdce76f21612c9..cbd4b3a909eab280aebcb959d86abcc6 if (!allowMovement) { io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index f8e0275ebac65edfca3e8bb5d53001becd9a963f..81cf649fd4690fe5061c88e99db3d01d7faf67bf 100644 +index 0129274ab88a151600f4fdde92dae73bec352fb2..37f6e22d9f8f0fffede79b1d273d65a69f8d675c 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -1118,7 +1118,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1127,7 +1127,13 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name return; } } @@ -80,7 +80,7 @@ index f8e0275ebac65edfca3e8bb5d53001becd9a963f..81cf649fd4690fe5061c88e99db3d01d ProfilerFiller profilerFiller = Profiler.get(); profilerFiller.push("move"); if (this.stuckSpeedMultiplier.lengthSqr() > 1.0E-7) { -@@ -2137,6 +2143,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2193,6 +2199,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name this.yo = y; this.zo = d1; this.setPos(d, y, d1); @@ -89,10 +89,10 @@ index f8e0275ebac65edfca3e8bb5d53001becd9a963f..81cf649fd4690fe5061c88e99db3d01d } diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index fbf884201442c6e75b5ab4533517a10e78f02f94..841dc41e455da73ff1bfdb8feaf231ade29d1e41 100644 +index 759c320fc331704efe5df10d3f1f33aa87262290..545e9c5f46dd4f8e016ed0a93f2049d1b687dd3c 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -3328,6 +3328,11 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3368,6 +3368,11 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.fallFlyTicks++; } else { this.fallFlyTicks = 0; @@ -105,10 +105,10 @@ index fbf884201442c6e75b5ab4533517a10e78f02f94..841dc41e455da73ff1bfdb8feaf231ad if (this.isSleeping()) { diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index 61baebc707cb6afcaf8c7f56fd906813d309a2cf..eca523fe027d3570eb549756d825678e17e74152 100644 +index 7b0fdecf7ca4a5b6dd910369d6546a909926dff2..4e7e8b8f4004cab2cf5af0dafe81e72df78f7258 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -219,6 +219,7 @@ public abstract class Player extends LivingEntity { +@@ -181,6 +181,7 @@ public abstract class Player extends Avatar implements ContainerUser { private int currentImpulseContextResetGraceTime = 0; public boolean affectsSpawning = true; // Paper - Affects Spawning API public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage @@ -117,10 +117,10 @@ index 61baebc707cb6afcaf8c7f56fd906813d309a2cf..eca523fe027d3570eb549756d825678e // CraftBukkit start public boolean fauxSleeping; diff --git a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index d8dc196ef92e97f831cf97cd1536a46f81f9d5d1..92da11f86a95ff635277cbfcea73c48731080953 100644 +index 145ed3c5f5823c7505767b6d7f4f4d16cc863948..e2662b4574366dd734f5e68db3bf5505ff4e4767 100644 --- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -324,7 +324,7 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { +@@ -325,7 +325,7 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { this.spawningEntity = input.read("SpawningEntity", net.minecraft.core.UUIDUtil.CODEC).orElse(null); // Paper } diff --git a/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch b/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch index 601f6272..759211b3 100644 --- a/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch +++ b/leaves-server/minecraft-patches/features/0055-No-block-update-command.patch @@ -5,53 +5,53 @@ Subject: [PATCH] No block update command diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java -index 5d4eb61af0b0f39a5d4c37f4a303fa24b3a2936d..48bb795216ca3fb301813080de403a048bbfa98c 100644 +index 65e2edf39857b2e03c5a32dfb3b822b5cb4ce93c..1a680c491ae2ed764d3f24b465de72372b65f68d 100644 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -381,7 +381,7 @@ public class ServerPlayerGameMode { +@@ -401,7 +401,7 @@ public class ServerPlayerGameMode { org.bukkit.block.BlockState state = bblock.getState(); this.level.captureDrops = new java.util.ArrayList<>(); // CraftBukkit end - BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player); -+ BlockState blockState1 = org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update ++ BlockState blockState1 = org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update boolean flag = this.level.removeBlock(pos, false); - if (flag) { - block.destroy(this.level, pos, blockState1); + if (SharedConstants.DEBUG_BLOCK_BREAK) { + LOGGER.info("server broke {} {} -> {}", pos, blockState1, this.level.getBlockState(pos)); diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index ef8a072838558caab19e8a85f4b59cac570c2635..590252ca203124f0b720a73f174c92fbe49bc685 100644 +index feafaaeca7ffa6fda5af9897c448b61ee1760290..48eca978dc58c3c2045c5746aac5d7f5b732ff89 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -1089,6 +1089,11 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -1043,6 +1043,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft) { + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + flags = flags & ~1 | net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE; + } + // Leaves end - no block update // CraftBukkit start - tree generation if (this.captureTreeGeneration) { // Paper start - Protect Bedrock and End Portal/Frames from being destroyed -@@ -1190,6 +1195,11 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -1144,6 +1149,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl BlockState state = newState; BlockState blockState = oldState; BlockState blockState1 = currentState; + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + flags = flags & ~1 | net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE; + } + // Leaves end - no block update if (blockState1 == state) { if (blockState != blockState1) { this.setBlocksDirty(pos, blockState, blockState1); -@@ -1208,7 +1218,12 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -1162,7 +1172,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl if ((flags & 16) == 0 && recursionLeft > 0) { int i = flags & -34; - + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + this.updatePOIOnBlockStateChange(pos, blockState, blockState1); + return; + } @@ -60,19 +60,19 @@ index ef8a072838558caab19e8a85f4b59cac570c2635..590252ca203124f0b720a73f174c92fb blockState.updateIndirectNeighbourShapes(this, pos, i, recursionLeft - 1); // Don't call an event for the old block to limit event spam boolean cancelledUpdates = false; // Paper - Fix block place logic diff --git a/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index 16aa9f5996dc6eda95541fddb01e00e41305357a..31ab92e0769aa4ce09da5073ad9b734eeebac9c5 100644 +index 114aa0f1ac9feefdb856bfc821489b864aba18f3..295357c842a4a4e9e18de68c570168b1cae9593a 100644 --- a/net/minecraft/world/level/block/piston/PistonBaseBlock.java +++ b/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -105,6 +105,7 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -106,6 +106,7 @@ public class PistonBaseBlock extends DirectionalBlock { } private void checkIfExtend(Level level, BlockPos pos, BlockState state) { -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update Direction direction = state.getValue(FACING); boolean neighborSignal = this.getNeighborSignal(level, pos, direction); if (neighborSignal && !state.getValue(EXTENDED)) { diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java -index 263bf2b795057c2d5218bf9cfb684e526601aa77..da1e77ccd8805ac0cb0729720b4a1742da67d35c 100644 +index 77ed7a6a4bea3dfc77d060c49f77f4e080da200b..be5d8ca78b4e293766add81ed6cacdae7cb02436 100644 --- a/net/minecraft/world/level/redstone/NeighborUpdater.java +++ b/net/minecraft/world/level/redstone/NeighborUpdater.java @@ -34,6 +34,11 @@ public interface NeighborUpdater { @@ -80,18 +80,18 @@ index 263bf2b795057c2d5218bf9cfb684e526601aa77..da1e77ccd8805ac0cb0729720b4a1742 LevelAccessor level, Direction direction, BlockPos pos, BlockPos neighborPos, BlockState neighborState, int flags, int recursionLeft ) { + // Leaves start - no block update -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + flags = flags & ~1 | net.minecraft.world.level.block.Block.UPDATE_SKIP_ON_PLACE; + } + // Leaves end - no block update BlockState blockState = level.getBlockState(pos); - if ((flags & 128) == 0 || !blockState.is(Blocks.REDSTONE_WIRE)) { + if ((flags & Block.UPDATE_SKIP_SHAPE_UPDATE_ON_WIRE) == 0 || !blockState.is(Blocks.REDSTONE_WIRE)) { BlockState blockState1 = blockState.updateShape(level, level, pos, direction, neighborPos, neighborState, level.getRandom()); @@ -48,6 +53,7 @@ public interface NeighborUpdater { static void executeUpdate(Level level, BlockState state, BlockPos pos, Block neighborBlock, @Nullable Orientation orientation, boolean movedByPiston, BlockPos sourcePos) { // Paper end - Add source block to BlockPhysicsEvent -+ if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update ++ if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) return; // Leaves - no block update try { // CraftBukkit start org.bukkit.event.block.BlockPhysicsEvent event = new org.bukkit.event.block.BlockPhysicsEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(state), org.bukkit.craftbukkit.block.CraftBlock.at(level, sourcePos)); // Paper - Add source block to BlockPhysicsEvent diff --git a/leaves-server/minecraft-patches/features/0056-Container-open-passthrough.patch b/leaves-server/minecraft-patches/features/0056-Container-open-passthrough.patch index 5c5dc253..dff1bf1a 100644 --- a/leaves-server/minecraft-patches/features/0056-Container-open-passthrough.patch +++ b/leaves-server/minecraft-patches/features/0056-Container-open-passthrough.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Container open passthrough diff --git a/net/minecraft/world/entity/decoration/ItemFrame.java b/net/minecraft/world/entity/decoration/ItemFrame.java -index 90fd3ca5ecd29befa9237222e9f86a8a79a011e4..cc26f2bfd8992207fffd74b89752275abe2be623 100644 +index e6012d2cfe9b84782c8d5a0ba424eeda98086c09..431ebb89eb98c594829f7dbf622033e76240cbb9 100644 --- a/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/net/minecraft/world/entity/decoration/ItemFrame.java -@@ -412,6 +412,20 @@ public class ItemFrame extends HangingEntity { +@@ -421,6 +421,16 @@ public class ItemFrame extends HangingEntity { return InteractionResult.PASS; } } else { @@ -16,13 +16,9 @@ index 90fd3ca5ecd29befa9237222e9f86a8a79a011e4..cc26f2bfd8992207fffd74b89752275a + if (org.leavesmc.leaves.LeavesConfig.modify.containerPassthrough && !player.isShiftKeyDown()) { + BlockPos pos1 = this.pos.relative(this.getDirection().getOpposite()); + if (level().getBlockEntity(pos1) instanceof net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity) { -+ BlockState blockState = level().getBlockState(pos1); + net.minecraft.world.phys.BlockHitResult hitResult = new net.minecraft.world.phys.BlockHitResult(Vec3.atCenterOf(pos1), this.getDirection(), pos1, false); -+ if (flag1) { -+ return blockState.useItemOn(itemInHand, level(), player, hand, hitResult); -+ } else { -+ return blockState.useWithoutItem(level(), player, hitResult); -+ } ++ net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player; ++ return serverPlayer.gameMode.useItemOn(serverPlayer, level(), itemInHand, hand, hitResult); + } + } + // Leaves end - itemFrameContainerPassthrough diff --git a/leaves-server/minecraft-patches/features/0058-Faster-chunk-serialization.patch b/leaves-server/minecraft-patches/features/0058-Faster-chunk-serialization.patch index 07204835..19ed0f4c 100644 --- a/leaves-server/minecraft-patches/features/0058-Faster-chunk-serialization.patch +++ b/leaves-server/minecraft-patches/features/0058-Faster-chunk-serialization.patch @@ -16,7 +16,7 @@ As part of: Lithium (https://github.com/CaffeineMC/lithium-fabric) Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html) diff --git a/net/minecraft/util/BitStorage.java b/net/minecraft/util/BitStorage.java -index 02502d50f0255f5bbcc0ecb965abb48cc1a112da..674d714ba21fa0306283dae35ece466dcfcbdf6c 100644 +index 02502d50f0255f5bbcc0ecb965abb48cc1a112da..45f61e66b1c24af63e3840fc54c3564f6bc317af 100644 --- a/net/minecraft/util/BitStorage.java +++ b/net/minecraft/util/BitStorage.java @@ -38,4 +38,6 @@ public interface BitStorage extends ca.spottedleaf.moonrise.patches.block_counti @@ -24,10 +24,10 @@ index 02502d50f0255f5bbcc0ecb965abb48cc1a112da..674d714ba21fa0306283dae35ece466d } // Paper end - block counting + -+ void compact(net.minecraft.world.level.chunk.Palette srcPalette, net.minecraft.world.level.chunk.Palette dstPalette, short[] out); // Leaves - Gale - Lithium - faster chunk serialization ++ void compact(net.minecraft.world.level.chunk.Palette srcPalette, net.minecraft.world.level.chunk.Palette dstPalette, short[] out, net.minecraft.world.level.chunk.PalettedContainer resizeHandler); // Leaves - Gale - Lithium - faster chunk serialization } diff --git a/net/minecraft/util/SimpleBitStorage.java b/net/minecraft/util/SimpleBitStorage.java -index e6306a68c8652d4c5d22d5ecb1416f5f931f76ee..bbebf19cfc78d31319948943fa3fea5229f4aaf3 100644 +index e6306a68c8652d4c5d22d5ecb1416f5f931f76ee..1c7986dbfd27c20e37824cab94ba61da3465ce9e 100644 --- a/net/minecraft/util/SimpleBitStorage.java +++ b/net/minecraft/util/SimpleBitStorage.java @@ -465,4 +465,45 @@ public class SimpleBitStorage implements BitStorage { @@ -37,7 +37,7 @@ index e6306a68c8652d4c5d22d5ecb1416f5f931f76ee..bbebf19cfc78d31319948943fa3fea52 + + // Leaves start - Gale - Lithium - faster chunk serialization + @Override -+ public void compact(net.minecraft.world.level.chunk.Palette srcPalette, net.minecraft.world.level.chunk.Palette dstPalette, short[] out) { ++ public void compact(net.minecraft.world.level.chunk.Palette srcPalette, net.minecraft.world.level.chunk.Palette dstPalette, short[] out, net.minecraft.world.level.chunk.PalettedContainer resizeHandler) { + if (this.size >= Short.MAX_VALUE) { + throw new IllegalStateException("Array too large"); + } @@ -58,7 +58,7 @@ index e6306a68c8652d4c5d22d5ecb1416f5f931f76ee..bbebf19cfc78d31319948943fa3fea52 + int remappedId = mappings[value]; + + if (remappedId == 0) { -+ remappedId = dstPalette.idFor(srcPalette.valueFor(value)) + 1; ++ remappedId = dstPalette.idFor(srcPalette.valueFor(value), resizeHandler) + 1; + mappings[value] = (short) remappedId; + } + @@ -77,7 +77,7 @@ index e6306a68c8652d4c5d22d5ecb1416f5f931f76ee..bbebf19cfc78d31319948943fa3fea52 + } diff --git a/net/minecraft/util/ZeroBitStorage.java b/net/minecraft/util/ZeroBitStorage.java -index 09fd99c9cbd23b5f3c899bfb00c9b89651948ed8..d58539fe376f548930b49141c87ec5eb23b29af7 100644 +index 09fd99c9cbd23b5f3c899bfb00c9b89651948ed8..bdbeff9c93b6775cf9d4a2db878dada767d172ee 100644 --- a/net/minecraft/util/ZeroBitStorage.java +++ b/net/minecraft/util/ZeroBitStorage.java @@ -80,4 +80,6 @@ public class ZeroBitStorage implements BitStorage { @@ -85,24 +85,13 @@ index 09fd99c9cbd23b5f3c899bfb00c9b89651948ed8..d58539fe376f548930b49141c87ec5eb } // Paper end - block counting + -+ @Override public void compact(net.minecraft.world.level.chunk.Palette srcPalette, net.minecraft.world.level.chunk.Palette dstPalette, short[] out) {} // Leaves - Gale - Lithium - faster chunk serialization - } -diff --git a/net/minecraft/world/level/chunk/PaletteResize.java b/net/minecraft/world/level/chunk/PaletteResize.java -index c723606fa0be811e580ba47de8c9c575583cc930..2483210ca43221feaa5a2f1ced5c59731d5189fc 100644 ---- a/net/minecraft/world/level/chunk/PaletteResize.java -+++ b/net/minecraft/world/level/chunk/PaletteResize.java -@@ -1,5 +1,5 @@ - package net.minecraft.world.level.chunk; - --interface PaletteResize { -+public interface PaletteResize { - int onResize(int bits, T objectAdded); ++ @Override public void compact(net.minecraft.world.level.chunk.Palette srcPalette, net.minecraft.world.level.chunk.Palette dstPalette, short[] out, net.minecraft.world.level.chunk.PalettedContainer resizeHandler) {} // Leaves - Gale - Lithium - faster chunk serialization } diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java -index a251ba67644cd02a0b00d7c8b0e2c64aa5e26291..a826aff16aee6692ca07d485ab3c79c1c4a38b52 100644 +index 54d71bd666a946bdf6eece520e080c3f96003452..f16484ab8cd77d34b6e061282dd08b049ba915bc 100644 --- a/net/minecraft/world/level/chunk/PalettedContainer.java +++ b/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -24,6 +24,22 @@ import net.minecraft.util.ThreadingDetector; +@@ -23,6 +23,22 @@ import net.minecraft.util.ThreadingDetector; import net.minecraft.util.ZeroBitStorage; public class PalettedContainer implements PaletteResize, PalettedContainerRO { @@ -123,10 +112,10 @@ index a251ba67644cd02a0b00d7c8b0e2c64aa5e26291..a826aff16aee6692ca07d485ab3c79c1 + // Leaves end - Gale - Lithium - faster chunk serialization + private static final int MIN_PALETTE_BITS = 0; - private final PaletteResize dummyPaletteResize = (bits, objectAdded) -> 0; - public final IdMap registry; -@@ -343,6 +359,56 @@ public class PalettedContainer implements PaletteResize, PalettedContainer - public synchronized PalettedContainerRO.PackedData pack(IdMap registry, PalettedContainer.Strategy strategy) { // Paper - synchronize + public volatile PalettedContainer.Data data; // Paper - optimise collisions - public + private final Strategy strategy; +@@ -338,6 +354,56 @@ public class PalettedContainer implements PaletteResize, PalettedContainer + public synchronized PalettedContainerRO.PackedData pack(Strategy strategy) { // Paper - synchronize this.acquire(); + // Leaves start - Gale - Lithium - faster chunk serialization @@ -147,17 +136,17 @@ index a251ba67644cd02a0b00d7c8b0e2c64aa5e26291..a826aff16aee6692ca07d485ab3c79c1 + } + + if (elements == null) { -+ org.leavesmc.leaves.lithium.common.world.chunk.LithiumHashPalette compactedPalette = new org.leavesmc.leaves.lithium.common.world.chunk.LithiumHashPalette<>(registry, storage.getBits(), this.dummyPaletteResize); -+ short[] array = this.getOrCreate(strategy.size()); ++ org.leavesmc.leaves.lithium.common.world.chunk.LithiumHashPalette compactedPalette = new org.leavesmc.leaves.lithium.common.world.chunk.LithiumHashPalette<>(storage.getBits()); ++ short[] array = this.getOrCreate(strategy.entryCount()); + -+ storage.compact(this.data.palette(), compactedPalette, array); ++ storage.compact(this.data.palette(), compactedPalette, array, this); + + // If the palette didn't change during compaction, do a simple copy of the data array -+ if (hashPalette != null && hashPalette.getSize() == compactedPalette.getSize() && storage.getBits() == strategy.calculateBitsForSerialization(registry, hashPalette.getSize())) { // paletteSize can de-sync from palette - see https://github.com/CaffeineMC/lithium-fabric/issues/279 ++ if (hashPalette != null && hashPalette.getSize() == compactedPalette.getSize() && storage.getBits() == strategy.getConfigurationForPaletteSize(hashPalette.getSize()).bitsInStorage()) { // paletteSize can de-sync from palette - see https://github.com/CaffeineMC/lithium-fabric/issues/279 + data = this.asOptional(storage.getRaw().clone()); + elements = hashPalette.getElements(); + } else { -+ int bits = strategy.calculateBitsForSerialization(registry, compactedPalette.getSize()); ++ int bits = strategy.getConfigurationForPaletteSize(compactedPalette.getSize()).bitsInStorage(); + if (bits != 0) { + // Re-pack the integer array as the palette has changed size + SimpleBitStorage copy = new SimpleBitStorage(bits, array.length); @@ -179,10 +168,10 @@ index a251ba67644cd02a0b00d7c8b0e2c64aa5e26291..a826aff16aee6692ca07d485ab3c79c1 + return new PalettedContainerRO.PackedData<>(elements, data); + } + // Leaves end - Gale - Lithium - faster chunk serialization - PalettedContainerRO.PackedData var12; + PalettedContainerRO.PackedData var14; try { - HashMapPalette hashMapPalette = new HashMapPalette<>(registry, this.data.storage.getBits(), this.dummyPaletteResize); -@@ -404,13 +470,43 @@ public class PalettedContainer implements PaletteResize, PalettedContainer + BitStorage bitStorage = this.data.storage; +@@ -410,13 +476,43 @@ public class PalettedContainer implements PaletteResize, PalettedContainer @Override public void count(PalettedContainer.CountConsumer countConsumer) { @@ -231,4 +220,4 @@ index a251ba67644cd02a0b00d7c8b0e2c64aa5e26291..a826aff16aee6692ca07d485ab3c79c1 + // Leaves end - Gale - Lithium - faster chunk serialization } - record Configuration(Palette.Factory factory, int bits) { + @FunctionalInterface diff --git a/leaves-server/minecraft-patches/features/0062-Optimize-sun-burn-tick.patch b/leaves-server/minecraft-patches/features/0062-Optimize-sun-burn-tick.patch index 8e4caef4..f880a2ad 100644 --- a/leaves-server/minecraft-patches/features/0062-Optimize-sun-burn-tick.patch +++ b/leaves-server/minecraft-patches/features/0062-Optimize-sun-burn-tick.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Optimize sun burn tick This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 81cf649fd4690fe5061c88e99db3d01d7faf67bf..2170020f55abc47d489838f98a7d67bcef2a33a0 100644 +index 37f6e22d9f8f0fffede79b1d273d65a69f8d675c..39e31c547dcd60f48e607a9c98cfe03a38ae88b1 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -2118,9 +2118,20 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2174,9 +2174,20 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name @Deprecated public float getLightLevelDependentMagicValue() { @@ -33,7 +33,7 @@ index 81cf649fd4690fe5061c88e99db3d01d7faf67bf..2170020f55abc47d489838f98a7d67bc } public void absSnapTo(double x, double y, double z, float yRot, float xRot) { -@@ -2135,6 +2146,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2191,6 +2202,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name this.xRotO = this.getXRot(); this.setYHeadRot(yRot); // Paper - Update head rotation } @@ -42,10 +42,10 @@ index 81cf649fd4690fe5061c88e99db3d01d7faf67bf..2170020f55abc47d489838f98a7d67bc public void absSnapTo(double x, double y, double z) { double d = Mth.clamp(x, -3.0E7, 3.0E7); diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java -index 16cb4b7472b05c8aab195d5b865dd21ccd4adef8..3b73d52ea902bb1c8bd615c77444c57917f8b645 100644 +index 0659e1b95055e85e3eefd206ccb01ee4a4949a5b..1cefdab82744600c6e5886646450d4c3fab03181 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -1546,17 +1546,39 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1565,17 +1565,39 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab protected void playAttackSound() { } @@ -55,7 +55,7 @@ index 16cb4b7472b05c8aab195d5b865dd21ccd4adef8..3b73d52ea902bb1c8bd615c77444c579 + // Leaves end - optimize sun burn tick + public boolean isSunBurnTick() { - if (this.level().isBrightOutside() && !this.level().isClientSide) { + if (this.level().isBrightOutside() && !this.level().isClientSide()) { - float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); - BlockPos blockPos = BlockPos.containing(this.getX(), this.getEyeY(), this.getZ()); - boolean flag = this.isInWaterOrRain() || this.isInPowderSnow || this.wasInPowderSnow; diff --git a/leaves-server/minecraft-patches/features/0063-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch b/leaves-server/minecraft-patches/features/0063-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch index ec7bd139..6bb91779 100644 --- a/leaves-server/minecraft-patches/features/0063-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch +++ b/leaves-server/minecraft-patches/features/0063-Reduce-lambda-and-Optional-allocation-in-EntityBased.patch @@ -7,23 +7,23 @@ Subject: [PATCH] Reduce lambda and Optional allocation in This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java b/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java -index 52cb2dcd714cf8c16f167466333eeb923e4ff183..8f2fbfb8d0a24d53697442addf940fa18ae4c69b 100644 +index b1ee207527d1bf43bcc1c9d2c2a1ae2ad7993371..4bceb069ecf2e4137940ff16128ca6b5a17524fb 100644 --- a/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java +++ b/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java @@ -15,8 +15,20 @@ public class EntityBasedExplosionDamageCalculator extends ExplosionDamageCalcula @Override - public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter reader, BlockPos pos, BlockState state, FluidState fluid) { -- return super.getBlockExplosionResistance(explosion, reader, pos, state, fluid) -- .map(resistance -> this.source.getBlockExplosionResistance(explosion, reader, pos, state, fluid, resistance)); + public Optional getBlockExplosionResistance(Explosion explosion, BlockGetter level, BlockPos pos, BlockState state, FluidState fluid) { +- return super.getBlockExplosionResistance(explosion, level, pos, state, fluid) +- .map(resistance -> this.source.getBlockExplosionResistance(explosion, level, pos, state, fluid, resistance)); + if (!org.leavesmc.leaves.LeavesConfig.performance.remove.damageLambda) { -+ return super.getBlockExplosionResistance(explosion, reader, pos, state, fluid) -+ .map(max -> this.source.getBlockExplosionResistance(explosion, reader, pos, state, fluid, max)); ++ return super.getBlockExplosionResistance(explosion, level, pos, state, fluid) ++ .map(max -> this.source.getBlockExplosionResistance(explosion, level, pos, state, fluid, max)); + } else { -+ Optional optionalBlastResistance = super.getBlockExplosionResistance(explosion, reader, pos, state, fluid); ++ Optional optionalBlastResistance = super.getBlockExplosionResistance(explosion, level, pos, state, fluid); + if (optionalBlastResistance.isPresent()) { + float blastResistance = optionalBlastResistance.get(); -+ float effectiveExplosionResistance = this.source.getBlockExplosionResistance(explosion, reader, pos, state, fluid, blastResistance); ++ float effectiveExplosionResistance = this.source.getBlockExplosionResistance(explosion, level, pos, state, fluid, blastResistance); + if (effectiveExplosionResistance != blastResistance) { + return Optional.of(effectiveExplosionResistance); + } diff --git a/leaves-server/minecraft-patches/features/0066-Check-frozen-ticks-before-landing-block.patch b/leaves-server/minecraft-patches/features/0066-Check-frozen-ticks-before-landing-block.patch index 3ab6b524..2e5c87cd 100644 --- a/leaves-server/minecraft-patches/features/0066-Check-frozen-ticks-before-landing-block.patch +++ b/leaves-server/minecraft-patches/features/0066-Check-frozen-ticks-before-landing-block.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Check frozen ticks before landing block This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 9c85639394826f7e683d67e53c1be8cdf9369a78..1bf4cda041189aa5ac67be4a1bda312620788388 100644 +index 545e9c5f46dd4f8e016ed0a93f2049d1b687dd3c..1a7135f2fda41265c75448e8ca9fec1c64de8e97 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -537,10 +537,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -544,10 +544,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin } protected void tryAddFrost() { diff --git a/leaves-server/minecraft-patches/features/0067-Skip-entity-move-if-movement-is-zero.patch b/leaves-server/minecraft-patches/features/0067-Skip-entity-move-if-movement-is-zero.patch index c8f0aeaa..7573e177 100644 --- a/leaves-server/minecraft-patches/features/0067-Skip-entity-move-if-movement-is-zero.patch +++ b/leaves-server/minecraft-patches/features/0067-Skip-entity-move-if-movement-is-zero.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Skip entity move if movement is zero This patch is Powered by Gale(https://github.com/GaleMC/Gale) diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 2170020f55abc47d489838f98a7d67bcef2a33a0..6cf6e63d5c298b61d6cbb03c085530ca290ca57e 100644 +index 39e31c547dcd60f48e607a9c98cfe03a38ae88b1..d2fafdbce9fe1db0451bb4ad819d8e075122530e 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -262,6 +262,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -263,6 +263,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name public float yRotO; public float xRotO; private AABB bb = INITIAL_AABB; @@ -17,7 +17,7 @@ index 2170020f55abc47d489838f98a7d67bcef2a33a0..6cf6e63d5c298b61d6cbb03c085530ca public boolean onGround; public boolean horizontalCollision; public boolean verticalCollision; -@@ -1094,6 +1095,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1099,6 +1100,13 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name // Paper end - detailed watchdog information public void move(MoverType type, Vec3 movement) { @@ -31,7 +31,7 @@ index 2170020f55abc47d489838f98a7d67bcef2a33a0..6cf6e63d5c298b61d6cbb03c085530ca final Vec3 originalMovement = movement; // Paper - Expose pre-collision velocity // Paper start - detailed watchdog information ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread("Cannot move an entity off-main"); -@@ -4421,6 +4429,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4466,6 +4474,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name } public final void setBoundingBox(AABB bb) { diff --git a/leaves-server/minecraft-patches/features/0069-Avoid-anvil-too-expensive.patch b/leaves-server/minecraft-patches/features/0069-Avoid-anvil-too-expensive.patch index 83fb2662..7f42294c 100644 --- a/leaves-server/minecraft-patches/features/0069-Avoid-anvil-too-expensive.patch +++ b/leaves-server/minecraft-patches/features/0069-Avoid-anvil-too-expensive.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Avoid anvil too expensive diff --git a/net/minecraft/world/inventory/AnvilMenu.java b/net/minecraft/world/inventory/AnvilMenu.java -index 2346e1fc0c94084c3bb95c00be8aac36ae5f26ae..fa5fb93e2d3abd7171f4f7db9a74d42ec37b8ecd 100644 +index 9a3887752aa4b39224c9bf6e6145e20fa6962439..a7f84100b350b097d33b571be65296fe76d13e82 100644 --- a/net/minecraft/world/inventory/AnvilMenu.java +++ b/net/minecraft/world/inventory/AnvilMenu.java -@@ -266,7 +266,7 @@ public class AnvilMenu extends ItemCombinerMenu { +@@ -268,7 +268,7 @@ public class AnvilMenu extends ItemCombinerMenu { this.onlyRenaming = true; } diff --git a/leaves-server/minecraft-patches/features/0070-Bow-infinity-fix.patch b/leaves-server/minecraft-patches/features/0070-Bow-infinity-fix.patch index 600edcd1..6891cd5c 100644 --- a/leaves-server/minecraft-patches/features/0070-Bow-infinity-fix.patch +++ b/leaves-server/minecraft-patches/features/0070-Bow-infinity-fix.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Bow infinity fix diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index eca523fe027d3570eb549756d825678e17e74152..799e30efa861b6094617dcec0ba23eda49d1519a 100644 +index 4e7e8b8f4004cab2cf5af0dafe81e72df78f7258..d894741db7ce97f9809d835270148093f3293f30 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java -@@ -2187,8 +2187,10 @@ public abstract class Player extends LivingEntity { +@@ -1968,8 +1968,10 @@ public abstract class Player extends Avatar implements ContainerUser { } } diff --git a/leaves-server/minecraft-patches/features/0072-Replay-Mod-API.patch b/leaves-server/minecraft-patches/features/0072-Replay-Mod-API.patch index 5af98f0f..841af737 100644 --- a/leaves-server/minecraft-patches/features/0072-Replay-Mod-API.patch +++ b/leaves-server/minecraft-patches/features/0072-Replay-Mod-API.patch @@ -6,23 +6,23 @@ Subject: [PATCH] Replay Mod API This patch is Powered by ReplayMod(https://github.com/ReplayMod) diff --git a/net/minecraft/commands/CommandSourceStack.java b/net/minecraft/commands/CommandSourceStack.java -index 3acfb2a78845dd8081dc3c01d653034232c76e60..efe3f1849e68e5bbe2cdb3793dafc8b58c3d8415 100644 +index be42e2bd05a7468911698e53a33d87abf4a1080b..76350460f530d2edf3d58c30bff0291e7e498106 100644 --- a/net/minecraft/commands/CommandSourceStack.java +++ b/net/minecraft/commands/CommandSourceStack.java @@ -580,7 +580,7 @@ public class CommandSourceStack implements ExecutionCommandSource getOnlinePlayerNames() { -- return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players -+ return this.entity instanceof ServerPlayer sourcePlayer && !(sourcePlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().getName()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players // Leaves - only real player +- return this.entity instanceof ServerPlayer sourcePlayer && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().name()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players ++ return this.entity instanceof ServerPlayer sourcePlayer && !(sourcePlayer instanceof org.leavesmc.leaves.replay.ServerPhotographer) && !sourcePlayer.getBukkitEntity().hasPermission("paper.bypass-visibility.tab-completion") ? this.getServer().getPlayerList().getPlayers().stream().filter(serverPlayer -> sourcePlayer.getBukkitEntity().canSee(serverPlayer.getBukkitEntity())).map(serverPlayer -> serverPlayer.getGameProfile().name()).toList() : Lists.newArrayList(this.server.getPlayerNames()); // Paper - Make CommandSourceStack respect hidden players // Leaves - only real player } @Override diff --git a/net/minecraft/commands/arguments/selector/EntitySelector.java b/net/minecraft/commands/arguments/selector/EntitySelector.java -index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378fa55b6c3 100644 +index d438e31a082b675d7eb0eead7067a0b92363a9f9..c08f34bc17bec9f73c377b45389a77558f53d2a2 100644 --- a/net/minecraft/commands/arguments/selector/EntitySelector.java +++ b/net/minecraft/commands/arguments/selector/EntitySelector.java -@@ -128,11 +128,12 @@ public class EntitySelector { +@@ -129,11 +129,12 @@ public class EntitySelector { return this.findPlayers(source); } else if (this.playerName != null) { ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName); @@ -36,7 +36,7 @@ index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378 if (entity.getType().isEnabled(source.enabledFeatures())) { return List.of(entity); } -@@ -146,7 +147,7 @@ public class EntitySelector { +@@ -147,7 +148,7 @@ public class EntitySelector { AABB absoluteAabb = this.getAbsoluteAabb(vec3); if (this.currentEntity) { Predicate predicate = this.getPredicate(vec3, absoluteAabb, null); @@ -45,7 +45,7 @@ index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378 } else { Predicate predicate = this.getPredicate(vec3, absoluteAabb, source.enabledFeatures()); List list = new ObjectArrayList<>(); -@@ -157,6 +158,7 @@ public class EntitySelector { +@@ -158,6 +159,7 @@ public class EntitySelector { this.addEntities(list, serverLevel1, absoluteAabb, predicate); } } @@ -53,7 +53,7 @@ index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378 return this.sortAndLimit(vec3, list); } -@@ -192,9 +194,11 @@ public class EntitySelector { +@@ -193,9 +195,11 @@ public class EntitySelector { this.checkPermissions(source); if (this.playerName != null) { ServerPlayer playerByName = source.getServer().getPlayerList().getPlayerByName(this.playerName); @@ -65,7 +65,7 @@ index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378 return playerByName == null ? List.of() : List.of(playerByName); } else { Vec3 vec3 = this.position.apply(source.getPosition()); -@@ -206,11 +210,11 @@ public class EntitySelector { +@@ -207,11 +211,11 @@ public class EntitySelector { int resultLimit = this.getResultLimit(); List players; if (this.isWorldLimited()) { @@ -80,10 +80,10 @@ index 514f8fbdeb776087608665c35de95294aadf5cf0..b75772897cabc3e7c59301d451685378 players.add(serverPlayer1); if (players.size() >= resultLimit) { diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index cbc9f4fbad0a88bc324111a7ce80c2880ed1d3be..64b2a52ec6c4df487a9bb8ed540a429adbb6f10f 100644 +index fa2ae16481541308d525d0ac70a8bbc2c66a8851..89067dceacb1f4fb6f7acacd4ec16874da049efe 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1639,7 +1639,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop packet : stopTrackingPackets) { serverPlayer.connection.send(packet); -diff --git a/net/minecraft/server/commands/DefaultGameModeCommands.java b/net/minecraft/server/commands/DefaultGameModeCommands.java -index 84baf29ad8af6a8af0cd00ce3921b3c5b8b89451..17f5543b802d88811c3e373e579a6e8b4c9f263a 100644 ---- a/net/minecraft/server/commands/DefaultGameModeCommands.java -+++ b/net/minecraft/server/commands/DefaultGameModeCommands.java -@@ -27,7 +27,7 @@ public class DefaultGameModeCommands { - server.setDefaultGameType(gamemode); - GameType forcedGameType = server.getForcedGameType(); - if (forcedGameType != null) { -- for (ServerPlayer serverPlayer : server.getPlayerList().getPlayers()) { -+ for (ServerPlayer serverPlayer : server.getPlayerList().realPlayers) { // Leaves - only real players - // Paper start - Expand PlayerGameModeChangeEvent - org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gamemode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, net.kyori.adventure.text.Component.empty()); - if (event != null && event.isCancelled()) { diff --git a/net/minecraft/server/commands/ListPlayersCommand.java b/net/minecraft/server/commands/ListPlayersCommand.java -index c6ae34f91b3629990294fc5e69237a1e600ef038..2109b0a2d4099e64c34cd1c45b83f72654d3b615 100644 +index e7c778a7f292fd0749cbd5e6586ad1b93ac7f29e..024b56405bb58801b17a6adad7fec7a461d12a5c 100644 --- a/net/minecraft/server/commands/ListPlayersCommand.java +++ b/net/minecraft/server/commands/ListPlayersCommand.java @@ -33,7 +33,7 @@ public class ListPlayersCommand { @@ -181,7 +177,7 @@ index c6ae34f91b3629990294fc5e69237a1e600ef038..2109b0a2d4099e64c34cd1c45b83f726 org.bukkit.entity.Player sender = (org.bukkit.entity.Player) source.getBukkitSender(); playersTemp = playersTemp.stream().filter((ep) -> sender.canSee(ep.getBukkitEntity())).collect(java.util.stream.Collectors.toList()); diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java -index e6c7bbb023000b9de90c1256274ff5aba4a6478a..98f8804d58616592332e2a968282be6ad8903ea8 100644 +index 065af7f615711d7830002cd8f3046fab706082c1..d78fbc78369aab0139b99a008300b799b1dc369f 100644 --- a/net/minecraft/server/commands/OpCommand.java +++ b/net/minecraft/server/commands/OpCommand.java @@ -25,7 +25,7 @@ public class OpCommand { @@ -191,10 +187,10 @@ index e6c7bbb023000b9de90c1256274ff5aba4a6478a..98f8804d58616592332e2a968282be6a - playerList.getPlayers() + playerList.realPlayers // Leaves - only real player .stream() - .filter(serverPlayer -> !playerList.isOp(serverPlayer.getGameProfile())) - .map(serverPlayer -> serverPlayer.getGameProfile().getName()), + .filter(serverPlayer -> !playerList.isOp(serverPlayer.nameAndId())) + .map(serverPlayer -> serverPlayer.getGameProfile().name()), diff --git a/net/minecraft/server/commands/ParticleCommand.java b/net/minecraft/server/commands/ParticleCommand.java -index 33d96239f4b72a5587dc70f9602847a870d6d6a5..a83ce2cd112fca02cf3545f8c38e5cafae2c7c0e 100644 +index 51f76f7a711257e5ee432ee0b2ebe7b2e129cda0..802322cccaff58e4fcd754a8f73ac2967fbab298 100644 --- a/net/minecraft/server/commands/ParticleCommand.java +++ b/net/minecraft/server/commands/ParticleCommand.java @@ -36,7 +36,7 @@ public class ParticleCommand { @@ -243,7 +239,7 @@ index 33d96239f4b72a5587dc70f9602847a870d6d6a5..a83ce2cd112fca02cf3545f8c38e5caf ) .then( diff --git a/net/minecraft/server/commands/TeamMsgCommand.java b/net/minecraft/server/commands/TeamMsgCommand.java -index 134d7b1a9d5a5a47ebf4aabff110dde914cd6fe1..894dd1d048904b8a775416ea6cb3112215c567bc 100644 +index 0ae4d68dfe42004839a0c5ad457de592f6b4af8b..1d1e396e4b29f33669872fb39e3a7f1d474a49f7 100644 --- a/net/minecraft/server/commands/TeamMsgCommand.java +++ b/net/minecraft/server/commands/TeamMsgCommand.java @@ -40,7 +40,7 @@ public class TeamMsgCommand { @@ -256,20 +252,20 @@ index 134d7b1a9d5a5a47ebf4aabff110dde914cd6fe1..894dd1d048904b8a775416ea6cb31122 .filter(player -> player == entityOrException || player.getTeam() == team) .toList(); diff --git a/net/minecraft/server/commands/WhitelistCommand.java b/net/minecraft/server/commands/WhitelistCommand.java -index 763a51d9a0859296eb4ea52b6879d6c7703db673..25b4fcf79dbf3e227451b3321d8fd38bab55ffe9 100644 +index 9f4715c1214d6848b67637622bd24fc8f6fa5f2a..d69333e308ea772515c440f89b0b39fbd458f85c 100644 --- a/net/minecraft/server/commands/WhitelistCommand.java +++ b/net/minecraft/server/commands/WhitelistCommand.java -@@ -43,7 +43,7 @@ public class WhitelistCommand { +@@ -44,7 +44,7 @@ public class WhitelistCommand { (commandContext, suggestionsBuilder) -> { PlayerList playerList = commandContext.getSource().getServer().getPlayerList(); return SharedSuggestionProvider.suggest( - playerList.getPlayers() + playerList.realPlayers // Leaves - only real player .stream() - .filter(serverPlayer -> !playerList.getWhiteList().isWhiteListed(serverPlayer.getGameProfile())) - .map(serverPlayer -> serverPlayer.getGameProfile().getName()), + .map(Player::nameAndId) + .filter(nameAndId -> !playerList.getWhiteList().isWhiteListed(nameAndId)) diff --git a/net/minecraft/server/gui/PlayerListComponent.java b/net/minecraft/server/gui/PlayerListComponent.java -index f5ba0c9a4c3f9eaa38eeb689de915c25c7165433..24bbc32bc17802edbd9cc14310fe8141c0ad85b0 100644 +index 5a8cd3e6b448a4472092690cf589bca10b142126..8f22d5faf89006153b1fff4ff0b622f8de9fb588 100644 --- a/net/minecraft/server/gui/PlayerListComponent.java +++ b/net/minecraft/server/gui/PlayerListComponent.java @@ -17,8 +17,8 @@ public class PlayerListComponent extends JList { @@ -277,17 +273,17 @@ index f5ba0c9a4c3f9eaa38eeb689de915c25c7165433..24bbc32bc17802edbd9cc14310fe8141 Vector list = new Vector<>(); - for (int i = 0; i < this.server.getPlayerList().getPlayers().size(); i++) { -- list.add(this.server.getPlayerList().getPlayers().get(i).getGameProfile().getName()); +- list.add(this.server.getPlayerList().getPlayers().get(i).getGameProfile().name()); + for (int i = 0; i < this.server.getPlayerList().realPlayers.size(); i++) { // Leaves - only real players -+ list.add(this.server.getPlayerList().realPlayers.get(i).getGameProfile().getName()); // Leaves - only real players ++ list.add(this.server.getPlayerList().realPlayers.get(i).getGameProfile().name()); // Leaves - only real players } this.setListData(list); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index d64292ebe3ed40655720ea112f7cbc2fb2108d9e..405ee6161e480ea0dc533527f1fb8381d1e9741f 100644 +index b4edd659a77139c1771b0714eaa35b6810d96d78..ead3e1d538f138dc5370db49d8b4293aff376d46 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2695,7 +2695,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2764,7 +2764,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.add(serverPlayer); // Leaves start - skip @@ -296,7 +292,7 @@ index d64292ebe3ed40655720ea112f7cbc2fb2108d9e..405ee6161e480ea0dc533527f1fb8381 ServerLevel.this.realPlayers.add(serverPlayer); } // Leaves end - skip -@@ -2778,7 +2778,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2847,7 +2847,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.remove(serverPlayer); // Leaves start - skip @@ -305,19 +301,32 @@ index d64292ebe3ed40655720ea112f7cbc2fb2108d9e..405ee6161e480ea0dc533527f1fb8381 ServerLevel.this.realPlayers.remove(serverPlayer); } // Leaves end - skip +diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java +index 97e133f3555057e36e3e7157f1411ba923ab2823..44b1d56fb3ce3827290ef4cf987aa2386d07eb9c 100644 +--- a/net/minecraft/server/level/ServerPlayer.java ++++ b/net/minecraft/server/level/ServerPlayer.java +@@ -523,7 +523,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc + // Paper start - Expand PlayerGameModeChangeEvent + this.loadGameTypes(input); + } +- private void loadGameTypes(ValueInput input) { ++ public void loadGameTypes(ValueInput input) { // Leaves - private -> public + if (this.server.getForcedGameType() != null && this.server.getForcedGameType() != readPlayerMode(input, "playerGameType")) { + if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), org.bukkit.GameMode.getByValue(this.server.getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) { + this.gameMode.setGameModeForPlayer(this.server.getForcedGameType(), GameType.DEFAULT_MODE); diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e3506366c1412d 100644 +index 7977a0cfe18c99c4c6ba8c5b56387b690ede554d..c8628c6d505a7599b0765decfcd037c8b3212054 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -130,6 +130,7 @@ public abstract class PlayerList { +@@ -126,6 +126,7 @@ public abstract class PlayerList { + private int simulationDistance; private boolean allowCommandsForAllPlayers; - private static final boolean ALLOW_LOGOUTIVATOR = false; private int sendAllPlayerInfoIn; + public final List realPlayers = new java.util.concurrent.CopyOnWriteArrayList(); // Leaves - replay api // CraftBukkit start private org.bukkit.craftbukkit.CraftServer cserver; -@@ -148,6 +149,125 @@ public abstract class PlayerList { +@@ -149,6 +150,125 @@ public abstract class PlayerList { abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor @@ -366,7 +375,7 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 + this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot + this.playersByUUID.put(player.getUUID(), player); + -+ player.supressTrackerForLogin = true; ++ player.suppressTrackerForLogin = true; + worldserver1.addNewPlayer(player); + this.server.getCustomBossEvents().onPlayerConnect(player); + org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity(); @@ -382,7 +391,7 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 + if (org.leavesmc.leaves.LeavesConfig.modify.fakeplayer.enable) { + org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName()); + if (bot != null) { -+ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false); ++ this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false); + } + this.server.getBotList().bots.forEach(bot1 -> { + bot1.sendPlayerInfo(player); @@ -412,7 +421,7 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 + } + + player.sentListPacket = true; -+ player.supressTrackerForLogin = false; ++ player.suppressTrackerForLogin = false; + ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); + + this.sendLevelInfo(player, worldserver1); @@ -443,15 +452,15 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie) { player.isRealPlayer = true; // Paper player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed -@@ -310,6 +430,7 @@ public abstract class PlayerList { +@@ -216,6 +336,7 @@ public abstract class PlayerList { - // player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below - this.players.add(player); -+ this.realPlayers.add(player); // Leaves - replay api - this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot - this.playersByUUID.put(player.getUUID(), player); - // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below -@@ -503,6 +624,7 @@ public abstract class PlayerList { + // player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below + this.players.add(player); ++ this.realPlayers.add(player); // Leaves - replay api + this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot + this.playersByUUID.put(player.getUUID(), player); + // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below +@@ -420,6 +541,7 @@ public abstract class PlayerList { } protected void save(ServerPlayer player) { @@ -459,7 +468,7 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit player.lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving this.playerIo.save(player); -@@ -517,6 +639,43 @@ public abstract class PlayerList { +@@ -434,6 +556,43 @@ public abstract class PlayerList { } } @@ -503,7 +512,7 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player) { // CraftBukkit - return string // Paper - return Component // Paper start - Fix kick event leave message not being sent return this.remove(player, net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? player.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName()))); -@@ -590,6 +749,7 @@ public abstract class PlayerList { +@@ -507,6 +666,7 @@ public abstract class PlayerList { player.retireScheduler(); // Paper - Folia schedulers player.getAdvancements().stopListening(); this.players.remove(player); @@ -511,7 +520,7 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot this.server.getCustomBossEvents().onPlayerDisconnect(player); UUID uuid = player.getUUID(); -@@ -964,14 +1124,14 @@ public abstract class PlayerList { +@@ -835,14 +995,14 @@ public abstract class PlayerList { } public String[] getPlayerNamesArray() { @@ -519,24 +528,24 @@ index 7a0d36b9c6a633919a116fc4d47e500b2c6cbc28..95cb24f44412e2aad5f15f8256e35063 + String[] strings = new String[this.realPlayers.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support, and skip photographer - for (int i = 0; i < this.players.size(); i++) { -- strings[i] = this.players.get(i).getGameProfile().getName(); +- strings[i] = this.players.get(i).getGameProfile().name(); + for (int i = 0; i < this.realPlayers.size(); i++) { // Leaves - only real players -+ strings[i] = this.realPlayers.get(i).getGameProfile().getName(); // Leaves - only real players ++ strings[i] = this.realPlayers.get(i).getGameProfile().name(); // Leaves - only real players } // Leaves start - fakeplayer support - for (int i = this.players.size(); i < strings.length; ++i) { - strings[i] = this.server.getBotList().bots.get(i - this.players.size()).getGameProfile().getName(); + for (int i = this.realPlayers.size(); i < strings.length; ++i) { // Leaves - only real players -+ strings[i] = this.server.getBotList().bots.get(i - this.realPlayers.size()).getGameProfile().getName(); // Leaves - only real players ++ strings[i] = this.server.getBotList().bots.get(i - this.realPlayers.size()).getGameProfile().name(); // Leaves - only real players } // Leaves end - fakeplayer support -@@ -1030,7 +1190,7 @@ public abstract class PlayerList { +@@ -911,7 +1071,7 @@ public abstract class PlayerList { // Paper start - whitelist verify event / login event - public LoginResult canBypassFullServerLogin(final GameProfile profile, final LoginResult currentResult) { -- final boolean shouldKick = this.players.size() >= this.maxPlayers && !this.canBypassPlayerLimit(profile); -+ final boolean shouldKick = this.realPlayers.size() >= this.maxPlayers && !this.canBypassPlayerLimit(profile); // Leaves - only real player + public LoginResult canBypassFullServerLogin(final NameAndId nameAndId, final LoginResult currentResult) { +- final boolean shouldKick = this.players.size() >= this.getMaxPlayers() && !this.canBypassPlayerLimit(nameAndId); ++ final boolean shouldKick = this.realPlayers.size() >= this.getMaxPlayers() && !this.canBypassPlayerLimit(nameAndId); // Leaves - only real player final io.papermc.paper.event.player.PlayerServerFullCheckEvent fullCheckEvent = new io.papermc.paper.event.player.PlayerServerFullCheckEvent( - com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitMirror(profile), + new com.destroystokyo.paper.profile.CraftPlayerProfile(nameAndId), io.papermc.paper.adventure.PaperAdventure.asAdventure(currentResult.message), diff --git a/leaves-server/minecraft-patches/features/0073-Leaves-I18n-support.patch b/leaves-server/minecraft-patches/features/0073-Leaves-I18n-support.patch index a4039032..ddee8d39 100644 --- a/leaves-server/minecraft-patches/features/0073-Leaves-I18n-support.patch +++ b/leaves-server/minecraft-patches/features/0073-Leaves-I18n-support.patch @@ -26,10 +26,10 @@ index 7b9e2a1a208b46a69c16e6afd8b502259893574f..8ef3627217a8c495e4e31b70e61ad1b7 loadFromJson(resourceAsStream, output); } catch (JsonParseException | IOException var7) { diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java -index e673df664b06c654a7be0622874b9b27ad7ef20f..898bf4d1e3269135f9514cdfd923040b947eef33 100644 +index 30b681bc234eac8dc44ce3bf6e228171f5a71a7a..e7a4a977cd1dcdbdeb163016ff30346bc3289f99 100644 --- a/net/minecraft/server/Main.java +++ b/net/minecraft/server/Main.java -@@ -154,6 +154,8 @@ public class Main { +@@ -152,6 +152,8 @@ public class Main { return; } @@ -39,13 +39,13 @@ index e673df664b06c654a7be0622874b9b27ad7ef20f..898bf4d1e3269135f9514cdfd923040b String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck(); if (awtException != null) { diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index 91babab6152bb12768399ef6f2ea6afcb5e644b7..bb6863ed3fdb7bcf73ddecc1a93f89d5f84b728e 100644 +index 677ad1a39e76efc98fc3b953ad66b329184612e0..51400ef2db6e93bfa032108f72687cddfc60c88e 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -187,6 +187,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -280,6 +280,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface org.leavesmc.leaves.LeavesConfig.init((java.io.File) options.valueOf("leaves-settings")); // Leaves - Server Config - this.getBotList().loadBotInfo(); // Leaves - load resident bot info + this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info + org.leavesmc.leaves.util.ServerI18nUtil.init(); // Leaves I18n com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics // Leaves - down diff --git a/leaves-server/minecraft-patches/features/0075-RNG-Fishing.patch b/leaves-server/minecraft-patches/features/0075-RNG-Fishing.patch index 107f3a39..1b1b08d3 100644 --- a/leaves-server/minecraft-patches/features/0075-RNG-Fishing.patch +++ b/leaves-server/minecraft-patches/features/0075-RNG-Fishing.patch @@ -5,10 +5,10 @@ Subject: [PATCH] RNG Fishing diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java -index 8c139d572bd3c44b8e2b6205e28ab09f82c9abfe..a5df132c2d97c30ad0960197ea7ce8640ee9e863 100644 +index 2c79332e148375c2f277df94b16ce7dd2422c004..a22590c8c48049733d751306a2daa5686cbcf082 100644 --- a/net/minecraft/world/entity/projectile/FishingHook.java +++ b/net/minecraft/world/entity/projectile/FishingHook.java -@@ -529,7 +529,7 @@ public class FishingHook extends Projectile { +@@ -534,7 +534,7 @@ public class FishingHook extends Projectile { .withLuck(this.luck + playerOwner.getLuck()) .create(LootContextParamSets.FISHING); LootTable lootTable = this.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.FISHING); diff --git a/leaves-server/minecraft-patches/features/0076-Wool-Hopper-Counter.patch b/leaves-server/minecraft-patches/features/0076-Wool-Hopper-Counter.patch index f6919b78..d2ee7d90 100644 --- a/leaves-server/minecraft-patches/features/0076-Wool-Hopper-Counter.patch +++ b/leaves-server/minecraft-patches/features/0076-Wool-Hopper-Counter.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Wool Hopper Counter This patch is Powered by fabric-carpet(https://github.com/gnembon/fabric-carpet) diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 6dfdd4853d084f63285a7de3db49a245004c4fa5..3145b6ee853f720c5c201f5dd464645eb039100c 100644 +index a1799e2646569bf9db4fcdd3a9758f486f96f56e..6781a1362f4318e37cb298c232bffde5d0fe7a67 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -205,8 +205,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -206,8 +206,30 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen flag |= validator.getAsBoolean(); // Paper - note: this is not a validator, it's what adds/sucks in items } @@ -40,7 +40,7 @@ index 6dfdd4853d084f63285a7de3db49a245004c4fa5..3145b6ee853f720c5c201f5dd464645e setChanged(level, pos, state); // Leaves start - pca if (org.leavesmc.leaves.LeavesConfig.protocol.pca.enable) { -@@ -432,6 +454,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -433,6 +455,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen // Paper end - Perf: Optimize Hoppers private static boolean ejectItems(Level level, BlockPos pos, HopperBlockEntity blockEntity) { @@ -54,7 +54,7 @@ index 6dfdd4853d084f63285a7de3db49a245004c4fa5..3145b6ee853f720c5c201f5dd464645e Container attachedContainer = getAttachedContainer(level, pos, blockEntity); if (attachedContainer == null) { return false; -@@ -498,6 +527,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -499,6 +528,26 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } @@ -81,7 +81,7 @@ index 6dfdd4853d084f63285a7de3db49a245004c4fa5..3145b6ee853f720c5c201f5dd464645e private static int[] getSlots(Container container, Direction direction) { if (container instanceof WorldlyContainer worldlyContainer) { return worldlyContainer.getSlotsForFace(direction); -@@ -632,6 +681,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -633,6 +682,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } public static boolean addItem(Container container, ItemEntity item) { diff --git a/leaves-server/minecraft-patches/features/0077-Spider-jockeys-drop-gapples.patch b/leaves-server/minecraft-patches/features/0077-Spider-jockeys-drop-gapples.patch index c4829040..0db30909 100644 --- a/leaves-server/minecraft-patches/features/0077-Spider-jockeys-drop-gapples.patch +++ b/leaves-server/minecraft-patches/features/0077-Spider-jockeys-drop-gapples.patch @@ -5,17 +5,26 @@ Subject: [PATCH] Spider jockeys drop gapples diff --git a/net/minecraft/world/entity/monster/Skeleton.java b/net/minecraft/world/entity/monster/Skeleton.java -index 743bc2986b962d4aaef00d2e457117f375ca65c7..7a982b5720278ad6870446bfc1cffb220d08279e 100644 +index 37a60cf7b00adaadbca129659b3aea3d8f10c4e2..f1dab982211cf9e1018f98d238cea04cfd82e31b 100644 --- a/net/minecraft/world/entity/monster/Skeleton.java +++ b/net/minecraft/world/entity/monster/Skeleton.java -@@ -140,4 +140,16 @@ public class Skeleton extends AbstractSkeleton { - this.spawnAtLocation(level, Items.SKELETON_SKULL); - } +@@ -130,4 +130,25 @@ public class Skeleton extends AbstractSkeleton { + SoundEvent getStepSound() { + return SoundEvents.SKELETON_STEP; } + + // Leaves start - spider jockeys drop gapples + @Override -+ protected void dropFromLootTable(ServerLevel level, DamageSource damageSource, boolean causedByPlayer) { ++ protected void dropCustomDeathLoot(net.minecraft.server.level.ServerLevel level, DamageSource damageSource, boolean recentlyHit) { ++ super.dropCustomDeathLoot(level, damageSource, recentlyHit); ++ if (damageSource.getEntity() instanceof Creeper creeper && creeper.isPowered() && !creeper.droppedSkulls) { ++ creeper.droppedSkulls = true; ++ this.spawnAtLocation(level, net.minecraft.world.item.Items.SKELETON_SKULL); ++ } ++ } ++ ++ @Override ++ protected void dropFromLootTable(net.minecraft.server.level.ServerLevel level, DamageSource damageSource, boolean causedByPlayer) { + super.dropFromLootTable(level, damageSource, causedByPlayer); + if (org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples > 0.0D) { + if (this.getRootVehicle().getType() == EntityType.SPIDER && this.random.nextDouble() < org.leavesmc.leaves.LeavesConfig.modify.spiderJockeysDropGapples) { @@ -26,7 +35,7 @@ index 743bc2986b962d4aaef00d2e457117f375ca65c7..7a982b5720278ad6870446bfc1cffb22 + // Leaves end - spider jockeys drop gapples } diff --git a/net/minecraft/world/entity/monster/Spider.java b/net/minecraft/world/entity/monster/Spider.java -index 60c4ac37bb491af13f9f9bf730b85bbe544cf81d..aaba82e591ac380314a1b7c59e4e04cca9864d31 100644 +index a0008c2c5338d442040598ee79a667060a649695..3b578eb1a4bffb790b2baec7ba35d027158ea8d2 100644 --- a/net/minecraft/world/entity/monster/Spider.java +++ b/net/minecraft/world/entity/monster/Spider.java @@ -139,6 +139,18 @@ public class Spider extends Monster { diff --git a/leaves-server/minecraft-patches/features/0078-Force-Void-Trade.patch b/leaves-server/minecraft-patches/features/0078-Force-Void-Trade.patch index 5553d88c..baf951d6 100644 --- a/leaves-server/minecraft-patches/features/0078-Force-Void-Trade.patch +++ b/leaves-server/minecraft-patches/features/0078-Force-Void-Trade.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Force Void Trade diff --git a/net/minecraft/world/entity/npc/AbstractVillager.java b/net/minecraft/world/entity/npc/AbstractVillager.java -index 38572ecba568072b132b9e7fc12e6c0c38edd2e2..c3bec7a52f167a5169f96da709bcf9269a5bbae1 100644 +index ea7364f3cc9f339578232ba1103008a9ed50234a..99ec0cac20dac363cd5a6b97bddf900266fc4498 100644 --- a/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/net/minecraft/world/entity/npc/AbstractVillager.java @@ -43,6 +43,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @@ -14,8 +14,8 @@ index 38572ecba568072b132b9e7fc12e6c0c38edd2e2..c3bec7a52f167a5169f96da709bcf926 private final SimpleContainer inventory = new SimpleContainer(8, (org.bukkit.craftbukkit.entity.CraftAbstractVillager) this.getBukkitEntity()); // CraftBukkit - add argument + protected boolean voidTrade = false; // Leaves - force void trade - public AbstractVillager(EntityType entityType, Level level) { - super(entityType, level); + public AbstractVillager(EntityType type, Level level) { + super(type, level); @@ -144,7 +145,13 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @Override public void processTrade(MerchantOffer offer, @Nullable io.papermc.paper.event.player.PlayerPurchaseEvent event) { // The MerchantRecipe passed in here is the one set by the PlayerPurchaseEvent @@ -43,7 +43,7 @@ index 38572ecba568072b132b9e7fc12e6c0c38edd2e2..c3bec7a52f167a5169f96da709bcf926 @@ -173,7 +180,7 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @Override public void notifyTradeUpdated(ItemStack stack) { - if (!this.level().isClientSide && this.ambientSoundTime > -this.getAmbientSoundInterval() + 20) { + if (!this.level().isClientSide() && this.ambientSoundTime > -this.getAmbientSoundInterval() + 20) { - this.ambientSoundTime = -this.getAmbientSoundInterval(); + if (!voidTrade) this.ambientSoundTime = -this.getAmbientSoundInterval(); // Leaves - force void trade this.makeSound(this.getTradeUpdatedSound(!stack.isEmpty())); @@ -74,10 +74,10 @@ index 38572ecba568072b132b9e7fc12e6c0c38edd2e2..c3bec7a52f167a5169f96da709bcf926 + // Leaves end - force void trade } diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java -index e1e2bdb35866a8f32a41f6efd24ad77cf916b2e9..27812825f74903715eef560e576136b52b8cf778 100644 +index d10a407bef7da29a24582e48d8ee599c981384c5..9fb83137caeee95d35bce9265e1f86cef1adac0e 100644 --- a/net/minecraft/world/entity/npc/Villager.java +++ b/net/minecraft/world/entity/npc/Villager.java -@@ -383,6 +383,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -384,6 +384,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler } private void startTrading(Player player) { @@ -85,7 +85,7 @@ index e1e2bdb35866a8f32a41f6efd24ad77cf916b2e9..27812825f74903715eef560e576136b5 this.updateSpecialPrices(player); this.setTradingPlayer(player); this.openTradingScreen(player, this.getDisplayName(), this.getVillagerData().level()); -@@ -622,8 +623,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -623,8 +624,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @Override protected void rewardTradeXp(MerchantOffer offer) { int i = 3 + this.random.nextInt(4); @@ -101,10 +101,10 @@ index e1e2bdb35866a8f32a41f6efd24ad77cf916b2e9..27812825f74903715eef560e576136b5 this.updateMerchantTimer = 40; this.increaseProfessionLevelOnUpdate = true; diff --git a/net/minecraft/world/entity/npc/WanderingTrader.java b/net/minecraft/world/entity/npc/WanderingTrader.java -index c2573946dd1244eb5d1ef2be7823211064daa80d..567c24f7c87a23a11c54be1dad531f29d2b3a569 100644 +index 4c7287c4a081b4e1f0049c8c9bdf6a42b51e8274..c87bf6a5cfaaa1a68cba6b734e67db49709c6c5b 100644 --- a/net/minecraft/world/entity/npc/WanderingTrader.java +++ b/net/minecraft/world/entity/npc/WanderingTrader.java -@@ -124,9 +124,10 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill +@@ -124,9 +124,10 @@ public class WanderingTrader extends AbstractVillager implements Consumable.Over return InteractionResult.CONSUME; } @@ -119,7 +119,7 @@ index c2573946dd1244eb5d1ef2be7823211064daa80d..567c24f7c87a23a11c54be1dad531f29 return InteractionResult.SUCCESS; } else { diff --git a/net/minecraft/world/inventory/MerchantMenu.java b/net/minecraft/world/inventory/MerchantMenu.java -index 1bf2a015fa35981328c098f2fec363c84b85b2a7..8aa4079e7fb5fb81f33859d106a425d0183f13df 100644 +index ade7732b638b30ad0ae50605793cbf75754aad0e..8ca85b07ad3a9902359704bf7071146d99153959 100644 --- a/net/minecraft/world/inventory/MerchantMenu.java +++ b/net/minecraft/world/inventory/MerchantMenu.java @@ -25,7 +25,7 @@ public class MerchantMenu extends AbstractContainerMenu { @@ -132,7 +132,7 @@ index 1bf2a015fa35981328c098f2fec363c84b85b2a7..8aa4079e7fb5fb81f33859d106a425d0 private int merchantLevel; private boolean showProgressBar; diff --git a/net/minecraft/world/item/trading/MerchantOffer.java b/net/minecraft/world/item/trading/MerchantOffer.java -index 64c99df8ff305fa28c75dc03fc5ef8c61634ad84..a7799f226d7b7d75c5626d6d3d8394f40af930c5 100644 +index 6afeb92c2e00ca5b945b7c7de9257bd741d53c3d..f5b82f56a59dd150938e35dde0333e7ea91fd042 100644 --- a/net/minecraft/world/item/trading/MerchantOffer.java +++ b/net/minecraft/world/item/trading/MerchantOffer.java @@ -39,6 +39,7 @@ public class MerchantOffer { @@ -142,7 +142,7 @@ index 64c99df8ff305fa28c75dc03fc5ef8c61634ad84..a7799f226d7b7d75c5626d6d3d8394f4 + public int voidTradeUses; // Leaves - force void trade // CraftBukkit start - private org.bukkit.craftbukkit.inventory.@org.jspecify.annotations.Nullable CraftMerchantRecipe bukkitHandle; + private @javax.annotation.Nullable org.bukkit.craftbukkit.inventory.CraftMerchantRecipe bukkitHandle; @@ -78,6 +79,7 @@ public class MerchantOffer { this.priceMultiplier = priceMultiplier; this.xp = xp; @@ -178,7 +178,7 @@ index 64c99df8ff305fa28c75dc03fc5ef8c61634ad84..a7799f226d7b7d75c5626d6d3d8394f4 public void setToOutOfStock() { diff --git a/net/minecraft/world/level/block/EndGatewayBlock.java b/net/minecraft/world/level/block/EndGatewayBlock.java -index 68914268ca9350a6c1d794e011e1f9a8aecd609c..f22d502df5f444703a248fff50c864d2924c4549 100644 +index 6161cd82dade8b4119ab0b8ba84451d592ce5858..cc90b8ebfe8c5d451710c202c5e87433e2a45c7b 100644 --- a/net/minecraft/world/level/block/EndGatewayBlock.java +++ b/net/minecraft/world/level/block/EndGatewayBlock.java @@ -109,6 +109,17 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { diff --git a/leaves-server/minecraft-patches/features/0080-CCE-update-suppression.patch b/leaves-server/minecraft-patches/features/0080-CCE-update-suppression.patch index 6217e7da..b5f7a3b6 100644 --- a/leaves-server/minecraft-patches/features/0080-CCE-update-suppression.patch +++ b/leaves-server/minecraft-patches/features/0080-CCE-update-suppression.patch @@ -5,11 +5,11 @@ Subject: [PATCH] CCE update suppression diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java -index 787a4226789b0e6d35ef1a36601655b0a8666b6f..45e48e6d225a2741cd615345711072610d728474 100644 +index ffca65d881ee6f4bde8e579d012ee5c1a11a0c2d..efb25d556f2192b1ee499c28d14aa7d11bcabef8 100644 --- a/net/minecraft/world/level/block/ShulkerBoxBlock.java +++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java @@ -185,7 +185,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock { - protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) { + protected int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos, Direction direction) { // Leaves start - update suppression crash fix try { - return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos)); diff --git a/leaves-server/minecraft-patches/features/0081-Disable-offline-warn-if-use-proxy.patch b/leaves-server/minecraft-patches/features/0081-Disable-offline-warn-if-use-proxy.patch index ca011833..0fb17dee 100644 --- a/leaves-server/minecraft-patches/features/0081-Disable-offline-warn-if-use-proxy.patch +++ b/leaves-server/minecraft-patches/features/0081-Disable-offline-warn-if-use-proxy.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Disable offline warn if use proxy diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java -index bb6863ed3fdb7bcf73ddecc1a93f89d5f84b728e..6a6209750854f5bad7f069cd6694d339bd9ce834 100644 +index 70f0adbd01aa6aabc7b8ecc9e02dd93e2f479a69..144d1ff610d2743e554e6a4940bcb184e09c1520 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java -@@ -247,7 +247,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -335,7 +335,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface String proxyFlavor = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "Velocity" : "BungeeCord"; String proxyLink = (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.velocity.enabled) ? "https://docs.papermc.io/velocity/security" : "http://www.spigotmc.org/wiki/firewall-guide/"; // Paper end - Add Velocity IP Forwarding Support diff --git a/leaves-server/minecraft-patches/features/0082-Make-Item-tick-vanilla.patch b/leaves-server/minecraft-patches/features/0082-Make-Item-tick-vanilla.patch index f787f022..375fee9b 100644 --- a/leaves-server/minecraft-patches/features/0082-Make-Item-tick-vanilla.patch +++ b/leaves-server/minecraft-patches/features/0082-Make-Item-tick-vanilla.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make Item tick vanilla diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index af0467f60e5a873eeed7b741717c327272746a9a..fc8d3e56771998a04d5e0b35ad7638a44def8c77 100644 +index 78edda120dd53be66f3e995dcf4e62799a837532..4bd9b16ad73114c457eb5987adeb18231ec6eea7 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java -@@ -138,6 +138,9 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -129,6 +129,9 @@ public class ItemEntity extends Entity implements TraceableEntity { // Paper start - EAR 2 @Override public void inactiveTick() { @@ -18,7 +18,7 @@ index af0467f60e5a873eeed7b741717c327272746a9a..fc8d3e56771998a04d5e0b35ad7638a4 super.inactiveTick(); if (this.pickupDelay > 0 && this.pickupDelay != 32767) { this.pickupDelay--; -@@ -155,6 +158,8 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -146,6 +149,8 @@ public class ItemEntity extends Entity implements TraceableEntity { // CraftBukkit end this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause } diff --git a/leaves-server/minecraft-patches/features/0083-Copper-Bulb-1-gt-delay.patch b/leaves-server/minecraft-patches/features/0083-Copper-Bulb-1-gt-delay.patch index 517340ee..c8395c0c 100644 --- a/leaves-server/minecraft-patches/features/0083-Copper-Bulb-1-gt-delay.patch +++ b/leaves-server/minecraft-patches/features/0083-Copper-Bulb-1-gt-delay.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Copper Bulb 1 gt delay diff --git a/net/minecraft/world/level/block/CopperBulbBlock.java b/net/minecraft/world/level/block/CopperBulbBlock.java -index 25caeb117d9a49fa00f46ec895a35dee8242aacd..ce1d34f28f9318b741df074fccddfe91f16b57cf 100644 +index 54511c27d8d85f1a9702d899f1f7c7dda201cdfa..1e8e7f7081b7f9d6a9d31e6cfd5900daf0a364db 100644 --- a/net/minecraft/world/level/block/CopperBulbBlock.java +++ b/net/minecraft/world/level/block/CopperBulbBlock.java -@@ -32,14 +32,26 @@ public class CopperBulbBlock extends Block { +@@ -33,14 +33,26 @@ public class CopperBulbBlock extends Block { @Override protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { if (oldState.getBlock() != state.getBlock() && level instanceof ServerLevel serverLevel) { @@ -37,7 +37,7 @@ index 25caeb117d9a49fa00f46ec895a35dee8242aacd..ce1d34f28f9318b741df074fccddfe91 } } -@@ -56,6 +68,15 @@ public class CopperBulbBlock extends Block { +@@ -57,6 +69,15 @@ public class CopperBulbBlock extends Block { } } diff --git a/leaves-server/minecraft-patches/features/0084-Crafter-1-gt-delay.patch b/leaves-server/minecraft-patches/features/0084-Crafter-1-gt-delay.patch index d7a8a6fd..4c4115d8 100644 --- a/leaves-server/minecraft-patches/features/0084-Crafter-1-gt-delay.patch +++ b/leaves-server/minecraft-patches/features/0084-Crafter-1-gt-delay.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Crafter 1 gt delay diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java -index caf31218a1aff84367da126ee1dc46b8c8a1e5d1..a073188275456ee2eee776b149a14f68e4557f4a 100644 +index 59cea0d226829267e9a5dff9f81789673bd3f062..9ff207acba5584480481e0df63ad3ca9bced0354 100644 --- a/net/minecraft/world/level/block/CrafterBlock.java +++ b/net/minecraft/world/level/block/CrafterBlock.java @@ -75,7 +75,7 @@ public class CrafterBlock extends BaseEntityBlock { @@ -14,7 +14,7 @@ index caf31218a1aff84367da126ee1dc46b8c8a1e5d1..a073188275456ee2eee776b149a14f68 if (hasNeighborSignal && !triggeredValue) { - level.scheduleTick(pos, this, 4); + level.scheduleTick(pos, this, !org.leavesmc.leaves.LeavesConfig.modify.oldMC.crafter1gt ? 4 : 1); // Leaves - crafter 1 gt delay - level.setBlock(pos, state.setValue(TRIGGERED, true), 2); + level.setBlock(pos, state.setValue(TRIGGERED, true), Block.UPDATE_CLIENTS); this.setBlockEntityTriggered(blockEntity, true); } else if (!hasNeighborSignal && triggeredValue) { @@ -125,7 +125,7 @@ public class CrafterBlock extends BaseEntityBlock { diff --git a/leaves-server/minecraft-patches/features/0085-More-Region-Format-Support.patch b/leaves-server/minecraft-patches/features/0085-More-Region-Format-Support.patch index 426105c3..4cf609b2 100644 --- a/leaves-server/minecraft-patches/features/0085-More-Region-Format-Support.patch +++ b/leaves-server/minecraft-patches/features/0085-More-Region-Format-Support.patch @@ -21,10 +21,10 @@ index a814512fcfb85312474ae2c2c21443843bf57831..2b0349568f38321c893a8ffa16607350 public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite( final int chunkX, final int chunkZ, final CompoundTag compound diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java -index f5ed467c0880e4bcdf1b9ae773a5aac21c4381c3..349741f48bf21777b640a4698a0ae8da0b2487c5 100644 +index aa3d5a6ea59ac77665f2cfaa56a7d383016d08d0..2f56cda82824053b3f5321cec2e93f9c6a7e84e8 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java -@@ -1260,7 +1260,7 @@ public final class MoonriseRegionFileIO { +@@ -1274,7 +1274,7 @@ public final class MoonriseRegionFileIO { this.regionDataController.finishWrite(this.chunkX, this.chunkZ, writeData); // Paper start - flush regionfiles on save if (this.world.paperConfig().chunks.flushRegionsOnSave) { @@ -33,7 +33,7 @@ index f5ed467c0880e4bcdf1b9ae773a5aac21c4381c3..349741f48bf21777b640a4698a0ae8da if (regionFile != null) { regionFile.flush(); } // else: evicted from cache, which should have called flush -@@ -1470,7 +1470,7 @@ public final class MoonriseRegionFileIO { +@@ -1490,7 +1490,7 @@ public final class MoonriseRegionFileIO { public static interface IORunnable { @@ -54,15 +54,15 @@ index 51c126735ace8fdde89ad97b5cab62f244212db0..a6573e327ace16b7ea320eb1440ffcbc + public void moonrise$write(final org.leavesmc.leaves.region.IRegionFile regionFile) throws IOException; // Leaves - more region format } diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 1241b008d66bacd8640302a6dbf52a2e592b29b9..0172b4f0c3d5753a3a3d8ccfe591c09328216e48 100644 +index 89067dceacb1f4fb6f7acacd4ec16874da049efe..d4409971d20e19266ff80b940b05edf07e8d52e3 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -944,10 +944,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> REGION_SHIFT, chunkPos.z >> REGION_SHIFT); @@ -327,7 +327,7 @@ index 384f2cd090d6d23bd1308d6e82c24338f2bf55d1..7b86212082f49bef0c087c8e080874fe if (ret != null) { return ret; } -@@ -291,13 +301,22 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -292,13 +302,22 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise this.regionCache.removeLast().close(); } @@ -352,7 +352,7 @@ index 384f2cd090d6d23bd1308d6e82c24338f2bf55d1..7b86212082f49bef0c087c8e080874fe this.regionCache.putAndMoveToFirst(key, ret); -@@ -311,7 +330,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -312,7 +331,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); } @@ -361,7 +361,7 @@ index 384f2cd090d6d23bd1308d6e82c24338f2bf55d1..7b86212082f49bef0c087c8e080874fe synchronized (regionfile) { try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) { CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); -@@ -346,7 +365,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -347,7 +366,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise @Nullable public CompoundTag read(ChunkPos chunkPos) throws IOException { // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing @@ -370,7 +370,7 @@ index 384f2cd090d6d23bd1308d6e82c24338f2bf55d1..7b86212082f49bef0c087c8e080874fe if (regionFile == null) { return null; } -@@ -385,7 +404,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -386,7 +405,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise public void scanChunk(ChunkPos chunkPos, StreamTagVisitor visitor) throws IOException { // CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing @@ -379,16 +379,16 @@ index 384f2cd090d6d23bd1308d6e82c24338f2bf55d1..7b86212082f49bef0c087c8e080874fe if (regionFile == null) { return; } -@@ -399,7 +418,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise - } +@@ -401,7 +420,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise public void write(ChunkPos chunkPos, @Nullable CompoundTag chunkData) throws IOException { // Paper - rewrite chunk system - public -- RegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system -+ org.leavesmc.leaves.region.IRegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system // Leaves - more region format - // Paper start - rewrite chunk system - if (regionFile == null) { - // if the RegionFile doesn't exist, no point in deleting from it -@@ -429,7 +448,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise + if (!SharedConstants.DEBUG_DONT_SAVE_WORLD) { +- RegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system ++ org.leavesmc.leaves.region.IRegionFile regionFile = this.getRegionFile(chunkPos, chunkData == null); // CraftBukkit // Paper - rewrite chunk system // Leaves - more region format + // Paper start - rewrite chunk system + if (regionFile == null) { + // if the RegionFile doesn't exist, no point in deleting from it +@@ -432,7 +451,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise // Paper start - rewrite chunk system synchronized (this) { final ExceptionCollector exceptionCollector = new ExceptionCollector<>(); @@ -397,7 +397,7 @@ index 384f2cd090d6d23bd1308d6e82c24338f2bf55d1..7b86212082f49bef0c087c8e080874fe try { regionFile.close(); } catch (final IOException ex) { -@@ -445,7 +464,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -448,7 +467,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise // Paper start - rewrite chunk system synchronized (this) { final ExceptionCollector exceptionCollector = new ExceptionCollector<>(); diff --git a/leaves-server/minecraft-patches/features/0086-No-TNT-place-update.patch b/leaves-server/minecraft-patches/features/0086-No-TNT-place-update.patch index af66fae0..de7604d6 100644 --- a/leaves-server/minecraft-patches/features/0086-No-TNT-place-update.patch +++ b/leaves-server/minecraft-patches/features/0086-No-TNT-place-update.patch @@ -5,12 +5,12 @@ Subject: [PATCH] No TNT place update diff --git a/net/minecraft/world/level/block/TntBlock.java b/net/minecraft/world/level/block/TntBlock.java -index 93d6e05578622b057d8e973c71f880a17036a6b5..807b2d9bde6d9a365feff13adc4a8b546bec6d0c 100644 +index 938dbdbbaa90181865ad9f19446c99cf301ab653..0862ef425b518e8d322f9fa7d9a3aacdd03f8237 100644 --- a/net/minecraft/world/level/block/TntBlock.java +++ b/net/minecraft/world/level/block/TntBlock.java @@ -47,7 +47,7 @@ public class TntBlock extends Block { @Override - protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { if (!oldState.is(state.getBlock())) { - if (level.hasNeighborSignal(pos) && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent + if (level.hasNeighborSignal(pos) && !org.leavesmc.leaves.LeavesConfig.modify.noTNTPlaceUpdate && prime(level, pos, () -> org.bukkit.craftbukkit.event.CraftEventFactory.callTNTPrimeEvent(level, pos, org.bukkit.event.block.TNTPrimeEvent.PrimeCause.REDSTONE, null, null))) { // CraftBukkit - TNTPrimeEvent // Leaves - prevent update diff --git a/leaves-server/minecraft-patches/features/0087-Servux-Protocol.patch b/leaves-server/minecraft-patches/features/0087-Servux-Protocol.patch index f0eebca2..c5cb3241 100644 --- a/leaves-server/minecraft-patches/features/0087-Servux-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0087-Servux-Protocol.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Servux Protocol diff --git a/net/minecraft/server/ServerTickRateManager.java b/net/minecraft/server/ServerTickRateManager.java -index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..c0504614b9239a69f2a6a49d964a97647469c1e4 100644 +index 4257c47d33e3773fac766817138cc21c55d9ab76..8638f3f7aa853802a60ddeb681d089e0c6143693 100644 --- a/net/minecraft/server/ServerTickRateManager.java +++ b/net/minecraft/server/ServerTickRateManager.java -@@ -128,4 +128,10 @@ public class ServerTickRateManager extends TickRateManager { +@@ -129,4 +129,10 @@ public class ServerTickRateManager extends TickRateManager { player.connection.send(ClientboundTickingStatePacket.from(this)); player.connection.send(ClientboundTickingStepPacket.from(this)); } @@ -20,14 +20,28 @@ index 40338efd1c0e56d869d03f1d0687e7ff0fcbf11a..c0504614b9239a69f2a6a49d964a9764 + // Leaves end - servux } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 405ee6161e480ea0dc533527f1fb8381d1e9741f..dcb1f6975b1cb18f38e0cf8a43d551f07836b12f 100644 +index ead3e1d538f138dc5370db49d8b4293aff376d46..dbebfec31e8bd9b9ea6bbf486875396fdcba93b6 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2233,6 +2233,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } +@@ -2285,9 +2285,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + // Paper end + } - this.lastSpawnChunkRadius = i; -+ org.leavesmc.leaves.protocol.servux.ServuxHudDataProtocol.refreshSpawnMetadata = true; // Leaves - servux ++ + @Override + public LevelData.RespawnData getRespawnData() { + return this.getServer().getRespawnData(); ++ // TODO: 1.21.9 removed spawn chunk, should we keep this? ++ // int i = this.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS) + 1; ++ // if (i > 1) { ++ // // Paper start - allow disabling gamerule limits ++ // for (ChunkPos chunkPos : io.papermc.paper.util.MCUtil.getSpiralOutChunks(pos, i - 2)) { ++ // this.getChunkSource().addTicketAtLevel(TicketType.START, chunkPos, ChunkLevel.ENTITY_TICKING_LEVEL); ++ // } ++ // // Paper end - allow disabling gamerule limits ++ // } ++ // this.lastSpawnChunkRadius = i; ++ // org.leavesmc.leaves.protocol.servux.ServuxHudDataProtocol.refreshSpawnMetadata = true; // Leaves - servux } public LongSet getForceLoadedChunks() { diff --git a/leaves-server/minecraft-patches/features/0088-Placing-locked-hopper-no-longer-send-NC-updates.patch b/leaves-server/minecraft-patches/features/0088-Placing-locked-hopper-no-longer-send-NC-updates.patch index ee3e35e5..87b7e194 100644 --- a/leaves-server/minecraft-patches/features/0088-Placing-locked-hopper-no-longer-send-NC-updates.patch +++ b/leaves-server/minecraft-patches/features/0088-Placing-locked-hopper-no-longer-send-NC-updates.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Placing locked hopper no longer send NC updates diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 1bca7c6ca429ae3d58b802991464f62568a4d430..f31a48530e965f01507c335f50d898ed72767e3c 100644 +index 48eca978dc58c3c2045c5746aac5d7f5b732ff89..07ab2907bb9e4de5810889bec6d2b08f9abfec0c 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -1210,7 +1210,11 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -1164,7 +1164,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } if ((flags & 1) != 0) { @@ -18,6 +18,6 @@ index 1bca7c6ca429ae3d58b802991464f62568a4d430..f31a48530e965f01507c335f50d898ed + this.updateNeighborsAt(pos, blockState.getBlock()); + } + // Leaves end - Placing locked hopper doesn't send NC updates. - if (!this.isClientSide && state.hasAnalogOutputSignal()) { + if (!this.isClientSide() && state.hasAnalogOutputSignal()) { this.updateNeighbourForOutputSignal(pos, newState.getBlock()); } diff --git a/leaves-server/minecraft-patches/features/0089-Renewable-deepslate.patch b/leaves-server/minecraft-patches/features/0089-Renewable-deepslate.patch index 4e5e29c0..0435d652 100644 --- a/leaves-server/minecraft-patches/features/0089-Renewable-deepslate.patch +++ b/leaves-server/minecraft-patches/features/0089-Renewable-deepslate.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Renewable deepslate diff --git a/net/minecraft/world/level/block/LiquidBlock.java b/net/minecraft/world/level/block/LiquidBlock.java -index 7320b416e8d660419018b0699f49ab6f45a3373b..553c6b298ec5929dba6acd859bd38bfbe293838b 100644 +index 70cb8b2cf79833d8b5f9cee6d9c5495e5b706078..24e0484f0570d071c9ccdc67250a2b5ecd112dfd 100644 --- a/net/minecraft/world/level/block/LiquidBlock.java +++ b/net/minecraft/world/level/block/LiquidBlock.java -@@ -190,7 +190,7 @@ public class LiquidBlock extends Block implements BucketPickup { +@@ -196,7 +196,7 @@ public class LiquidBlock extends Block implements BucketPickup { for (Direction direction : POSSIBLE_FLOW_DIRECTIONS) { BlockPos blockPos = pos.relative(direction.getOpposite()); if (level.getFluidState(blockPos).is(FluidTags.WATER)) { @@ -18,12 +18,12 @@ index 7320b416e8d660419018b0699f49ab6f45a3373b..553c6b298ec5929dba6acd859bd38bfb if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level, pos, block.defaultBlockState(), 3)) { this.fizz(level, pos); diff --git a/net/minecraft/world/level/material/LavaFluid.java b/net/minecraft/world/level/material/LavaFluid.java -index 033f252248b671e35135269dd2df6e7ca4585604..5bea04f4d70566e6791bef49e32c775cc5546d6c 100644 +index 6f9e277f8ec94169e2ff8b70b63d5ef52729b069..371b864b85da51a0444cafc4b127ff8f036c7f1b 100644 --- a/net/minecraft/world/level/material/LavaFluid.java +++ b/net/minecraft/world/level/material/LavaFluid.java -@@ -223,7 +223,7 @@ public abstract class LavaFluid extends FlowingFluid { +@@ -226,7 +226,7 @@ public abstract class LavaFluid extends FlowingFluid { if (this.is(FluidTags.LAVA) && fluidState1.is(FluidTags.WATER)) { - if (blockState.getBlock() instanceof LiquidBlock) { + if (state.getBlock() instanceof LiquidBlock) { // CraftBukkit start - if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level.getMinecraftWorld(), pos, Blocks.STONE.defaultBlockState(), 3)) { + if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(level.getMinecraftWorld(), pos, org.leavesmc.leaves.LeavesConfig.modify.renewableDeepslate && level.getMinecraftWorld().dimension() == Level.OVERWORLD && pos.getY() < 0 ? Blocks.DEEPSLATE.defaultBlockState() : Blocks.STONE.defaultBlockState(), 3)) { // Leaves - renewable deepslate diff --git a/leaves-server/minecraft-patches/features/0090-Renewable-sponges.patch b/leaves-server/minecraft-patches/features/0090-Renewable-sponges.patch index 7bec76d3..460d44d0 100644 --- a/leaves-server/minecraft-patches/features/0090-Renewable-sponges.patch +++ b/leaves-server/minecraft-patches/features/0090-Renewable-sponges.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Renewable sponges diff --git a/net/minecraft/world/entity/monster/Guardian.java b/net/minecraft/world/entity/monster/Guardian.java -index a36f0181e1aa24538d6c868a8675da89427bdeae..b9c08ae9579ab5867adff4e0c5e7824b56203b3c 100644 +index c907feb2ab6862d980f89f6341402131a8a966f2..daad38e533360501529f2f7a0bdfee213ac56ca6 100644 --- a/net/minecraft/world/entity/monster/Guardian.java +++ b/net/minecraft/world/entity/monster/Guardian.java -@@ -452,6 +452,28 @@ public class Guardian extends Monster { +@@ -453,6 +453,28 @@ public class Guardian extends Monster { } } diff --git a/leaves-server/minecraft-patches/features/0092-Vanilla-hopper.patch b/leaves-server/minecraft-patches/features/0092-Vanilla-hopper.patch index f17f2fa1..55c20449 100644 --- a/leaves-server/minecraft-patches/features/0092-Vanilla-hopper.patch +++ b/leaves-server/minecraft-patches/features/0092-Vanilla-hopper.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Vanilla hopper This is a temporary solution designed to attempt to restore the vanilla behavior of the funnel while preserving optimizations as much as possible. It should ultimately be replaced by the optimization solution provided by lithium. diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 84092e0182dc2c20e57b4c14a52c3a9622318fd4..a6776df02ec71470696836cf89b942cc34c782ec 100644 +index 6781a1362f4318e37cb298c232bffde5d0fe7a67..6b432c555d380098b07ba53039a9b148b2571de2 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -307,36 +307,58 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -308,36 +308,58 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen ItemStack movedItem = origItemStack; final int originalItemCount = origItemStack.getCount(); final int movedItemCount = Math.min(level.spigotConfig.hopperAmount, originalItemCount); diff --git a/leaves-server/minecraft-patches/features/0093-Old-hopper-suckin-behavior.patch b/leaves-server/minecraft-patches/features/0093-Old-hopper-suckin-behavior.patch index 81ec1446..9e83af3c 100644 --- a/leaves-server/minecraft-patches/features/0093-Old-hopper-suckin-behavior.patch +++ b/leaves-server/minecraft-patches/features/0093-Old-hopper-suckin-behavior.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Old hopper suckin behavior diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index deb67f1636d7fcb24946019d36fbdf97c022e764..09083d971ffc6e8af17cac9e71acbead2e666fc4 100644 +index 6b432c555d380098b07ba53039a9b148b2571de2..a7ade5f683e43463f9ea42ad6843e9c80f2fa46c 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -629,7 +629,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -630,7 +630,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen return false; } else { diff --git a/leaves-server/minecraft-patches/features/0094-Fix-falling-block-s-block-location.patch b/leaves-server/minecraft-patches/features/0094-Fix-falling-block-s-block-location.patch index 4e86b782..9c63574f 100644 --- a/leaves-server/minecraft-patches/features/0094-Fix-falling-block-s-block-location.patch +++ b/leaves-server/minecraft-patches/features/0094-Fix-falling-block-s-block-location.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix falling block's block location diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 6cf6e63d5c298b61d6cbb03c085530ca290ca57e..4952bfcb1414e9cc71587a40fefc715e87b73ae0 100644 +index d2fafdbce9fe1db0451bb4ad819d8e075122530e..a18f2f0d1df0fecb6f8b22a252d7a6d715eb8439 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -5026,6 +5026,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5052,6 +5052,15 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name int floor = Mth.floor(x); int floor1 = Mth.floor(y); int floor2 = Mth.floor(z); diff --git a/leaves-server/minecraft-patches/features/0095-Bytebuf-API.patch b/leaves-server/minecraft-patches/features/0095-Bytebuf-API.patch index 601e0be1..319dc2d0 100644 --- a/leaves-server/minecraft-patches/features/0095-Bytebuf-API.patch +++ b/leaves-server/minecraft-patches/features/0095-Bytebuf-API.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Bytebuf API diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 95cb24f44412e2aad5f15f8256e3506366c1412d..d4eb10d3734930a43b8270cdc7eb78bf40907c94 100644 +index c8628c6d505a7599b0765decfcd037c8b3212054..f376b03e267ae9c3acc9636b6ccee733497027d2 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -384,6 +384,13 @@ public abstract class PlayerList { - boolean _boolean = gameRules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN); - boolean _boolean1 = gameRules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); - boolean _boolean2 = gameRules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); +@@ -290,6 +290,13 @@ public abstract class PlayerList { + boolean _boolean = gameRules.getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN); + boolean _boolean1 = gameRules.getBoolean(GameRules.RULE_REDUCEDDEBUGINFO); + boolean _boolean2 = gameRules.getBoolean(GameRules.RULE_LIMITED_CRAFTING); + + // Leaves start - Bytebuf API + if (!(player instanceof org.leavesmc.leaves.bot.ServerBot) && !(player instanceof org.leavesmc.leaves.replay.ServerPhotographer)) { @@ -19,6 +19,6 @@ index 95cb24f44412e2aad5f15f8256e3506366c1412d..d4eb10d3734930a43b8270cdc7eb78bf + } + // Leaves end - Bytebuf API + - serverGamePacketListenerImpl.send( - new ClientboundLoginPacket( - player.getId(), + serverGamePacketListenerImpl.send( + new ClientboundLoginPacket( + player.getId(), diff --git a/leaves-server/minecraft-patches/features/0096-Allow-grindstone-overstacking.patch b/leaves-server/minecraft-patches/features/0096-Allow-grindstone-overstacking.patch index 3b0f8c09..eccf9e8a 100644 --- a/leaves-server/minecraft-patches/features/0096-Allow-grindstone-overstacking.patch +++ b/leaves-server/minecraft-patches/features/0096-Allow-grindstone-overstacking.patch @@ -22,7 +22,7 @@ index 75170c8d3be477a6ea2a1d62018a6ab630b0e54e..e5f348daf1ae9e604ae12928e5c8618c this.setChanged(); } diff --git a/net/minecraft/world/entity/vehicle/ContainerEntity.java b/net/minecraft/world/entity/vehicle/ContainerEntity.java -index 99f109e2653eff10c011f380694bd77a76381cee..3d7ea706747a6bcd8db8dd62139989669acb9c08 100644 +index 358de981544b220bde770410c24e5f6b10520d91..d079513d0fcafc1f9d0b6384602d0d3f4093b9db 100644 --- a/net/minecraft/world/entity/vehicle/ContainerEntity.java +++ b/net/minecraft/world/entity/vehicle/ContainerEntity.java @@ -163,6 +163,11 @@ public interface ContainerEntity extends Container, MenuProvider { @@ -38,7 +38,7 @@ index 99f109e2653eff10c011f380694bd77a76381cee..3d7ea706747a6bcd8db8dd6213998966 } diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index 47963968763cbee60016853d617f159c0761d282..c1ca84cf0dbb4fd091cfab517721c87e0f9074a0 100644 +index e78baa9433b6f5cb32142fe583fe95831b173d5a..509d368f7fa9e6330da02615d7bf78debb932623 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -607,7 +607,7 @@ public abstract class AbstractContainerMenu { @@ -91,10 +91,10 @@ index 47963968763cbee60016853d617f159c0761d282..c1ca84cf0dbb4fd091cfab517721c87e if (isCheck) { stack.shrink(Math.min(stack.getCount(), i1)); diff --git a/net/minecraft/world/inventory/GrindstoneMenu.java b/net/minecraft/world/inventory/GrindstoneMenu.java -index 18c15a7657e6fd994a8f17d0812c822d6adc8eab..00a0ce28632a7f515a94087c2752e8787212f0d9 100644 +index ad70a0f7debee27d9f3b2ff39cb0429b39485190..c8d3a8b9087460b20547dc49c1bf70bda87c218d 100644 --- a/net/minecraft/world/inventory/GrindstoneMenu.java +++ b/net/minecraft/world/inventory/GrindstoneMenu.java -@@ -178,7 +178,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -179,7 +179,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { int i2 = i + i1 + max * 5 / 100; int i3 = 1; if (!inputItem.isDamageableItem()) { @@ -103,20 +103,20 @@ index 18c15a7657e6fd994a8f17d0812c822d6adc8eab..00a0ce28632a7f515a94087c2752e878 return ItemStack.EMPTY; } -@@ -247,7 +247,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { +@@ -248,7 +248,7 @@ public class GrindstoneMenu extends AbstractContainerMenu { ItemStack item1 = this.repairSlots.getItem(0); ItemStack item2 = this.repairSlots.getItem(1); - if (index == 2) { + if (slotIndex == 2) { - if (!this.moveItemStackTo(item, 3, 39, true)) { + if (!this.moveItemStackTo(item, 3, 39, true, false, org.leavesmc.leaves.LeavesConfig.modify.oldMC.allowGrindstoneOverstacking)) { // Leaves - allowGrindstoneOverstacking: Disable stack check return ItemStack.EMPTY; } diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 4fdb3c36b39213f01f86ba281c7b62af99f5dcce..646d4c26870bb03f6d397b5e03ad97923d0928b2 100644 +index 8a93c4b9571b3088dc92317544d209603880d3fa..005fd35dcae20d404922ef797cf22ef69ecd6c3a 100644 --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -409,7 +409,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -410,7 +410,11 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit ItemStack itemStack = this.items.get(index); boolean flag = !stack.isEmpty() && ItemStack.isSameItemSameComponents(itemStack, stack); this.items.set(index, stack); @@ -130,10 +130,10 @@ index 4fdb3c36b39213f01f86ba281c7b62af99f5dcce..646d4c26870bb03f6d397b5e03ad9792 this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API this.cookingTimer = 0; diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index 63d6a43dab067aa4c8fb67095c455130196eef9f..561acadcf81dc219d88e8ec8bdbd4f5f8fcbadc3 100644 +index 701a12db0c342c9ff2c974e581b112182dec2ea6..1e6819928ffab524197003bd9469adb3976dce3a 100644 --- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -@@ -145,6 +145,12 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co +@@ -149,6 +149,12 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co @Override public void setItem(int slot, ItemStack stack) { this.getItems().set(slot, stack); @@ -147,10 +147,10 @@ index 63d6a43dab067aa4c8fb67095c455130196eef9f..561acadcf81dc219d88e8ec8bdbd4f5f this.setChanged(); } diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 4dca615d263f1b0dacf574cfaa00ea23abee2714..d9969741bb8efbf83df51692ebcd12e3d77c10f6 100644 +index a7ade5f683e43463f9ea42ad6843e9c80f2fa46c..83a8dc51d0346fb5b28922e7b54d5ee58b315228 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -@@ -113,6 +113,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -114,6 +114,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen public void setItem(int index, ItemStack stack) { this.unpackLootTable(null); this.getItems().set(index, stack); diff --git a/leaves-server/minecraft-patches/features/0097-Configurable-MC-67.patch b/leaves-server/minecraft-patches/features/0097-Configurable-MC-67.patch index 3d00ede2..2add63ce 100644 --- a/leaves-server/minecraft-patches/features/0097-Configurable-MC-67.patch +++ b/leaves-server/minecraft-patches/features/0097-Configurable-MC-67.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable MC-67 diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 4952bfcb1414e9cc71587a40fefc715e87b73ae0..e09eb2612eb3943c9d108885bf189b04e050f459 100644 +index a18f2f0d1df0fecb6f8b22a252d7a6d715eb8439..8bd5f957d61c429cf75e5a14296f735c33149e39 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -4200,6 +4200,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4245,6 +4245,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name } public boolean canTeleport(Level fromLevel, Level toLevel) { diff --git a/leaves-server/minecraft-patches/features/0099-Disable-crystal-portal-proximity-check.patch b/leaves-server/minecraft-patches/features/0099-Disable-crystal-portal-proximity-check.patch index c04325ab..eb5ce003 100644 --- a/leaves-server/minecraft-patches/features/0099-Disable-crystal-portal-proximity-check.patch +++ b/leaves-server/minecraft-patches/features/0099-Disable-crystal-portal-proximity-check.patch @@ -27,10 +27,10 @@ index 05ec512839898f96d9769bb0d00f6ba11dda0c4b..27b225344c34e561d4913b3a6ca1c4a4 } diff --git a/net/minecraft/world/level/dimension/end/EndDragonFight.java b/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 37d74a98689166355e7ed6165f1611cdb8cd1db7..7d7656cf8fdec9073ad3a1d026cbeb1f2f297d6a 100644 +index d2e49f8490bff739a3726e73a303b2c24c47617f..5a616d89522aacd1230e356197dec49abcfef872 100644 --- a/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -576,12 +576,14 @@ public class EndDragonFight { +@@ -577,12 +577,14 @@ public class EndDragonFight { } public boolean tryRespawn() { // CraftBukkit - return boolean @@ -45,7 +45,7 @@ index 37d74a98689166355e7ed6165f1611cdb8cd1db7..7d7656cf8fdec9073ad3a1d026cbeb1f if (this.dragonKilled && this.respawnStage == null) { BlockPos blockPos = this.portalLocation; if (blockPos == null) { -@@ -596,6 +598,7 @@ public class EndDragonFight { +@@ -597,6 +599,7 @@ public class EndDragonFight { blockPos = this.portalLocation; } @@ -53,7 +53,7 @@ index 37d74a98689166355e7ed6165f1611cdb8cd1db7..7d7656cf8fdec9073ad3a1d026cbeb1f // Paper start - Perf: Do crystal-portal proximity check before entity lookup if (placedEndCrystalPos != null && !level.paperConfig().misc.allowRemoteEnderDragonRespawning) { // The end crystal must be 0 or 1 higher than the portal origin -@@ -611,7 +614,7 @@ public class EndDragonFight { +@@ -612,7 +615,7 @@ public class EndDragonFight { } } // Paper end - Perf: Do crystal-portal proximity check before entity lookup diff --git a/leaves-server/minecraft-patches/features/0100-Can-disable-LivingEntity-aiStep-alive-check.patch b/leaves-server/minecraft-patches/features/0100-Can-disable-LivingEntity-aiStep-alive-check.patch index cebbf6c0..ec69cbd8 100644 --- a/leaves-server/minecraft-patches/features/0100-Can-disable-LivingEntity-aiStep-alive-check.patch +++ b/leaves-server/minecraft-patches/features/0100-Can-disable-LivingEntity-aiStep-alive-check.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Can disable LivingEntity aiStep alive check diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 1bf4cda041189aa5ac67be4a1bda312620788388..59a352427b8d6445f3da3c6033bae4826277ed60 100644 +index 1a7135f2fda41265c75448e8ca9fec1c64de8e97..0f2a3002ec01451e92b3e4869373a910be6ccab2 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -3285,7 +3285,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3325,7 +3325,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin } } diff --git a/leaves-server/minecraft-patches/features/0101-Fix-FallingBlockEntity-Duplicate.patch b/leaves-server/minecraft-patches/features/0101-Fix-FallingBlockEntity-Duplicate.patch index 94f4226f..d5d36ed6 100644 --- a/leaves-server/minecraft-patches/features/0101-Fix-FallingBlockEntity-Duplicate.patch +++ b/leaves-server/minecraft-patches/features/0101-Fix-FallingBlockEntity-Duplicate.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix FallingBlockEntity Duplicate diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java -index 595dee03e3a7d98d703e48fb53d82d7f392a2b3d..0fd2c522a5fb038a8c002970af6feebd9dc9c436 100644 +index 308af61031070d57556532645f73b41517d696e9..387f7a48499421858ea024bca01e372d3dbcdb57 100644 --- a/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -387,7 +387,7 @@ public class FallingBlockEntity extends Entity { +@@ -386,7 +386,7 @@ public class FallingBlockEntity extends Entity { ResourceKey resourceKey1 = this.level().dimension(); boolean flag = (resourceKey1 == Level.END || resourceKey == Level.END) && resourceKey1 != resourceKey; Entity entity = super.teleport(teleportTransition); diff --git a/leaves-server/minecraft-patches/features/0102-Old-Block-remove-behaviour.patch b/leaves-server/minecraft-patches/features/0102-Old-Block-remove-behaviour.patch index 51199039..b1f1fe54 100644 --- a/leaves-server/minecraft-patches/features/0102-Old-Block-remove-behaviour.patch +++ b/leaves-server/minecraft-patches/features/0102-Old-Block-remove-behaviour.patch @@ -25,7 +25,7 @@ index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab + // Leaves end - behaviour 1.21.1- } diff --git a/net/minecraft/world/level/block/AbstractFurnaceBlock.java b/net/minecraft/world/level/block/AbstractFurnaceBlock.java -index d52eeff0d564a24bddb873750c81e3fe999f16f0..aa2597d825f93b0b0623ab7fae29e45de3f3ebcc 100644 +index 9cbc52312c065cc1e7a01368f3c3bd6f374f4e16..271a71aab53e206798c5e3a7be385da4e4f01e12 100644 --- a/net/minecraft/world/level/block/AbstractFurnaceBlock.java +++ b/net/minecraft/world/level/block/AbstractFurnaceBlock.java @@ -51,6 +51,26 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock { @@ -56,7 +56,7 @@ index d52eeff0d564a24bddb873750c81e3fe999f16f0..aa2597d825f93b0b0623ab7fae29e45d protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java -index f7820265f10b78674acd13e6204b9212fd27b038..700bd0f6a4f4fd6cd85b3e666fff1b3fd0a96b8e 100644 +index 95a1e4c332becb284af0e71c55f02e8e6338fdce..0597ec660c85c2ae5c50588016b2c15e951e2d56 100644 --- a/net/minecraft/world/level/block/BarrelBlock.java +++ b/net/minecraft/world/level/block/BarrelBlock.java @@ -49,6 +49,14 @@ public class BarrelBlock extends BaseEntityBlock { @@ -75,7 +75,7 @@ index f7820265f10b78674acd13e6204b9212fd27b038..700bd0f6a4f4fd6cd85b3e666fff1b3f protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java -index 42ee3f32fe44c1f0680c994a69201f7bd7792673..19214c236bca4e454e3bbe7dc50e00b66398c119 100644 +index a9c511e7debb8d47125d31291a0867791d9ab41b..aace49e366d2723c552d2efb082ab53b786fb5c5 100644 --- a/net/minecraft/world/level/block/BasePressurePlateBlock.java +++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java @@ -125,6 +125,19 @@ public abstract class BasePressurePlateBlock extends Block { @@ -99,7 +99,7 @@ index 42ee3f32fe44c1f0680c994a69201f7bd7792673..19214c236bca4e454e3bbe7dc50e00b6 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston && this.getSignalForState(state) > 0) { diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java -index 5f99e18244501ed2d85be77b71f48cc93058cdb7..6bf50d9c3921b15f40b4fba273abeb4c2e0f30b3 100644 +index 37705ccc6b12113d22a1b7c2d8f8a05e4c812604..e6c732e29b0d3c7217e80e287483ce15fa29c043 100644 --- a/net/minecraft/world/level/block/BaseRailBlock.java +++ b/net/minecraft/world/level/block/BaseRailBlock.java @@ -121,6 +121,23 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl @@ -127,10 +127,10 @@ index 5f99e18244501ed2d85be77b71f48cc93058cdb7..6bf50d9c3921b15f40b4fba273abeb4c protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston) { diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java -index f563f8ea63e67f808802baa4c6a700e803c045a0..0cc4479d9d3f6aea280c9f88997d141dc24917a9 100644 +index 265736cb7b96dae60e9c6c7911d10f9a430a548c..687ea91d4e18adf97a5277340af976d07bb4d13a 100644 --- a/net/minecraft/world/level/block/BrewingStandBlock.java +++ b/net/minecraft/world/level/block/BrewingStandBlock.java -@@ -78,6 +78,14 @@ public class BrewingStandBlock extends BaseEntityBlock { +@@ -79,6 +79,14 @@ public class BrewingStandBlock extends BaseEntityBlock { level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0); } @@ -146,7 +146,7 @@ index f563f8ea63e67f808802baa4c6a700e803c045a0..0cc4479d9d3f6aea280c9f88997d141d protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java -index 66c589bc633d32ebf36b1ab55ba6250ca2ddd6f6..f96d3c7b7ec15973aca3aabe056608fd5efb856b 100644 +index a0d4f27ec05a18fcd460a01507a004897abb1e4f..924b11ed548bd069c21c411f4ec1ec0d5ee573e5 100644 --- a/net/minecraft/world/level/block/ButtonBlock.java +++ b/net/minecraft/world/level/block/ButtonBlock.java @@ -132,6 +132,19 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock { @@ -170,7 +170,7 @@ index 66c589bc633d32ebf36b1ab55ba6250ca2ddd6f6..f96d3c7b7ec15973aca3aabe056608fd protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston && state.getValue(POWERED)) { diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java -index 028e2ad8bcb23b3f9f80a5ec551204bb2d7db1ae..c9e2becc0644de707e0bd251318813c50fc82be2 100644 +index d6aaebacfb9b713dafb718d1e7ade8da8111ebb5..99fd2486c16c8d9d299862002cd82decc7442410 100644 --- a/net/minecraft/world/level/block/CampfireBlock.java +++ b/net/minecraft/world/level/block/CampfireBlock.java @@ -105,6 +105,20 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB @@ -192,14 +192,14 @@ index 028e2ad8bcb23b3f9f80a5ec551204bb2d7db1ae..c9e2becc0644de707e0bd251318813c5 + // Leaves end - behaviour 1.21.1- + @Override - protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) { + protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier, boolean pastEdges) { if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java -index c4937d1b482e2ec60961bda62ad6cc155f0ce8f7..818b1a5df0e9a0566210e4b3512ad856515e385f 100644 +index 3cce87fd6e1d9d65d6b28bf44dd218541e815788..2b4260aef5bc56a9b2a5834f16c7d3ef2c8c2d2f 100644 --- a/net/minecraft/world/level/block/ChestBlock.java +++ b/net/minecraft/world/level/block/ChestBlock.java -@@ -244,6 +244,14 @@ public class ChestBlock extends AbstractChestBlock implements - return blockState.is(this) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null; +@@ -276,6 +276,14 @@ public class ChestBlock extends AbstractChestBlock implements + return this.chestCanConnectTo(blockState) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null; } + // Leaves start - behaviour 1.21.1- @@ -214,10 +214,10 @@ index c4937d1b482e2ec60961bda62ad6cc155f0ce8f7..818b1a5df0e9a0566210e4b3512ad856 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java -index eb315a50a83dc7230d7ad66f4daeb0d632679941..7bccf15310f6851875bfd77d4c66f4ce863b65e1 100644 +index 77eee6728ecb0d5cb035a6a7969d5b3498a19b62..899508fbf9f59287d6ece9635e9cf071231d87b4 100644 --- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java +++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java -@@ -180,6 +180,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock { +@@ -150,6 +150,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock implements Selectabl SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property)); } @@ -246,7 +246,7 @@ index eb315a50a83dc7230d7ad66f4daeb0d632679941..7bccf15310f6851875bfd77d4c66f4ce protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java -index a073188275456ee2eee776b149a14f68e4557f4a..89e69eb87d43d35002a352bdb187f503033f6630 100644 +index 9ff207acba5584480481e0df63ad3ca9bced0354..3e011483a74bd45269b5623e5f423495d0300120 100644 --- a/net/minecraft/world/level/block/CrafterBlock.java +++ b/net/minecraft/world/level/block/CrafterBlock.java @@ -129,6 +129,14 @@ public class CrafterBlock extends BaseEntityBlock { @@ -265,7 +265,7 @@ index a073188275456ee2eee776b149a14f68e4557f4a..89e69eb87d43d35002a352bdb187f503 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java -index 73885449a3316face50292756de2a3f298d3d111..333e18e4ead0bb6ef9681ce27ec156f79821af7c 100644 +index 80fe93eedad9ff6cd5308c8039f988d2635cd574..6c1f1a00ad32bf579643b37b932f6aa3db50d77c 100644 --- a/net/minecraft/world/level/block/CreakingHeartBlock.java +++ b/net/minecraft/world/level/block/CreakingHeartBlock.java @@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock { @@ -286,7 +286,7 @@ index 73885449a3316face50292756de2a3f298d3d111..333e18e4ead0bb6ef9681ce27ec156f7 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java -index f1570f1f4f7e43aacbcffef8bcf8ef27d46899da..6afd1c618112234ce4940105582a4399e20ab34c 100644 +index ba27d15c674582607f4be6a99541475f790aeb1a..b2a0d53f7480ec7e152d77b239345b21919678ed 100644 --- a/net/minecraft/world/level/block/DecoratedPotBlock.java +++ b/net/minecraft/world/level/block/DecoratedPotBlock.java @@ -165,6 +165,14 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog @@ -305,7 +305,7 @@ index f1570f1f4f7e43aacbcffef8bcf8ef27d46899da..6afd1c618112234ce4940105582a4399 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java -index 558751ade918a92a1173096ccfeacf238f4260d0..94d35e4812705771756a0ee1a9b0255be75e3770 100644 +index 1158bdc1993a1c8f907070d6190c5a7d02d4bdb6..b975297c0475049935c38554a8c736abbf9882de 100644 --- a/net/minecraft/world/level/block/DiodeBlock.java +++ b/net/minecraft/world/level/block/DiodeBlock.java @@ -175,6 +175,16 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock { @@ -326,7 +326,7 @@ index 558751ade918a92a1173096ccfeacf238f4260d0..94d35e4812705771756a0ee1a9b0255b protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston) { diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java -index 7ff6255fcd50344cd6ac7f8a67d61fd59c85e413..7a23d27ce76ae6b90d01c4dc7af416bb6b6516ea 100644 +index 78375f2ec7e62db803961f4b9feb3e467db20477..58e65813461b76baa6ec01a691549650e65468a2 100644 --- a/net/minecraft/world/level/block/DispenserBlock.java +++ b/net/minecraft/world/level/block/DispenserBlock.java @@ -147,6 +147,14 @@ public class DispenserBlock extends BaseEntityBlock { @@ -345,7 +345,7 @@ index 7ff6255fcd50344cd6ac7f8a67d61fd59c85e413..7a23d27ce76ae6b90d01c4dc7af416bb protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java -index 46a27f60ba407dacdac190b5e292ab3f1db5a078..d3535a9dc462d92a306aea981d7799d8d975f59d 100644 +index 3140269761935201882173e568004488147a4110..32b2f73d371b4dd53cdadfc94ff5e4d7bdaf7e37 100644 --- a/net/minecraft/world/level/block/HopperBlock.java +++ b/net/minecraft/world/level/block/HopperBlock.java @@ -125,6 +125,14 @@ public class HopperBlock extends BaseEntityBlock { @@ -364,7 +364,7 @@ index 46a27f60ba407dacdac190b5e292ab3f1db5a078..d3535a9dc462d92a306aea981d7799d8 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java -index 56cf6528f0cd9b8528490d7cee9a1f0e54108ef9..955854e5b3a18b8f1441145554a97c5454a65d12 100644 +index c48ffdca3adb53005af18a743fc368a0e9e78f0a..5a095afc88f31cab4be59f2bd5962b67d9236b27 100644 --- a/net/minecraft/world/level/block/JukeboxBlock.java +++ b/net/minecraft/world/level/block/JukeboxBlock.java @@ -73,6 +73,19 @@ public class JukeboxBlock extends BaseEntityBlock { @@ -388,10 +388,10 @@ index 56cf6528f0cd9b8528490d7cee9a1f0e54108ef9..955854e5b3a18b8f1441145554a97c54 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java -index 5a9b601b7bf7e80b04ebd8f5c8b7d121031132c7..b714d3c7649384a8fdbe0a713e2193e241c80618 100644 +index 8e18ff02e9773a76ec27e2f62b75a05ec0241dc0..c2615055354ef2539052096ef9ff042ac52460ba 100644 --- a/net/minecraft/world/level/block/LecternBlock.java +++ b/net/minecraft/world/level/block/LecternBlock.java -@@ -197,6 +197,36 @@ public class LecternBlock extends BaseEntityBlock { +@@ -198,6 +198,36 @@ public class LecternBlock extends BaseEntityBlock { changePowered(level, pos, state, false); } @@ -429,7 +429,7 @@ index 5a9b601b7bf7e80b04ebd8f5c8b7d121031132c7..b714d3c7649384a8fdbe0a713e2193e2 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (state.getValue(POWERED)) { diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java -index 76f2a29f37187344324d68941307d58e6343b6ae..3645ca9589aa1a74134180c9918a6f67bc64ce7a 100644 +index 20207bcd2a9def5d94e994e2b7807d18df551015..358abfa6f4e4cfc648923caa4fa26e0fab9986bc 100644 --- a/net/minecraft/world/level/block/LeverBlock.java +++ b/net/minecraft/world/level/block/LeverBlock.java @@ -125,6 +125,19 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock { @@ -453,7 +453,7 @@ index 76f2a29f37187344324d68941307d58e6343b6ae..3645ca9589aa1a74134180c9918a6f67 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston && state.getValue(POWERED)) { diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java -index 13b92472d50a41446b86c62ec31919fe0a953374..d567a7c303bf1baa92fc24ff47870d56c70907af 100644 +index 622f28a3661eec0487179aa9798f5771c0d957f7..4175957f56ddaaaa6e7fd7639f8173e39ce92d71 100644 --- a/net/minecraft/world/level/block/LightningRodBlock.java +++ b/net/minecraft/world/level/block/LightningRodBlock.java @@ -120,6 +120,18 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc @@ -476,7 +476,7 @@ index 13b92472d50a41446b86c62ec31919fe0a953374..d567a7c303bf1baa92fc24ff47870d56 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (state.getValue(POWERED)) { diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java -index bd2aa00ce8b78c16f6107064dd00bfbb072df0df..6db3a21bcc37ae79f82b19ee0a851f539d4a654d 100644 +index 3c12d8e23f20b666b0005e597ba2e803c02d5d78..17c371f4c24e8a81705bdd322b1de5de4b8be8b7 100644 --- a/net/minecraft/world/level/block/ObserverBlock.java +++ b/net/minecraft/world/level/block/ObserverBlock.java @@ -127,6 +127,17 @@ public class ObserverBlock extends DirectionalBlock { @@ -498,7 +498,7 @@ index bd2aa00ce8b78c16f6107064dd00bfbb072df0df..6db3a21bcc37ae79f82b19ee0a851f53 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) { diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java -index 35dc47d5ba1a2659304ccc08010611438ccf04d8..04cc3c5a6ae0bea5f3a47ff7f9a7fe1f486294eb 100644 +index 6f9ab1b41222832c29949bca1bdfb717ceecf5fa..6e6d10b0a9c2cf4516d29fb747f7e6e7f6063666 100644 --- a/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/net/minecraft/world/level/block/RedStoneWireBlock.java @@ -363,6 +363,27 @@ public class RedStoneWireBlock extends Block { @@ -530,7 +530,7 @@ index 35dc47d5ba1a2659304ccc08010611438ccf04d8..04cc3c5a6ae0bea5f3a47ff7f9a7fe1f protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston) { diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java -index 33e2f2de19208b7af6551132887e310744b4b702..d36c3bdb59bf9b9467d1a9807ab789b4c180010d 100644 +index 1ecf736ceeca45bb91dbe31a1dcb0262cbb9c1c7..52cc39babc8b884d01e6e50f04d113130b87eaa8 100644 --- a/net/minecraft/world/level/block/RedstoneTorchBlock.java +++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java @@ -53,6 +53,15 @@ public class RedstoneTorchBlock extends BaseTorchBlock { @@ -550,7 +550,7 @@ index 33e2f2de19208b7af6551132887e310744b4b702..d36c3bdb59bf9b9467d1a9807ab789b4 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston) { diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java -index f0101e88140f480c1a94f899744991f78c9e3756..fa9cb4c40a41eea7fd63a4513d0b0f39067de9ba 100644 +index 957f019773d5c042086c1f7c3887ac85b97960ed..de3d5e6eb82c13667f21a3af95b1d2dca02bea94 100644 --- a/net/minecraft/world/level/block/SculkSensorBlock.java +++ b/net/minecraft/world/level/block/SculkSensorBlock.java @@ -129,6 +129,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg @@ -573,7 +573,7 @@ index f0101e88140f480c1a94f899744991f78c9e3756..fa9cb4c40a41eea7fd63a4513d0b0f39 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (getPhase(state) == SculkSensorPhase.ACTIVE) { diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java -index 757f8453e147875ab9f14d9726bb734ef27447c9..d0558d0e33f3d6e25af2dd71650d723e8997dae6 100644 +index 465d13a748b5b6773bc0ee26ac3eda582c9f5bcd..484b97494ff45f9d1bc1ca80d01b74995dc220f9 100644 --- a/net/minecraft/world/level/block/SculkShriekerBlock.java +++ b/net/minecraft/world/level/block/SculkShriekerBlock.java @@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo @@ -594,7 +594,7 @@ index 757f8453e147875ab9f14d9726bb734ef27447c9..d0558d0e33f3d6e25af2dd71650d723e protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { if (state.getValue(SHRIEKING)) { diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java -index 45e48e6d225a2741cd615345711072610d728474..80520260ccb52935f3c1564c2f161bb148ba7baa 100644 +index c64685c9aef0ec3c95dc27d631318d2293c1a361..f69f9fa1ec89baafeef9e6a0f01a108c2f443259 100644 --- a/net/minecraft/world/level/block/ShulkerBoxBlock.java +++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java @@ -152,6 +152,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock { @@ -618,7 +618,7 @@ index 45e48e6d225a2741cd615345711072610d728474..80520260ccb52935f3c1564c2f161bb1 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { Containers.updateNeighboursAfterDestroy(state, level, pos); diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java -index c8f793d1cdeef7e3e0d5fceb45a4507d542e4b33..27f382f6c663b2954a6fb966ece05ba021fcd6b1 100644 +index 9d005c3db8f0c784cdd7217e7b110daa703a9cf3..190d7cd818f768bd44fc1b4e62af2c9b3aacbe4d 100644 --- a/net/minecraft/world/level/block/TripWireBlock.java +++ b/net/minecraft/world/level/block/TripWireBlock.java @@ -108,6 +108,16 @@ public class TripWireBlock extends Block { @@ -639,7 +639,7 @@ index c8f793d1cdeef7e3e0d5fceb45a4507d542e4b33..27f382f6c663b2954a6fb966ece05ba0 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java -index a92462c76a648e6c175b8c2ef3e925aba81ba774..b32760f1096581059418f479b060019f7dccbd67 100644 +index 219cbb38de6452fcc0a7b4db1cf648bbf2f1feac..dbefb8bbcc84ee910287d80ddc5d9abe46721f8f 100644 --- a/net/minecraft/world/level/block/TripWireHookBlock.java +++ b/net/minecraft/world/level/block/TripWireHookBlock.java @@ -245,6 +245,25 @@ public class TripWireHookBlock extends Block { @@ -669,10 +669,10 @@ index a92462c76a648e6c175b8c2ef3e925aba81ba774..b32760f1096581059418f479b060019f protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { if (!movedByPiston) { diff --git a/net/minecraft/world/level/block/entity/BlockEntityType.java b/net/minecraft/world/level/block/entity/BlockEntityType.java -index 386e6a48701b4c9256e33174123381a93d61e292..abade114c5b5051ce96b6489f08feb7e1cc774ee 100644 +index 33e8479f20d1a07c518ba736322517c422cd2763..caaf5a1324e1a3d8447145b8deb55e6c8cf8c56a 100644 --- a/net/minecraft/world/level/block/entity/BlockEntityType.java +++ b/net/minecraft/world/level/block/entity/BlockEntityType.java -@@ -263,7 +263,7 @@ public class BlockEntityType { +@@ -303,7 +303,7 @@ public class BlockEntityType { } public boolean isValid(BlockState state) { @@ -682,7 +682,7 @@ index 386e6a48701b4c9256e33174123381a93d61e292..abade114c5b5051ce96b6489f08feb7e @Deprecated diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java -index 05bbc2e59384702439548a988e128a85f1adbe82..af516d5b6bd31de2c6a388ec8001126e2a351cf3 100644 +index 9f013b6a87a18f83188d6efec9f84d8895876f24..3594d97bd7e233bd418e0763db75330a27759c7a 100644 --- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java +++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java @@ -67,6 +67,18 @@ public class MovingPistonBlock extends BaseEntityBlock { @@ -705,7 +705,7 @@ index 05bbc2e59384702439548a988e128a85f1adbe82..af516d5b6bd31de2c6a388ec8001126e public void destroy(LevelAccessor level, BlockPos pos, BlockState state) { BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java -index 6c789e56f21f01252c21786cfeb48d88485b5636..e24a61a4e2dac0159d52f07c93ddf860f4bfb8f7 100644 +index 8c35c7e54373f8be187a84bd4b4a9ce9d6341dff..894e0532cf4cdc0a92300b5ead2398da3a836d8e 100644 --- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java +++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java @@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock { @@ -729,10 +729,10 @@ index 6c789e56f21f01252c21786cfeb48d88485b5636..e24a61a4e2dac0159d52f07c93ddf860 protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java -index be66f0f1cb1b0bcec8f9489a1fdd8777df1adb6b..67719dce9017a4c86a70b62fb660bddc636d5582 100644 +index a38618c28819405f0fb35aa686d1f3f0e94e5da2..683a6a48593218b7504d6c99a0357278fb380665 100644 --- a/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -171,6 +171,15 @@ public abstract class BlockBehaviour implements FeatureElement { +@@ -170,6 +170,15 @@ public abstract class BlockBehaviour implements FeatureElement { org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot } @@ -748,7 +748,7 @@ index be66f0f1cb1b0bcec8f9489a1fdd8777df1adb6b..67719dce9017a4c86a70b62fb660bddc protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) { } -@@ -867,6 +876,12 @@ public abstract class BlockBehaviour implements FeatureElement { +@@ -869,6 +878,12 @@ public abstract class BlockBehaviour implements FeatureElement { // CraftBukkit end } @@ -762,22 +762,22 @@ index be66f0f1cb1b0bcec8f9489a1fdd8777df1adb6b..67719dce9017a4c86a70b62fb660bddc this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston); } diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 0e22116fefcbdbf2049b7ec285b35fd03c723dc5..45386818312fbd99bbcb72d14ad9e54cd864a2a8 100644 +index 7c5f827134e0fa81031660a78d4d404c21840cb6..479723aaee1cf9ea6be8606a63f721236b3e2424 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -396,20 +396,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -403,22 +403,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot boolean flag = !blockState.is(block); - boolean flag1 = (flags & 64) != 0; - boolean flag2 = (flags & 256) == 0; -- if (flag && blockState.hasBlockEntity()) { -- if (!this.level.isClientSide && flag2) { + boolean flag1 = (flags & Block.UPDATE_MOVE_BY_PISTON) != 0; + boolean flag2 = (flags & Block.UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS) == 0; +- if (flag && blockState.hasBlockEntity() && !state.shouldChangedStateKeepBlockEntity(blockState)) { +- if (!this.level.isClientSide() && flag2) { - BlockEntity blockEntity = this.level.getBlockEntity(pos); - if (blockEntity != null) { - blockEntity.preRemoveSideEffects(pos, blockState); + // Leaves start - behaviour 1.21.1- + if (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.updater.oldBlockRemoveBehaviour) { + if (flag && blockState.hasBlockEntity()) { -+ if (!this.level.isClientSide && flag2) { ++ if (!this.level.isClientSide() && flag2) { + BlockEntity blockEntity = this.level.getBlockEntity(pos); + if (blockEntity != null) { + blockEntity.preRemoveSideEffects(pos, blockState); @@ -790,9 +790,13 @@ index 0e22116fefcbdbf2049b7ec285b35fd03c723dc5..45386818312fbd99bbcb72d14ad9e54c + this.removeBlockEntity(pos); + } -- if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) { +- if ((flag || block instanceof BaseRailBlock) +- && this.level instanceof ServerLevel serverLevel +- && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) { - blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1); -+ if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) { ++ if ((flag || block instanceof BaseRailBlock) ++ && this.level instanceof ServerLevel serverLevel ++ && ((flags & Block.UPDATE_NEIGHBORS) != 0 || flag1)) { + blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1); + } + } else { diff --git a/leaves-server/minecraft-patches/features/0103-Old-raid-behavior.patch b/leaves-server/minecraft-patches/features/0103-Old-raid-behavior.patch index 7eadfbcf..e7873358 100644 --- a/leaves-server/minecraft-patches/features/0103-Old-raid-behavior.patch +++ b/leaves-server/minecraft-patches/features/0103-Old-raid-behavior.patch @@ -21,10 +21,10 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..d7f443bcf91ac7817fe79881122960f4 if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) { serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier)); diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java -index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93835dfc06 100644 +index 5181a9334066a15e0d502d3522c23337e5eef2b5..36b4aeeb63319d28d637541c3b97a481a8673fd7 100644 --- a/net/minecraft/world/entity/raid/Raid.java +++ b/net/minecraft/world/entity/raid/Raid.java -@@ -256,7 +256,7 @@ public class Raid { +@@ -258,7 +258,7 @@ public class Raid { } public boolean absorbRaidOmen(ServerPlayer player) { @@ -33,7 +33,7 @@ index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93 if (effect == null) { return false; } else { -@@ -333,7 +333,13 @@ public class Raid { +@@ -335,7 +335,13 @@ public class Raid { } if (flag1) { @@ -48,7 +48,7 @@ index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93 } if (this.raidCooldownTicks == 300 || this.raidCooldownTicks % 20 == 0) { -@@ -368,7 +374,14 @@ public class Raid { +@@ -390,7 +396,14 @@ public class Raid { int i = 0; while (this.shouldSpawnGroup()) { @@ -64,7 +64,7 @@ index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93 if (blockPos != null) { this.started = true; this.spawnGroup(level, blockPos); -@@ -380,7 +393,7 @@ public class Raid { +@@ -402,7 +415,7 @@ public class Raid { i++; } @@ -73,7 +73,7 @@ index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93 org.bukkit.craftbukkit.event.CraftEventFactory.callRaidStopEvent(level, this, org.bukkit.event.raid.RaidStopEvent.Reason.UNSPAWNABLE); // CraftBukkit this.stop(); break; -@@ -667,7 +680,7 @@ public class Raid { +@@ -689,7 +702,7 @@ public class Raid { int i2 = this.center.getX() + Mth.floor(Mth.cos(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f); int i3 = this.center.getZ() + Mth.floor(Mth.sin(f2) * 32.0F * f) + level.random.nextInt(3) * Mth.floor(f); int height = level.getHeight(Heightmap.Types.WORLD_SURFACE, i2, i3); @@ -82,7 +82,7 @@ index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93 mutableBlockPos.set(i2, height, i3); if (!level.isVillage(mutableBlockPos) || i <= 7) { int i4 = 10; -@@ -686,6 +699,36 @@ public class Raid { +@@ -708,6 +721,36 @@ public class Raid { return null; } @@ -119,7 +119,7 @@ index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93 private boolean addWaveMob(ServerLevel level, int wave, Raider raider) { return this.addWaveMob(level, wave, raider, true); } -@@ -843,4 +886,43 @@ public class Raid { +@@ -865,4 +908,43 @@ public class Raid { this.spawnsPerWaveBeforeBonus = spawnsPerWaveBeforeBonus; } } @@ -164,7 +164,7 @@ index b3a29ce523fb5de71589c7c17598bba17622f988..8f90f3234c9b80b7a194d5dbffd8ea93 + // Leaves end - old FindSpawnPosition } diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java -index a495789b2d21fa9a24d5dca4ecfa196ddce49466..86e8ca07a1163094b14c55fe8913c7312eeff124 100644 +index 8d8315edfb69b062ed5e3d957f4043ec411dd5d7..1c668b9dd246d29c37fc0de9d27e320d6b899a3f 100644 --- a/net/minecraft/world/entity/raid/Raider.java +++ b/net/minecraft/world/entity/raid/Raider.java @@ -128,6 +128,43 @@ public abstract class Raider extends PatrollingMonster { @@ -210,4 +210,4 @@ index a495789b2d21fa9a24d5dca4ecfa196ddce49466..86e8ca07a1163094b14c55fe8913c731 + // Leaves end - Revert raid changes } - super.die(cause); + super.die(damageSource); diff --git a/leaves-server/minecraft-patches/features/0104-Allow-anvil-destroy-item-entities.patch b/leaves-server/minecraft-patches/features/0104-Allow-anvil-destroy-item-entities.patch index 3c825524..32c321f0 100644 --- a/leaves-server/minecraft-patches/features/0104-Allow-anvil-destroy-item-entities.patch +++ b/leaves-server/minecraft-patches/features/0104-Allow-anvil-destroy-item-entities.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow anvil destroy item entities diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java -index 0fd2c522a5fb038a8c002970af6feebd9dc9c436..2d0d6ad8c37c3187fbf35e5c7ff9a509da59c648 100644 +index 387f7a48499421858ea024bca01e372d3dbcdb57..9395301f25d2b525d1412b7b79b82fa06c2bebbb 100644 --- a/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -282,7 +282,7 @@ public class FallingBlockEntity extends Entity { +@@ -281,7 +281,7 @@ public class FallingBlockEntity extends Entity { if (ceil < 0) { return false; } else { diff --git a/leaves-server/minecraft-patches/features/0106-Fix-EntityPortalExitEvent-logic.patch b/leaves-server/minecraft-patches/features/0106-Fix-EntityPortalExitEvent-logic.patch index 8eb2157d..b1700fb8 100644 --- a/leaves-server/minecraft-patches/features/0106-Fix-EntityPortalExitEvent-logic.patch +++ b/leaves-server/minecraft-patches/features/0106-Fix-EntityPortalExitEvent-logic.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix EntityPortalExitEvent logic diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index e09eb2612eb3943c9d108885bf189b04e050f459..9309ef573407cbdf6bb1859021939798bbcf4669 100644 +index 8bd5f957d61c429cf75e5a14296f735c33149e39..7376b7f56009865ba2db24b68f008b077bcf34d3 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -3990,19 +3990,21 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4052,19 +4052,21 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name ); event.callEvent(); diff --git a/leaves-server/minecraft-patches/features/0107-Fix-CraftPortalEvent-logic.patch b/leaves-server/minecraft-patches/features/0107-Fix-CraftPortalEvent-logic.patch index 2bb5b241..e2397f16 100644 --- a/leaves-server/minecraft-patches/features/0107-Fix-CraftPortalEvent-logic.patch +++ b/leaves-server/minecraft-patches/features/0107-Fix-CraftPortalEvent-logic.patch @@ -5,18 +5,19 @@ Subject: [PATCH] Fix CraftPortalEvent logic diff --git a/net/minecraft/world/level/block/EndPortalBlock.java b/net/minecraft/world/level/block/EndPortalBlock.java -index f6c64277c3d6e16250e2bf963b6427404e27aa9b..2d908255439ea548aa7679219b5092334243a641 100644 +index fb51a78e16fd461d95f670eae43ef93c64b46843..dca30a02110181bf45306ca6b2f9508e20cd643f 100644 --- a/net/minecraft/world/level/block/EndPortalBlock.java +++ b/net/minecraft/world/level/block/EndPortalBlock.java -@@ -105,9 +105,9 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { +@@ -111,10 +111,10 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { } // CraftBukkit start - set.removeAll(Relative.ROTATION); // remove relative rotation flags to simplify event mutation + // set.removeAll(Relative.ROTATION); // remove relative rotation flags to simplify event mutation // Leaves - no - float absoluteYaw = flag ? f : entity.getYRot() + f; -- org.bukkit.craftbukkit.event.CraftPortalEvent event = entity.callPortalEvent(entity, org.bukkit.craftbukkit.util.CraftLocation.toBukkit(bottomCenter, level1.getWorld(), absoluteYaw, entity.getXRot()), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); -+ org.bukkit.craftbukkit.event.CraftPortalEvent event = entity.callPortalEvent(entity, org.bukkit.craftbukkit.util.CraftLocation.toBukkit(bottomCenter, level1.getWorld(), absoluteYaw, 0.0F), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); // Leaves - fix - if (event == null) { + float absoluteYaw = !flag ? f : entity.getYRot() + f; + float absolutePitch = entity.getXRot() + f1; +- org.bukkit.craftbukkit.event.PortalEventResult result = org.bukkit.craftbukkit.event.CraftEventFactory.handlePortalEvents(entity, org.bukkit.craftbukkit.util.CraftLocation.toBukkit(bottomCenter, level1, absoluteYaw, absolutePitch), org.bukkit.PortalType.ENDER, 0, 0); ++ org.bukkit.craftbukkit.event.PortalEventResult result = org.bukkit.craftbukkit.event.CraftEventFactory.handlePortalEvents(entity, org.bukkit.craftbukkit.util.CraftLocation.toBukkit(bottomCenter, level1.getWorld(), absoluteYaw, 0.0F), org.bukkit.PortalType.ENDER, 0, 0); + if (result == null) { return null; } diff --git a/leaves-server/minecraft-patches/features/0108-Xaero-Map-Protocol.patch b/leaves-server/minecraft-patches/features/0108-Xaero-Map-Protocol.patch index 49121adf..d9060e37 100644 --- a/leaves-server/minecraft-patches/features/0108-Xaero-Map-Protocol.patch +++ b/leaves-server/minecraft-patches/features/0108-Xaero-Map-Protocol.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Xaero Map Protocol diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index d4eb10d3734930a43b8270cdc7eb78bf40907c94..81a6b4d9c35056b3eda889800f61964ab522a8b9 100644 +index f376b03e267ae9c3acc9636b6ccee733497027d2..5661e05cc1ffbfc7015ca45cf0820e0ba616bcc6 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1318,6 +1318,7 @@ public abstract class PlayerList { - player.connection.send(new ClientboundInitializeBorderPacket(worldBorder)); - player.connection.send(new ClientboundSetTimePacket(level.getGameTime(), level.getDayTime(), level.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT))); - player.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle())); +@@ -1204,6 +1204,7 @@ public abstract class PlayerList { + player.connection.send(new ClientboundSetChunkCacheRadiusPacket(level.spigotConfig.viewDistance)); + player.connection.send(new ClientboundSetSimulationDistancePacket(level.spigotConfig.simulationDistance)); + // Paper end + org.leavesmc.leaves.protocol.XaeroMapProtocol.onSendWorldInfo(player); // Leaves - xaero map protocol if (level.isRaining()) { // CraftBukkit start - handle player weather diff --git a/leaves-server/minecraft-patches/features/0109-Skip-negligible-planar-movement-multiplication.patch b/leaves-server/minecraft-patches/features/0109-Skip-negligible-planar-movement-multiplication.patch index 536ea9d6..c52b3a59 100644 --- a/leaves-server/minecraft-patches/features/0109-Skip-negligible-planar-movement-multiplication.patch +++ b/leaves-server/minecraft-patches/features/0109-Skip-negligible-planar-movement-multiplication.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Skip negligible planar movement multiplication This patch is Powered by Gale(https://github.com/Dreeam-qwq/Gale) diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 9309ef573407cbdf6bb1859021939798bbcf4669..d7eea7b8b5836b4aba510cfbbdb3788cf21c2abc 100644 +index 7376b7f56009865ba2db24b68f008b077bcf34d3..0260ccee26a4dad7c7ea53504a45c645abe3c28f 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -1234,8 +1234,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1246,8 +1246,17 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name } } diff --git a/leaves-server/minecraft-patches/features/0111-Vanilla-player-display-name.patch b/leaves-server/minecraft-patches/features/0111-Vanilla-player-display-name.patch index deddd91f..f46bae44 100644 --- a/leaves-server/minecraft-patches/features/0111-Vanilla-player-display-name.patch +++ b/leaves-server/minecraft-patches/features/0111-Vanilla-player-display-name.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Vanilla player display name diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index e355939e153c05f9434482c4713743755b280d69..76af3083d6f4c308802be7b8625d905105c3355c 100644 +index 44b1d56fb3ce3827290ef4cf987aa2386d07eb9c..77f82c8bf2ffbe642f1149aa4a5269818964296a 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -476,7 +476,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -491,7 +491,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.object = null; // CraftBukkit start this.displayName = this.getScoreboardName(); @@ -18,7 +18,7 @@ index e355939e153c05f9434482c4713743755b280d69..76af3083d6f4c308802be7b8625d9051 this.maxHealthCache = this.getMaxHealth(); // CraftBukkit end diff --git a/net/minecraft/world/scores/Scoreboard.java b/net/minecraft/world/scores/Scoreboard.java -index 4275d048a8f5e98c7436f5bf2d55a9b68f7ba818..c68399f1ada71f6b301b41bdc83af024a9d2f1d3 100644 +index e25075f6436a8020bd1b0d9e53ed93d0eb914d6a..e20fe2d12b28e108763156781444a59a9dbdc25d 100644 --- a/net/minecraft/world/scores/Scoreboard.java +++ b/net/minecraft/world/scores/Scoreboard.java @@ -282,6 +282,16 @@ public class Scoreboard { @@ -40,11 +40,11 @@ index 4275d048a8f5e98c7436f5bf2d55a9b68f7ba818..c68399f1ada71f6b301b41bdc83af024 @@ -301,6 +311,14 @@ public class Scoreboard { } else { - this.teamsByPlayer.remove(username); - playerTeam.getPlayers().remove(username); + this.teamsByPlayer.remove(playerName); + team.getPlayers().remove(playerName); + // Leaves start - vanilla display name + if (org.leavesmc.leaves.LeavesConfig.fix.vanillaDisplayName) { -+ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(username); ++ net.minecraft.server.level.ServerPlayer player = net.minecraft.server.MinecraftServer.getServer().getPlayerList().getPlayerByName(playerName); + if (player != null) { + player.adventure$displayName = io.papermc.paper.adventure.PaperAdventure.asAdventure(player.getDisplayName()); + } diff --git a/leaves-server/minecraft-patches/features/0112-Fix-SculkCatalyst-exp-skip.patch b/leaves-server/minecraft-patches/features/0112-Fix-SculkCatalyst-exp-skip.patch index 4aa115b5..9ce866ea 100644 --- a/leaves-server/minecraft-patches/features/0112-Fix-SculkCatalyst-exp-skip.patch +++ b/leaves-server/minecraft-patches/features/0112-Fix-SculkCatalyst-exp-skip.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Fix SculkCatalyst exp skip diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 76af3083d6f4c308802be7b8625d905105c3355c..531b38be36cb2990cf5fbefbd58f917a0d84f0d3 100644 +index 77f82c8bf2ffbe642f1149aa4a5269818964296a..60a5bf1fa503dab25a7fef9d094fd6dc5a80fdca 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1107,7 +1107,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1214,7 +1214,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc } // SPIGOT-5478 must be called manually now -- if (event.shouldDropExperience()) this.dropExperience(this.level(), cause.getEntity()); // Paper - tie to event -+ if (shouldDropExperience(event.shouldDropExperience(), event.forceUseEventDropStatus())) this.dropExperience(this.level(), cause.getEntity()); // Paper - tie to event // Leaves - exp fix +- if (event.shouldDropExperience()) this.dropExperience(this.level(), damageSource.getEntity()); // Paper - tie to event ++ if (shouldDropExperience(event.shouldDropExperience(), event.forceUseEventDropStatus())) this.dropExperience(this.level(), damageSource.getEntity()); // Paper - tie to event // Leaves - exp fix // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. if (!event.getKeepInventory()) { // Paper start - PlayerDeathEvent#getItemsToKeep -@@ -1154,6 +1154,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1261,6 +1261,15 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.setClientLoaded(false); } @@ -30,14 +30,14 @@ index 76af3083d6f4c308802be7b8625d905105c3355c..531b38be36cb2990cf5fbefbd58f917a + } + // Leaves end - exp fix + - private void tellNeutralMobsThatIDied() { + protected void tellNeutralMobsThatIDied() { // Leaves private -> protected AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0); this.level() diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 59a352427b8d6445f3da3c6033bae4826277ed60..6b776ff621275e842c113000bd69528c96a598c3 100644 +index 0f2a3002ec01451e92b3e4869373a910be6ccab2..0610df1c343f1c5cf724a79fbc68ed1372de5da5 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -277,6 +277,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -279,6 +279,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin private Waypoint.Icon locatorBarIcon = new Waypoint.Icon(); // CraftBukkit start public int expToDrop; @@ -45,15 +45,15 @@ index 59a352427b8d6445f3da3c6033bae4826277ed60..6b776ff621275e842c113000bd69528c public List drops = new java.util.ArrayList<>(); // Paper - Restore vanilla drops behavior public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; public boolean collides = true; -@@ -1861,6 +1862,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin - entity.killedEntity((ServerLevel) this.level(), this); +@@ -1872,6 +1873,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin + entity.killedEntity((ServerLevel) this.level(), this, damageSource); } this.gameEvent(GameEvent.ENTITY_DIE); + if (!this.wasExperienceConsumed()) this.dropExperience((ServerLevel) this.level(), damageSource.getEntity()); // Leaves - exp fix } else { this.dead = false; this.setHealth((float) deathEvent.getReviveHealth()); -@@ -1934,7 +1936,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -1948,7 +1950,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.drops = new java.util.ArrayList<>(); // this.dropEquipment(level); // CraftBukkit - moved up // CraftBukkit end @@ -63,10 +63,10 @@ index 59a352427b8d6445f3da3c6033bae4826277ed60..6b776ff621275e842c113000bd69528c } diff --git a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -index 0a94670dc20bb9c521b0395633eb100393895f6a..a2f73e8210ac554a7529067bbe9f50267f2bf0e2 100644 +index ab7be4298be22af32c4726f178b93896b96f599d..7bce957dca7ef797100b685f0e5a25820be0f4b4 100644 --- a/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +++ b/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -@@ -96,8 +96,7 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi +@@ -97,8 +97,7 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi public boolean handleGameEvent(ServerLevel level, Holder gameEvent, GameEvent.Context context, Vec3 pos) { if (gameEvent.is(GameEvent.ENTITY_DIE) && context.sourceEntity() instanceof LivingEntity livingEntity) { if (!livingEntity.wasExperienceConsumed()) { diff --git a/leaves-server/minecraft-patches/features/0113-Vanilla-creative-pickup-behavior.patch b/leaves-server/minecraft-patches/features/0113-Vanilla-creative-pickup-behavior.patch index 60818f62..c27dbc37 100644 --- a/leaves-server/minecraft-patches/features/0113-Vanilla-creative-pickup-behavior.patch +++ b/leaves-server/minecraft-patches/features/0113-Vanilla-creative-pickup-behavior.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Vanilla creative pickup behavior diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java -index 71df58ae26325a2d28b6679733c474c0c59f7654..c73a1289a122dd0525e93fafb522d774566dceac 100644 +index b849b04f227b43d036f4f6b3ae7accfafc389d9f..c001055c89cfd3705ce0fcbafd7461cf401f35b5 100644 --- a/net/minecraft/world/entity/player/Inventory.java +++ b/net/minecraft/world/entity/player/Inventory.java -@@ -176,6 +176,13 @@ public class Inventory implements Container, Nameable { +@@ -177,6 +177,13 @@ public class Inventory implements Container, Nameable { // CraftBukkit start - Watch method above! :D public int canHold(ItemStack itemStack) { int remains = itemStack.getCount(); diff --git a/leaves-server/minecraft-patches/features/0114-Vanilla-portal-handle.patch b/leaves-server/minecraft-patches/features/0114-Vanilla-portal-handle.patch index 204710f8..e2ad09a2 100644 --- a/leaves-server/minecraft-patches/features/0114-Vanilla-portal-handle.patch +++ b/leaves-server/minecraft-patches/features/0114-Vanilla-portal-handle.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Vanilla portal handle diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index d7eea7b8b5836b4aba510cfbbdb3788cf21c2abc..c011fd65f5814c88cb3f6a4f62283efb9b6188ec 100644 +index 0260ccee26a4dad7c7ea53504a45c645abe3c28f..03972434172ff8615f0f5defa1076d348e0b6b19 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -836,6 +836,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -841,6 +841,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name // CraftBukkit start public void postTick() { @@ -16,7 +16,7 @@ index d7eea7b8b5836b4aba510cfbbdb3788cf21c2abc..c011fd65f5814c88cb3f6a4f62283efb // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities this.handlePortal(); -@@ -856,7 +857,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -861,7 +862,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name this.boardingCooldown--; } @@ -26,7 +26,7 @@ index d7eea7b8b5836b4aba510cfbbdb3788cf21c2abc..c011fd65f5814c88cb3f6a4f62283efb this.spawnSprintParticle(); } diff --git a/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/net/minecraft/world/entity/vehicle/AbstractMinecart.java -index 7e61d68b36ca2768f70dc1fc130a8d7b95347b6b..8e73204f6e7d159d66c3d90c7e2845bfde867e7a 100644 +index 3454506b2d7ada401600e2adccd462a15bd86723..c8b053b01b06af6033b9a74452946333dbeb77fa 100644 --- a/net/minecraft/world/entity/vehicle/AbstractMinecart.java +++ b/net/minecraft/world/entity/vehicle/AbstractMinecart.java @@ -293,7 +293,7 @@ public abstract class AbstractMinecart extends VehicleEntity { diff --git a/leaves-server/minecraft-patches/features/0115-Fix-chunk-reload-detector.patch b/leaves-server/minecraft-patches/features/0115-Fix-chunk-reload-detector.patch index ca114a73..9ae19a7d 100644 --- a/leaves-server/minecraft-patches/features/0115-Fix-chunk-reload-detector.patch +++ b/leaves-server/minecraft-patches/features/0115-Fix-chunk-reload-detector.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix chunk reload detector diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index f6b2d541fdfd11c6ff6033fbf4cd5153796634e3..5e06cc272b9617d780c507b5b819b380e7462eaf 100644 +index 1099280bd8e28c167702b74041928f260695ba7c..42c5e027ab04d03e761d956343bb41c3496da1ff 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java -@@ -390,7 +390,7 @@ public class ServerEntity { +@@ -371,7 +371,7 @@ public class ServerEntity { if (!list.isEmpty()) { consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list, true)); // Paper - data sanitization } diff --git a/leaves-server/minecraft-patches/features/0116-Do-not-reset-placed-block-on-exception.patch b/leaves-server/minecraft-patches/features/0116-Do-not-reset-placed-block-on-exception.patch index 11a77121..5115ecd7 100644 --- a/leaves-server/minecraft-patches/features/0116-Do-not-reset-placed-block-on-exception.patch +++ b/leaves-server/minecraft-patches/features/0116-Do-not-reset-placed-block-on-exception.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Do not reset placed block on exception diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index 593e65ef3a768d4039047e42e666c8382a5d38eb..cf143589407dc2146c9ce18f509077017fba0b48 100644 +index cf00493cbf131d0af2137a852c9ffba9dbeaddb3..13c357688f381e36ff4179a65a0654c73e1219b1 100644 --- a/net/minecraft/world/item/BlockItem.java +++ b/net/minecraft/world/item/BlockItem.java -@@ -92,20 +92,22 @@ public class BlockItem extends Item { +@@ -91,20 +91,22 @@ public class BlockItem extends Item { BlockState blockState = level.getBlockState(clickedPos); if (blockState.is(placementState.getBlock())) { blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState); diff --git a/leaves-server/minecraft-patches/features/0117-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch b/leaves-server/minecraft-patches/features/0117-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch index 9621ebab..c1a85d9c 100644 --- a/leaves-server/minecraft-patches/features/0117-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch +++ b/leaves-server/minecraft-patches/features/0117-Do-not-prevent-block-entity-and-entity-crash-at-Leve.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Do not prevent block entity and entity crash at LevelChunk diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index 45386818312fbd99bbcb72d14ad9e54cd864a2a8..b27cbb55fcb980679819a605112533f366abc97e 100644 +index 479723aaee1cf9ea6be8606a63f721236b3e2424..e6cc97e21e31faab0562e2a43766bd00f0451a19 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -952,12 +952,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -988,12 +988,14 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot profilerFiller.pop(); } catch (Throwable var5) { diff --git a/leaves-server/minecraft-patches/features/0119-Spawn-invulnerable-time.patch b/leaves-server/minecraft-patches/features/0119-Spawn-invulnerable-time.patch index beb87774..9a7f8f25 100644 --- a/leaves-server/minecraft-patches/features/0119-Spawn-invulnerable-time.patch +++ b/leaves-server/minecraft-patches/features/0119-Spawn-invulnerable-time.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Spawn invulnerable time diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 531b38be36cb2990cf5fbefbd58f917a0d84f0d3..3fc5a892555a737243fe887b5d5d6a54187d8218 100644 +index 60a5bf1fa503dab25a7fef9d094fd6dc5a80fdca..2d957b4bd98497100a9fc62fa4709b6898a6374f 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -232,6 +232,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -241,6 +241,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc private int lastSentFood = -99999999; private boolean lastFoodSaturationZero = true; public int lastSentExp = -99999999; @@ -16,7 +16,7 @@ index 531b38be36cb2990cf5fbefbd58f917a0d84f0d3..3fc5a892555a737243fe887b5d5d6a54 private ChatVisiblity chatVisibility = ChatVisiblity.FULL; public ParticleStatus particleStatus = ParticleStatus.ALL; private boolean canChatColor = true; -@@ -752,6 +753,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -730,6 +731,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.resetOperationCountPerTick(); // Leaves - player operation limiter this.gameMode.tick(); this.wardenSpawnTracker.tick(); @@ -24,7 +24,7 @@ index 531b38be36cb2990cf5fbefbd58f917a0d84f0d3..3fc5a892555a737243fe887b5d5d6a54 if (this.invulnerableTime > 0) { this.invulnerableTime--; } -@@ -1205,6 +1207,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1313,6 +1315,13 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc if (this.isInvulnerableTo(level, damageSource)) { return false; } else { diff --git a/leaves-server/minecraft-patches/features/0120-Old-zombie-reinforcement.patch b/leaves-server/minecraft-patches/features/0120-Old-zombie-reinforcement.patch index 636942dd..532cfed4 100644 --- a/leaves-server/minecraft-patches/features/0120-Old-zombie-reinforcement.patch +++ b/leaves-server/minecraft-patches/features/0120-Old-zombie-reinforcement.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Old zombie reinforcement diff --git a/net/minecraft/world/entity/monster/Zombie.java b/net/minecraft/world/entity/monster/Zombie.java -index a23607874a72723914cbfeea0ad1c51236c044d8..cb7b248276bfb6a9721e0bcc42ef00bf7029f263 100644 +index afe4a2304268224f6b0a1cc40a41f7b67f9d3275..1a5f3bdfcd6811bd26f75f43e325cc0bd3bbc814 100644 --- a/net/minecraft/world/entity/monster/Zombie.java +++ b/net/minecraft/world/entity/monster/Zombie.java @@ -341,7 +341,7 @@ public class Zombie extends Monster { diff --git a/leaves-server/minecraft-patches/features/0123-Fast-exp-orb-absorb.patch b/leaves-server/minecraft-patches/features/0123-Fast-exp-orb-absorb.patch index 630d6b37..d3a0e78f 100644 --- a/leaves-server/minecraft-patches/features/0123-Fast-exp-orb-absorb.patch +++ b/leaves-server/minecraft-patches/features/0123-Fast-exp-orb-absorb.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fast exp orb absorb diff --git a/net/minecraft/world/entity/ExperienceOrb.java b/net/minecraft/world/entity/ExperienceOrb.java -index 0aef8e15a75752e5c83af6245b1d8cdb53e7fc1b..f4f213cc1bf7f576a982faf0d8e85b02b36e7c56 100644 +index 8bd430c5c417c76db02cf1e2c0bc6f229ed150f1..80eab68a6b5a34c4dd37ff4d74b9b6133be090b9 100644 --- a/net/minecraft/world/entity/ExperienceOrb.java +++ b/net/minecraft/world/entity/ExperienceOrb.java @@ -358,6 +358,20 @@ public class ExperienceOrb extends Entity { @@ -13,12 +13,12 @@ index 0aef8e15a75752e5c83af6245b1d8cdb53e7fc1b..f4f213cc1bf7f576a982faf0d8e85b02 if (entity instanceof ServerPlayer serverPlayer) { if (entity.takeXpDelay == 0 && new com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent(serverPlayer.getBukkitEntity(), (org.bukkit.entity.ExperienceOrb) this.getBukkitEntity()).callEvent()) { // Paper - PlayerPickupExperienceEvent + if (org.leavesmc.leaves.LeavesConfig.modify.fastAbsorbPredicate.test(serverPlayer)) { -+ entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, 0, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entityhuman.takeXpDelay = 2; ++ entity.takeXpDelay = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerXpCooldownEvent(entity, 0, org.bukkit.event.player.PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); // CraftBukkit - entity.takeXpDelay = 2; + while (this.count > 0) { + entity.take(this, 1); + int i = this.repairPlayerItems(serverPlayer, this.getValue()); + if (i > 0) { -+ entity.giveExperiencePoints(org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerExpChangeEvent(entity, this, i).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object ++ entity.giveExperiencePoints(org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerExpChangeEvent(entity, this, 1).getAmount()); // CraftBukkit - this.value -> event.getAmount() // Paper - supply experience orb object + } + this.count--; + } diff --git a/leaves-server/minecraft-patches/features/0124-Vanilla-Fluid-Pushing.patch b/leaves-server/minecraft-patches/features/0124-Vanilla-Fluid-Pushing.patch index 2b46cac1..e2f45935 100644 --- a/leaves-server/minecraft-patches/features/0124-Vanilla-Fluid-Pushing.patch +++ b/leaves-server/minecraft-patches/features/0124-Vanilla-Fluid-Pushing.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Vanilla Fluid Pushing diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index c011fd65f5814c88cb3f6a4f62283efb9b6188ec..bea4089920191b5e3231e9792a078747923d0c14 100644 +index 03972434172ff8615f0f5defa1076d348e0b6b19..5c63b9603f7b6f6c4ceca0d836df4a4972568631 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -4735,8 +4735,82 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4770,8 +4770,82 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name return Mth.lerp(partialTick, this.yRotO, this.yRot); } diff --git a/leaves-server/minecraft-patches/features/0125-Configurable-item-damage-check.patch b/leaves-server/minecraft-patches/features/0125-Configurable-item-damage-check.patch index 589acc5f..2293b261 100644 --- a/leaves-server/minecraft-patches/features/0125-Configurable-item-damage-check.patch +++ b/leaves-server/minecraft-patches/features/0125-Configurable-item-damage-check.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable item damage check diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index 31b5dd406de54636fd0b86e031ce247abbcde063..e59b8d42d602bbdae1071f2a5be1180420c4efb7 100644 +index 13d5cb566f31ce0657b93c24c8e20a5ce3559fa4..fba077a5b6b9256dd117ae72c6aa0c63452a3eaa 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -597,11 +597,11 @@ public final class ItemStack implements DataComponentHolder { +@@ -598,11 +598,11 @@ public final class ItemStack implements DataComponentHolder { } public int getDamageValue() { diff --git a/leaves-server/minecraft-patches/features/0128-Old-wet-tnt-explode-behavior.patch b/leaves-server/minecraft-patches/features/0128-Old-wet-tnt-explode-behavior.patch index a2ace95b..199d90f3 100644 --- a/leaves-server/minecraft-patches/features/0128-Old-wet-tnt-explode-behavior.patch +++ b/leaves-server/minecraft-patches/features/0128-Old-wet-tnt-explode-behavior.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Old wet tnt explode behavior diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java -index 07e4025ca6c9c31905db2e6921138a0ded479dde..87635f6db2f1e77edc7ba6a26e9818d070a9faf7 100644 +index 1c521f9f32340cf75310686c90777e521ac3ae5c..8b0341c060d9f61698f32dd05c360c303a443c9b 100644 --- a/net/minecraft/world/level/ServerExplosion.java +++ b/net/minecraft/world/level/ServerExplosion.java -@@ -729,6 +729,7 @@ public class ServerExplosion implements Explosion { +@@ -719,6 +719,7 @@ public class ServerExplosion implements Explosion { public boolean shouldAffectBlocklikeEntities() { boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); boolean flag = this.source == null || this.source.getType() != EntityType.BREEZE_WIND_CHARGE && this.source.getType() != EntityType.WIND_CHARGE; diff --git a/leaves-server/minecraft-patches/features/0129-Old-projectile-explosion-behavior.patch b/leaves-server/minecraft-patches/features/0129-Old-projectile-explosion-behavior.patch index 37ed415b..6df3e5c0 100644 --- a/leaves-server/minecraft-patches/features/0129-Old-projectile-explosion-behavior.patch +++ b/leaves-server/minecraft-patches/features/0129-Old-projectile-explosion-behavior.patch @@ -5,15 +5,15 @@ Subject: [PATCH] Old projectile explosion behavior diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java -index 87635f6db2f1e77edc7ba6a26e9818d070a9faf7..b4a63faf11d4bf153d079aba5cfea7ed022891f7 100644 +index 8b0341c060d9f61698f32dd05c360c303a443c9b..7a3f9305abc7f094611c6d7ca36ca664bd483a73 100644 --- a/net/minecraft/world/level/ServerExplosion.java +++ b/net/minecraft/world/level/ServerExplosion.java -@@ -551,7 +551,7 @@ public class ServerExplosion implements Explosion { - // Paper end - knockback events - } - // CraftBukkit end -- entity.push(vec3); -+ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldProjectileExplosionBehavior) entity.setDeltaMovement(entity.getDeltaMovement().add(vec3)); else entity.push(vec3); // Leaves - old projectile explosion behavior - if (entity instanceof Player player && !player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying) && !level.paperConfig().environment.disableExplosionKnockback) { // Paper - Option to disable explosion knockback - this.hitPlayers.put(player, vec3); - } +@@ -538,7 +538,7 @@ public class ServerExplosion implements Explosion { + // Paper end - knockback events + } + // CraftBukkit end +- entity.push(vec32); ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldProjectileExplosionBehavior) entity.setDeltaMovement(entity.getDeltaMovement().add(vec32)); else entity.push(vec32); // Leaves - old projectile explosion behavior + if (entity.getType().is(EntityTypeTags.REDIRECTABLE_PROJECTILE) && entity instanceof Projectile projectile) { + projectile.setOwner(this.damageSource.getEntity()); + } else if (entity instanceof Player player && !player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying) && !level.paperConfig().environment.disableExplosionKnockback) { // Paper - Option to disable explosion knockback diff --git a/leaves-server/minecraft-patches/features/0130-Prevent-loss-of-item-drops-due-to-update-suppression.patch b/leaves-server/minecraft-patches/features/0130-Prevent-loss-of-item-drops-due-to-update-suppression.patch index bb8e2049..c31e811a 100644 --- a/leaves-server/minecraft-patches/features/0130-Prevent-loss-of-item-drops-due-to-update-suppression.patch +++ b/leaves-server/minecraft-patches/features/0130-Prevent-loss-of-item-drops-due-to-update-suppression.patch @@ -6,16 +6,20 @@ Subject: [PATCH] Prevent loss of item drops due to update suppression when diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java -index f258bc30014f94243ad832b33dcb6c9acd1f2f08..9a4eb1f8e01517707befa30b3ccacc7c84c0abe9 100644 +index fc205e54941d40a5583129b0c6540950f97a6b49..2b69ff82977f3592fb99ef494d090d77be34c186 100644 --- a/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -382,7 +382,18 @@ public class ServerPlayerGameMode { +@@ -402,11 +402,21 @@ public class ServerPlayerGameMode { this.level.captureDrops = new java.util.ArrayList<>(); // CraftBukkit end - BlockState blockState1 = org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update + BlockState blockState1 = org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update - boolean flag = this.level.removeBlock(pos, false); + // Leaves start - Prevent loss of item drops due to update suppression when breaking blocks + boolean flag; + if (SharedConstants.DEBUG_BLOCK_BREAK) { + LOGGER.info("server broke {} {} -> {}", pos, blockState1, this.level.getBlockState(pos)); + } +- + org.leavesmc.leaves.util.UpdateSuppressionException ex = null; + try { + flag = this.level.removeBlock(pos, false); @@ -29,7 +33,7 @@ index f258bc30014f94243ad832b33dcb6c9acd1f2f08..9a4eb1f8e01517707befa30b3ccacc7c if (flag) { block.destroy(this.level, pos, blockState1); } -@@ -410,6 +421,7 @@ public class ServerPlayerGameMode { +@@ -434,6 +444,7 @@ public class ServerPlayerGameMode { if (event.isDropItems()) { org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world } diff --git a/leaves-server/minecraft-patches/features/0131-Fix-block-place-desync-due-to-update-suppression.patch b/leaves-server/minecraft-patches/features/0131-Fix-block-place-desync-due-to-update-suppression.patch index 45b4ea3a..6f02159b 100644 --- a/leaves-server/minecraft-patches/features/0131-Fix-block-place-desync-due-to-update-suppression.patch +++ b/leaves-server/minecraft-patches/features/0131-Fix-block-place-desync-due-to-update-suppression.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix block place desync due to update suppression diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index e59b8d42d602bbdae1071f2a5be1180420c4efb7..a63330b232dc41f0a5bb36bb94dfb84f01504699 100644 +index fba077a5b6b9256dd117ae72c6aa0c63452a3eaa..33df00727e42ee0728dfb6a8c0816395fab5d4a9 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -389,8 +389,18 @@ public final class ItemStack implements DataComponentHolder { +@@ -390,8 +390,18 @@ public final class ItemStack implements DataComponentHolder { } } InteractionResult interactionResult; @@ -27,7 +27,7 @@ index e59b8d42d602bbdae1071f2a5be1180420c4efb7..a63330b232dc41f0a5bb36bb94dfb84f } finally { serverLevel.captureBlockStates = false; } -@@ -537,6 +547,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -538,6 +548,7 @@ public final class ItemStack implements DataComponentHolder { serverLevel.capturedBlockStates.clear(); // CraftBukkit end diff --git a/leaves-server/minecraft-patches/features/0132-TEMP-Merge-Paper-11831.patch b/leaves-server/minecraft-patches/features/0132-TEMP-Merge-Paper-11831.patch index 17cb482c..b4b9f239 100644 --- a/leaves-server/minecraft-patches/features/0132-TEMP-Merge-Paper-11831.patch +++ b/leaves-server/minecraft-patches/features/0132-TEMP-Merge-Paper-11831.patch @@ -32,26 +32,26 @@ index f6e18d62db18616a422ae74d6f329d1b3a96300b..eb34f3f9821f50f0a31fb22d9314c26b return targets.size(); diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index bea4089920191b5e3231e9792a078747923d0c14..3b9bd49fa39e3b44a7cbf51072e7cf09b186f254 100644 +index 5c63b9603f7b6f6c4ceca0d836df4a4972568631..01b4bcf6f975a9d7d083909f23c9bfb02fc074b2 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -2844,10 +2844,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2888,10 +2888,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name return null; } // CraftBukkit end - ItemEntity itemEntity = new ItemEntity(level, this.getX() + offset.x, this.getY() + offset.y, this.getZ() + offset.z, stack.copy()); // Paper - copy so we can destroy original - stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe - -- itemEntity.setDefaultPickUpDelay(); +- itemEntity.setDefaultPickUpDelay(); // Paper - diff on change (in dropConsumer) + ItemEntity itemEntity = new ItemEntity(level, this.getX() + offset.x, this.getY() + offset.y, this.getZ() + offset.z, stack.copy()); // Paper - copy - itemEntity.setDefaultPickUpDelay(); // Paper - diff on change (in dropConsumer) // Paper start - Call EntityDropItemEvent return this.spawnAtLocation(level, itemEntity); + } diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 6b776ff621275e842c113000bd69528c96a598c3..0d493c8343057898166f94a4006a374a214ae7b2 100644 +index 0610df1c343f1c5cf724a79fbc68ed1372de5da5..7a849ba0e22574f00f3580a432e2fe8343c883c6 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -3961,11 +3961,6 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3996,11 +3996,6 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin return null; } else { double d = this.getEyeY() - 0.3F; @@ -64,7 +64,7 @@ index 6b776ff621275e842c113000bd69528c96a598c3..0d493c8343057898166f94a4006a374a itemEntity.setPickUpDelay(40); if (includeThrower) { diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index c1ca84cf0dbb4fd091cfab517721c87e0f9074a0..403afadbd2280325f1289e302a1ff409f8f0941c 100644 +index 509d368f7fa9e6330da02615d7bf78debb932623..5ac49ee4743f7c4847e40dae6575f559df25abeb 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -652,7 +652,11 @@ public abstract class AbstractContainerMenu { diff --git a/leaves-server/minecraft-patches/features/0133-Old-ender-dragon-part-can-use-end-portal.patch b/leaves-server/minecraft-patches/features/0133-Old-ender-dragon-part-can-use-end-portal.patch index c03c8ddd..5913ae74 100644 --- a/leaves-server/minecraft-patches/features/0133-Old-ender-dragon-part-can-use-end-portal.patch +++ b/leaves-server/minecraft-patches/features/0133-Old-ender-dragon-part-can-use-end-portal.patch @@ -26,19 +26,19 @@ This patch is Powered by CrystalCarpetAddition(https://github.com/Crystal0404/Cr */ diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 3b9bd49fa39e3b44a7cbf51072e7cf09b186f254..6b56178967872923be58983ce8b14102ec0c3e14 100644 +index 01b4bcf6f975a9d7d083909f23c9bfb02fc074b2..4e0f223aaa3d719e6216ee8ab8415e32490a0da7 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -185,7 +185,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -186,7 +186,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name // Paper end - Share random for entities to make them more random public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason - private volatile @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity; // Paper - Folia schedulers - volatile + public volatile @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity; // Paper - Folia schedulers - volatile // Leaves - private -> public - public boolean collisionLoadChunks = false; // Paper public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() { -@@ -3958,7 +3958,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + if (this.bukkitEntity == null) { +@@ -4020,7 +4020,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name @Nullable public Entity teleport(TeleportTransition teleportTransition) { // Paper start - Fix item duplication and teleport issues @@ -47,16 +47,16 @@ index 3b9bd49fa39e3b44a7cbf51072e7cf09b186f254..6b56178967872923be58983ce8b14102 LOGGER.warn("Illegal Entity Teleport {} to {}:{}", this, teleportTransition.newLevel(), teleportTransition.position(), new Throwable()); return null; } -@@ -4074,7 +4074,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4136,7 +4136,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + // Paper end - Fix item duplication and teleport issues entityx.restoreFrom(this); this.removeAfterChangingDimensions(); - entityx.teleportSetPosition(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); -- if (this.inWorld) newLevel.addDuringTeleport(entityx); // CraftBukkit - Don't spawn the new entity if the current entity isn't spawned -+ if (this.inWorld || (org.leavesmc.leaves.LeavesConfig.modify.oldMC.enderDragonPartCanUseEndPortal && this instanceof net.minecraft.world.entity.boss.EnderDragonPart)) newLevel.addDuringTeleport(entityx); // CraftBukkit - Don't spawn the new entity if the current entity isn't spawned // Leaves - endDragonPartCanUseEndPortal +- entityx.teleportSetPosition(PositionMoveRotation.of(this), PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); ++ entityx.teleportSetPosition(PositionMoveRotation.of(teleportTransition), teleportTransition.relatives()); + if (this.inWorld) newLevel.addDuringTeleport(entityx); // CraftBukkit - Don't spawn the new entity if the current entity isn't spawned for (Entity entity2 : list) { - entity2.startRiding(entityx, true); -@@ -4209,6 +4209,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4254,6 +4254,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name } public boolean canTeleport(Level fromLevel, Level toLevel) { @@ -65,11 +65,11 @@ index 3b9bd49fa39e3b44a7cbf51072e7cf09b186f254..6b56178967872923be58983ce8b14102 if (!this.isAlive() || !this.valid) return false; // Paper - Fix item duplication and teleport issues if (fromLevel.dimension() == Level.END && toLevel.dimension() == Level.OVERWORLD) { diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java -index 3b73d52ea902bb1c8bd615c77444c57917f8b645..5cab5889446d7d48259300cec96da4a4811967e5 100644 +index 1cefdab82744600c6e5886646450d4c3fab03181..e783710f312b8c7b97dfd227866b71cee45c4d21 100644 --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -385,6 +385,16 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab - if (!this.level().isClientSide && this.tickCount % 5 == 0) { +@@ -395,6 +395,16 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab + if (!this.level().isClientSide() && this.tickCount % 5 == 0) { this.updateControlFlags(); } + // Leaves start - ender dragon part can use end portal diff --git a/leaves-server/minecraft-patches/features/0136-Lithium-Sleeping-Block-Entity.patch b/leaves-server/minecraft-patches/features/0136-Lithium-Sleeping-Block-Entity.patch index af3a70c2..c0a25fd0 100644 --- a/leaves-server/minecraft-patches/features/0136-Lithium-Sleeping-Block-Entity.patch +++ b/leaves-server/minecraft-patches/features/0136-Lithium-Sleeping-Block-Entity.patch @@ -17,11 +17,11 @@ As part of: Lithium (https://github.com/CaffeineMC/lithium) Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html) diff --git a/net/minecraft/core/NonNullList.java b/net/minecraft/core/NonNullList.java -index 7e31c5c8659d24948fd45a2d6ee7bdeca6027d27..387325b971b7cec6aeb677bf6c49b8bf21b3a344 100644 +index 40b4222ecc5a87e374e561513eb25cd1aa39e33d..e8b9542294f9b227c8817bddbb28a4d08d19e48c 100644 --- a/net/minecraft/core/NonNullList.java +++ b/net/minecraft/core/NonNullList.java -@@ -9,7 +9,7 @@ import javax.annotation.Nullable; - import org.apache.commons.lang3.Validate; +@@ -9,7 +9,7 @@ import javax.annotation.Nonnull; + import javax.annotation.Nullable; public class NonNullList extends AbstractList { - private final List list; @@ -30,7 +30,7 @@ index 7e31c5c8659d24948fd45a2d6ee7bdeca6027d27..387325b971b7cec6aeb677bf6c49b8bf private final E defaultValue; diff --git a/net/minecraft/core/component/PatchedDataComponentMap.java b/net/minecraft/core/component/PatchedDataComponentMap.java -index 3af6c1e2549ba3aeb60aa9d498a976be3680c0ee..1e7c7e242b5be6fdf52124864e1e284fd9542771 100644 +index 766b6080160d87742ef4d8caa73b3b8fa52d5589..10c811e960fe8e68908a7216c78ddd196a2c60e2 100644 --- a/net/minecraft/core/component/PatchedDataComponentMap.java +++ b/net/minecraft/core/component/PatchedDataComponentMap.java @@ -14,7 +14,7 @@ import java.util.Map.Entry; @@ -42,7 +42,7 @@ index 3af6c1e2549ba3aeb60aa9d498a976be3680c0ee..1e7c7e242b5be6fdf52124864e1e284f private final DataComponentMap prototype; private Reference2ObjectMap, Optional> patch; private boolean copyOnWrite; -@@ -135,6 +135,7 @@ public final class PatchedDataComponentMap implements DataComponentMap { +@@ -140,6 +140,7 @@ public final class PatchedDataComponentMap implements DataComponentMap { } private void ensureMapOwnership() { @@ -50,7 +50,7 @@ index 3af6c1e2549ba3aeb60aa9d498a976be3680c0ee..1e7c7e242b5be6fdf52124864e1e284f if (this.copyOnWrite) { this.patch = new Reference2ObjectArrayMap<>(this.patch); this.copyOnWrite = false; -@@ -238,4 +239,22 @@ public final class PatchedDataComponentMap implements DataComponentMap { +@@ -243,4 +244,22 @@ public final class PatchedDataComponentMap implements DataComponentMap { public String toString() { return "{" + this.stream().map(TypedDataComponent::toString).collect(Collectors.joining(", ")) + "}"; } @@ -74,7 +74,7 @@ index 3af6c1e2549ba3aeb60aa9d498a976be3680c0ee..1e7c7e242b5be6fdf52124864e1e284f + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/server/commands/data/EntityDataAccessor.java b/net/minecraft/server/commands/data/EntityDataAccessor.java -index 3092454bf7071deca75fecfc203072593fe5c7e7..c20e12726a020429f36b9fbe0d6da2afccb220a2 100644 +index 2b8d394dc30d459127289a1afeee0780003f4c79..6b7a9a05cebdf53ab7eb4d389c48090c6c2a2983 100644 --- a/net/minecraft/server/commands/data/EntityDataAccessor.java +++ b/net/minecraft/server/commands/data/EntityDataAccessor.java @@ -55,6 +55,7 @@ public class EntityDataAccessor implements DataAccessor { @@ -86,10 +86,10 @@ index 3092454bf7071deca75fecfc203072593fe5c7e7..c20e12726a020429f36b9fbe0d6da2af } } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index dcb1f6975b1cb18f38e0cf8a43d551f07836b12f..69dffeecbf0faa789bde3a93a44ff5e75db6f6b2 100644 +index dbebfec31e8bd9b9ea6bbf486875396fdcba93b6..fa5d582843387e3846b70c01ac85c71e9031f2f1 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -2404,6 +2404,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe +@@ -2472,6 +2472,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe for (TickingBlockEntity tickingBlockEntity : this.blockEntityTickers) { BlockPos pos = tickingBlockEntity.getPos(); @@ -98,10 +98,10 @@ index dcb1f6975b1cb18f38e0cf8a43d551f07836b12f..69dffeecbf0faa789bde3a93a44ff5e7 } } diff --git a/net/minecraft/world/Container.java b/net/minecraft/world/Container.java -index 86cac164a2bf0e76528396e6aabbfd64cfc29559..da99b4bc7fe8460945070915073be141f9bd6778 100644 +index 5493576c54e87823f68bbf8a18441b373aae0461..10d786ef9f29f1af1cb5088f5e054f19b97cdc13 100644 --- a/net/minecraft/world/Container.java +++ b/net/minecraft/world/Container.java -@@ -11,7 +11,7 @@ import net.minecraft.world.item.ItemStack; +@@ -13,7 +13,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -111,10 +111,10 @@ index 86cac164a2bf0e76528396e6aabbfd64cfc29559..da99b4bc7fe8460945070915073be141 int getContainerSize(); diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index b1b0e2b4deb5830660961cfff4669c4fd7037663..4748bd188f8860ed2a8b2e6123e020c1da17af5f 100644 +index 4e0f223aaa3d719e6216ee8ab8415e32490a0da7..d9fe2e6d424231c7acd15cd5bb6a05afa2e263c6 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -309,7 +309,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -310,7 +310,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name private static final EntityDataAccessor DATA_NO_GRAVITY = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.BOOLEAN); protected static final EntityDataAccessor DATA_POSE = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.POSE); public static final EntityDataAccessor DATA_TICKS_FROZEN = SynchedEntityData.defineId(Entity.class, EntityDataSerializers.INT); @@ -123,7 +123,7 @@ index b1b0e2b4deb5830660961cfff4669c4fd7037663..4748bd188f8860ed2a8b2e6123e020c1 private final VecDeltaCodec packetPositionCodec = new VecDeltaCodec(); public boolean hasImpulse; @Nullable -@@ -5150,6 +5150,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5176,6 +5176,19 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name this.setBoundingBox(this.makeBoundingBox()); } // Paper end - Block invalid positions and bounding box @@ -144,7 +144,7 @@ index b1b0e2b4deb5830660961cfff4669c4fd7037663..4748bd188f8860ed2a8b2e6123e020c1 public void checkDespawn() { diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java -index fc8d3e56771998a04d5e0b35ad7638a44def8c77..9b0625e2ee59659a68749bce5ac44bba8c038b0b 100644 +index ca0905258d6308a71a0cda552feef6ee6f082a4b..dadd06970b02a3cd220c6db2ccc2ffd066168530 100644 --- a/net/minecraft/world/entity/item/ItemEntity.java +++ b/net/minecraft/world/entity/item/ItemEntity.java @@ -34,8 +34,12 @@ import net.minecraft.world.level.portal.TeleportTransition; @@ -161,7 +161,7 @@ index fc8d3e56771998a04d5e0b35ad7638a44def8c77..9b0625e2ee59659a68749bce5ac44bba private static final EntityDataAccessor DATA_ITEM = SynchedEntityData.defineId(ItemEntity.class, EntityDataSerializers.ITEM_STACK); private static final float FLOAT_HEIGHT = 0.1F; public static final float EYE_HEIGHT = 0.2125F; -@@ -535,6 +539,25 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -526,6 +530,25 @@ public class ItemEntity extends Entity implements TraceableEntity { } public void setItem(ItemStack stack) { @@ -187,7 +187,7 @@ index fc8d3e56771998a04d5e0b35ad7638a44def8c77..9b0625e2ee59659a68749bce5ac44bba this.getEntityData().set(DATA_ITEM, stack); this.despawnRate = this.level().paperConfig().entities.spawning.altItemDespawnRate.enabled ? this.level().paperConfig().entities.spawning.altItemDespawnRate.items.getOrDefault(stack.getItem(), this.level().spigotConfig.itemDespawnRate) : this.level().spigotConfig.itemDespawnRate; // Paper - Alternative item-despawn-rate } -@@ -614,4 +637,76 @@ public class ItemEntity extends Entity implements TraceableEntity { +@@ -601,4 +624,76 @@ public class ItemEntity extends Entity implements TraceableEntity { public SlotAccess getSlot(int slot) { return slot == 0 ? SlotAccess.of(this::getItem, this::setItem) : super.getSlot(slot); } @@ -265,7 +265,7 @@ index fc8d3e56771998a04d5e0b35ad7638a44def8c77..9b0625e2ee59659a68749bce5ac44bba + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java -index 7781ca07a0c8fe1140f341b695e66de95802ee2e..f190e8f244d011bdb7f04ccf0f0a35cb9d2c684a 100644 +index 8fdde0cc090c80b65b4c0d679bf4b412b6b761ee..92aa3950ec751378c5e2b17dc109bbf79df758b3 100644 --- a/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +++ b/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java @@ -21,7 +21,7 @@ import net.minecraft.world.level.storage.ValueOutput; @@ -294,7 +294,7 @@ index 7781ca07a0c8fe1140f341b695e66de95802ee2e..f190e8f244d011bdb7f04ccf0f0a35cb + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java -index 403afadbd2280325f1289e302a1ff409f8f0941c..029b8fcc951875c7bc845c507e4f7a91cebc1156 100644 +index 5ac49ee4743f7c4847e40dae6575f559df25abeb..80c3e83882fd43926b5d964a3b44320f19a910de 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -935,6 +935,7 @@ public abstract class AbstractContainerMenu { @@ -306,10 +306,10 @@ index 403afadbd2280325f1289e302a1ff409f8f0941c..029b8fcc951875c7bc845c507e4f7a91 ItemStack item = container.getItem(i); if (!item.isEmpty()) { diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java -index a63330b232dc41f0a5bb36bb94dfb84f01504699..7fbce8302739ab016f1b64f8227c6d7286b85850 100644 +index b60e6e198e50e5d3794bb27a32023f9952121e86..024785b39c60776ce73e14bb9cd12cd4de013d27 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java -@@ -93,8 +93,12 @@ import net.minecraft.world.level.block.state.pattern.BlockInWorld; +@@ -95,8 +95,12 @@ import net.minecraft.world.level.block.state.pattern.BlockInWorld; import org.apache.commons.lang3.function.TriConsumer; import org.apache.commons.lang3.mutable.MutableBoolean; import org.slf4j.Logger; @@ -323,7 +323,7 @@ index a63330b232dc41f0a5bb36bb94dfb84f01504699..7fbce8302739ab016f1b64f8227c6d72 private static final List OP_NBT_WARNING = List.of( Component.translatable("item.op_warning.line1").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), Component.translatable("item.op_warning.line2").withStyle(ChatFormatting.RED), -@@ -978,6 +982,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -979,6 +983,7 @@ public final class ItemStack implements DataComponentHolder { @Nullable public T set(DataComponentType component, @Nullable T value) { @@ -331,7 +331,7 @@ index a63330b232dc41f0a5bb36bb94dfb84f01504699..7fbce8302739ab016f1b64f8227c6d72 return this.components.set(component, value); } -@@ -1322,6 +1327,23 @@ public final class ItemStack implements DataComponentHolder { +@@ -1326,6 +1331,23 @@ public final class ItemStack implements DataComponentHolder { } public void setCount(int count) { @@ -355,7 +355,7 @@ index a63330b232dc41f0a5bb36bb94dfb84f01504699..7fbce8302739ab016f1b64f8227c6d72 this.count = count; } -@@ -1377,4 +1399,90 @@ public final class ItemStack implements DataComponentHolder { +@@ -1381,4 +1403,90 @@ public final class ItemStack implements DataComponentHolder { public boolean canDestroyBlock(BlockState state, Level level, BlockPos pos, Player player) { return this.getItem().canDestroyBlock(this, state, level, pos, player); } @@ -447,18 +447,18 @@ index a63330b232dc41f0a5bb36bb94dfb84f01504699..7fbce8302739ab016f1b64f8227c6d72 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index f31a48530e965f01507c335f50d898ed72767e3c..e5b12f0be3c21b14b1fd8a33b20a9292e3b7b8df 100644 +index 07ab2907bb9e4de5810889bec6d2b08f9abfec0c..a8d8dce19cf780ecb8dd1025a36c642d50ee5f06 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java -@@ -1224,6 +1224,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -1178,6 +1178,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl int i = flags & -34; // Leaves start - no block update - if (org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + if (org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate()) { + if (org.leavesmc.leaves.LeavesConfig.performance.sleepingBlockEntity) org.leavesmc.leaves.lithium.common.hopper.HopperHelper.updateHopperOnUpdateSuppression(this, pos, flags, chunkAt, oldState != currentState); // Leaves - Lithium Sleeping Block Entity this.updatePOIOnBlockStateChange(pos, blockState, blockState1); return; } -@@ -1487,7 +1488,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -1439,7 +1440,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // Spigot end if (tickingBlockEntity.isRemoved()) { toRemove.add(tickingBlockEntity); // Paper - Fix MC-117075; use removeAll @@ -467,7 +467,7 @@ index f31a48530e965f01507c335f50d898ed72767e3c..e5b12f0be3c21b14b1fd8a33b20a9292 tickingBlockEntity.tick(); // Paper start - rewrite chunk system if ((++tickedEntities & 7) == 0) { -@@ -2149,4 +2150,25 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl +@@ -2138,4 +2139,25 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl return this.id; } } @@ -494,7 +494,7 @@ index f31a48530e965f01507c335f50d898ed72767e3c..e5b12f0be3c21b14b1fd8a33b20a9292 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/ComposterBlock.java b/net/minecraft/world/level/block/ComposterBlock.java -index a647d76d365a60b95a3eb7927ac426bf70d417f3..c84c8e7080cd71d19fab3dbc34ae3e83cd1fc132 100644 +index 0707e08970a325f6a21f3fc2f48c0b7bfbcbcd45..e3d3875c9befe09587ce4318fbdf642bb3c8ae58 100644 --- a/net/minecraft/world/level/block/ComposterBlock.java +++ b/net/minecraft/world/level/block/ComposterBlock.java @@ -411,7 +411,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { @@ -518,7 +518,7 @@ index a647d76d365a60b95a3eb7927ac426bf70d417f3..c84c8e7080cd71d19fab3dbc34ae3e83 @@ -479,12 +479,13 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder { } // Paper end - Add CompostItemEvent and EntityCompostItemEvent - this.level.levelEvent(1500, this.pos, blockState != this.state ? 1 : 0); + this.level.levelEvent(LevelEvent.COMPOSTER_FILL, this.pos, blockState != this.state ? 1 : 0); + if (org.leavesmc.leaves.LeavesConfig.performance.sleepingBlockEntity) this.changed = false; // Leaves - Lithium Sleeping Block Entity this.removeItemNoUpdate(0); } @@ -531,19 +531,19 @@ index a647d76d365a60b95a3eb7927ac426bf70d417f3..c84c8e7080cd71d19fab3dbc34ae3e83 private final LevelAccessor level; private final BlockPos pos; diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java -index 94d35e4812705771756a0ee1a9b0255be75e3770..f2e19b6e89195fa99a2eca7f1c647e94b5594689 100644 +index b975297c0475049935c38554a8c736abbf9882de..0457761189ffd179c6cc1b7f9ffb4e67d9e5790a 100644 --- a/net/minecraft/world/level/block/DiodeBlock.java +++ b/net/minecraft/world/level/block/DiodeBlock.java @@ -173,6 +173,7 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock { @Override - protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { this.updateNeighborsInFront(level, pos, state); + if (org.leavesmc.leaves.LeavesConfig.performance.sleepingBlockEntity && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity } // Leaves start - behaviour 1.21.1- diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java -index d3535a9dc462d92a306aea981d7799d8d975f59d..47377bc98eb183c2761c710575a7d811261f02e0 100644 +index 32b2f73d371b4dd53cdadfc94ff5e4d7bdaf7e37..870df1a752e676fc8a6879250393c388496b1597 100644 --- a/net/minecraft/world/level/block/HopperBlock.java +++ b/net/minecraft/world/level/block/HopperBlock.java @@ -38,7 +38,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; @@ -556,7 +556,7 @@ index d3535a9dc462d92a306aea981d7799d8d975f59d..47377bc98eb183c2761c710575a7d811 public static final EnumProperty FACING = BlockStateProperties.FACING_HOPPER; public static final BooleanProperty ENABLED = BlockStateProperties.ENABLED; @@ -101,6 +101,17 @@ public class HopperBlock extends BaseEntityBlock { - protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) { + protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { if (!oldState.is(state.getBlock())) { this.checkPoweredState(level, pos, state); + // Leaves start - Lithium Sleeping Block Entity @@ -608,10 +608,10 @@ index d3535a9dc462d92a306aea981d7799d8d975f59d..47377bc98eb183c2761c710575a7d811 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -index 646d4c26870bb03f6d397b5e03ad97923d0928b2..77cfc97b3c8926b8126076f41c801c418f3b93fd 100644 +index 005fd35dcae20d404922ef797cf22ef69ecd6c3a..7f2b702ec1dfc900e87a8871944e7b7ad2896b5e 100644 --- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java +++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java -@@ -39,7 +39,7 @@ import net.minecraft.world.level.storage.ValueInput; +@@ -40,7 +40,7 @@ import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.phys.Vec3; @@ -620,7 +620,7 @@ index 646d4c26870bb03f6d397b5e03ad97923d0928b2..77cfc97b3c8926b8126076f41c801c41 protected static final int SLOT_INPUT = 0; protected static final int SLOT_FUEL = 1; protected static final int SLOT_RESULT = 2; -@@ -164,6 +164,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -165,6 +165,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit this.recipesUsed.clear(); this.recipesUsed.putAll(input.read("RecipesUsed", RECIPES_USED_CODEC).orElse(Map.of())); this.cookSpeedMultiplier = input.getDoubleOr("Paper.CookSpeedMultiplier", 1); // Paper - cook speed multiplier API @@ -628,7 +628,7 @@ index 646d4c26870bb03f6d397b5e03ad97923d0928b2..77cfc97b3c8926b8126076f41c801c41 } @Override -@@ -269,6 +270,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -270,6 +271,7 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit if (flag) { setChanged(level, pos, state); } @@ -636,7 +636,7 @@ index 646d4c26870bb03f6d397b5e03ad97923d0928b2..77cfc97b3c8926b8126076f41c801c41 } private static boolean canBurn( -@@ -541,4 +543,53 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit +@@ -542,4 +544,53 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit this.getRecipesToAwardAndPopExperience(serverLevel, Vec3.atCenterOf(pos)); } } @@ -674,7 +674,7 @@ index 646d4c26870bb03f6d397b5e03ad97923d0928b2..77cfc97b3c8926b8126076f41c801c41 + + @Override + public void lithium$handleSetChanged() { -+ if (this.isSleeping() && this.level != null && !this.level.isClientSide) { ++ if (this.isSleeping() && this.level != null && !this.level.isClientSide()) { + this.wakeUpNow(); + } + } @@ -691,10 +691,10 @@ index 646d4c26870bb03f6d397b5e03ad97923d0928b2..77cfc97b3c8926b8126076f41c801c41 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -index f0ba09c0edc598dfc4e501ba69016e8a2f8d3a7c..2bb30d6c5ca56b47d685e1e095dbeb046720cd04 100644 +index 6741fe3abc4396236dc0ca31074e36d66e42c39a..780474a3f7b7128ca571356e26d0ae32b848d7b0 100644 --- a/net/minecraft/world/level/block/entity/BarrelBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BarrelBlockEntity.java -@@ -20,7 +20,7 @@ import net.minecraft.world.level.block.state.BlockState; +@@ -23,7 +23,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; @@ -703,7 +703,7 @@ index f0ba09c0edc598dfc4e501ba69016e8a2f8d3a7c..2bb30d6c5ca56b47d685e1e095dbeb04 // CraftBukkit start - add fields and methods public java.util.List transaction = new java.util.ArrayList<>(); private int maxStack = MAX_STACK; -@@ -119,6 +119,7 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -122,6 +122,7 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { @Override protected void setItems(NonNullList items) { this.items = items; @@ -711,7 +711,7 @@ index f0ba09c0edc598dfc4e501ba69016e8a2f8d3a7c..2bb30d6c5ca56b47d685e1e095dbeb04 } // Leaves start - pca -@@ -172,4 +173,18 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { +@@ -181,4 +182,18 @@ public class BarrelBlockEntity extends RandomizableContainerBlockEntity { double d2 = this.worldPosition.getZ() + 0.5 + unitVec3i.getZ() / 2.0; this.level.playSound(null, d, d1, d2, sound, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F); } @@ -731,7 +731,7 @@ index f0ba09c0edc598dfc4e501ba69016e8a2f8d3a7c..2bb30d6c5ca56b47d685e1e095dbeb04 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index 561acadcf81dc219d88e8ec8bdbd4f5f8fcbadc3..bfa6b473d44a5494fcbcc03a690db6292ee67320 100644 +index 1e6819928ffab524197003bd9469adb3976dce3a..cb9b653af455847312e4298b1acd2c7952f9c407 100644 --- a/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java @@ -23,8 +23,17 @@ import net.minecraft.world.item.component.ItemContainerContents; @@ -761,7 +761,7 @@ index 561acadcf81dc219d88e8ec8bdbd4f5f8fcbadc3..bfa6b473d44a5494fcbcc03a690db629 } @Override -@@ -206,4 +216,97 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co +@@ -210,4 +220,97 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co return org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.worldPosition, this.level); } // CraftBukkit end @@ -860,15 +860,15 @@ index 561acadcf81dc219d88e8ec8bdbd4f5f8fcbadc3..bfa6b473d44a5494fcbcc03a690db629 + } } diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java -index 5986825d6a381eeb445dd424dd127864aa703163..99c394aa6c7dce90d4fb4687772b1117e8e4d7a6 100644 +index bd038bdaa00fb1e09b098b4d2809d17e2382288b..fb53735c637bee86237d6a411d14569d48a0c915 100644 --- a/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -33,8 +33,16 @@ import net.minecraft.world.level.storage.TagValueOutput; +@@ -35,8 +35,16 @@ import net.minecraft.world.level.storage.TagValueOutput; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import org.slf4j.Logger; - --public abstract class BlockEntity { +-public abstract class BlockEntity implements DebugValueSource { +// Leaves start - Lithium Sleeping Block Entity +import net.minecraft.core.Direction; +import org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracker; @@ -878,11 +878,11 @@ index 5986825d6a381eeb445dd424dd127864aa703163..99c394aa6c7dce90d4fb4687772b1117 +import org.leavesmc.leaves.lithium.common.block.entity.SetChangedHandlingBlockEntity; +// Leaves end - Lithium Sleeping Block Entity + -+public abstract class BlockEntity implements ComparatorTracker, SetBlockStateHandlingBlockEntity, SetChangedHandlingBlockEntity { // Leaves - Lithium Sleeping Block Entity ++public abstract class BlockEntity implements DebugValueSource, ComparatorTracker, SetBlockStateHandlingBlockEntity, SetChangedHandlingBlockEntity { // Leaves - Lithium Sleeping Block Entity static boolean ignoreBlockEntityUpdates; // Paper - Perf: Optimize Hoppers // CraftBukkit start - data containers private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry(); -@@ -56,6 +64,7 @@ public abstract class BlockEntity { +@@ -58,6 +66,7 @@ public abstract class BlockEntity implements DebugValueSource { this.validateBlockState(blockState); this.blockState = blockState; this.persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init @@ -890,7 +890,7 @@ index 5986825d6a381eeb445dd424dd127864aa703163..99c394aa6c7dce90d4fb4687772b1117 } private void validateBlockState(BlockState state) { -@@ -230,6 +239,7 @@ public abstract class BlockEntity { +@@ -232,6 +241,7 @@ public abstract class BlockEntity implements DebugValueSource { if (this.level != null) { if (ignoreBlockEntityUpdates) return; // Paper - Perf: Optimize Hoppers setChanged(this.level, this.worldPosition, this.blockState); @@ -898,7 +898,7 @@ index 5986825d6a381eeb445dd424dd127864aa703163..99c394aa6c7dce90d4fb4687772b1117 } } -@@ -262,7 +272,9 @@ public abstract class BlockEntity { +@@ -264,7 +274,9 @@ public abstract class BlockEntity implements DebugValueSource { } public void setRemoved() { @@ -908,7 +908,7 @@ index 5986825d6a381eeb445dd424dd127864aa703163..99c394aa6c7dce90d4fb4687772b1117 } public void clearRemoved() { -@@ -302,6 +314,7 @@ public abstract class BlockEntity { +@@ -304,6 +316,7 @@ public abstract class BlockEntity implements DebugValueSource { public void setBlockState(BlockState blockState) { this.validateBlockState(blockState); this.blockState = blockState; @@ -916,7 +916,7 @@ index 5986825d6a381eeb445dd424dd127864aa703163..99c394aa6c7dce90d4fb4687772b1117 } protected void applyImplicitComponents(DataComponentGetter componentGetter) { -@@ -402,4 +415,32 @@ public abstract class BlockEntity { +@@ -408,4 +421,32 @@ public abstract class BlockEntity implements DebugValueSource { return this.blockEntity.getNameForReporting() + "@" + this.blockEntity.getBlockPos(); } } @@ -950,10 +950,10 @@ index 5986825d6a381eeb445dd424dd127864aa703163..99c394aa6c7dce90d4fb4687772b1117 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java -index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9e693b1c5 100644 +index a4d3d5b6830d156c76e381c5437867c0ed104016..db6a4c2ca481796cfde8e5e5a6e38217a37a027c 100644 --- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java -@@ -24,7 +24,7 @@ import net.minecraft.world.level.block.state.BlockState; +@@ -26,7 +26,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; @@ -962,7 +962,7 @@ index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9 private static final int INGREDIENT_SLOT = 3; private static final int FUEL_SLOT = 4; private static final int[] SLOTS_FOR_UP = new int[]{3}; -@@ -135,6 +135,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -138,6 +138,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements } public static void serverTick(Level level, BlockPos pos, BlockState state, BrewingStandBlockEntity blockEntity) { @@ -970,7 +970,7 @@ index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9 ItemStack itemStack = blockEntity.items.get(4); if (blockEntity.fuel <= 0 && itemStack.is(ItemTags.BREWING_FUEL)) { // CraftBukkit start -@@ -152,6 +153,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -155,6 +156,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements itemStack.shrink(1); } // CraftBukkit end @@ -978,7 +978,7 @@ index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9 setChanged(level, pos, state); } -@@ -166,7 +168,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -169,7 +171,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements } else if (!isBrewable || !itemStack1.is(blockEntity.ingredient)) { blockEntity.brewTime = 0; } @@ -987,7 +987,7 @@ index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9 setChanged(level, pos, state); } else if (isBrewable && blockEntity.fuel > 0) { blockEntity.fuel--; -@@ -179,6 +181,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -182,6 +184,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements blockEntity.brewTime = event.getBrewingTime(); // 400 -> event.getTotalBrewTime() // Paper - use brewing time from event // CraftBukkit end blockEntity.ingredient = itemStack1.getItem(); @@ -995,7 +995,7 @@ index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9 setChanged(level, pos, state); } -@@ -285,6 +288,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -288,6 +291,7 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements } this.fuel = input.getByteOr("Fuel", (byte)0); @@ -1003,7 +1003,7 @@ index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9 } @Override -@@ -341,4 +345,52 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements +@@ -344,4 +348,52 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements } } // Leaves end - pca @@ -1057,10 +1057,10 @@ index 7eac2188a38fff2ecfa4082b5d023b111cf7d8f6..0a6d8b7cec4916496f76f0ef101263d9 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -index fb7932e17d7d00ee3050e71c88510fa23befb1bb..6e3cfa4bb776299be4faf48fe165f5120cae2dc5 100644 +index 78c4d1fc052d72f8599c82291d2233ec2e552137..a961ec0cfa334d924cf6016e729256987309d64c 100644 --- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java +++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java -@@ -38,7 +38,7 @@ import net.minecraft.world.level.storage.ValueInput; +@@ -39,7 +39,7 @@ import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import org.slf4j.Logger; @@ -1069,7 +1069,7 @@ index fb7932e17d7d00ee3050e71c88510fa23befb1bb..6e3cfa4bb776299be4faf48fe165f512 private static final Logger LOGGER = LogUtils.getLogger(); private static final int BURN_COOL_SPEED = 2; private static final int NUM_SLOTS = 4; -@@ -112,7 +112,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { +@@ -113,7 +113,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { if (flag) { setChanged(level, pos, state); @@ -1078,7 +1078,7 @@ index fb7932e17d7d00ee3050e71c88510fa23befb1bb..6e3cfa4bb776299be4faf48fe165f512 } public static void cooldownTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity) { -@@ -127,7 +127,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { +@@ -128,7 +128,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { if (flag) { setChanged(level, pos, state); @@ -1087,7 +1087,7 @@ index fb7932e17d7d00ee3050e71c88510fa23befb1bb..6e3cfa4bb776299be4faf48fe165f512 } public static void particleTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity) { -@@ -183,6 +183,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { +@@ -184,6 +184,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { System.arraycopy(cookingState, 0, this.stopCooking, 0, Math.min(this.stopCooking.length, bytes.capacity())); }); // Paper end - Add more Campfire API @@ -1095,7 +1095,7 @@ index fb7932e17d7d00ee3050e71c88510fa23befb1bb..6e3cfa4bb776299be4faf48fe165f512 } @Override -@@ -237,6 +238,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { +@@ -238,6 +239,7 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { this.cookingTime[i] = event.getTotalCookTime(); // i -> event.getTotalCookTime() // CraftBukkit end this.cookingProgress[i] = 0; @@ -1103,7 +1103,7 @@ index fb7932e17d7d00ee3050e71c88510fa23befb1bb..6e3cfa4bb776299be4faf48fe165f512 this.items.set(i, stack.consumeAndReturn(1, entity)); level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState())); this.markUpdated(); -@@ -280,4 +282,30 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { +@@ -281,4 +283,30 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable { public void removeComponentsFromTag(ValueOutput output) { output.discard("Items"); } @@ -1135,19 +1135,19 @@ index fb7932e17d7d00ee3050e71c88510fa23befb1bb..6e3cfa4bb776299be4faf48fe165f512 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/net/minecraft/world/level/block/entity/ChestBlockEntity.java -index 784e146b28370dc2dac094d5f2ac654a5bc47e01..b1c851771e03a70d9c6a87173e81d6dd2e43f057 100644 +index 5b209de34bd425bf6c209a5317603f1c6d7280bf..4e294825c2e8c15839629eadeb3ee956d7180bef 100644 --- a/net/minecraft/world/level/block/entity/ChestBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ChestBlockEntity.java -@@ -24,7 +24,7 @@ import net.minecraft.world.level.block.state.properties.ChestType; +@@ -25,7 +25,7 @@ import net.minecraft.world.level.block.state.properties.ChestType; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; -public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity { +public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeEmitter, org.leavesmc.leaves.lithium.common.block.entity.SetBlockStateHandlingBlockEntity, org.leavesmc.leaves.lithium.common.block.entity.SleepingBlockEntity, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity private static final int EVENT_SET_OPEN_COUNT = 1; + public static final Component DEFAULT_NAME = Component.translatable("container.chest"); private NonNullList items = NonNullList.withSize(27, ItemStack.EMPTY); - public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { -@@ -127,6 +127,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement +@@ -133,6 +133,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement public static void lidAnimateTick(Level level, BlockPos pos, BlockState state, ChestBlockEntity blockEntity) { blockEntity.chestLidController.tickLid(); @@ -1155,7 +1155,7 @@ index 784e146b28370dc2dac094d5f2ac654a5bc47e01..b1c851771e03a70d9c6a87173e81d6dd } public static void playSound(Level level, BlockPos pos, BlockState state, SoundEvent sound) { -@@ -148,6 +149,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement +@@ -154,6 +155,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement @Override public boolean triggerEvent(int id, int type) { if (id == 1) { @@ -1163,7 +1163,7 @@ index 784e146b28370dc2dac094d5f2ac654a5bc47e01..b1c851771e03a70d9c6a87173e81d6dd this.chestLidController.shouldBeOpen(type > 0); return true; } else { -@@ -177,6 +179,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement +@@ -189,6 +191,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement @Override protected void setItems(NonNullList items) { this.items = items; @@ -1171,7 +1171,7 @@ index 784e146b28370dc2dac094d5f2ac654a5bc47e01..b1c851771e03a70d9c6a87173e81d6dd } @Override -@@ -227,4 +230,52 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement +@@ -239,4 +242,52 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement Block block = state.getBlock(); level.blockEvent(pos, block, 1, eventParam); } @@ -1225,19 +1225,19 @@ index 784e146b28370dc2dac094d5f2ac654a5bc47e01..b1c851771e03a70d9c6a87173e81d6dd + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java -index 969ac280ae563e3412dba406ba68ceaa8a75d519..b7e804676c39a26174758c9491f2ef4209b51f2e 100644 +index 25cde0c41ef94f9fb602ed346baad7b4b0ae77f9..a5ca4fd18d4a7f66b41392627f63e61c6762e0e9 100644 --- a/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEntity.java @@ -22,7 +22,7 @@ import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import org.slf4j.Logger; --public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container { -+public class ChiseledBookShelfBlockEntity extends BlockEntity implements Container, org.leavesmc.leaves.lithium.api.inventory.LithiumTransferConditionInventory { // Leaves - Lithium Sleeping Block Entity +-public class ChiseledBookShelfBlockEntity extends BlockEntity implements ListBackedContainer { ++public class ChiseledBookShelfBlockEntity extends BlockEntity implements ListBackedContainer, org.leavesmc.leaves.lithium.api.inventory.LithiumTransferConditionInventory { // Leaves - Lithium Sleeping Block Entity public static final int MAX_BOOKS_IN_STORAGE = 6; private static final Logger LOGGER = LogUtils.getLogger(); private static final int DEFAULT_LAST_INTERACTED_SLOT = -1; -@@ -195,4 +195,6 @@ public class ChiseledBookShelfBlockEntity extends BlockEntity implements Contain +@@ -171,4 +171,6 @@ public class ChiseledBookShelfBlockEntity extends BlockEntity implements ListBac public void removeComponentsFromTag(ValueOutput output) { output.discard("Items"); } @@ -1245,10 +1245,10 @@ index 969ac280ae563e3412dba406ba68ceaa8a75d519..b7e804676c39a26174758c9491f2ef42 + @Override public boolean lithium$itemInsertionTestRequiresStackSize1() {return true;} // Leaves - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java -index 9ce4b5a3954eda08ef587cf95dec8ed119b7a598..46939269cfb7491fdf0be7ac74a78df5476637e8 100644 +index ffb5f2a07afcd6a3df0442ba48faa1557184d27c..2fa18d7dbfeccade1d47c7e8c4f1e13503c14210 100644 --- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java +++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java -@@ -22,7 +22,7 @@ import net.minecraft.world.level.block.state.BlockState; +@@ -23,7 +23,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; @@ -1257,7 +1257,7 @@ index 9ce4b5a3954eda08ef587cf95dec8ed119b7a598..46939269cfb7491fdf0be7ac74a78df5 public static final int CONTAINER_WIDTH = 3; public static final int CONTAINER_HEIGHT = 3; public static final int CONTAINER_SIZE = 9; -@@ -169,6 +169,7 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme +@@ -171,6 +171,7 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme } }); this.containerData.set(9, input.getIntOr("triggered", 0)); @@ -1265,8 +1265,8 @@ index 9ce4b5a3954eda08ef587cf95dec8ed119b7a598..46939269cfb7491fdf0be7ac74a78df5 } @Override -@@ -278,10 +279,12 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme - level.setBlock(pos, state.setValue(CrafterBlock.CRAFTING, false), 3); +@@ -280,10 +281,12 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme + level.setBlock(pos, state.setValue(CrafterBlock.CRAFTING, false), Block.UPDATE_ALL); } } + if (org.leavesmc.leaves.LeavesConfig.performance.sleepingBlockEntity && i < 0) crafter.checkSleep(); // Leaves - Lithium Sleeping Block Entity @@ -1278,7 +1278,7 @@ index 9ce4b5a3954eda08ef587cf95dec8ed119b7a598..46939269cfb7491fdf0be7ac74a78df5 } public int getRedstoneSignal() { -@@ -300,4 +303,43 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme +@@ -302,4 +305,43 @@ public class CrafterBlockEntity extends RandomizableContainerBlockEntity impleme private boolean slotCanBeDisabled(int slot) { return slot > -1 && slot < 9 && this.items.get(slot).isEmpty(); } @@ -1316,14 +1316,14 @@ index 9ce4b5a3954eda08ef587cf95dec8ed119b7a598..46939269cfb7491fdf0be7ac74a78df5 + + @Override + public void lithium$handleSetChanged() { -+ if (this.isSleeping() && this.level != null && !this.level.isClientSide) { ++ if (this.isSleeping() && this.level != null && !this.level.isClientSide()) { + this.wakeUpNow(); + } + } + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java -index 36b9362e1ce31b63c100ec65921e095fb7871e82..fb5a7af71fee8d680eb739f45e58ec53cfc2839f 100644 +index 2fbfe925c81126cb99a4330a232d7d1b1f035973..36445dbf5e4691ce32ef996d32fbb228226a1f87 100644 --- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java +++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState; @@ -1333,9 +1333,9 @@ index 36b9362e1ce31b63c100ec65921e095fb7871e82..fb5a7af71fee8d680eb739f45e58ec53 -public class DispenserBlockEntity extends RandomizableContainerBlockEntity { +public class DispenserBlockEntity extends RandomizableContainerBlockEntity implements org.leavesmc.leaves.lithium.common.block.entity.inventory_change_tracking.InventoryChangeTracker, org.leavesmc.leaves.lithium.api.inventory.LithiumInventory { // Leaves - Lithium Sleeping Block Entity public static final int CONTAINER_SIZE = 9; + private static final Component DEFAULT_NAME = Component.translatable("container.dispenser"); private NonNullList items = NonNullList.withSize(9, ItemStack.EMPTY); - -@@ -144,10 +144,23 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity { +@@ -145,10 +145,23 @@ public class DispenserBlockEntity extends RandomizableContainerBlockEntity { @Override protected void setItems(NonNullList items) { this.items = items; @@ -1360,10 +1360,10 @@ index 36b9362e1ce31b63c100ec65921e095fb7871e82..fb5a7af71fee8d680eb739f45e58ec53 + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -index 363d85c96bd3fb1a1945595df36e30bd6dd2fa4e..542910b3d5faa85f2b14022932c058bcd1d8d904 100644 +index 775928cfe700202a70b19589ca72afd9768b62f1..c87e57f4f0aa2ffcf5531a55d971c8042a1b3eaf 100644 --- a/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java +++ b/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java -@@ -9,7 +9,7 @@ import net.minecraft.world.level.Level; +@@ -10,7 +10,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; @@ -1372,7 +1372,7 @@ index 363d85c96bd3fb1a1945595df36e30bd6dd2fa4e..542910b3d5faa85f2b14022932c058bc private final ChestLidController chestLidController = new ChestLidController(); public final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { @Override -@@ -57,11 +57,13 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity +@@ -58,11 +58,13 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity public static void lidAnimateTick(Level level, BlockPos pos, BlockState state, EnderChestBlockEntity blockEntity) { blockEntity.chestLidController.tickLid(); @@ -1386,9 +1386,9 @@ index 363d85c96bd3fb1a1945595df36e30bd6dd2fa4e..542910b3d5faa85f2b14022932c058bc this.chestLidController.shouldBeOpen(type > 0); return true; } else { -@@ -95,4 +97,36 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity - public float getOpenNess(float partialTicks) { - return this.chestLidController.getOpenness(partialTicks); +@@ -99,4 +101,36 @@ public class EnderChestBlockEntity extends BlockEntity implements LidBlockEntity + public float getOpenNess(float partialTick) { + return this.chestLidController.getOpenness(partialTick); } + + // Leaves start - Lithium Sleeping Block Entity @@ -1424,7 +1424,7 @@ index 363d85c96bd3fb1a1945595df36e30bd6dd2fa4e..542910b3d5faa85f2b14022932c058bc + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee184a7948 100644 +index 83a8dc51d0346fb5b28922e7b54d5ee58b315228..b67a1cacad31a93276988560ef03879a43c15aff 100644 --- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java @@ -27,8 +27,29 @@ import net.minecraft.world.level.block.state.BlockState; @@ -1459,7 +1459,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee public static final int MOVE_ITEM_SPEED = 8; public static final int HOPPER_CONTAINER_SIZE = 5; private static final int[][] CACHED_SLOTS = new int[54][]; -@@ -123,6 +144,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -124,6 +145,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @Override public void setBlockState(BlockState blockState) { @@ -1467,7 +1467,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee super.setBlockState(blockState); this.facing = blockState.getValue(HopperBlock.FACING); } -@@ -151,6 +173,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -152,6 +174,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen boolean result = tryMoveItems(level, pos, state, blockEntity, () -> { return suckInItems(level, blockEntity); }); @@ -1475,7 +1475,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee if (!result && blockEntity.level.spigotConfig.hopperCheck > 1) { blockEntity.setCooldown(blockEntity.level.spigotConfig.hopperCheck); } -@@ -240,6 +263,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -241,6 +264,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen org.leavesmc.leaves.protocol.PcaSyncProtocol.syncBlockEntityToClient(blockEntity); } // Leaves end - pca @@ -1490,7 +1490,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee return true; } } -@@ -438,6 +469,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -439,6 +470,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen private static void applyCooldown(final Hopper hopper) { if (hopper instanceof HopperBlockEntity blockEntity && blockEntity.getLevel() != null) { blockEntity.setCooldown(blockEntity.getLevel().spigotConfig.hopperTransfer); @@ -1498,7 +1498,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee } } -@@ -488,11 +520,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -489,11 +521,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } // Leaves end - hopper counter @@ -1519,7 +1519,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee if (isFullContainer(attachedContainer, opposite)) { return false; } else { -@@ -621,10 +661,18 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -622,10 +662,18 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen public static boolean suckInItems(Level level, Hopper hopper) { BlockPos blockPos = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY() + 1.0, hopper.getLevelZ()); BlockState blockState = level.getBlockState(blockPos); @@ -1539,7 +1539,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee for (int i : getSlots(sourceContainer, direction)) { if (tryTakeInItemFromSlot(hopper, sourceContainer, i, direction, level)) { // Spigot -@@ -636,7 +684,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -637,7 +685,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } else { boolean flag = hopper.isGridAligned() && (!org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldHopperSuckInBehavior && blockState.isCollisionShapeFullBlock(level, blockPos)) && !blockState.is(BlockTags.DOES_NOT_BLOCK_HOPPERS); // Leaves - oldHopperSuckInBehavior if (!flag) { @@ -1548,7 +1548,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee if (addItem(hopper, itemEntity)) { return true; } -@@ -807,7 +855,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -808,7 +856,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen // CraftBukkit start @Nullable private static Container runHopperInventorySearchEvent( @@ -1557,7 +1557,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee org.bukkit.craftbukkit.block.CraftBlock hopper, org.bukkit.craftbukkit.block.CraftBlock searchLocation, org.bukkit.event.inventory.HopperInventorySearchEvent.ContainerType containerType -@@ -935,6 +983,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -936,6 +984,19 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } public void setCooldown(int cooldownTime) { @@ -1577,7 +1577,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee this.cooldownTime = cooldownTime; } -@@ -954,6 +1015,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -955,6 +1016,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @Override protected void setItems(NonNullList items) { this.items = items; @@ -1585,7 +1585,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee } public static void entityInside(Level level, BlockPos pos, BlockState state, Entity entity, HopperBlockEntity blockEntity) { -@@ -968,4 +1030,757 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -969,4 +1031,757 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen protected AbstractContainerMenu createMenu(int id, Inventory player) { return new HopperMenu(id, player, this); } @@ -2344,7 +2344,7 @@ index d3e1a968fdbba65a388a67d0d578876188f5dc12..d9d3fe8fcf2949a4e82d88ff3936afee + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java -index c1d1e28daa3b4d2a0bb359af08670f5d071e51ed..97a18901f320286f8eac2bfa698b353f94a621b3 100644 +index 7e8ca373a48f89d30d4efdfcfe2acdc903a1fed9..7ba5024c645fd0026c77ab0bef64dafddc88f33d 100644 --- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java +++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java @@ -32,7 +32,7 @@ import net.minecraft.world.level.storage.ValueOutput; @@ -2356,7 +2356,7 @@ index c1d1e28daa3b4d2a0bb359af08670f5d071e51ed..97a18901f320286f8eac2bfa698b353f public static final int COLUMNS = 9; public static final int ROWS = 3; public static final int CONTAINER_SIZE = 27; -@@ -134,6 +134,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -135,6 +135,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl doNeighborUpdates(level, pos, state); } } @@ -2364,7 +2364,7 @@ index c1d1e28daa3b4d2a0bb359af08670f5d071e51ed..97a18901f320286f8eac2bfa698b353f } public ShulkerBoxBlockEntity.AnimationStatus getAnimationStatus() { -@@ -174,6 +175,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -175,6 +176,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl @Override public boolean triggerEvent(int id, int type) { @@ -2372,7 +2372,7 @@ index c1d1e28daa3b4d2a0bb359af08670f5d071e51ed..97a18901f320286f8eac2bfa698b353f if (id == 1) { this.openCount = type; if (type == 0) { -@@ -265,6 +267,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -266,6 +268,7 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl @Override protected void setItems(NonNullList items) { this.itemStacks = items; @@ -2380,7 +2380,7 @@ index c1d1e28daa3b4d2a0bb359af08670f5d071e51ed..97a18901f320286f8eac2bfa698b353f } // Leaves start - pca -@@ -316,4 +319,39 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl +@@ -317,4 +320,39 @@ public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity impl OPENED, CLOSING; } @@ -2421,10 +2421,10 @@ index c1d1e28daa3b4d2a0bb359af08670f5d071e51ed..97a18901f320286f8eac2bfa698b353f + // Leaves end - Lithium Sleeping Block Entity } diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java -index 67719dce9017a4c86a70b62fb660bddc636d5582..c1cbb635b6c22b04ca33c68a4c9777f067b30b4b 100644 +index 683a6a48593218b7504d6c99a0357278fb380665..d9f20b103361a788955b11048dbd91e405cca733 100644 --- a/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/net/minecraft/world/level/block/state/BlockBehaviour.java -@@ -85,7 +85,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; +@@ -84,7 +84,7 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; @@ -2433,7 +2433,7 @@ index 67719dce9017a4c86a70b62fb660bddc636d5582..c1cbb635b6c22b04ca33c68a4c9777f0 protected static final Direction[] UPDATE_SHAPE_ORDER = new Direction[]{ Direction.WEST, Direction.EAST, Direction.NORTH, Direction.SOUTH, Direction.DOWN, Direction.UP }; -@@ -157,6 +157,7 @@ public abstract class BlockBehaviour implements FeatureElement { +@@ -156,6 +156,7 @@ public abstract class BlockBehaviour implements FeatureElement { BlockState neighborState, RandomSource random ) { @@ -2442,10 +2442,10 @@ index 67719dce9017a4c86a70b62fb660bddc636d5582..c1cbb635b6c22b04ca33c68a4c9777f0 } diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java -index b27cbb55fcb980679819a605112533f366abc97e..b9931ba80f79db6d4c80fb707c788e449c71f52e 100644 +index e6cc97e21e31faab0562e2a43766bd00f0451a19..0ae3b15906b0bee7c55dce64a4fe46623ee2ebe2 100644 --- a/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java -@@ -898,12 +898,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -934,12 +934,14 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot (pos, ticker1) -> { TickingBlockEntity tickingBlockEntity = this.createTicker(blockEntity, ticker); if (ticker1 != null) { @@ -2460,7 +2460,7 @@ index b27cbb55fcb980679819a605112533f366abc97e..b9931ba80f79db6d4c80fb707c788e44 this.level.addBlockEntityTicker(rebindableTickingBlockEntityWrapper); return rebindableTickingBlockEntityWrapper; } else { -@@ -997,14 +999,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1033,14 +1035,14 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot void run(LevelChunk chunk); } diff --git a/leaves-server/minecraft-patches/features/0137-Bring-back-LivingEntity-effect-CME.patch b/leaves-server/minecraft-patches/features/0137-Bring-back-LivingEntity-effect-CME.patch index 6b4a82b7..16ab7048 100644 --- a/leaves-server/minecraft-patches/features/0137-Bring-back-LivingEntity-effect-CME.patch +++ b/leaves-server/minecraft-patches/features/0137-Bring-back-LivingEntity-effect-CME.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Bring back LivingEntity effect CME diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 0d493c8343057898166f94a4006a374a214ae7b2..951300caeca0421cabda44496ed2f09fc2258dd0 100644 +index 7a849ba0e22574f00f3580a432e2fe8343c883c6..b0db5cec1293109b32fd6bb40b350d81ea0afc7a 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -1151,7 +1151,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -1158,7 +1158,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) { // Paper end - Don't fire sync event during generation // org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API diff --git a/leaves-server/minecraft-patches/features/0138-Do-not-tick-Arrow-life-regardless.patch b/leaves-server/minecraft-patches/features/0138-Do-not-tick-Arrow-life-regardless.patch index e04e2a1c..69026154 100644 --- a/leaves-server/minecraft-patches/features/0138-Do-not-tick-Arrow-life-regardless.patch +++ b/leaves-server/minecraft-patches/features/0138-Do-not-tick-Arrow-life-regardless.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Do not tick Arrow life regardless diff --git a/net/minecraft/world/entity/projectile/AbstractArrow.java b/net/minecraft/world/entity/projectile/AbstractArrow.java -index 11adb3eacce9d46f15e6c5216e9b2494df158baf..85d358a86ff118ce34276d3b03c655c807cdea73 100644 +index 1be2a7f45866bfe69b8f181fee98d1336b0cfba3..1a60d8f993d28a2cd2364acdf68b353220de49ab 100644 --- a/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -218,7 +218,7 @@ public abstract class AbstractArrow extends Projectile { +@@ -212,7 +212,7 @@ public abstract class AbstractArrow extends Projectile { this.setSharedFlagOnFire(this.getRemainingFireTicks() > 0); } } else { diff --git a/leaves-server/minecraft-patches/features/0139-Modify-end-void-rings-generation.patch b/leaves-server/minecraft-patches/features/0139-Modify-end-void-rings-generation.patch index 03db30b5..65da1192 100644 --- a/leaves-server/minecraft-patches/features/0139-Modify-end-void-rings-generation.patch +++ b/leaves-server/minecraft-patches/features/0139-Modify-end-void-rings-generation.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Modify end void rings generation diff --git a/net/minecraft/world/level/levelgen/DensityFunctions.java b/net/minecraft/world/level/levelgen/DensityFunctions.java -index 04527a5c65ad630f794fed9071d485aedd02257a..0298ba0c68447c5d0d555431b3118552b3d90a34 100644 +index 2dede0dc630097c878f4afc10b10a304eb458a99..b16cb2063e7aa42d0b85b518eba590c0cf3c5b8e 100644 --- a/net/minecraft/world/level/levelgen/DensityFunctions.java +++ b/net/minecraft/world/level/levelgen/DensityFunctions.java -@@ -528,7 +528,7 @@ public final class DensityFunctions { +@@ -534,7 +534,7 @@ public final class DensityFunctions { int i1 = z / 2; int i2 = x % 2; int i3 = z % 2; diff --git a/leaves-server/minecraft-patches/features/0140-Lithium-Equipment-Tracking.patch b/leaves-server/minecraft-patches/features/0140-Lithium-Equipment-Tracking.patch index 51b82a79..3e433ddf 100644 --- a/leaves-server/minecraft-patches/features/0140-Lithium-Equipment-Tracking.patch +++ b/leaves-server/minecraft-patches/features/0140-Lithium-Equipment-Tracking.patch @@ -24,7 +24,7 @@ As part of: Lithium (https://github.com/CaffeineMC/lithium) Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html) diff --git a/net/minecraft/world/entity/EntityEquipment.java b/net/minecraft/world/entity/EntityEquipment.java -index 90814ad07a2686c5a274860395f5aca29cc3bf13..758a8bd797f06cd6998f71b095c475e09906e343 100644 +index 1e00a7bd89d885cabb4b9ca3c86fbd8cd93cebf5..08e3d257ffdc5dfa996b1e16e477b4e0f8660c54 100644 --- a/net/minecraft/world/entity/EntityEquipment.java +++ b/net/minecraft/world/entity/EntityEquipment.java @@ -7,7 +7,7 @@ import java.util.Objects; @@ -48,10 +48,10 @@ index 90814ad07a2686c5a274860395f5aca29cc3bf13..758a8bd797f06cd6998f71b095c475e0 private EntityEquipment(EnumMap items) { this.items = items; -@@ -29,7 +34,13 @@ public class EntityEquipment { +@@ -28,7 +33,13 @@ public class EntityEquipment { + } public ItemStack set(EquipmentSlot slot, ItemStack stack) { - stack.getItem().verifyComponentsAfterLoad(stack); - return Objects.requireNonNullElse(this.items.put(slot, stack), ItemStack.EMPTY); + // Leaves start - Lithium - equipment tracking + ItemStack oldStack = Objects.requireNonNullElse(this.items.put(slot, stack), ItemStack.EMPTY); @@ -63,7 +63,7 @@ index 90814ad07a2686c5a274860395f5aca29cc3bf13..758a8bd797f06cd6998f71b095c475e0 } public ItemStack get(EquipmentSlot slot) { -@@ -56,8 +67,23 @@ public class EntityEquipment { +@@ -55,8 +66,23 @@ public class EntityEquipment { } public void setAll(EntityEquipment equipment) { @@ -87,7 +87,7 @@ index 90814ad07a2686c5a274860395f5aca29cc3bf13..758a8bd797f06cd6998f71b095c475e0 } public void dropAll(LivingEntity entity) { -@@ -70,6 +96,7 @@ public class EntityEquipment { +@@ -69,6 +95,7 @@ public class EntityEquipment { public void clear() { this.items.replaceAll((equipmentSlot, itemStack) -> ItemStack.EMPTY); @@ -95,7 +95,7 @@ index 90814ad07a2686c5a274860395f5aca29cc3bf13..758a8bd797f06cd6998f71b095c475e0 } // Paper start - EntityDeathEvent -@@ -78,4 +105,98 @@ public class EntityEquipment { +@@ -77,4 +104,98 @@ public class EntityEquipment { return this.items.containsKey(slot); } // Paper end - EntityDeathEvent @@ -195,10 +195,10 @@ index 90814ad07a2686c5a274860395f5aca29cc3bf13..758a8bd797f06cd6998f71b095c475e0 + // Leaves end - Lithium - equipment tracking } diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 951300caeca0421cabda44496ed2f09fc2258dd0..eb1a6644670c126c03ef871c8ac4bc2d0e389872 100644 +index b0db5cec1293109b32fd6bb40b350d81ea0afc7a..c275942cb57f2e5fe1e1cc8bee92abef4343297b 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java -@@ -425,9 +425,17 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -432,9 +432,17 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.getSleepingPos().ifPresent(this::setPosToBed); } @@ -218,7 +218,7 @@ index 951300caeca0421cabda44496ed2f09fc2258dd0..eb1a6644670c126c03ef871c8ac4bc2d super.baseTick(); ProfilerFiller profilerFiller = Profiler.get(); -@@ -3348,6 +3356,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3388,6 +3396,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin public void detectEquipmentUpdates() { Map map = this.collectEquipmentChanges(); if (map != null) { @@ -226,7 +226,7 @@ index 951300caeca0421cabda44496ed2f09fc2258dd0..eb1a6644670c126c03ef871c8ac4bc2d this.handleHandSwap(map); if (!map.isEmpty()) { this.handleEquipmentChanges(map); -@@ -3357,6 +3366,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin +@@ -3397,6 +3406,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin @Nullable private Map collectEquipmentChanges() { @@ -242,10 +242,10 @@ index 951300caeca0421cabda44496ed2f09fc2258dd0..eb1a6644670c126c03ef871c8ac4bc2d // Paper start - EntityEquipmentChangedEvent record EquipmentChangeImpl(org.bukkit.inventory.ItemStack oldItem, org.bukkit.inventory.ItemStack newItem) implements io.papermc.paper.event.entity.EntityEquipmentChangedEvent.EquipmentChange { diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java -index d7725b5ca689e3d5b512baab04e113be77c0b2ee..abe5d681f81f60facc019660a6eae833e5742cef 100644 +index 9420ca7e32ae71ce9cecf8afd808ae6e9f8f4258..de89f78978ee5ae67049eb83fda3d56ef8371781 100644 --- a/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/net/minecraft/world/entity/decoration/ArmorStand.java -@@ -89,7 +89,7 @@ public class ArmorStand extends LivingEntity { +@@ -90,7 +90,7 @@ public class ArmorStand extends LivingEntity { // Paper start - Allow ArmorStands not to tick public boolean canTick = true; public boolean canTickSetByAPI = false; @@ -253,8 +253,8 @@ index d7725b5ca689e3d5b512baab04e113be77c0b2ee..abe5d681f81f60facc019660a6eae833 + public boolean noTickEquipmentDirty = false; // Leaves - private -> public // Paper end - Allow ArmorStands not to tick - public ArmorStand(EntityType entityType, Level level) { -@@ -530,8 +530,9 @@ public class ArmorStand extends LivingEntity { + public ArmorStand(EntityType type, Level level) { +@@ -531,8 +531,9 @@ public class ArmorStand extends LivingEntity { public void tick() { if (!this.canTick) { if (this.noTickEquipmentDirty) { diff --git a/leaves-server/minecraft-patches/features/0141-Do-not-check-NaN-values-in-entities.patch b/leaves-server/minecraft-patches/features/0141-Do-not-check-NaN-values-in-entities.patch index a3b517b3..b1f8c13e 100644 --- a/leaves-server/minecraft-patches/features/0141-Do-not-check-NaN-values-in-entities.patch +++ b/leaves-server/minecraft-patches/features/0141-Do-not-check-NaN-values-in-entities.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Do not check NaN values in entities diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 4748bd188f8860ed2a8b2e6123e020c1da17af5f..5c17fb5211da426b41c1ebb298563f083bc09099 100644 +index d9fe2e6d424231c7acd15cd5bb6a05afa2e263c6..50c143bb15108f02918fbacdff1eebfc14ee8aa6 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java -@@ -2512,10 +2512,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2561,10 +2561,12 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name } } // CraftBukkit @@ -22,7 +22,7 @@ index 4748bd188f8860ed2a8b2e6123e020c1da17af5f..5c17fb5211da426b41c1ebb298563f08 if (Float.isNaN(this.yRot)) { this.yRot = 0; } -@@ -2523,7 +2525,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2572,7 +2574,9 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name if (Float.isNaN(this.xRot)) { this.xRot = 0; } @@ -32,7 +32,7 @@ index 4748bd188f8860ed2a8b2e6123e020c1da17af5f..5c17fb5211da426b41c1ebb298563f08 output.store("Rotation", Vec2.CODEC, new Vec2(this.getYRot(), this.getXRot())); output.putDouble("fall_distance", this.fallDistance); output.putShort("Fire", (short)this.remainingFireTicks); -@@ -2646,7 +2650,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2695,7 +2699,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name public void load(ValueInput input) { try { Vec3 vec3 = input.read("Pos", Vec3.CODEC).orElse(Vec3.ZERO); diff --git a/leaves-server/minecraft-patches/features/0142-Modify-merge-ItemEntity-logic.patch b/leaves-server/minecraft-patches/features/0142-Modify-merge-ItemEntity-logic.patch new file mode 100644 index 00000000..e078ce7b --- /dev/null +++ b/leaves-server/minecraft-patches/features/0142-Modify-merge-ItemEntity-logic.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Helvetica Volubi +Date: Fri, 3 Oct 2025 19:43:36 +0800 +Subject: [PATCH] Modify merge ItemEntity logic + +Add followTickSequenceMerge to modify merge items, due to Paper's modification of the merge radius, when the merge radius is large and stacks containing many items get stuck in an unexpected position, individual items may never reach their destination. This configuration option is added to fix this behavior. + +diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java +index f9a1ccee0c1e608fd5f48de466046fc4e6a7dfc7..3c29483f0d915fedbbfb0e001ee92a3cb34c05ca 100644 +--- a/net/minecraft/world/entity/item/ItemEntity.java ++++ b/net/minecraft/world/entity/item/ItemEntity.java +@@ -297,7 +297,7 @@ public class ItemEntity extends Entity implements TraceableEntity, ChangePublish + ItemStack item = this.getItem(); + ItemStack item1 = itemEntity.getItem(); + if (Objects.equals(this.target, itemEntity.target) && areMergable(item, item1)) { +- if (item1.getCount() < item.getCount()) { ++ if (org.leavesmc.leaves.LeavesConfig.modify.followTickSequenceMerge || item1.getCount() < item.getCount()) { // Leaves - add follow Tick Sequence Merge, see Paper#13073 + merge(this, item, itemEntity, item1); + } else { + merge(itemEntity, item1, this, item); diff --git a/leaves-server/minecraft-patches/features/0143-Old-minecart-motion-behavior.patch b/leaves-server/minecraft-patches/features/0143-Old-minecart-motion-behavior.patch new file mode 100644 index 00000000..28a54d79 --- /dev/null +++ b/leaves-server/minecraft-patches/features/0143-Old-minecart-motion-behavior.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MC_XiaoHei +Date: Wed, 8 Oct 2025 18:07:47 +0800 +Subject: [PATCH] Old minecart motion behavior + +This patch is Powered by [CPCA](https://github.com/liuyuexiaoyu1/carpet_pc_additon) + +This patch is based on the following mixins: +* "com/pigconnon/carpet_pc_addition/mixin/MinecartMotionFix/EntityMixin.java" +* "com/pigconnon/carpet_pc_addition/mixin/MinecartMotionFix/NetherPortalBlockMixin.java" +By: liuyuexiaoyu1 +As part of: CPCA (https://github.com/liuyuexiaoyu1/carpet_pc_additon) +Licensed under: MIT (https://mit-license.org) + +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index 50c143bb15108f02918fbacdff1eebfc14ee8aa6..7e4cf37e85b15be40e74aaa5a5d2227d4d837c7c 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -4174,7 +4174,7 @@ public abstract class Entity implements SyncedDataHolder, DebugValueSource, Name + teleportTransition.relatives().contains(Relative.Y) ? 0.0 : vec3.y(), + teleportTransition.relatives().contains(Relative.Z) ? 0.0 : vec3.z() + ); +- return teleportTransition.withPosition(vec31).withRotation(f, f1).transitionAsPassenger(); ++ return org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldMinecartMotionBehavior ? new TeleportTransition(teleportTransition.newLevel(), teleportTransition.position(), teleportTransition.deltaMovement(), 0, 0, teleportTransition.postTeleportTransition()) : teleportTransition.withPosition(vec31).withRotation(f, f1).transitionAsPassenger(); // Leaves - old minecart motion behavior + } + + private void sendTeleportTransitionToRidingPlayers(TeleportTransition teleportTransition) { +diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java +index 1ad863dc255a7b91d0b163000b6bb5d43e2ad204..512416c99e46d6eecc1fa4ca43f329923ceae868 100644 +--- a/net/minecraft/world/level/block/NetherPortalBlock.java ++++ b/net/minecraft/world/level/block/NetherPortalBlock.java +@@ -259,14 +259,24 @@ public class NetherPortalBlock extends Block implements Portal { + double d = rectangle.axis1Size; + double d1 = rectangle.axis2Size; + EntityDimensions dimensions = entity.getDimensions(entity.getPose()); +- int i = axis == axis1 ? 0 : 90; ++ // Leaves start - old minecart motion behavior ++ int i; ++ Vec3 vec3d3; ++ if (org.leavesmc.leaves.LeavesConfig.modify.oldMC.oldMinecartMotionBehavior) { ++ vec3d3 = axis == axis1 ? entity.getDeltaMovement() : new Vec3(entity.getDeltaMovement().z, entity.getDeltaMovement().y, -entity.getDeltaMovement().x); ++ i = 0; ++ } else { ++ vec3d3 = Vec3.ZERO; ++ i = axis == axis1 ? 0 : 90; ++ } + double d2 = dimensions.width() / 2.0 + (d - dimensions.width()) * offset.x(); + double d3 = (d1 - dimensions.height()) * offset.y(); + double d4 = 0.5 + offset.z(); + boolean flag = axis1 == Direction.Axis.X; + Vec3 vec3 = new Vec3(blockPos.getX() + (flag ? d2 : d4), blockPos.getY() + d3, blockPos.getZ() + (flag ? d4 : d2)); + Vec3 vec31 = PortalShape.findCollisionFreePosition(vec3, level, entity, dimensions); +- return new TeleportTransition(level, vec31, Vec3.ZERO, i, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), postTeleportTransition, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); // CraftBukkit ++ return new TeleportTransition(level, vec31, vec3d3, i, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), postTeleportTransition, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); // CraftBukkit ++ // Leaves end - old minecart motion behavior + } + + @Override diff --git a/leaves-server/paper-patches/features/0001-Build-changes.patch b/leaves-server/paper-patches/features/0001-Build-changes.patch index 87779147..69390475 100644 --- a/leaves-server/paper-patches/features/0001-Build-changes.patch +++ b/leaves-server/paper-patches/features/0001-Build-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Build changes diff --git a/src/main/java/com/destroystokyo/paper/Metrics.java b/src/main/java/com/destroystokyo/paper/Metrics.java -index 6abc57669e87f7f98f3b76af3c0e50825fea6eb1..c7ee6d3a158ca7d3de54bc12622affbf01584e7b 100644 +index 9f4d73fd321f6f0cd19fdd1b63068d2ea6c0816b..339d4c13daafc3fd7fdf6fc8909a7e7f80ba8ece 100644 --- a/src/main/java/com/destroystokyo/paper/Metrics.java +++ b/src/main/java/com/destroystokyo/paper/Metrics.java @@ -593,7 +593,8 @@ public class Metrics { @@ -106,20 +106,28 @@ index 74ffdc823e66fc5ec027c4b7c462382bcbfe2be2..f38f8e5851ec65a8f3f98018d55de74e private static final String BUILD_DEV = "DEV"; diff --git a/src/main/java/io/papermc/paper/command/PaperVersionCommand.java b/src/main/java/io/papermc/paper/command/PaperVersionCommand.java -index a7d1a959af6a810c0ce6d5baa08e4429e14d4f5b..88dbb30dd736b63f562918fb166678ba5f757fca 100644 +index bfacb856623b5cb6af4f1b65ee89200cdfb1ef13..a427a962ea90b089bef1a8177b187f4ba1063582 100644 --- a/src/main/java/io/papermc/paper/command/PaperVersionCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperVersionCommand.java -@@ -45,7 +45,7 @@ public class PaperVersionCommand { +@@ -24,7 +24,6 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + import org.bukkit.command.CommandSender; +-import org.bukkit.craftbukkit.util.CraftMagicNumbers; + import org.bukkit.plugin.Plugin; + import org.bukkit.util.StringUtil; + import org.jspecify.annotations.NullMarked; +@@ -45,7 +44,7 @@ public class PaperVersionCommand { private static final Component FAILED_TO_FETCH = Component.text("Could not fetch version information!", NamedTextColor.RED); private static final Component FETCHING = Component.text("Checking version, please wait...", NamedTextColor.WHITE, TextDecoration.ITALIC); -- private final VersionFetcher versionFetcher = new PaperVersionFetcher(); +- private final VersionFetcher versionFetcher = CraftMagicNumbers.INSTANCE.getVersionFetcher(); + private final VersionFetcher versionFetcher = new org.leavesmc.leaves.util.LeavesVersionFetcher(); // Leaves - build change private CompletableFuture computedVersion = CompletableFuture.completedFuture(new ComputedVersion(Component.empty(), -1)); // Precompute-- someday move that stuff out of bukkit public static LiteralCommandNode create() { diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 7675acdca2162e403f4ff523bcdd6efe0cb42d49..a950bfb0c6aeb0b19150c59cea13337005c2752a 100644 +index 5bd6da467a1f536eb56c93ea00f98050cfaa36d0..26b30fac9a12c88b3e8ed114a9225f57603b937e 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -231,7 +231,7 @@ public class Main { @@ -132,7 +140,7 @@ index 7675acdca2162e403f4ff523bcdd6efe0cb42d49..a950bfb0c6aeb0b19150c59cea133370 } } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index c1aad9203af20102e560571435dfa75150b37c1b..ea97ea679b1ba64c9d33e52f39d010a923ef4385 100644 +index f83067eaa4eedc8108460c254782ba45a2933372..98baec88662eb1519468eb0095b0a23ae7dfe876 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -481,7 +481,7 @@ public final class CraftMagicNumbers implements UnsafeValues { @@ -158,7 +166,7 @@ index 774556a62eb240da42e84db4502e2ed43495be17..fdef98a7796d84c7b0ee61241859e10c if (stream != null) { diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index c77748061f1c8bb2b0dc8dbd80f608d431752015..7dac2652e3d4964682982e50f533bd4b38ee5b4b 100644 +index e2dc6644ae44ce02821100275ede4b0712cf260d..c7a7870199065aa853b4848f9aea75cc952eb6e6 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -75,14 +75,14 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre diff --git a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch b/leaves-server/paper-patches/features/0003-Leaves-Server-Config.patch similarity index 58% rename from leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch rename to leaves-server/paper-patches/features/0003-Leaves-Server-Config.patch index 97e25a1a..62fe9d52 100644 --- a/leaves-server/paper-patches/features/0003-Leaves-Server-Config-And-Command.patch +++ b/leaves-server/paper-patches/features/0003-Leaves-Server-Config.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Sat, 1 Feb 2025 14:21:06 +0800 -Subject: [PATCH] Leaves Server Config And Command +Subject: [PATCH] Leaves Server Config diff --git a/src/main/java/io/papermc/paper/SparksFly.java b/src/main/java/io/papermc/paper/SparksFly.java @@ -17,29 +17,11 @@ index 62e2d5704c348955bc8284dc2d54c933b7bcdd06..7ef20f0138fad39a1d23edd7b26ddc88 @Override public void executeAsync(final Runnable runnable) { MCUtil.scheduleAsyncTask(this.catching(runnable, "asynchronous")); -diff --git a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -index 5c52b1563d20d7e977a5bb958c18b19dec5c365a..65664441c5692620a8b22513ded497b7951a3245 100644 ---- a/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -+++ b/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java -@@ -106,6 +106,13 @@ public class BukkitCommandNode extends LiteralCommandNode { - List results = null; - Location pos = context.getSource().getLocation(); - try { -+ // Leaves start - custom suggestion -+ if (this.command instanceof org.leavesmc.leaves.command.LeavesSuggestionCommand suggestionCommand) { -+ org.leavesmc.leaves.command.LeavesSuggestionBuilder suggestionBuilder = new org.leavesmc.leaves.command.LeavesSuggestionBuilder(builder.createOffset(builder.getInput().lastIndexOf(' ') + 1)); -+ suggestionCommand.suggest(sender, this.literal, args, pos.clone(), suggestionBuilder); -+ return suggestionBuilder.build(); -+ } -+ // Leaves end - custom suggestion - results = this.command.tabComplete(sender, this.literal, args, pos.clone()); - } catch (CommandException ex) { - sender.sendMessage(Component.text("An internal error occurred while attempting to tab-complete this command", NamedTextColor.RED)); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 32fe51b19323e3c4c56e7f9e621e6e808ee5fe38..2eba1d900b20a781c4bb08caa2b30bfeb2d02b9d 100644 +index 34d74014fd042f6eeafafadb6237a838b1ddd47c..01672aff7c4028da9714448bb3386b7d8369db59 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1076,6 +1076,7 @@ public final class CraftServer implements Server { +@@ -1020,6 +1020,7 @@ public final class CraftServer implements Server { playerMetadata.removeAll(plugin); } // Paper end @@ -48,7 +30,7 @@ index 32fe51b19323e3c4c56e7f9e621e6e808ee5fe38..2eba1d900b20a781c4bb08caa2b30bfe org.spigotmc.SpigotConfig.registerCommands(); // Spigot io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index a950bfb0c6aeb0b19150c59cea13337005c2752a..7f68edab68fc82a7ae269f01633c786b2d1026a8 100644 +index 26b30fac9a12c88b3e8ed114a9225f57603b937e..0aa959d64b34446d29961684eb050db336c79dfe 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -169,6 +169,14 @@ public class Main { diff --git a/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch b/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch index 1e5f22ec..b5201933 100644 --- a/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch +++ b/leaves-server/paper-patches/features/0004-Leaves-Protocol-Core.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaves Protocol Core diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 2eba1d900b20a781c4bb08caa2b30bfeb2d02b9d..203ea4231e5b0d3bf7c35856ca55b2f812044608 100644 +index 01672aff7c4028da9714448bb3386b7d8369db59..3a81b4c659d35fd273542a8bb343c256c29dfccc 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -497,6 +497,7 @@ public final class CraftServer implements Server { +@@ -485,6 +485,7 @@ public final class CraftServer implements Server { this.potionBrewer = new io.papermc.paper.potion.PaperPotionBrewer(console); // Paper - custom potion mixes datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark @@ -16,7 +16,7 @@ index 2eba1d900b20a781c4bb08caa2b30bfeb2d02b9d..203ea4231e5b0d3bf7c35856ca55b2f8 } public boolean getCommandBlockOverride(String command) { -@@ -1083,6 +1084,7 @@ public final class CraftServer implements Server { +@@ -1027,6 +1028,7 @@ public final class CraftServer implements Server { this.spark.registerCommandBeforePlugins(this); // Paper - spark this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); diff --git a/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch b/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch index 89f36e14..305e9b1b 100644 --- a/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch +++ b/leaves-server/paper-patches/features/0005-Leaves-Fakeplayer.patch @@ -32,22 +32,22 @@ index a589689e3a9de1fffef62e0e3dcd79bb2e848c5b..c0910f908ffad3bb94563836c032bb1d RegisteredListener[] listeners = handlers.getRegisteredListeners(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java -index 0a10f49ee410d93e95ceb90108200a1a9d12b54b..d2eee37d810a6d5cf514bc71dea66a4d2b0d09e2 100644 +index 119f4c23e351eab0a503f78b48136dc6ae55bf60..7d99e7f29156723a3f20f1daba21aed2bc6649c6 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java -@@ -423,6 +423,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor { +@@ -373,6 +373,7 @@ public abstract class CraftRegionAccessor implements RegionAccessor { @SuppressWarnings("unchecked") public T addEntity(T entity) { Preconditions.checkArgument(!entity.isInWorld(), "Entity has already been added to a world"); + Preconditions.checkState(!(entity instanceof org.leavesmc.leaves.entity.bot.CraftBot), "[Leaves] Fakeplayers do not support changing world, Please use leaves fakeplayer-api instead!"); net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle(); if (nmsEntity.level() != this.getHandle().getLevel()) { - nmsEntity = nmsEntity.teleport(new TeleportTransition(this.getHandle().getLevel(), nmsEntity, TeleportTransition.DO_NOTHING)); + throw new IllegalArgumentException(entity + " wasn't created with this world, you must create the entity with the world you want to add it to."); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 203ea4231e5b0d3bf7c35856ca55b2f812044608..8ec1308877f82c1207867429f2d5d3e3ca200649 100644 +index 3a81b4c659d35fd273542a8bb343c256c29dfccc..dd132b146a694ac60348b0a3173d12fdd064f29e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -316,6 +316,7 @@ public final class CraftServer implements Server { +@@ -305,6 +305,7 @@ public final class CraftServer implements Server { private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; public final io.papermc.paper.SparksFly spark; private final ServerConfiguration serverConfig = new PaperServerConfiguration(); @@ -55,7 +55,7 @@ index 203ea4231e5b0d3bf7c35856ca55b2f812044608..8ec1308877f82c1207867429f2d5d3e3 // Paper start - Folia region threading API private final io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler(); -@@ -498,6 +499,7 @@ public final class CraftServer implements Server { +@@ -486,6 +487,7 @@ public final class CraftServer implements Server { datapackManager = new io.papermc.paper.datapack.PaperDatapackManager(console.getPackRepository()); // Paper this.spark = new io.papermc.paper.SparksFly(this); // Paper - spark org.leavesmc.leaves.protocol.core.LeavesProtocolManager.init(); // Leaves - protocol @@ -63,7 +63,7 @@ index 203ea4231e5b0d3bf7c35856ca55b2f812044608..8ec1308877f82c1207867429f2d5d3e3 } public boolean getCommandBlockOverride(String command) { -@@ -1444,7 +1446,7 @@ public final class CraftServer implements Server { +@@ -1341,7 +1343,7 @@ public final class CraftServer implements Server { return false; } @@ -72,7 +72,7 @@ index 203ea4231e5b0d3bf7c35856ca55b2f812044608..8ec1308877f82c1207867429f2d5d3e3 return false; } -@@ -3189,4 +3191,11 @@ public final class CraftServer implements Server { +@@ -2965,4 +2967,11 @@ public final class CraftServer implements Server { public void allowPausing(final Plugin plugin, final boolean value) { this.console.addPluginAllowingSleep(plugin.getName(), value); } @@ -85,10 +85,10 @@ index 203ea4231e5b0d3bf7c35856ca55b2f812044608..8ec1308877f82c1207867429f2d5d3e3 + // Leaves end - Bot API } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index ee7a4169003b23766b5d2e6edf9221375d80d83c..e0851fc1fa599c2a35d15c7fec7959cb33bb3562 100644 +index e92827b83d2cd7f18ed214ce389ac423b6d2d922..7fca335bb7db5b85ee5fc155cc4341b808db9a07 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -249,7 +249,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -251,7 +251,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getPlayerCount() { @@ -97,7 +97,7 @@ index ee7a4169003b23766b5d2e6edf9221375d80d83c..e0851fc1fa599c2a35d15c7fec7959cb } @Override -@@ -1266,9 +1266,9 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1111,9 +1111,9 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public List getPlayers() { @@ -109,7 +109,7 @@ index ee7a4169003b23766b5d2e6edf9221375d80d83c..e0851fc1fa599c2a35d15c7fec7959cb HumanEntity bukkitEntity = human.getBukkitEntity(); if ((bukkitEntity != null) && (bukkitEntity instanceof Player)) { -@@ -1950,7 +1950,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1600,7 +1600,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { public void playSound(final net.kyori.adventure.sound.Sound sound) { org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper final long seed = sound.seed().orElseGet(this.world.getRandom()::nextLong); @@ -118,7 +118,7 @@ index ee7a4169003b23766b5d2e6edf9221375d80d83c..e0851fc1fa599c2a35d15c7fec7959cb player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player.getX(), player.getY(), player.getZ(), seed, null)); } } -@@ -1978,7 +1978,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1628,7 +1628,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { org.spigotmc.AsyncCatcher.catchOp("play sound"); // Paper final long seed = sound.seed().orElseGet(this.getHandle().getRandom()::nextLong); if (emitter == net.kyori.adventure.sound.Sound.Emitter.self()) { @@ -127,17 +127,17 @@ index ee7a4169003b23766b5d2e6edf9221375d80d83c..e0851fc1fa599c2a35d15c7fec7959cb player.connection.send(io.papermc.paper.adventure.PaperAdventure.asSoundPacket(sound, player, seed, null)); } } else if (emitter instanceof CraftEntity craftEntity) { -@@ -2208,7 +2208,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1792,7 +1792,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { Preconditions.checkArgument(particle.getDataType().isInstance(data), "data (%s) should be %s", data.getClass(), particle.getDataType()); } this.getHandle().sendParticlesSource( -- receivers == null ? this.getHandle().players() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API -+ receivers == null ? this.getHandle().realPlayers() : receivers.stream().map(player -> ((CraftPlayer) player).getHandle()).collect(java.util.stream.Collectors.toList()), // Paper - Particle API // Leaves - skip +- receivers == null ? this.getHandle().players() : Lists.transform(receivers, player -> ((CraftPlayer) player).getHandle()), // Paper - Particle API ++ receivers == null ? this.getHandle().realPlayers() : Lists.transform(receivers, player -> ((CraftPlayer) player).getHandle()), // Paper - Particle API sender != null ? ((CraftPlayer) sender).getHandle() : null, // Sender // Paper - Particle API CraftParticle.createParticleParam(particle, data), // Particle force, diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index b38073628d3b1381ccc4e5c6c44b2b7ec8ba1273..c775b2956d008338d7d48ab709013b7111b1ac8f 100644 +index b177e23db960323b901909a3f845a9ae0426d0df..b28129242d13afc72ea863aaf405063c38663e0e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -121,6 +121,8 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -150,10 +150,10 @@ index b38073628d3b1381ccc4e5c6c44b2b7ec8ba1273..c775b2956d008338d7d48ab709013b71 if (entity instanceof EnderDragonPart complexPart) { if (complexPart.parentMob instanceof EnderDragon) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 08db922da37984b82f57c210f6613543d32303bc..f4fc9723958d3e2d78244ec93efa1b767793d6cc 100644 +index d5496e5fbb5fcd65df2933ebc7cb39df7d832923..250a7d5427fc59478d8a540cfb2319939a489e65 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -896,7 +896,11 @@ public class CraftEventFactory { +@@ -882,7 +882,11 @@ public class CraftEventFactory { event.setKeepInventory(keepInventory); event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel populateFields(victim, event); // Paper - make cancellable diff --git a/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch b/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch index 1aebf537..aef60ca3 100644 --- a/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch +++ b/leaves-server/paper-patches/features/0007-MC-Technical-Survival-Mode.patch @@ -6,10 +6,10 @@ Subject: [PATCH] MC Technical Survival Mode Will automatically overwrite some configuration after startup diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -index a972eeddbdc59e53279a7c5c704e28c2fcdf7290..584e4fd53a0b78b4dbdf756c3a714c482bb7c3b8 100644 +index 940f60cd846107a82c1c523d73f9028b50a929d9..19a82b1e3b30b0e0877c726c166d8ab5b0c27c45 100644 --- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java +++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -@@ -336,6 +336,7 @@ public class PaperConfigurations extends Configurations CONFIG_TYPES = new ArrayList<>(); - + public static final PluginFileType PAPER = new PluginFileType<>(PAPER_PLUGIN_YML, PaperPluginParent.FACTORY) { @@ -43,8 +44,21 @@ public abstract class PluginFileType { entrypointHandler.register(Entrypoint.PLUGIN, provider); @@ -261,10 +261,10 @@ index fbad4a2242aa1ab910b2e2ae4cce973ff63fda84..89d4fa952d072dd6e071dc9eef51f405 } catch (final IOException ex) { return CompletableFuture.failedFuture(new RuntimeException("Failed to open plugin jar " + inputFile, ex)); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index edd9a88605c4aab5263b3455ac321c3068d33834..9dd48f07c9c8799623074d153eca6ee7f9ac6e49 100644 +index 6167dfe78793bd23748fcbd86a37618b8a4f76ea..8481618e09ed02afa04393a36c384237d0cca59d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -3194,6 +3194,13 @@ public final class CraftServer implements Server { +@@ -2970,6 +2970,13 @@ public final class CraftServer implements Server { this.console.addPluginAllowingSleep(plugin.getName(), value); } diff --git a/leaves-server/paper-patches/features/0014-Fix-SculkCatalyst-exp-skip.patch b/leaves-server/paper-patches/features/0014-Fix-SculkCatalyst-exp-skip.patch index 9bc7ce82..5fecf9d9 100644 --- a/leaves-server/paper-patches/features/0014-Fix-SculkCatalyst-exp-skip.patch +++ b/leaves-server/paper-patches/features/0014-Fix-SculkCatalyst-exp-skip.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SculkCatalyst exp skip diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d74ce689380246eb176596f5905275fa5187aace..4e456eb1740a674eaf4e2ed37c16f6aa4714b11a 100644 +index 250a7d5427fc59478d8a540cfb2319939a489e65..3697a98306601030a0c717fb46823aa976d411c0 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -862,7 +862,7 @@ public class CraftEventFactory { +@@ -848,7 +848,7 @@ public class CraftEventFactory { CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource); CraftWorld world = (CraftWorld) entity.getWorld(); @@ -17,7 +17,7 @@ index d74ce689380246eb176596f5905275fa5187aace..4e456eb1740a674eaf4e2ed37c16f6aa populateFields(victim, event); // Paper - make cancellable Bukkit.getServer().getPluginManager().callEvent(event); -@@ -873,6 +873,7 @@ public class CraftEventFactory { +@@ -859,6 +859,7 @@ public class CraftEventFactory { playDeathSound(victim, event, damageSource); // Paper end victim.expToDrop = event.getDroppedExp(); @@ -25,7 +25,7 @@ index d74ce689380246eb176596f5905275fa5187aace..4e456eb1740a674eaf4e2ed37c16f6aa lootCheck.run(); // Paper - advancement triggers before destroying items // Paper start - Restore vanilla drops behavior -@@ -912,6 +913,7 @@ public class CraftEventFactory { +@@ -898,6 +899,7 @@ public class CraftEventFactory { victim.newLevel = event.getNewLevel(); victim.newTotalExp = event.getNewTotalExp(); victim.expToDrop = event.getDroppedExp(); diff --git a/leaves-server/paper-patches/features/0015-Leaves-Config-API.patch b/leaves-server/paper-patches/features/0015-Leaves-Config-API.patch index f4c98cdf..e6c2af56 100644 --- a/leaves-server/paper-patches/features/0015-Leaves-Config-API.patch +++ b/leaves-server/paper-patches/features/0015-Leaves-Config-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaves Config API diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 9dd48f07c9c8799623074d153eca6ee7f9ac6e49..193b56ecf6757279b0f950b7818aaa560b3b2ee3 100644 +index 8481618e09ed02afa04393a36c384237d0cca59d..9504f84d4a75419bc5551534ce7914f9a33c09f9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -3225,4 +3225,11 @@ public final class CraftServer implements Server { +@@ -3001,4 +3001,11 @@ public final class CraftServer implements Server { return internalBytebufHandler; } // Leaves end - Bytebuf API diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 3ba74ebc..febef2d9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -6,17 +6,17 @@ import net.kyori.adventure.text.Component; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; -import org.bukkit.command.Command; +import org.bukkit.Bukkit; import org.bukkit.configuration.MemorySection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginManager; import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.bot.BotCommand; +import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.Actions; -import org.leavesmc.leaves.command.LeavesCommand; +import org.leavesmc.leaves.command.bot.BotCommand; +import org.leavesmc.leaves.command.leaves.LeavesCommand; import org.leavesmc.leaves.config.GlobalConfigManager; import org.leavesmc.leaves.config.annotations.GlobalConfig; import org.leavesmc.leaves.config.annotations.GlobalConfigCategory; @@ -53,10 +53,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.Random; import java.util.function.Predicate; +@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"}) public final class LeavesConfig { public static final String CONFIG_HEADER = "Configuration file for Leaves."; @@ -93,7 +93,7 @@ public final class LeavesConfig { GlobalConfigManager.init(); - registerCommand("leaves", new LeavesCommand()); + LeavesCommand.INSTANCE.register(); } public static void reload() { @@ -119,18 +119,6 @@ public final class LeavesConfig { } } - public static void registerCommand(String name, Command command) { - MinecraftServer.getServer().server.getCommandMap().register(name, "leaves", command); - MinecraftServer.getServer().server.syncCommands(); - } - - public static void unregisterCommand(String name) { - name = name.toLowerCase(Locale.ENGLISH).trim(); - MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove(name); - MinecraftServer.getServer().server.getCommandMap().getKnownCommands().remove("leaves:" + name); - MinecraftServer.getServer().server.syncCommands(); - } - public static ModifyConfig modify = new ModifyConfig(); @GlobalConfigCategory("modify") @@ -148,11 +136,13 @@ public final class LeavesConfig { private static class FakeplayerValidator extends BooleanConfigValidator { @Override public void verify(Boolean old, Boolean value) throws IllegalArgumentException { - if (value) { - registerCommand("bot", new BotCommand()); - Actions.registerAll(); - } else { - unregisterCommand("bot"); + if (!value.equals(old)) { + if (value) { + BotCommand.INSTANCE.register(); + } else { + BotCommand.INSTANCE.unregister(); + BotList.INSTANCE.removeAll(); + } } } } @@ -188,15 +178,50 @@ public final class LeavesConfig { @GlobalConfig("open-fakeplayer-inventory") public boolean canOpenInventory = false; - @GlobalConfig("use-action") + @GlobalConfig(value = "use-action", validator = CanUseConfigValidator.class) public boolean canUseAction = true; - @GlobalConfig("modify-config") + private static class CanUseConfigValidator extends BotSubcommandValidator { + private CanUseConfigValidator() { + super("use"); + } + } + + @GlobalConfig(value = "modify-config", validator = CanModifyConfigValidator.class) public boolean canModifyConfig = false; - @GlobalConfig("manual-save-and-load") + private static class CanModifyConfigValidator extends BotSubcommandValidator { + private CanModifyConfigValidator() { + super("config"); + } + } + + @GlobalConfig(value = "manual-save-and-load", validator = CanManualSaveAndLoadValidator.class) public boolean canManualSaveAndLoad = false; + private static class CanManualSaveAndLoadValidator extends BotSubcommandValidator { + private CanManualSaveAndLoadValidator() { + super("save", "load"); + } + } + + private static class BotSubcommandValidator extends BooleanConfigValidator { + private final List subcommands; + + private BotSubcommandValidator(String... subcommand) { + this.subcommands = List.of(subcommand); + } + + @Override + public void verify(Boolean old, Boolean value) throws IllegalArgumentException { + if (old != null && !old.equals(value)) { + Bukkit.getOnlinePlayers().stream() + .filter(sender -> subcommands.stream().allMatch(subcommand -> BotCommand.hasPermission(sender, subcommand))) + .forEach(org.bukkit.entity.Player::updateCommands); + } + } + } + @GlobalConfig(value = "cache-skin", lock = true) public boolean useSkinCache = false; @@ -280,6 +305,7 @@ public final class LeavesConfig { @GlobalConfig("shears-in-dispenser-can-zero-amount") public boolean shearsInDispenserCanZeroAmount = false; + @SuppressWarnings("unused") @GlobalConfig(value = "villager-infinite-discounts", validator = VillagerInfiniteDiscountsValidator.class) private boolean villagerInfiniteDiscounts = false; @@ -397,6 +423,9 @@ public final class LeavesConfig { @GlobalConfig("ender-dragon-part-can-use-end-portal") public boolean enderDragonPartCanUseEndPortal = false; + + @GlobalConfig("old-minecart-motion-behavior") + public boolean oldMinecartMotionBehavior = false; } public ElytraAeronauticsConfig elytraAeronautics = new ElytraAeronauticsConfig(); @@ -634,9 +663,20 @@ public final class LeavesConfig { } } - @GlobalConfig(value = "no-block-update-command") + @GlobalConfig(value = "no-block-update-command", validator = NoBlockUpdateValidator.class) public boolean noBlockUpdateCommand = false; + private static class NoBlockUpdateValidator extends BooleanConfigValidator { + @Override + public void verify(Boolean old, Boolean value) throws IllegalArgumentException { + if (old != null && !old.equals(value)) { + Bukkit.getOnlinePlayers().stream() + .filter(sender -> LeavesCommand.hasPermission(sender, "blockupdate")) + .forEach(org.bukkit.entity.Player::updateCommands); + } + } + } + @GlobalConfig("no-tnt-place-update") public boolean noTNTPlaceUpdate = false; @@ -662,9 +702,20 @@ public final class LeavesConfig { public static class HopperCounterConfig { @TransferConfig(value = "modify.hopper-counter", transformer = HopperCounterTransfer.class) @TransferConfig("modify.counter.enable") - @GlobalConfig("enable") + @GlobalConfig(value = "enable", validator = HopperCounterValidator.class) public boolean enable = false; + private static class HopperCounterValidator extends BooleanConfigValidator { + @Override + public void verify(Boolean old, Boolean value) throws IllegalArgumentException { + if (old != null && !old.equals(value)) { + Bukkit.getOnlinePlayers().stream() + .filter(sender -> LeavesCommand.hasPermission(sender, "counter")) + .forEach(org.bukkit.entity.Player::updateCommands); + } + } + } + @TransferConfig("modify.counter.unlimited-speed") @GlobalConfig("unlimited-speed") public boolean unlimitedSpeed = false; @@ -716,6 +767,7 @@ public final class LeavesConfig { @GlobalConfig("disable-vault-blacklist") public boolean disableVaultBlacklist = false; + @SuppressWarnings("unused") @GlobalConfig(value = "exp-orb-absorb-mode", validator = ExpOrbModeValidator.class) private ExpOrbAbsorbMode expOrbAbsorbMode = ExpOrbAbsorbMode.VANILLA; @@ -735,6 +787,9 @@ public final class LeavesConfig { }; } } + + @GlobalConfig("follow-tick-sequence-merge") + public boolean followTickSequenceMerge = false; } public static PerformanceConfig performance = new PerformanceConfig(); @@ -1092,6 +1147,7 @@ public final class LeavesConfig { @GlobalConfig("login-protect") public boolean loginProtect = false; + @SuppressWarnings("unused") @GlobalConfig(value = "urls", lock = true, validator = ExtraYggdrasilUrlsValidator.class) private List serviceList = List.of("https://url.with.authlib-injector-yggdrasil"); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java deleted file mode 100644 index bf58ff5d..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.leavesmc.leaves.bot; - -import net.minecraft.Util; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.subcommands.BotActionCommand; -import org.leavesmc.leaves.bot.subcommands.BotConfigCommand; -import org.leavesmc.leaves.bot.subcommands.BotCreateCommand; -import org.leavesmc.leaves.bot.subcommands.BotListCommand; -import org.leavesmc.leaves.bot.subcommands.BotLoadCommand; -import org.leavesmc.leaves.bot.subcommands.BotRemoveCommand; -import org.leavesmc.leaves.bot.subcommands.BotSaveCommand; -import org.leavesmc.leaves.command.LeavesRootCommand; -import org.leavesmc.leaves.command.LeavesSubcommand; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public class BotCommand extends LeavesRootCommand { - - // subcommand label -> subcommand - private static final Map SUBCOMMANDS = Util.make(() -> { - final Map, LeavesSubcommand> commands = new HashMap<>(); - commands.put(Set.of("create"), new BotCreateCommand()); - commands.put(Set.of("remove"), new BotRemoveCommand()); - commands.put(Set.of("action"), new BotActionCommand()); - commands.put(Set.of("config"), new BotConfigCommand()); - commands.put(Set.of("save"), new BotSaveCommand()); - commands.put(Set.of("load"), new BotLoadCommand()); - commands.put(Set.of("list"), new BotListCommand()); - - return commands.entrySet().stream() - .flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue()))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - }); - - public BotCommand() { - super("bot", "FakePlayer Command", "bukkit.command.bot", SUBCOMMANDS); - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.enable; - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCreateState.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCreateState.java index 65e116fa..2fb51266 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCreateState.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotCreateState.java @@ -16,7 +16,7 @@ import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; import java.util.Objects; import java.util.function.Consumer; -public record BotCreateState(String realName, String name, String skinName, String[] skin, Location location, BotCreateEvent.CreateReason createReason, CommandSender creator) { +public record BotCreateState(String rawName, String fullName, String skinName, String[] skin, Location location, BotCreateEvent.CreateReason createReason, CommandSender creator) { private static final MinecraftServer server = MinecraftServer.getServer(); @@ -25,15 +25,15 @@ public record BotCreateState(String realName, String name, String skinName, Stri } @NotNull - public static Builder builder(@NotNull String realName, @Nullable Location location) { - return new Builder(realName, location); + public static Builder builder(@NotNull String rawName, @Nullable Location location) { + return new Builder(rawName, location); } public static class Builder implements BotCreator { - private final String realName; + private final String rawName; // For internal calculation, use it as little as possible - private String name; + private String fullName; private Location location; private String skinName; @@ -42,14 +42,14 @@ public record BotCreateState(String realName, String name, String skinName, Stri private BotCreateEvent.CreateReason createReason; private CommandSender creator; - private Builder(@NotNull String realName, @Nullable Location location) { - Objects.requireNonNull(realName); + private Builder(@NotNull String rawName, @Nullable Location location) { + Objects.requireNonNull(rawName); - this.realName = realName; + this.rawName = rawName; this.location = location; - this.name = LeavesConfig.modify.fakeplayer.prefix + realName + LeavesConfig.modify.fakeplayer.suffix; - this.skinName = this.realName; + this.fullName = BotUtil.getFullName(rawName); + this.skinName = this.rawName; this.skin = null; this.createReason = BotCreateEvent.CreateReason.UNKNOWN; this.creator = null; @@ -57,7 +57,7 @@ public record BotCreateState(String realName, String name, String skinName, Stri public Builder name(@NotNull String name) { Objects.requireNonNull(name); - this.name = name; + this.fullName = name; return this; } @@ -95,7 +95,7 @@ public record BotCreateState(String realName, String name, String skinName, Stri } public BotCreateState build() { - return new BotCreateState(realName, name, skinName, skin, location, createReason, creator); + return new BotCreateState(rawName, fullName, skinName, skin, location, createReason, creator); } public void spawnWithSkin(Consumer consumer) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java index a23420ab..7cde7139 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotDataStorage.java @@ -19,10 +19,7 @@ import java.io.File; import java.io.IOException; import java.util.Optional; -public class BotDataStorage implements IPlayerDataStorage { - - private static final LevelResource BOT_DATA_DIR = new LevelResource("fakeplayerdata"); - private static final LevelResource BOT_LIST_FILE = new LevelResource("fakeplayer.dat"); +public class BotDataStorage { private static final Logger LOGGER = LogUtils.getLogger(); private final File botDir; @@ -30,9 +27,9 @@ public class BotDataStorage implements IPlayerDataStorage { private CompoundTag savedBotList; - public BotDataStorage(LevelStorageSource.@NotNull LevelStorageAccess session) { - this.botDir = session.getLevelPath(BOT_DATA_DIR).toFile(); - this.botListFile = session.getLevelPath(BOT_LIST_FILE).toFile(); + public BotDataStorage(LevelStorageSource.@NotNull LevelStorageAccess session, String dataDir, String listFileName) { + this.botDir = session.getLevelPath(new LevelResource(dataDir)).toFile(); + this.botListFile = session.getLevelPath(new LevelResource(listFileName)).toFile(); this.botDir.mkdirs(); this.savedBotList = new CompoundTag(); @@ -45,7 +42,6 @@ public class BotDataStorage implements IPlayerDataStorage { } } - @Override public void save(Player player) { boolean flag = true; try { @@ -68,23 +64,27 @@ public class BotDataStorage implements IPlayerDataStorage { if (flag && player instanceof ServerBot bot) { CompoundTag nbt = new CompoundTag(); - nbt.putString("name", bot.createState.name()); + nbt.putString("name", bot.createState.fullName()); nbt.store("uuid", UUIDUtil.CODEC, bot.getUUID()); nbt.putBoolean("resume", bot.resume); - this.savedBotList.put(bot.createState.realName(), nbt); + this.savedBotList.put(bot.createState.fullName(), nbt); this.saveBotList(); } } - @Override - public Optional load(Player player, ProblemReporter reporter) { - return this.load(player.getScoreboardName(), player.getStringUUID()).map(nbt -> { - ValueInput valueInput = TagValueInput.create(reporter, player.registryAccess(), nbt); - player.load(valueInput); + + public Optional load(@NotNull ServerBot bot, ProblemReporter reporter) { + return this.load(bot.nameAndId().name(), bot.nameAndId().id().toString()).map(nbt -> { + ValueInput valueInput = TagValueInput.create(reporter, bot.registryAccess(), nbt); + bot.load(valueInput); return valueInput; }); } + public void removeSavedData(@NotNull ServerBot bot) { + this.load(bot.nameAndId().name(), bot.nameAndId().id().toString()); + } + private Optional load(String name, String uuid) { File file = new File(this.botDir, uuid + ".dat"); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java index 9a7ba737..a372a18c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java @@ -5,6 +5,7 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import com.mojang.logging.LogUtils; import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.profile.MutablePropertyMap; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; import net.minecraft.nbt.CompoundTag; @@ -26,6 +27,7 @@ import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.event.entity.EntityRemoveEvent; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesConfig; @@ -54,21 +56,33 @@ public class BotList { private final MinecraftServer server; public final List bots = new CopyOnWriteArrayList<>(); - private final BotDataStorage dataStorage; + private final BotDataStorage manualSaveDataStorage; + private final BotDataStorage resumeDataStorage; private final Map botsByUUID = Maps.newHashMap(); private final Map botsByName = Maps.newHashMap(); private final Map> botsNameByWorldUuid = Maps.newHashMap(); + private final Map> legacyBotsNameByWorldUuid = Maps.newHashMap(); - public BotList(MinecraftServer server) { + public BotList(@NotNull MinecraftServer server) { this.server = server; - this.dataStorage = new BotDataStorage(server.storageSource); + this.manualSaveDataStorage = new BotDataStorage(server.storageSource, "fakeplayerdata", "fakeplayer.dat"); + this.resumeDataStorage = new BotDataStorage(server.storageSource, "resume_fakeplayerdata", "resume_fakeplayer.dat"); INSTANCE = this; } - public ServerBot createNewBot(BotCreateState state) { - BotCreateEvent event = new BotCreateEvent(state.name(), state.skinName(), state.location(), state.createReason(), state.creator()); - event.setCancelled(!BotUtil.isCreateLegal(state.name())); + public void saveAllResumeBots() { + if (!LeavesConfig.modify.fakeplayer.enable || !LeavesConfig.modify.fakeplayer.canResident) { + return; + } + for (ServerBot bot : this.bots) { + this.resumeDataStorage.save(bot); + } + } + + public ServerBot createNewBot(@NotNull BotCreateState state) { + BotCreateEvent event = new BotCreateEvent(state.fullName(), state.skinName(), state.location(), state.createReason(), state.creator()); + event.setCancelled(!BotUtil.isCreateLegal(state.fullName())); this.server.server.getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -78,7 +92,7 @@ public class BotList { Location location = event.getCreateLocation(); ServerLevel world = ((CraftWorld) location.getWorld()).getHandle(); - CustomGameProfile profile = new CustomGameProfile(BotUtil.getBotUUID(state), state.name(), state.skin()); + GameProfile profile = createBotProfile(BotUtil.getBotUUID(state), state.fullName(), state.skin()); ServerBot bot = new ServerBot(this.server, world, profile); bot.createState = state; if (event.getCreator() instanceof org.bukkit.entity.Player player) { @@ -88,46 +102,55 @@ public class BotList { return this.placeNewBot(bot, world, location, null); } - public ServerBot loadNewBot(String realName) { - return this.loadNewBot(realName, this.dataStorage); + public ServerBot loadNewManualSavedBot(String fullName) { + return this.loadNewBot(fullName, this.manualSaveDataStorage); } - public ServerBot loadNewBot(String realName, IPlayerDataStorage playerIO) { - UUID uuid = BotUtil.getBotUUID(realName); + public ServerBot loadNewResumeBot(String fullName) { + return this.loadNewBot(fullName, this.resumeDataStorage); + } - BotLoadEvent event = new BotLoadEvent(realName, uuid); - this.server.server.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return null; - } + public ServerBot loadNewBot(String fullName, BotDataStorage storage) { + try { + UUID uuid = BotUtil.getBotUUID(fullName); - ServerBot bot = new ServerBot(this.server, this.server.getLevel(Level.OVERWORLD), new GameProfile(uuid, realName)); - bot.connection = new ServerBotPacketListenerImpl(this.server, bot); - Optional optional; - try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(bot.problemPath(), LOGGER)) { - optional = playerIO.load(bot, scopedCollector); - } catch (Exception e) { - throw new RuntimeException(e); - } - - if (optional.isEmpty()) { - return null; - } - ValueInput nbt = optional.get(); - - ResourceKey resourcekey = null; - if (nbt.getLong("WorldUUIDMost").isPresent() && nbt.getLong("WorldUUIDLeast").isPresent()) { - org.bukkit.World bWorld = Bukkit.getServer().getWorld(new UUID(nbt.getLong("WorldUUIDMost").orElseThrow(), nbt.getLong("WorldUUIDLeast").orElseThrow())); - if (bWorld != null) { - resourcekey = ((CraftWorld) bWorld).getHandle().dimension(); + BotLoadEvent event = new BotLoadEvent(fullName, uuid); + this.server.server.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return null; } - } - if (resourcekey == null) { + + ServerBot bot = new ServerBot(this.server, this.server.getLevel(Level.OVERWORLD), new GameProfile(uuid, fullName)); + bot.connection = new ServerBotPacketListenerImpl(this.server, bot); + Optional optional; + try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(bot.problemPath(), LOGGER)) { + optional = storage.load(bot, scopedCollector); + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (optional.isEmpty()) { + return null; + } + ValueInput nbt = optional.get(); + + ResourceKey resourcekey = null; + if (nbt.getLong("WorldUUIDMost").isPresent() && nbt.getLong("WorldUUIDLeast").isPresent()) { + org.bukkit.World bWorld = Bukkit.getServer().getWorld(new UUID(nbt.getLong("WorldUUIDMost").orElseThrow(), nbt.getLong("WorldUUIDLeast").orElseThrow())); + if (bWorld != null) { + resourcekey = ((CraftWorld) bWorld).getHandle().dimension(); + } + } + if (resourcekey == null) { + return null; + } + + ServerLevel world = this.server.getLevel(resourcekey); + return this.placeNewBot(bot, world, bot.getLocation(), nbt); + } catch (Exception e) { + LOGGER.error("Failed to load bot {}", fullName, e); return null; } - - ServerLevel world = this.server.getLevel(resourcekey); - return this.placeNewBot(bot, world, bot.getLocation(), nbt); } public ServerBot placeNewBot(@NotNull ServerBot bot, ServerLevel world, Location location, ValueInput save) { @@ -154,7 +177,7 @@ public class BotList { this.botsByName.put(bot.getScoreboardName().toLowerCase(Locale.ROOT), bot); this.botsByUUID.put(bot.getUUID(), bot); - bot.supressTrackerForLogin = true; + bot.suppressTrackerForLogin = true; world.addNewPlayer(bot); optional.ifPresent(nbt -> { bot.loadAndSpawnEnderPearls(nbt); @@ -170,28 +193,24 @@ public class BotList { } bot.renderInfo(); - bot.supressTrackerForLogin = false; + bot.suppressTrackerForLogin = false; bot.level().getChunkSource().chunkMap.addEntity(bot); bot.renderData(); bot.initInventoryMenu(); botsNameByWorldUuid .computeIfAbsent(bot.level().uuid.toString(), (k) -> new HashSet<>()) - .add(bot.getBukkitEntity().getRealName()); + .add(bot.getBukkitEntity().getName()); BotList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", bot.getName().getString(), "Local", bot.getId(), bot.level().serverLevelData.getLevelName(), bot.getX(), bot.getY(), bot.getZ()); return bot; } - public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveReason reason, @Nullable CommandSender remover, boolean saved) { - return this.removeBot(bot, reason, remover, saved, this.dataStorage); - } - - public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveReason reason, @Nullable CommandSender remover, boolean saved, IPlayerDataStorage playerIO) { - BotRemoveEvent event = new BotRemoveEvent(bot.getBukkitEntity(), reason, remover, PaperAdventure.asAdventure(Component.translatable("multiplayer.player.left", bot.getDisplayName())).style(Style.style(NamedTextColor.YELLOW)), saved); + public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveReason reason, @Nullable CommandSender remover, boolean save, boolean resume) { + BotRemoveEvent event = new BotRemoveEvent(bot.getBukkitEntity(), reason, remover, PaperAdventure.asAdventure(Component.translatable("multiplayer.player.left", bot.getDisplayName())).style(Style.style(NamedTextColor.YELLOW)), save); this.server.server.getPluginManager().callEvent(event); if (event.isCancelled() && event.getReason() != BotRemoveEvent.RemoveReason.INTERNAL) { - return true; + return false; } if (bot.removeTaskId != -1) { @@ -201,11 +220,16 @@ public class BotList { bot.disconnect(); + this.resumeDataStorage.removeSavedData(bot); if (event.shouldSave()) { - playerIO.save(bot); + if (resume) { + this.resumeDataStorage.save(bot); + } else { + this.manualSaveDataStorage.save(bot); + } } else { bot.dropAll(true); - botsNameByWorldUuid.getOrDefault(bot.level().uuid.toString(), new HashSet<>()).remove(bot.getBukkitEntity().getRealName()); + botsNameByWorldUuid.getOrDefault(bot.level().uuid.toString(), new HashSet<>()).remove(bot.getBukkitEntity().getName()); } if (bot.isPassenger() && event.shouldSave()) { @@ -259,10 +283,10 @@ public class BotList { } public void removeAllIn(String worldUuid) { - for (String realName : this.botsNameByWorldUuid.getOrDefault(worldUuid, new HashSet<>())) { - ServerBot bot = this.getBotByName(realName); + for (String fullName : this.botsNameByWorldUuid.getOrDefault(worldUuid, new HashSet<>())) { + ServerBot bot = this.getBotByName(fullName); if (bot != null) { - this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, LeavesConfig.modify.fakeplayer.canResident); + this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, LeavesConfig.modify.fakeplayer.canResident, LeavesConfig.modify.fakeplayer.canResident); } } } @@ -270,28 +294,43 @@ public class BotList { public void removeAll() { for (ServerBot bot : this.bots) { bot.resume = LeavesConfig.modify.fakeplayer.canResident; - this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, LeavesConfig.modify.fakeplayer.canResident); + this.removeBot(bot, BotRemoveEvent.RemoveReason.INTERNAL, null, LeavesConfig.modify.fakeplayer.canResident, LeavesConfig.modify.fakeplayer.canResident); } } - public void loadBotInfo() { + public void loadResumeBotInfo() { if (!LeavesConfig.modify.fakeplayer.enable || !LeavesConfig.modify.fakeplayer.canResident) { return; } - CompoundTag savedBotList = this.getSavedBotList().copy(); - for (String realName : savedBotList.keySet()) { - CompoundTag nbt = savedBotList.getCompound(realName).orElseThrow(); - if (!nbt.getBoolean("resume").orElse(false)) { - continue; - } - UUID levelUuid = BotUtil.getBotLevel(realName, this.dataStorage); + CompoundTag savedBotList = this.getResumeBotList().copy(); + for (String fullName : savedBotList.keySet()) { + UUID levelUuid = BotUtil.getBotLevel(fullName, this.resumeDataStorage); if (levelUuid == null) { - LOGGER.warn("Bot {} has no world UUID, skipping loading.", realName); + LOGGER.warn("Bot {} has no world UUID, skipping loading.", fullName); continue; } this.botsNameByWorldUuid .computeIfAbsent(levelUuid.toString(), (k) -> new HashSet<>()) - .add(realName); + .add(fullName); + } + loadLegacyResumeBotInfo(); + } + + private void loadLegacyResumeBotInfo() { + CompoundTag savedBotList = this.getManualSavedBotList().copy(); + for (String fullName : savedBotList.keySet()) { + CompoundTag nbt = savedBotList.getCompound(fullName).orElseThrow(); + if (!nbt.getBoolean("resume").orElse(false)) { + continue; + } + UUID levelUuid = BotUtil.getBotLevel(fullName, this.manualSaveDataStorage); + if (levelUuid == null) { + LOGGER.warn("Bot {} has no world UUID, skipping loading.", fullName); + continue; + } + this.legacyBotsNameByWorldUuid + .computeIfAbsent(levelUuid.toString(), (k) -> new HashSet<>()) + .add(fullName); } } @@ -299,23 +338,19 @@ public class BotList { if (!LeavesConfig.modify.fakeplayer.enable || !LeavesConfig.modify.fakeplayer.canResident) { return; } - Set bots = this.botsNameByWorldUuid.get(worldUuid); - if (bots == null) { - return; - } - Set botsCopy = new HashSet<>(bots); - botsCopy.forEach(this::loadNewBot); + new HashSet<>(this.botsNameByWorldUuid.getOrDefault(worldUuid, new HashSet<>())).forEach(this::loadNewResumeBot); + new HashSet<>(this.legacyBotsNameByWorldUuid.getOrDefault(worldUuid, new HashSet<>())).forEach(this::loadNewManualSavedBot); } - public void updateBotLevel(ServerBot bot, ServerLevel level) { + public void updateBotLevel(@NotNull ServerBot bot, @NotNull ServerLevel level) { String prevUuid = bot.level().uuid.toString(); String newUuid = level.uuid.toString(); this.botsNameByWorldUuid .computeIfAbsent(newUuid, (k) -> new HashSet<>()) - .add(bot.getBukkitEntity().getRealName()); + .add(bot.getBukkitEntity().getName()); this.botsNameByWorldUuid .computeIfAbsent(prevUuid, (k) -> new HashSet<>()) - .remove(bot.getBukkitEntity().getRealName()); + .remove(bot.getBukkitEntity().getName()); } public void networkTick() { @@ -332,21 +367,25 @@ public class BotList { return this.botsByName.get(name.toLowerCase(Locale.ROOT)); } - public CompoundTag getSavedBotList() { - return this.dataStorage.getSavedBotList(); + public CompoundTag getManualSavedBotList() { + return this.getSavedBotList(this.manualSaveDataStorage); } - public static class CustomGameProfile extends GameProfile { + public CompoundTag getResumeBotList() { + return this.getSavedBotList(this.resumeDataStorage); + } - public CustomGameProfile(UUID uuid, String name, String[] skin) { - super(uuid, name); - this.setSkin(skin); - } + public CompoundTag getSavedBotList(@NotNull BotDataStorage storage) { + return storage.getSavedBotList(); + } - public void setSkin(String[] skin) { - if (skin != null) { - this.getProperties().put("textures", new Property("textures", skin[0], skin[1])); - } + @Contract("_, _, _ -> new") + public static @NotNull GameProfile createBotProfile(UUID uuid, String name, String[] skin) { + GameProfile profile = new GameProfile(uuid, name, new MutablePropertyMap()); + profile.properties().put("is_bot", new Property("is_bot", "true")); + if (skin != null) { + profile.properties().put("textures", new Property("textures", skin[0], skin[1])); } + return profile; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java index 763dd1fb..e49bbafd 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotUtil.java @@ -68,15 +68,15 @@ public class BotUtil { @NotNull public static UUID getBotUUID(@NotNull BotCreateState state) { - return getBotUUID(state.realName()); + return getBotUUID(state.fullName()); } - public static UUID getBotUUID(@NotNull String realName) { - return UUID.nameUUIDFromBytes(("Fakeplayer:" + realName).getBytes(Charsets.UTF_8)); + public static UUID getBotUUID(@NotNull String fullName) { + return UUID.nameUUIDFromBytes(("Fakeplayer:" + fullName).getBytes(Charsets.UTF_8)); } - public static UUID getBotLevel(@NotNull String realName, BotDataStorage botDataStorage) { - UUID uuid = BotUtil.getBotUUID(realName); + public static UUID getBotLevel(@NotNull String fullName, BotDataStorage botDataStorage) { + UUID uuid = getBotUUID(fullName); Optional tagOptional = botDataStorage.read(uuid.toString()); if (tagOptional.isEmpty()) { return null; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/IPlayerDataStorage.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/IPlayerDataStorage.java deleted file mode 100644 index 614fb645..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/IPlayerDataStorage.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.leavesmc.leaves.bot; - -import net.minecraft.util.ProblemReporter; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.storage.ValueInput; - -import java.util.Optional; - -public interface IPlayerDataStorage { - - void save(Player player); - - Optional load(Player player, ProblemReporter reporter); -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java index 159a0384..2dae7096 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java @@ -59,10 +59,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.LeavesLogger; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; import org.leavesmc.leaves.bot.agent.Actions; import org.leavesmc.leaves.bot.agent.Configs; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; +import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; import org.leavesmc.leaves.entity.bot.CraftBot; import org.leavesmc.leaves.event.bot.BotActionScheduleEvent; import org.leavesmc.leaves.event.bot.BotCreateEvent; @@ -81,10 +81,12 @@ import java.util.Objects; import java.util.UUID; import java.util.function.Predicate; +import static net.minecraft.server.MinecraftServer.getServer; + public class ServerBot extends ServerPlayer { - private final List> actions; - private final Map, AbstractBotConfig> configs; + private final List> actions; + private final Map> configs; public boolean resume = false; public BotCreateState createState; @@ -106,9 +108,9 @@ public class ServerBot extends ServerPlayer { this.gameMode = new ServerBotGameMode(this); this.actions = new ArrayList<>(); - ImmutableMap.Builder, AbstractBotConfig> configBuilder = ImmutableMap.builder(); - for (Configs config : Configs.getConfigs()) { - configBuilder.put(config, config.createConfig(this)); + ImmutableMap.Builder> configBuilder = ImmutableMap.builder(); + for (AbstractBotConfig config : Configs.getConfigs()) { + configBuilder.put(config.getName(), config.create().setBot(this)); } this.configs = configBuilder.build(); @@ -199,7 +201,7 @@ public class ServerBot extends ServerPlayer { this.notSleepTicks = 0; } - if (!this.level().isClientSide && this.level().isBrightOutside()) { + if (!this.level().isClientSide() && this.level().isBrightOutside()) { this.stopSleepInBed(false, true); } } else if (this.sleepCounter > 0) { @@ -212,7 +214,7 @@ public class ServerBot extends ServerPlayer { this.updateIsUnderwater(); if (this.getConfigValue(Configs.TICK_TYPE) == TickType.NETWORK) { - this.getServer().scheduleOnMain(this::runAction); + getServer().scheduleOnMain(this::runAction); } this.livingEntityTick(); @@ -350,7 +352,7 @@ public class ServerBot extends ServerPlayer { if (LeavesConfig.modify.fakeplayer.canOpenInventory) { if (player instanceof ServerPlayer player1 && player.getMainHandItem().isEmpty()) { BotInventoryOpenEvent event = new BotInventoryOpenEvent(this.getBukkitEntity(), player1.getBukkitEntity()); - this.getServer().server.getPluginManager().callEvent(event); + getServer().server.getPluginManager().callEvent(event); if (!event.isCancelled()) { player.openMenu(new SimpleMenuProvider((i, inventory, p) -> ChestMenu.sixRows(i, inventory, this.container), this.getDisplayName())); return InteractionResult.SUCCESS; @@ -372,8 +374,8 @@ public class ServerBot extends ServerPlayer { nbt.putBoolean("isShiftKeyDown", this.isShiftKeyDown()); CompoundTag createNbt = new CompoundTag(); - createNbt.putString("realName", this.createState.realName()); - createNbt.putString("name", this.createState.name()); + createNbt.putString("rawName", this.createState.rawName()); + createNbt.putString("name", this.createState.fullName()); createNbt.putString("skinName", this.createState.skinName()); if (this.createState.skin() != null) { @@ -388,14 +390,14 @@ public class ServerBot extends ServerPlayer { if (!this.actions.isEmpty()) { ValueOutput.TypedOutputList actionNbt = nbt.list("actions", CompoundTag.CODEC); - for (ServerBotAction action : this.actions) { + for (AbstractBotAction action : this.actions) { actionNbt.add(action.save(new CompoundTag())); } } if (!this.configs.isEmpty()) { ValueOutput.TypedOutputList configNbt = nbt.list("configs", CompoundTag.CODEC); - for (AbstractBotConfig config : this.configs.values()) { + for (AbstractBotConfig config : this.configs.values()) { configNbt.add(config.save(new CompoundTag())); } } @@ -407,7 +409,11 @@ public class ServerBot extends ServerPlayer { this.setShiftKeyDown(nbt.getBooleanOr("isShiftKeyDown", false)); CompoundTag createNbt = nbt.read("createStatus", CompoundTag.CODEC).orElseThrow(); - BotCreateState.Builder createBuilder = BotCreateState.builder(createNbt.getString("realName").orElseThrow(), null).name(createNbt.getString("name").orElseThrow()); + BotCreateState.Builder createBuilder = BotCreateState + .builder(createNbt.getString("rawName") + .orElseGet(() -> createNbt.getString("realName") + .orElseThrow()), null) // Convert from legacy version, consider to use ca.spottedleaf.dataconverter.minecraft.MCDataConverter instead for release version + .name(createNbt.getString("name").orElseThrow()); String[] skin = null; if (createNbt.contains("skin")) { @@ -422,15 +428,15 @@ public class ServerBot extends ServerPlayer { createBuilder.createReason(BotCreateEvent.CreateReason.INTERNAL).creator(null); this.createState = createBuilder.build(); - this.gameProfile = new BotList.CustomGameProfile(this.getUUID(), this.createState.name(), this.createState.skin()); + this.gameProfile = BotList.createBotProfile(this.getUUID(), this.createState.fullName(), this.createState.skin()); if (nbt.list("actions", CompoundTag.CODEC).isPresent()) { ValueInput.TypedInputList actionNbt = nbt.list("actions", CompoundTag.CODEC).orElseThrow(); actionNbt.forEach(actionTag -> { - ServerBotAction action = Actions.getForName(actionTag.getString("actionName").orElseThrow()); + AbstractBotAction action = Actions.getForName(actionTag.getString("actionName").orElseThrow()); if (action != null) { - ServerBotAction newAction = action.create(); + AbstractBotAction newAction = action.create(); newAction.load(actionTag); this.actions.add(newAction); } @@ -440,9 +446,10 @@ public class ServerBot extends ServerPlayer { if (nbt.list("configs", CompoundTag.CODEC).isPresent()) { ValueInput.TypedInputList configNbt = nbt.list("configs", CompoundTag.CODEC).orElseThrow(); for (CompoundTag configTag : configNbt) { - Configs configKey = Configs.getConfig(configTag.getString("configName").orElseThrow()); - if (configKey != null) { - this.configs.get(configKey).load(configTag); + AbstractBotConfig config = Configs.getConfig(configTag.getString("configName").orElseThrow()); + if (config != null) { + config.setBot(this); + config.load(configTag); } } } @@ -479,17 +486,17 @@ public class ServerBot extends ServerPlayer { } public void renderInfo() { - this.getServer().getPlayerList().getPlayers().forEach(this::sendPlayerInfo); + getServer().getPlayerList().getPlayers().forEach(this::sendPlayerInfo); } public void renderData() { - this.getServer().getPlayerList().getPlayers().forEach( + getServer().getPlayerList().getPlayers().forEach( player -> this.sendFakeDataIfNeed(player, false) ); } private void sendPacket(Packet packet) { - this.getServer().getPlayerList().getPlayers().forEach(player -> player.connection.send(packet)); + getServer().getPlayerList().getPlayers().forEach(player -> player.connection.send(packet)); } @Override @@ -498,7 +505,7 @@ public class ServerBot extends ServerPlayer { Component defaultMessage = this.getCombatTracker().getDeathMessage(); BotDeathEvent event = new BotDeathEvent(this.getBukkitEntity(), PaperAdventure.asAdventure(defaultMessage), flag); - this.getServer().server.getPluginManager().callEvent(event); + getServer().server.getPluginManager().callEvent(event); if (event.isCancelled()) { if (this.getHealth() <= 0) { @@ -511,15 +518,20 @@ public class ServerBot extends ServerPlayer { net.kyori.adventure.text.Component deathMessage = event.deathMessage(); if (event.isSendDeathMessage() && deathMessage != null && !deathMessage.equals(net.kyori.adventure.text.Component.empty())) { - this.getServer().getPlayerList().broadcastSystemMessage(PaperAdventure.asVanilla(deathMessage), false); + getServer().getPlayerList().broadcastSystemMessage(PaperAdventure.asVanilla(deathMessage), false); } - this.getServer().getBotList().removeBot(this, BotRemoveEvent.RemoveReason.DEATH, null, false); + // TODO: separate die and remove logic, call super.die here + this.removeEntitiesOnShoulder(); + if (this.level().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) { + this.tellNeutralMobsThatIDied(); + } + getServer().getBotList().removeBot(this, BotRemoveEvent.RemoveReason.DEATH, null, false, false); } @Override - public boolean startRiding(@NotNull Entity vehicle, boolean force) { - if (super.startRiding(vehicle, force)) { + public boolean startRiding(@NotNull Entity vehicle, boolean force, boolean sendGameEvent) { + if (super.startRiding(vehicle, force, sendGameEvent)) { if (vehicle.getControllingPassenger() == this) { // see net.minecraft.server.networkServerGamePacketListenerImpl#handleMoveVehicle this.setDeltaMovement(Vec3.ZERO); this.setYRot(vehicle.yRotO); @@ -640,11 +652,11 @@ public class ServerBot extends ServerPlayer { private void runAction() { if (LeavesConfig.modify.fakeplayer.canUseAction) { this.actions.forEach(action -> action.tryTick(this)); - this.actions.removeIf(ServerBotAction::isCancelled); + this.actions.removeIf(AbstractBotAction::isCancelled); } } - public boolean addBotAction(ServerBotAction action, CommandSender sender) { + public boolean addBotAction(AbstractBotAction action, CommandSender sender) { if (!LeavesConfig.modify.fakeplayer.canUseAction) { return false; } @@ -658,7 +670,7 @@ public class ServerBot extends ServerPlayer { return true; } - public List> getBotActions() { + public List> getBotActions() { return actions; } @@ -669,11 +681,15 @@ public class ServerBot extends ServerPlayer { } @SuppressWarnings("unchecked") - public AbstractBotConfig getConfig(Configs config) { - return (AbstractBotConfig) Objects.requireNonNull(this.configs.get(config)); + public > AbstractBotConfig getConfig(@NotNull AbstractBotConfig config) { + return (AbstractBotConfig) Objects.requireNonNull(this.configs.get(config.getName())); } - public E getConfigValue(Configs config) { + public Collection> getAllConfigs() { + return configs.values(); + } + + public > T getConfigValue(@NotNull AbstractBotConfig config) { return this.getConfig(config).getValue(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java index bf16fe7f..c636ab69 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBotGameMode.java @@ -19,6 +19,8 @@ import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand.isNoBlockUpdate; + public class ServerBotGameMode extends ServerPlayerGameMode { public ServerBotGameMode(ServerBot bot) { @@ -62,7 +64,7 @@ public class ServerBotGameMode extends ServerPlayerGameMode { this.level.sendBlockUpdated(pos, blockState, blockState, 3); return false; } else { - BlockState blockState1 = org.leavesmc.leaves.command.subcommands.BlockUpdateCommand.isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update + BlockState blockState1 = isNoBlockUpdate() ? blockState : block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update boolean flag = this.level.removeBlock(pos, false); if (flag) { block.destroy(this.level, pos, blockState1); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotConfig.java deleted file mode 100644 index 4d85f5be..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/AbstractBotConfig.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.leavesmc.leaves.bot.agent; - -import net.minecraft.nbt.CompoundTag; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; - -import java.util.List; - -public abstract class AbstractBotConfig { - - private final String name; - private final CommandArgument argument; - - protected ServerBot bot; - - public AbstractBotConfig(String name, CommandArgument argument) { - this.name = name; - this.argument = argument; - } - - public AbstractBotConfig setBot(ServerBot bot) { - this.bot = bot; - return this; - } - - public abstract E getValue(); - - public abstract void setValue(E value) throws IllegalArgumentException; - - @SuppressWarnings("unchecked") - public void setFromCommand(@NotNull CommandArgumentResult result) throws IllegalArgumentException { - if (argument == CommandArgument.EMPTY) { - throw new IllegalArgumentException("No argument for " + this.getName()); - } - try { - this.setValue((E) result.read(argument.getArgumentTypes().getFirst().getType())); - } catch (ClassCastException e) { - throw new IllegalArgumentException("Invalid argument type for " + this.getName() + ": " + e.getMessage()); - } - } - - public List getMessage() { - return List.of(this.bot.getScoreboardName() + "'s " + this.getName() + ": " + this.getValue()); - } - - public List getChangeMessage() { - return List.of(this.bot.getScoreboardName() + "'s " + this.getName() + " changed: " + this.getValue()); - } - - public String getName() { - return name; - } - - public CommandArgument getArgument() { - return argument; - } - - @NotNull - public CompoundTag save(@NotNull CompoundTag nbt) { - nbt.putString("configName", this.name); - return nbt; - } - - public abstract void load(@NotNull CompoundTag nbt); -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java index 6b9cabc7..214165eb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Actions.java @@ -13,10 +13,10 @@ import java.util.Set; public class Actions { - private static final Map> actionsByName = new HashMap<>(); - private static final Map, ServerBotAction> actionsByClass = new HashMap<>(); + private static final Map> actionsByName = new HashMap<>(); + private static final Map, AbstractBotAction> actionsByClass = new HashMap<>(); - public static void registerAll() { + static { register(new ServerAttackAction(), AttackAction.class); register(new ServerBreakBlockAction(), BreakBlockAction.class); register(new ServerDropAction(), DropAction.class); @@ -38,7 +38,7 @@ public class Actions { register(new ServerSwapAction(), SwapAction.class); } - public static boolean register(@NotNull ServerBotAction action, Class> type) { + public static boolean register(@NotNull AbstractBotAction action, Class type) { if (!actionsByName.containsKey(action.getName())) { actionsByName.put(action.getName(), action); actionsByClass.put(type, action); @@ -47,14 +47,22 @@ public class Actions { return false; } + public static boolean register(@NotNull AbstractBotAction action) { + return register(action, action.getClass()); + } + public static boolean unregister(@NotNull String name) { - // TODO add in custom action api - return true; + AbstractBotAction action = actionsByName.remove(name); + if (action != null) { + actionsByClass.remove(action.getClass()); + return true; + } + return false; } @NotNull @Contract(pure = true) - public static Collection> getAll() { + public static Collection> getAll() { return actionsByName.values(); } @@ -64,12 +72,12 @@ public class Actions { } @Nullable - public static ServerBotAction getForName(String name) { + public static AbstractBotAction getForName(String name) { return actionsByName.get(name); } @Nullable - public static ServerBotAction getForClass(@NotNull Class type) { + public static AbstractBotAction getForClass(@NotNull Class type) { return actionsByClass.get(type); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java index 8608a262..602aff02 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java @@ -3,7 +3,7 @@ package org.leavesmc.leaves.bot.agent; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; import org.leavesmc.leaves.bot.agent.configs.AlwaysSendDataConfig; import org.leavesmc.leaves.bot.agent.configs.LocatorBarConfig; import org.leavesmc.leaves.bot.agent.configs.SimulationDistanceConfig; @@ -14,57 +14,35 @@ import org.leavesmc.leaves.bot.agent.configs.TickTypeConfig; import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.function.Supplier; -@SuppressWarnings("unused") -public class Configs { +@SuppressWarnings({"unused"}) +public class Configs { + private static final Map, AbstractBotConfig> configs = new HashMap<>(); - private static final Map> configs = new HashMap<>(); - - public static final Configs SKIP_SLEEP = register(SkipSleepConfig.class, SkipSleepConfig::new); - public static final Configs ALWAYS_SEND_DATA = register(AlwaysSendDataConfig.class, AlwaysSendDataConfig::new); - public static final Configs SPAWN_PHANTOM = register(SpawnPhantomConfig.class, SpawnPhantomConfig::new); - public static final Configs SIMULATION_DISTANCE = register(SimulationDistanceConfig.class, SimulationDistanceConfig::new); - public static final Configs TICK_TYPE = register(TickTypeConfig.class, TickTypeConfig::new); - public static final Configs ENABLE_LOCATOR_BAR = register(LocatorBarConfig.class, LocatorBarConfig::new); - - private final Class> configClass; - private final Supplier> configCreator; - - private Configs(Class> configClass, Supplier> configCreator) { - this.configClass = configClass; - this.configCreator = configCreator; - } - - public Class> getConfigClass() { - return configClass; - } - - public AbstractBotConfig createConfig(ServerBot bot) { - return configCreator.get().setBot(bot); - } + public static final SkipSleepConfig SKIP_SLEEP = register(new SkipSleepConfig()); + public static final AlwaysSendDataConfig ALWAYS_SEND_DATA = register(new AlwaysSendDataConfig()); + public static final SpawnPhantomConfig SPAWN_PHANTOM = register(new SpawnPhantomConfig()); + public static final SimulationDistanceConfig SIMULATION_DISTANCE = register(new SimulationDistanceConfig()); + public static final TickTypeConfig TICK_TYPE = register(new TickTypeConfig()); + public static final LocatorBarConfig ENABLE_LOCATOR_BAR = register(new LocatorBarConfig()); @Nullable - public static Configs getConfig(String name) { - return configs.get(name); + public static AbstractBotConfig getConfig(String name) { + return configs.values().stream() + .filter(config -> config.getName().equals(name)) + .findFirst() + .orElse(null); } @NotNull @Contract(pure = true) - public static Collection> getConfigs() { + public static Collection> getConfigs() { return configs.values(); } - @NotNull - @Contract(pure = true) - public static Collection getConfigNames() { - return configs.keySet(); - } - - @NotNull - private static Configs register(Class> configClass, Supplier> configCreator) { - Configs config = new Configs<>(configClass, configCreator); - configs.put(config.createConfig(null).getName(), config); - return config; + @SuppressWarnings("unchecked") + private static > @NotNull E register(AbstractBotConfig instance) { + configs.put(instance.getClass(), instance); + return (E) instance; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java new file mode 100644 index 00000000..46c852ab --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/ExtraData.java @@ -0,0 +1,11 @@ +package org.leavesmc.leaves.bot.agent; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.List; + +public record ExtraData(List> raw) { + public void add(String key, String value) { + raw.add(Pair.of(key, value)); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java similarity index 78% rename from leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java rename to leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java index 6d499951..8a67165c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractBotAction.java @@ -1,32 +1,36 @@ package org.leavesmc.leaves.bot.agent.actions; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.WrappedArgument; import org.leavesmc.leaves.event.bot.BotActionExecuteEvent; import org.leavesmc.leaves.event.bot.BotActionStopEvent; import org.leavesmc.leaves.util.UpdateSuppressionException; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; -import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; @SuppressWarnings("unchecked") -public abstract class ServerBotAction> { +public abstract class AbstractBotAction> { private final String name; - private final CommandArgument argument; + private final Map>>> arguments; private final Supplier creator; private UUID uuid; + private int currentFork = 0; private int initialTickDelay; private int initialTickInterval; @@ -40,11 +44,11 @@ public abstract class ServerBotAction> { private Consumer onSuccess; private Consumer onStop; - public ServerBotAction(String name, CommandArgument argument, Supplier creator) { + public AbstractBotAction(String name, Supplier creator) { this.name = name; - this.argument = argument; this.uuid = UUID.randomUUID(); this.creator = creator; + this.arguments = new HashMap<>(); this.cancel = false; this.setStartDelayTick(0); @@ -56,12 +60,39 @@ public abstract class ServerBotAction> { public abstract Object asCraft(); + public String getActionDataString() { + return getActionDataString(new ExtraData(new ArrayList<>())); + } + + public String getActionDataString(@NotNull ExtraData data) { + return data.raw().stream() + .map(pair -> pair.getLeft() + "=" + pair.getRight()) + .reduce((a, b) -> a + ", " + b) + .orElse("No arguments"); + } + public void init() { this.tickToNext = initialTickDelay; this.numberRemaining = this.getDoNumber(); this.setCancelled(false); } + public void fork(int fork) { + currentFork = fork; + } + + public WrappedArgument addArgument(String name, ArgumentType type) { + WrappedArgument argument = new WrappedArgument<>(name, type); + this.arguments + .computeIfAbsent(currentFork, k -> new ArrayList<>()) + .add(Pair.of(name, argument)); + return argument; + } + + public Map>>> getArguments() { + return this.arguments; + } + public void tryTick(ServerBot bot) { if (this.numberRemaining == 0) { this.stop(bot, BotActionStopEvent.Reason.DONE); @@ -149,19 +180,8 @@ public abstract class ServerBotAction> { } } - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - } - - public void setSuggestion(int n, BiFunction, String>> suggestion) { - this.argument.setSuggestion(n, suggestion); - } - - public void setSuggestion(int n, Pair, String> suggestion) { - this.setSuggestion(n, (sender, arg) -> suggestion); - } - - public void setSuggestion(int n, List tabComplete) { - this.setSuggestion(n, Pair.of(tabComplete, null)); + @SuppressWarnings("RedundantThrows") + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { } @NotNull @@ -169,10 +189,6 @@ public abstract class ServerBotAction> { return this.creator.get(); } - public CommandArgument getArgument() { - return this.argument; - } - public String getName() { return this.name; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java new file mode 100644 index 00000000..75876ab8 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractStateBotAction.java @@ -0,0 +1,10 @@ +package org.leavesmc.leaves.bot.agent.actions; + +import java.util.function.Supplier; + +public abstract class AbstractStateBotAction> extends AbstractBotAction { + public AbstractStateBotAction(String name, Supplier creator) { + super(name, creator); + this.setDoNumber(-1); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java new file mode 100644 index 00000000..817b5ec0 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractTimerBotAction.java @@ -0,0 +1,39 @@ +package org.leavesmc.leaves.bot.agent.actions; + +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; + +import java.util.function.Supplier; + +import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; +import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings; + +public abstract class AbstractTimerBotAction> extends AbstractBotAction { + + public AbstractTimerBotAction(String name, Supplier creator) { + super(name, creator); + this.addArgument("delay", integer(0)).suggests(strings("0", "5", "10", "20")).setOptional(true); + this.addArgument("interval", integer(0)).suggests(strings("20", "0", "5", "10")).setOptional(true); + this.addArgument("do_number", integer(-1)) + .suggests(((context, builder) -> builder.suggest("-1", Component.literal("do infinite times")))) + .setOptional(true); + } + + @Override + public void loadCommand(@NotNull CommandContext context) { + this.setStartDelayTick(context.getIntegerOrDefault("delay", 0)); + this.setDoIntervalTick(context.getIntegerOrDefault("interval", 20)); + this.setDoNumber(context.getIntegerOrDefault("do_number", 1)); + } + + @Override + public String getActionDataString(@NotNull ExtraData data) { + data.add("delay", String.valueOf(this.getStartDelayTick())); + data.add("interval", String.valueOf(this.getDoIntervalTick())); + data.add("do_number", String.valueOf(this.getDoNumber())); + data.add("remaining_do_number", String.valueOf(this.getDoNumberRemaining())); + return super.getActionDataString(data); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java similarity index 71% rename from leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java rename to leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java index b270c585..ddaeec33 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/AbstractUseBotAction.java @@ -1,33 +1,38 @@ package org.leavesmc.leaves.bot.agent.actions; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; +import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionResult; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -import java.util.List; import java.util.function.Supplier; -public abstract class ServerUseBotAction> extends ServerTimerBotAction { +import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; + +public abstract class AbstractUseBotAction> extends AbstractTimerBotAction { private int useTickTimeout = -1; private int alreadyUsedTick = 0; private int useItemRemainingTicks = 0; - public ServerUseBotAction(String name, Supplier supplier) { - super(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), supplier); - this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTickTimeout]")); + public AbstractUseBotAction(String name, Supplier supplier) { + super(name, supplier); + this.addArgument("use_timeout", integer(-1)) + .suggests((context, builder) -> { + builder.suggest("-1", Component.literal("no use timeout")); + builder.suggest("3", Component.literal("minimum bow shoot time")); + builder.suggest("10", Component.literal("minimum trident shoot time")); + }) + .setOptional(true); } @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - super.loadCommand(player, result); - this.useTickTimeout = result.readInt(-1); + public void loadCommand(@NotNull CommandContext context) { + super.loadCommand(context); + this.useTickTimeout = context.getIntegerOrDefault("use_timeout", -1); } @Override @@ -93,6 +98,13 @@ public abstract class ServerUseBotAction> extend this.alreadyUsedTick++; } + @Override + public String getActionDataString(@NotNull ExtraData data) { + data.add("use_timeout", String.valueOf(this.useTickTimeout)); + data.add("already_used_tick", String.valueOf(this.alreadyUsedTick)); + return super.getActionDataString(data); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java index c062b3e0..6a3add3b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerAttackAction.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftAttackAction; -public class ServerAttackAction extends ServerTimerBotAction { +public class ServerAttackAction extends AbstractTimerBotAction { public ServerAttackAction() { super("attack", ServerAttackAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java index 470c62fb..36a2e621 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerBreakBlockAction.java @@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftBreakBlockAction; -public class ServerBreakBlockAction extends ServerTimerBotAction { +public class ServerBreakBlockAction extends AbstractTimerBotAction { public ServerBreakBlockAction() { super("break", ServerBreakBlockAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java index a2818e7e..68e7e817 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerDropAction.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftDropAction; -public class ServerDropAction extends ServerTimerBotAction { +public class ServerDropAction extends AbstractTimerBotAction { public ServerDropAction() { super("drop", ServerDropAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java index 08789314..3e895f1a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerFishAction.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftFishAction; -public class ServerFishAction extends ServerTimerBotAction { +public class ServerFishAction extends AbstractTimerBotAction { public ServerFishAction() { super("fish", ServerFishAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java index 1930c1a7..f7571a79 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerJumpAction.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftJumpAction; -public class ServerJumpAction extends ServerTimerBotAction { +public class ServerJumpAction extends AbstractTimerBotAction { public ServerJumpAction() { super("jump", ServerJumpAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java index abc10852..8333826d 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerLookAction.java @@ -1,39 +1,53 @@ package org.leavesmc.leaves.bot.agent.actions; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.argument.ArgumentTypes; +import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; +import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.entity.Player; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Entity; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.entity.bot.actions.CraftLookAction; -import java.text.DecimalFormat; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Stream; - -public class ServerLookAction extends ServerBotAction { +public class ServerLookAction extends AbstractBotAction { private static final Vector ZERO_VECTOR = new Vector(0, 0, 0); - private static final DecimalFormat DF = new DecimalFormat("0.0"); private Vector pos = ZERO_VECTOR; private ServerPlayer target = null; public ServerLookAction() { - super("look", CommandArgument.of(CommandArgumentType.STRING, CommandArgumentType.DOUBLE, CommandArgumentType.DOUBLE), ServerLookAction::new); - this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ? - Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of(DF.format(player.getX()))).toList(), "|") : - Pair.of(Stream.concat(Arrays.stream(MinecraftServer.getServer().getPlayerNames()), Stream.of("0")).toList(), "|") - ); - this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getY())), "") : Pair.of(List.of("0"), "")); - this.setSuggestion(2, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getZ())), "") : Pair.of(List.of("0"), "")); + super("look", ServerLookAction::new); + this.addArgument("player", ArgumentTypes.player()).setOptional(true); + this.fork(1); + this.addArgument("location", ArgumentTypes.finePosition()); + } + + @Override + public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException { + PlayerSelectorArgumentResolver playerSelectorResolver = context.getArgumentOrDefault("player", PlayerSelectorArgumentResolver.class, null); + FinePositionResolver positionResolver = context.getArgumentOrDefault("location", FinePositionResolver.class, null); + CommandSourceStack source = context.getSource(); + if (playerSelectorResolver == null && positionResolver == null) { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + this.setPos(entity.getLocation().toVector()); + } else { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().create(); + } + } else if (playerSelectorResolver != null) { + CraftPlayer player = (CraftPlayer) playerSelectorResolver.resolve(source).getFirst(); + this.setTarget(player.getHandle()); + } else { + this.setPos(positionResolver.resolve(source).toVector()); + } } @Override @@ -87,22 +101,6 @@ public class ServerLookAction extends ServerBotAction { return true; } - @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - String nameOrX = result.readString(player.getScoreboardName()); - ServerPlayer player1 = player.getServer().getPlayerList().getPlayerByName(nameOrX); - if (player1 != null) { - this.setTarget(player1); - return; - } - try { - Vector vector = result.readVectorYZ(Double.parseDouble(nameOrX)); - this.setPos(vector); - } catch (Exception e) { - throw new IllegalArgumentException("Invalid vector"); - } - } - @Override public Object asCraft() { return new CraftLookAction(this); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java index c4a4a440..05a8a697 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMountAction.java @@ -1,21 +1,19 @@ package org.leavesmc.leaves.bot.agent.actions; -import net.minecraft.world.entity.Entity; import org.bukkit.Location; -import org.bukkit.craftbukkit.entity.CraftEntity; +import org.bukkit.craftbukkit.entity.CraftVehicle; import org.bukkit.entity.Vehicle; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftMountAction; import java.util.Comparator; import java.util.List; -public class ServerMountAction extends ServerBotAction { +public class ServerMountAction extends AbstractBotAction { public ServerMountAction() { - super("mount", CommandArgument.EMPTY, ServerMountAction::new); + super("mount", ServerMountAction::new); } @Override @@ -23,14 +21,17 @@ public class ServerMountAction extends ServerBotAction { Location center = bot.getBukkitEntity().getLocation(); List vehicles = center.getNearbyEntitiesByType( Vehicle.class, - 3, - vehicle -> manhattanDistance(bot, ((CraftEntity) vehicle).getHandle()) <= 2 + bot.entityInteractionRange() ).stream().sorted(Comparator.comparingDouble( (vehicle) -> center.distanceSquared(vehicle.getLocation()) )).toList(); for (Vehicle vehicle : vehicles) { - if (bot.startRiding(((CraftEntity) vehicle).getHandle(), false)) { + CraftVehicle craftVehicle = (CraftVehicle) vehicle; + if (!bot.hasLineOfSight(craftVehicle.getHandle())) { + continue; + } + if (bot.startRiding(craftVehicle.getHandle())) { return true; } } @@ -42,10 +43,4 @@ public class ServerMountAction extends ServerBotAction { public Object asCraft() { return new CraftMountAction(this); } - - private double manhattanDistance(@NotNull Entity entity1, @NotNull Entity entity2) { - return Math.abs(entity1.getX() - entity2.getX()) + - Math.abs(entity1.getY() - entity2.getY()) + - Math.abs(entity1.getZ() - entity2.getZ()); - } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java index 6f3e8b80..4023b469 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerMoveAction.java @@ -1,38 +1,25 @@ package org.leavesmc.leaves.bot.agent.actions; -import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.arguments.EnumArgumentType; import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection; import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -import java.util.Arrays; -import java.util.List; - -public class ServerMoveAction extends ServerStateBotAction { - - private static final Pair, String> suggestions = Pair.of( - Arrays.stream(MoveDirection.values()).map((it) -> it.name).toList(), - "" - ); +public class ServerMoveAction extends AbstractStateBotAction { private MoveDirection direction = MoveDirection.FORWARD; public ServerMoveAction() { - super("move", CommandArgument.of(CommandArgumentType.ofEnum(MoveDirection.class)), ServerMoveAction::new); - this.setSuggestion(0, suggestions); + super("move", ServerMoveAction::new); + this.addArgument("direction", EnumArgumentType.fromEnum(MoveDirection.class)); } @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - this.direction = result.read(MoveDirection.class); - if (direction == null) { - throw new IllegalArgumentException("Invalid direction"); - } + public void loadCommand(@NotNull CommandContext context) { + this.direction = context.getArgument("direction", MoveDirection.class); } @Override @@ -57,6 +44,12 @@ public class ServerMoveAction extends ServerStateBotAction { return true; } + @Override + public String getActionDataString(@NotNull ExtraData data) { + data.add("direction", direction.name); + return super.getActionDataString(data); + } + public MoveDirection getDirection() { return direction; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java index 0c278ea4..85f51064 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerRotationAction.java @@ -1,41 +1,60 @@ package org.leavesmc.leaves.bot.agent.actions; +import com.mojang.brigadier.arguments.FloatArgumentType; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.entity.Player; +import net.minecraft.network.chat.Component; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction; import java.text.DecimalFormat; -import java.util.List; -import java.util.Objects; -public class ServerRotationAction extends ServerBotAction { +public class ServerRotationAction extends AbstractBotAction { private static final DecimalFormat DF = new DecimalFormat("0.00"); public ServerRotationAction() { - super("rotation", CommandArgument.of(CommandArgumentType.FLOAT, CommandArgumentType.FLOAT), ServerRotationAction::new); - this.setSuggestion(0, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getYaw())), "[yaw]") : Pair.of(List.of("0"), "")); - this.setSuggestion(1, (sender, arg) -> sender instanceof Player player ? Pair.of(List.of(DF.format(player.getPitch())), "[pitch]") : Pair.of(List.of("0"), "")); + super("rotation", ServerRotationAction::new); + this.addArgument("yaw", FloatArgumentType.floatArg(-180, 180)) + .suggests((context, builder) -> { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + builder.suggest( + DF.format(entity.getYaw()), + Component.literal("current player yaw") + ); + } + }) + .setOptional(true); + this.addArgument("pitch", FloatArgumentType.floatArg(-90, 90)) + .suggests((context, builder) -> { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + builder.suggest( + DF.format(entity.getPitch()), + Component.literal("current player pitch") + ); + } + }) + .setOptional(true); } private float yaw = 0.0f; private float pitch = 0.0f; @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - try { - this.yaw = result.readFloat(Objects.requireNonNull(player).getYRot()); - this.pitch = result.readFloat(player.getXRot()); - } catch (Exception e) { - throw new IllegalArgumentException("No valid rotation specified", e); + public void loadCommand(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (sender instanceof Entity entity) { + this.yaw = entity.getYaw(); + this.pitch = entity.getPitch(); } + this.yaw = context.getFloatOrDefault("yaw", this.yaw); + this.pitch = context.getFloatOrDefault("pitch", this.pitch); } public void setYaw(float yaw) { @@ -54,6 +73,13 @@ public class ServerRotationAction extends ServerBotAction return this.pitch; } + @Override + public String getActionDataString(@NotNull ExtraData data) { + data.add("yaw", DF.format(this.yaw)); + data.add("pitch", DF.format(this.pitch)); + return super.getActionDataString(data); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java index 104cb194..7c6ac393 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSneakAction.java @@ -2,14 +2,13 @@ package org.leavesmc.leaves.bot.agent.actions; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; -public class ServerSneakAction extends ServerStateBotAction { +public class ServerSneakAction extends AbstractStateBotAction { public ServerSneakAction() { - super("sneak", CommandArgument.EMPTY, ServerSneakAction::new); + super("sneak", ServerSneakAction::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java deleted file mode 100644 index c67b7acb..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerStateBotAction.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.leavesmc.leaves.bot.agent.actions; - -import org.leavesmc.leaves.command.CommandArgument; - -import java.util.function.Supplier; - -public abstract class ServerStateBotAction> extends ServerBotAction { - - public ServerStateBotAction(String name, CommandArgument argument, Supplier creator) { - super(name, argument, creator); - this.setDoNumber(-1); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java index 8363b11d..12d737e3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwapAction.java @@ -4,13 +4,12 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction; -public class ServerSwapAction extends ServerBotAction { +public class ServerSwapAction extends AbstractBotAction { public ServerSwapAction() { - super("swap", CommandArgument.EMPTY, ServerSwapAction::new); + super("swap", ServerSwapAction::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java index 50576fe6..df5b0bf5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerSwimAction.java @@ -3,13 +3,12 @@ package org.leavesmc.leaves.bot.agent.actions; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.CommandArgument; import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction; -public class ServerSwimAction extends ServerStateBotAction { +public class ServerSwimAction extends AbstractStateBotAction { public ServerSwimAction() { - super("swim", CommandArgument.EMPTY, ServerSwimAction::new); + super("swim", ServerSwimAction::new); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java deleted file mode 100644 index 40edda63..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerTimerBotAction.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.leavesmc.leaves.bot.agent.actions; - -import net.minecraft.server.level.ServerPlayer; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.CommandArgumentType; - -import java.util.List; -import java.util.function.Supplier; - -public abstract class ServerTimerBotAction> extends ServerBotAction { - - public ServerTimerBotAction(String name, Supplier creator) { - this(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), creator); - } - - public ServerTimerBotAction(String name, CommandArgument argument, Supplier creator) { - super(name, argument, creator); - this.setSuggestion(0, Pair.of(List.of("0"), "[TickDelay]")); - this.setSuggestion(1, Pair.of(List.of("20"), "[TickInterval]")); - this.setSuggestion(2, Pair.of(List.of("1", "-1"), "[DoNumber]")); - } - - @Override - public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) { - this.setStartDelayTick(result.readInt(0)); - this.setDoIntervalTick(result.readInt(20)); - this.setDoNumber(result.readInt(1)); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java index 0172692f..ce5884b8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAction.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAction; -public class ServerUseItemAction extends ServerUseBotAction { +public class ServerUseItemAction extends AbstractUseBotAction { public ServerUseItemAction() { super("use", ServerUseItemAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java index ce979217..bfb5f537 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemAutoAction.java @@ -17,7 +17,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem; import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn; import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo; -public class ServerUseItemAutoAction extends ServerUseBotAction { +public class ServerUseItemAutoAction extends AbstractUseBotAction { public ServerUseItemAutoAction() { super("use_auto", ServerUseItemAutoAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java index 4983edb7..b05d8ab1 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOffhandAction.java @@ -7,7 +7,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOffhandAction; import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem; -public class ServerUseItemOffhandAction extends ServerUseBotAction { +public class ServerUseItemOffhandAction extends AbstractUseBotAction { public ServerUseItemOffhandAction() { super("use_offhand", ServerUseItemOffhandAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java index bec8358f..ee23b7a6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnAction.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnAction; -public class ServerUseItemOnAction extends ServerUseBotAction { +public class ServerUseItemOnAction extends AbstractUseBotAction { public ServerUseItemOnAction() { super("use_on", ServerUseItemOnAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java index 09f69565..ac06e27c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemOnOffhandAction.java @@ -8,7 +8,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnOffhandAction; import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn; -public class ServerUseItemOnOffhandAction extends ServerUseBotAction { +public class ServerUseItemOnOffhandAction extends AbstractUseBotAction { public ServerUseItemOnOffhandAction() { super("use_on_offhand", ServerUseItemOnOffhandAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java index 5f294055..9d985c0c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToAction.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToAction; -public class ServerUseItemToAction extends ServerUseBotAction { +public class ServerUseItemToAction extends AbstractUseBotAction { public ServerUseItemToAction() { super("use_to", ServerUseItemToAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java index 733246df..6ce3aec6 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/actions/ServerUseItemToOffhandAction.java @@ -8,7 +8,7 @@ import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToOffhandAction; import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo; -public class ServerUseItemToOffhandAction extends ServerUseBotAction { +public class ServerUseItemToOffhandAction extends AbstractUseBotAction { public ServerUseItemToOffhandAction() { super("use_to_offhand", ServerUseItemToOffhandAction::new); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java new file mode 100644 index 00000000..7b87332d --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AbstractBotConfig.java @@ -0,0 +1,98 @@ +package org.leavesmc.leaves.bot.agent.configs; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.nbt.CompoundTag; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.WrappedArgument; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.function.Supplier; + +public abstract class AbstractBotConfig> { + private final String name; + private final WrappedArgument argument; + private final Supplier creator; + + protected ServerBot bot; + + public AbstractBotConfig(String name, ArgumentType type, Supplier creator) { + this.name = name; + this.argument = new WrappedArgument<>(name, type); + if (shouldApplySuggestions()) { + this.argument.suggests(this::applySuggestions); + } + this.creator = creator; + } + + @SuppressWarnings("RedundantThrows") + public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { + } + + public AbstractBotConfig setBot(ServerBot bot) { + this.bot = bot; + return this; + } + + public E create() { + return creator.get(); + } + + public abstract T getValue(); + + public abstract void setValue(T value) throws CommandSyntaxException; + + public abstract T loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException; + + public String getName() { + return name; + } + + public Component getNameComponent() { + return Component.text(getName(), NamedTextColor.AQUA).hoverEvent(HoverEvent.showText(Component.text(getExtraDataString()))); + } + + public String getExtraDataString() { + return getExtraDataString(new ExtraData(new ArrayList<>())); + } + + public String getExtraDataString(@NotNull ExtraData data) { + return data.raw().stream() + .map(pair -> pair.getLeft() + "=" + pair.getRight()) + .reduce((a, b) -> a + ", " + b) + .orElse("No data"); + } + + public WrappedArgument getArgument() { + return argument; + } + + public ServerBot getBot() { + return bot; + } + + @NotNull + public CompoundTag save(@NotNull CompoundTag nbt) { + nbt.putString("configName", this.name); + return nbt; + } + + public abstract void load(@NotNull CompoundTag nbt); + + private boolean shouldApplySuggestions() { + for (Method method : getClass().getDeclaredMethods()) { + if (method.getName().equals("applySuggestions")) { + return method.getDeclaringClass() != AbstractBotConfig.class; + } + } + return false; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java index 8ef871cc..59ba3583 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/AlwaysSendDataConfig.java @@ -1,22 +1,16 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; - -import java.util.List; - -public class AlwaysSendDataConfig extends AbstractBotConfig { - - public static final String NAME = "always_send_data"; +import org.leavesmc.leaves.command.CommandContext; +public class AlwaysSendDataConfig extends AbstractBotConfig { private boolean value; public AlwaysSendDataConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("always_send_data", BoolArgumentType.bool(), AlwaysSendDataConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.canSendDataAlways; } @@ -30,16 +24,21 @@ public class AlwaysSendDataConfig extends AbstractBotConfig { this.value = value; } + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.canSendDataAlways)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.canSendDataAlways)); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java index 1b0a02f0..cfb94613 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/LocatorBarConfig.java @@ -1,23 +1,17 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.waypoints.ServerWaypointManager; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; - -import java.util.List; - -public class LocatorBarConfig extends AbstractBotConfig { - - public static final String NAME = "enable_locator_bar"; +import org.leavesmc.leaves.command.CommandContext; +public class LocatorBarConfig extends AbstractBotConfig { private boolean value; public LocatorBarConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("enable_locator_bar", BoolArgumentType.bool(), LocatorBarConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.enableLocatorBar; } @@ -27,7 +21,7 @@ public class LocatorBarConfig extends AbstractBotConfig { } @Override - public void setValue(Boolean value) throws IllegalArgumentException { + public void setValue(@NotNull Boolean value) throws IllegalArgumentException { this.value = value; ServerWaypointManager manager = this.bot.level().getWaypointManager(); if (value) { @@ -37,15 +31,20 @@ public class LocatorBarConfig extends AbstractBotConfig { } } + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); + } + @Override public @NotNull CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.enableLocatorBar)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.enableLocatorBar)); } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java index 56751f72..042064c7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SimulationDistanceConfig.java @@ -1,21 +1,27 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; import net.minecraft.nbt.CompoundTag; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.command.CommandContext; -import java.util.List; +import static net.minecraft.network.chat.Component.literal; -public class SimulationDistanceConfig extends AbstractBotConfig { - - public static final String NAME = "simulation_distance"; +public class SimulationDistanceConfig extends AbstractBotConfig { public SimulationDistanceConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.INTEGER).setSuggestion(0, Pair.of(List.of("2", "10"), ""))); + super("simulation_distance", IntegerArgumentType.integer(2, 32), SimulationDistanceConfig::new); + } + + @Override + public void applySuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { + builder.suggest("2", literal("Minimum simulation distance")); + builder.suggest("8"); + builder.suggest("12"); + builder.suggest("16"); + builder.suggest("32", literal("Maximum simulation distance")); } @Override @@ -25,22 +31,24 @@ public class SimulationDistanceConfig extends AbstractBotConfig { @Override public void setValue(Integer value) { - if (value < 2 || value > 32) { - throw new IllegalArgumentException("simulation_distance must be a number between 2 and 32, got: " + value); - } this.bot.getBukkitEntity().setSimulationDistance(value); } + @Override + public Integer loadFromCommand(@NotNull CommandContext context) { + return context.getInteger(getName()); + } + @Override @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putInt(NAME, this.getValue()); + nbt.putInt(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getIntOr(NAME, LeavesConfig.modify.fakeplayer.inGame.getSimulationDistance(this.bot))); + this.setValue(nbt.getIntOr(getName(), LeavesConfig.modify.fakeplayer.inGame.getSimulationDistance(this.bot))); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java index cf4b0610..9580313a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SkipSleepConfig.java @@ -1,20 +1,15 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.command.CommandContext; -import java.util.List; - -public class SkipSleepConfig extends AbstractBotConfig { - - public static final String NAME = "skip_sleep"; +public class SkipSleepConfig extends AbstractBotConfig { public SkipSleepConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("skip_sleep", BoolArgumentType.bool(), SkipSleepConfig::new); } @Override @@ -27,15 +22,20 @@ public class SkipSleepConfig extends AbstractBotConfig { bot.fauxSleeping = value; } + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); + } + @Override public @NotNull CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.canSkipSleep)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.canSkipSleep)); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java index 13be5fee..f155beda 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/SpawnPhantomConfig.java @@ -1,22 +1,17 @@ package org.leavesmc.leaves.bot.agent.configs; +import com.mojang.brigadier.arguments.BoolArgumentType; import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; - -import java.util.List; - -public class SpawnPhantomConfig extends AbstractBotConfig { - - public static final String NAME = "spawn_phantom"; +import org.leavesmc.leaves.bot.agent.ExtraData; +import org.leavesmc.leaves.command.CommandContext; +public class SpawnPhantomConfig extends AbstractBotConfig { private boolean value; public SpawnPhantomConfig() { - super(NAME, CommandArgument.of(CommandArgumentType.BOOLEAN).setSuggestion(0, List.of("true", "false"))); + super("spawn_phantom", BoolArgumentType.bool(), SpawnPhantomConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.canSpawnPhantom; } @@ -31,22 +26,25 @@ public class SpawnPhantomConfig extends AbstractBotConfig { } @Override - public List getMessage() { - return List.of( - bot.getScoreboardName() + "'s spawn_phantom: " + this.getValue(), - bot.getScoreboardName() + "'s not_sleeping_ticks: " + bot.notSleepTicks - ); + public String getExtraDataString(@NotNull ExtraData data) { + data.add("not_sleeping_ticks", String.valueOf(bot.notSleepTicks)); + return super.getExtraDataString(data); + } + + @Override + public Boolean loadFromCommand(@NotNull CommandContext context) { + return context.getBoolean(getName()); } @Override public @NotNull CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putBoolean(NAME, this.getValue()); + nbt.putBoolean(getName(), this.getValue()); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(nbt.getBooleanOr(NAME, LeavesConfig.modify.fakeplayer.inGame.canSpawnPhantom)); + this.setValue(nbt.getBooleanOr(getName(), LeavesConfig.modify.fakeplayer.inGame.canSpawnPhantom)); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java index 0615a439..828bf9b5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -4,24 +4,24 @@ import net.minecraft.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.command.CommandArgument; -import org.leavesmc.leaves.command.CommandArgumentType; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.arguments.EnumArgumentType; -import java.util.List; - -public class TickTypeConfig extends AbstractBotConfig { - - private static final String NAME = "tick_type"; - private static final CommandArgumentType TICK_TYPE_ARGUMENT = CommandArgumentType.ofEnum(ServerBot.TickType.class); +import java.util.Locale; +public class TickTypeConfig extends AbstractBotConfig { private ServerBot.TickType value; public TickTypeConfig() { - super(NAME, CommandArgument.of(TICK_TYPE_ARGUMENT).setSuggestion(0, List.of("network", "entity_list"))); + super("tick_type", EnumArgumentType.fromEnum(ServerBot.TickType.class), TickTypeConfig::new); this.value = LeavesConfig.modify.fakeplayer.inGame.tickType; } + @Override + public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) { + return context.getArgument("tick_type", ServerBot.TickType.class); + } + @Override public ServerBot.TickType getValue() { return value; @@ -36,12 +36,17 @@ public class TickTypeConfig extends AbstractBotConfig { @NotNull public CompoundTag save(@NotNull CompoundTag nbt) { super.save(nbt); - nbt.putString(NAME, this.getValue().toString()); + nbt.putString(getName(), this.getValue().toString().toLowerCase(Locale.ROOT)); return nbt; } @Override public void load(@NotNull CompoundTag nbt) { - this.setValue(TICK_TYPE_ARGUMENT.parse(nbt.getStringOr(NAME, LeavesConfig.modify.fakeplayer.inGame.tickType.name()))); + String raw = nbt.getStringOr(getName(), LeavesConfig.modify.fakeplayer.inGame.tickType.name()); + this.setValue(switch (raw.toLowerCase(Locale.ROOT)) { + case "network" -> ServerBot.TickType.NETWORK; + case "entity_list" -> ServerBot.TickType.ENTITY_LIST; + default -> throw new IllegalStateException("Unexpected bot tick type value: " + raw); + }); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java deleted file mode 100644 index ce938659..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotActionCommand.java +++ /dev/null @@ -1,181 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.network.chat.Component; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.Actions; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotActionStopEvent; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static net.kyori.adventure.text.Component.text; - -public class BotActionCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 2) { - sender.sendMessage(text("Use /bot action to make fakeplayer do action", NamedTextColor.RED)); - return; - } - - ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - switch (args[1].toLowerCase()) { - case "list" -> { - sender.sendMessage(bot.getScoreboardName() + "'s action list:"); - for (int i = 0; i < bot.getBotActions().size(); i++) { - sender.sendMessage(i + " " + bot.getBotActions().get(i).getName()); - } - } - case "start" -> executeStart(bot, sender, args); - case "stop" -> executeStop(bot, sender, args); - } - } - - private void executeStart(ServerBot bot, CommandSender sender, String[] args) { - if (args.length < 3) { - sender.sendMessage(text("Invalid action", NamedTextColor.RED)); - return; - } - ServerBotAction action = Actions.getForName(args[2]); - if (action == null) { - sender.sendMessage(text("Invalid action", NamedTextColor.RED)); - return; - } - - CraftPlayer player; - if (sender instanceof CraftPlayer) { - player = (CraftPlayer) sender; - } else { - player = bot.getBukkitEntity(); - } - - String[] realArgs = Arrays.copyOfRange(args, 3, args.length); - ServerBotAction newAction; - try { - newAction = action.create(); - newAction.loadCommand(player.getHandle(), action.getArgument().parse(0, realArgs)); - } catch (IllegalArgumentException e) { - sender.sendMessage(text("Action create error, please check your arguments, " + e.getMessage(), NamedTextColor.RED)); - return; - } - - if (bot.addBotAction(newAction, sender)) { - sender.sendMessage("Action " + action.getName() + " has been issued to " + bot.getName().getString()); - } - } - - private void executeStop(ServerBot bot, CommandSender sender, String[] args) { - if (args.length < 3) { - sender.sendMessage(text("Invalid index", NamedTextColor.RED)); - return; - } - - String index = args[2]; - if (index.equals("all")) { - Set> forRemoval = new HashSet<>(); - for (int i = 0; i < bot.getBotActions().size(); i++) { - ServerBotAction action = bot.getBotActions().get(i); - BotActionStopEvent event = new BotActionStopEvent( - bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender - ); - event.callEvent(); - if (!event.isCancelled()) { - forRemoval.add(action); - action.stop(bot, BotActionStopEvent.Reason.COMMAND); - } - } - bot.getBotActions().removeAll(forRemoval); - sender.sendMessage(bot.getScoreboardName() + "'s action list cleared."); - return; - } - try { - int i = Integer.parseInt(index); - if (i < 0 || i >= bot.getBotActions().size()) { - sender.sendMessage(text("Invalid index", NamedTextColor.RED)); - return; - } - - ServerBotAction action = bot.getBotActions().get(i); - BotActionStopEvent event = new BotActionStopEvent( - bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender - ); - event.callEvent(); - if (!event.isCancelled()) { - action.stop(bot, BotActionStopEvent.Reason.COMMAND); - bot.getBotActions().remove(i); - sender.sendMessage(bot.getScoreboardName() + "'s " + action.getName() + " stopped."); - - } - } catch (NumberFormatException e) { - sender.sendMessage(text("Invalid index", NamedTextColor.RED)); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String subCommand, String @NotNull [] args, Location location, @NotNull LeavesSuggestionBuilder builder) { - BotList botList = BotList.INSTANCE; - ServerBot serverBot = null; - - if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { - builder.suggest("<" + args[0] + " not found>"); - return; - } - - switch (args.length) { - case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - case 2 -> builder.suggest("start").suggest("stop").suggest("list"); - case 3 -> { - switch (args[1].toLowerCase()) { - case "start" -> Actions.getNames().forEach(builder::suggest); - case "stop" -> { - builder.suggest("all"); - int[] index = new int[]{0}; - serverBot.getBotActions().forEach(a -> builder.suggest(String.valueOf(index[0]++))); - } - } - } - case 4, 5, 6, 7 -> { - ServerBotAction action = Actions.getForName(args[2]); - if (action == null) { - return; - } - Pair, String> results = action.getArgument().suggestion(args.length - 4, sender, args[args.length - 2]); - if (results == null || results.getLeft() == null) { - return; - } - - for (String s : results.getLeft()) { - if (results.getRight() != null) { - builder.suggest(s, Component.literal(results.getRight())); - } else { - builder.suggest(s); - } - } - } - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canUseAction; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java deleted file mode 100644 index 883a47bf..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotConfigCommand.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import net.minecraft.network.chat.Component; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.AbstractBotConfig; -import org.leavesmc.leaves.bot.agent.Configs; -import org.leavesmc.leaves.command.CommandArgumentResult; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotConfigModifyEvent; - -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import static net.kyori.adventure.text.Component.text; - -public class BotConfigCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 2) { - sender.sendMessage(text("Use /bot config to modify fakeplayer's config", NamedTextColor.RED)); - return; - } - - ServerBot bot = BotList.INSTANCE.getBotByName(args[0]); - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - if (!Configs.getConfigNames().contains(args[1])) { - sender.sendMessage(text("This config is not accept", NamedTextColor.RED)); - return; - } - - AbstractBotConfig config = bot.getConfig(Objects.requireNonNull(Configs.getConfig(args[1]))); - if (args.length < 3) { - config.getMessage().forEach(sender::sendMessage); - } else { - String[] realArgs = Arrays.copyOfRange(args, 2, args.length); - - BotConfigModifyEvent event = new BotConfigModifyEvent(bot.getBukkitEntity(), config.getName(), realArgs, sender); - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - return; - } - CommandArgumentResult result = config.getArgument().parse(0, realArgs); - - try { - config.setFromCommand(result); - config.getChangeMessage().forEach(sender::sendMessage); - } catch (IllegalArgumentException e) { - sender.sendMessage(text(e.getMessage(), NamedTextColor.RED)); - } - } - } - - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - ServerBot serverBot = null; - - if (args.length > 1 && (serverBot = botList.getBotByName(args[0])) == null) { - builder.suggest("<" + args[0] + " not found>"); - return; - } - - switch (args.length) { - case 0, 1 -> botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - case 2 -> Configs.getConfigNames().forEach(builder::suggest); - case 3, 4 -> { - Configs config = Configs.getConfig(args[1]); - if (config == null) { - return; - } - AbstractBotConfig botConfig = serverBot.getConfig(config); - Pair, String> results = botConfig.getArgument().suggestion(args.length - 3, sender, args[args.length - 1]); - if (results == null || results.getLeft() == null) { - return; - } - - for (String s : results.getLeft()) { - if (results.getRight() != null) { - builder.suggest(s, Component.literal(results.getRight())); - } else { - builder.suggest(s); - } - } - } - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canModifyConfig; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java deleted file mode 100644 index 0cbd1869..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotCreateCommand.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.command.ConsoleCommandSender; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.LeavesLogger; -import org.leavesmc.leaves.bot.BotCreateState; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.BotUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotCreateEvent; - -import static net.kyori.adventure.text.Component.text; - -public class BotCreateCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Use /bot create [skin_name] to create a fakeplayer", NamedTextColor.RED)); - return; - } - - String botName = args[0]; - String fullName = BotUtil.getFullName(botName); - if (this.canCreate(sender, fullName)) { - BotCreateState.Builder builder = BotCreateState.builder(botName, Bukkit.getWorlds().getFirst().getSpawnLocation()).createReason(BotCreateEvent.CreateReason.COMMAND).creator(sender); - - if (args.length >= 2) { - builder.skinName(args[1]); - } - - if (sender instanceof Player player) { - builder.location(player.getLocation()); - } else if (sender instanceof ConsoleCommandSender) { - if (args.length >= 6) { - try { - World world = Bukkit.getWorld(args[2]); - double x = Double.parseDouble(args[3]); - double y = Double.parseDouble(args[4]); - double z = Double.parseDouble(args[5]); - if (world != null) { - builder.location(new Location(world, x, y, z)); - } - } catch (Exception e) { - LeavesLogger.LOGGER.warning("Can't build location", e); - } - } - } - - builder.spawnWithSkin(null); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (args.length <= 1) { - builder.suggest(""); - } - if (args.length == 2) { - builder.suggest("[SkinName]"); - } - if (sender instanceof ConsoleCommandSender && args.length == 3) { - Bukkit.getWorlds().forEach(world -> builder.suggest(world.getName())); - } - } - - private boolean canCreate(CommandSender sender, @NotNull String name) { - BotList botList = BotList.INSTANCE; - if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) { - sender.sendMessage(text("This name is illegal", NamedTextColor.RED)); - return false; - } - - if (Bukkit.getPlayerExact(name) != null || botList.getBotByName(name) != null) { - sender.sendMessage(text("This player is in server", NamedTextColor.RED)); - return false; - } - - if (LeavesConfig.modify.fakeplayer.unableNames.contains(name)) { - sender.sendMessage(text("This name is not allowed", NamedTextColor.RED)); - return false; - } - - if (botList.bots.size() >= LeavesConfig.modify.fakeplayer.limit) { - sender.sendMessage(text("Fakeplayer limit is full", NamedTextColor.RED)); - return false; - } - - return true; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotListCommand.java deleted file mode 100644 index 40088a0f..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotListCommand.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.entity.bot.Bot; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static net.kyori.adventure.text.Component.text; - -public class BotListCommand implements LeavesSubcommand { - - @NotNull - private static String formatPlayerNameList(@NotNull List list) { - if (list.isEmpty()) { - return ""; - } - String string = list.toString(); - return string.substring(1, string.length() - 1); - } - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - BotList botList = BotList.INSTANCE; - if (args.length < 2) { - Map> botMap = new HashMap<>(); - for (World world : Bukkit.getWorlds()) { - botMap.put(world, new ArrayList<>()); - } - - for (ServerBot bot : botList.bots) { - Bot bukkitBot = bot.getBukkitEntity(); - botMap.get(bukkitBot.getWorld()).add(bukkitBot.getName()); - } - - sender.sendMessage("Total number: (" + botList.bots.size() + "/" + LeavesConfig.modify.fakeplayer.limit + ")"); - for (World world : botMap.keySet()) { - sender.sendMessage(world.getName() + "(" + botMap.get(world).size() + "): " + formatPlayerNameList(botMap.get(world))); - } - } else { - World world = Bukkit.getWorld(args[1]); - - if (world == null) { - sender.sendMessage(text("Unknown world", NamedTextColor.RED)); - return; - } - - List snowBotList = new ArrayList<>(); - for (ServerBot bot : botList.bots) { - Bot bukkitBot = bot.getBukkitEntity(); - if (bukkitBot.getWorld() == world) { - snowBotList.add(bukkitBot.getName()); - } - } - - sender.sendMessage(world.getName() + "(" + botList.bots.size() + "): " + formatPlayerNameList(snowBotList)); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - Bukkit.getWorlds().forEach(world -> builder.suggest(world.getName())); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java deleted file mode 100644 index fbd223e3..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotLoadCommand.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; - -import static net.kyori.adventure.text.Component.text; - -public class BotLoadCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Use /bot load to save a fakeplayer", NamedTextColor.RED)); - return; - } - - String realName = args[0]; - BotList botList = BotList.INSTANCE; - if (!botList.getSavedBotList().contains(realName)) { - sender.sendMessage(text("This fakeplayer is not saved", NamedTextColor.RED)); - return; - } - - if (botList.loadNewBot(realName) == null) { - sender.sendMessage(text("Can't load bot, please check", NamedTextColor.RED)); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - if (args.length <= 1) { - botList.getSavedBotList().keySet().forEach(builder::suggest); - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotRemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotRemoveCommand.java deleted file mode 100644 index c40bd6a7..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotRemoveCommand.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotRemoveEvent; -import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; - -import static net.kyori.adventure.text.Component.text; - -public class BotRemoveCommand implements LeavesSubcommand { - - private final Component errorMessage = text("Usage: /bot remove [hour] [minute] [second]", NamedTextColor.RED); - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1 || args.length > 4) { - sender.sendMessage(errorMessage); - return; - } - - BotList botList = BotList.INSTANCE; - ServerBot bot = botList.getBotByName(args[0]); - - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - if (args.length == 2 && args[1].equals("cancel")) { - if (bot.removeTaskId == -1) { - sender.sendMessage(text("This fakeplayer is not scheduled to be removed", NamedTextColor.RED)); - return; - } - Bukkit.getScheduler().cancelTask(bot.removeTaskId); - bot.removeTaskId = -1; - sender.sendMessage(text("Remove cancel")); - return; - } - - if (args.length > 1) { - long time = 0; - int h; // Preventing out-of-range - long s = 0; - long m = 0; - - try { - h = Integer.parseInt(args[1]); - if (h < 0) { - throw new NumberFormatException(); - } - time += ((long) h) * 3600 * 20; - if (args.length > 2) { - m = Long.parseLong(args[2]); - if (m > 59 || m < 0) { - throw new NumberFormatException(); - } - time += m * 60 * 20; - } - if (args.length > 3) { - s = Long.parseLong(args[3]); - if (s > 59 || s < 0) { - throw new NumberFormatException(); - } - time += s * 20; - } - } catch (NumberFormatException e) { - sender.sendMessage(errorMessage); - return; - } - - boolean isReschedule = bot.removeTaskId != -1; - - if (isReschedule) { - Bukkit.getScheduler().cancelTask(bot.removeTaskId); - } - bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> { - bot.removeTaskId = -1; - botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false); - }, time).getTaskId(); - - sender.sendMessage("This fakeplayer will be removed in " + h + "h " + m + "m " + s + "s" + (isReschedule ? " (rescheduled)" : "")); - return; - } - - botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false); - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - - if (args.length <= 1) { - botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - } - - if (args.length == 2) { - builder.suggest("cancel"); - builder.suggest("[hour]"); - } - - if (args.length > 2 && !args[1].equals("cancel")) { - switch (args.length) { - case 3 -> builder.suggest("[minute]"); - case 4 -> builder.suggest("[second]"); - } - } - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotSaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotSaveCommand.java deleted file mode 100644 index d1b22d9c..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/subcommands/BotSaveCommand.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.leavesmc.leaves.bot.subcommands; - -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.bot.BotList; -import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.event.bot.BotRemoveEvent; - -import static net.kyori.adventure.text.Component.text; - -public class BotSaveCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Use /bot save to save a fakeplayer", NamedTextColor.RED)); - return; - } - - BotList botList = BotList.INSTANCE; - ServerBot bot = botList.getBotByName(args[0]); - - if (bot == null) { - sender.sendMessage(text("This fakeplayer is not in server", NamedTextColor.RED)); - return; - } - - if (botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true)) { - sender.sendMessage(bot.getScoreboardName() + " saved to " + bot.createState.realName()); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - BotList botList = BotList.INSTANCE; - if (args.length <= 1) { - botList.bots.forEach(bot -> builder.suggest(bot.getName().getString())); - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java new file mode 100644 index 00000000..dc134eed --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/ArgumentNode.java @@ -0,0 +1,66 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +public abstract class ArgumentNode extends CommandNode { + protected final ArgumentType argumentType; + + protected ArgumentNode(String name, ArgumentType argumentType) { + super(name); + this.argumentType = argumentType; + } + + @SuppressWarnings({"unused", "RedundantThrows"}) + protected CompletableFuture getSuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException { + return Suggestions.empty(); + } + + protected boolean overrideSuggestions() { + return isMethodOverridden("getSuggestions", ArgumentNode.class); + } + + @Override + protected ArgumentBuilder compileBase() { + RequiredArgumentBuilder argumentBuilder = Commands.argument(name, argumentType); + + if (overrideSuggestions()) { + argumentBuilder.suggests( + (context, builder) -> getSuggestions(new CommandContext(context), builder) + ); + } + + return argumentBuilder; + } + + public static class ArgumentSuggestions { + @Contract(pure = true) + public static WrappedArgument.@NotNull SuggestionApplier strings(String... values) { + return (context, builder) -> { + for (String s : values) { + builder.suggest(s); + } + }; + } + + @Contract(pure = true) + public static WrappedArgument.@NotNull SuggestionApplier strings(List values) { + return (context, builder) -> { + for (String s : values) { + builder.suggest(s); + } + }; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java deleted file mode 100644 index bc0c3dca..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgument.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.BiFunction; - -public class CommandArgument { - - public static final CommandArgument EMPTY = new CommandArgument(); - - private static final Pair, String> EMPTY_SUGGESTION_RESULT = Pair.of(List.of(), null); - private static final BiFunction, String>> EMPTY_SUGGESTION = (sender, arg) -> EMPTY_SUGGESTION_RESULT; - - private final List, String>>> suggestions; - private final List> argumentTypes; - - private CommandArgument(CommandArgumentType... argumentTypes) { - this.argumentTypes = List.of(argumentTypes); - this.suggestions = new ArrayList<>(); - for (int i = 0; i < argumentTypes.length; i++) { - suggestions.add(EMPTY_SUGGESTION); - } - } - - public static CommandArgument of(CommandArgumentType... argumentTypes) { - return new CommandArgument(argumentTypes); - } - - public List> getArgumentTypes() { - return argumentTypes; - } - - public CommandArgument setSuggestion(int n, BiFunction, String>> suggestion) { - this.suggestions.set(n, suggestion); - return this; - } - - public CommandArgument setSuggestion(int n, Pair, String> suggestion) { - return this.setSuggestion(n, (sender, arg) -> suggestion); - } - - public CommandArgument setSuggestion(int n, List tabComplete) { - return this.setSuggestion(n, Pair.of(tabComplete, null)); - } - - public Pair, String> suggestion(int n, CommandSender sender, String arg) { - if (suggestions.size() > n) { - return suggestions.get(n).apply(sender, arg); - } else { - return EMPTY_SUGGESTION.apply(sender, arg); - } - } - - public CommandArgumentResult parse(int index, String @NotNull [] args) { - Object[] result = new Object[argumentTypes.size()]; - Arrays.fill(result, null); - for (int i = index, j = 0; i < args.length && j < result.length; i++, j++) { - result[j] = argumentTypes.get(j).parse(args[i]); - } - return new CommandArgumentResult(new ArrayList<>(Arrays.asList(result))); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java deleted file mode 100644 index a56cd7b8..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentResult.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.leavesmc.leaves.command; - -import net.minecraft.core.BlockPos; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Objects; - -public class CommandArgumentResult { - - private final List result; - - public CommandArgumentResult(List result) { - this.result = result; - } - - public int readInt(int def) { - return Objects.requireNonNullElse(read(Integer.class), def); - } - - public double readDouble(double def) { - return Objects.requireNonNullElse(read(Double.class), def); - } - - public float readFloat(float def) { - return Objects.requireNonNullElse(read(Float.class), def); - } - - public String readString(String def) { - return Objects.requireNonNullElse(read(String.class), def); - } - - public boolean readBoolean(boolean def) { - return Objects.requireNonNullElse(read(Boolean.class), def); - } - - public BlockPos readPos() { - Integer[] pos = {read(Integer.class), read(Integer.class), read(Integer.class)}; - for (Integer po : pos) { - if (po == null) { - return null; - } - } - return new BlockPos(pos[0], pos[1], pos[2]); - } - - public @Nullable Vector readVector() { - Double[] pos = {read(Double.class), read(Double.class), read(Double.class)}; - for (Double po : pos) { - if (po == null) { - return null; - } - } - return new Vector(pos[0], pos[1], pos[2]); - } - - public @NotNull Vector readVectorYZ(double x) { - Double[] pos = {x, read(Double.class), read(Double.class)}; - for (Double po : pos) { - if (po == null) { - throw new IllegalArgumentException("Failed to read vector!"); - } - } - return new Vector(pos[0], pos[1], pos[2]); - } - - public Object readObject() { - if (result.isEmpty()) { - return null; - } - return result.removeFirst(); - } - - public T read(Class tClass, T def) { - return Objects.requireNonNullElse(read(tClass), def); - } - - public T read(Class tClass) { - if (result.isEmpty()) { - return null; - } - - Object obj = result.removeFirst(); - if (tClass.isInstance(obj)) { - return tClass.cast(obj); - } else { - return null; - } - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java deleted file mode 100644 index b39f6f46..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandArgumentType.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Function; - -public abstract class CommandArgumentType { - - public static final CommandArgumentType STRING = CommandArgumentType.string(); - public static final CommandArgumentType INTEGER = CommandArgumentType.of(Integer.class, Integer::parseInt); - public static final CommandArgumentType DOUBLE = CommandArgumentType.of(Double.class, Double::parseDouble); - public static final CommandArgumentType FLOAT = CommandArgumentType.of(Float.class, Float::parseFloat); - public static final CommandArgumentType BOOLEAN = CommandArgumentType.of(Boolean.class, Boolean::parseBoolean); - - private final Class type; - - private CommandArgumentType(Class type) { - this.type = type; - } - - @NotNull - @Contract(value = "_, _ -> new", pure = true) - public static CommandArgumentType of(Class type, Function parse) { - return new CommandArgumentType<>(type) { - @Override - public E parse(@NotNull String arg) { - try { - return parse.apply(arg); - } catch (Exception ignore) { - return null; - } - } - }; - } - - @NotNull - @Contract(value = "_ -> new", pure = true) - public static > CommandArgumentType ofEnum(Class type) { - return of(type, (string -> Enum.valueOf(type, string.toUpperCase()))); - } - - @NotNull - @Contract(value = " -> new", pure = true) - private static CommandArgumentType string() { - return new CommandArgumentType<>(String.class) { - @Override - public String parse(@NotNull String arg) { - return arg; - } - }; - } - - public Class getType() { - return type; - } - - public abstract E parse(@NotNull String arg); -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java new file mode 100644 index 00000000..21dee9f9 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandContext.java @@ -0,0 +1,125 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.RedirectModifier; +import com.mojang.brigadier.context.ParsedCommandNode; +import com.mojang.brigadier.context.StringRange; +import com.mojang.brigadier.tree.CommandNode; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +import static org.leavesmc.leaves.command.CommandNode.getNameForNode; + +@SuppressWarnings({"ClassCanBeRecord", "unused"}) +public class CommandContext { + private final com.mojang.brigadier.context.CommandContext source; + + public CommandContext(com.mojang.brigadier.context.CommandContext source) { + this.source = source; + } + + public com.mojang.brigadier.context.CommandContext getChild() { + return source.getChild(); + } + + public com.mojang.brigadier.context.CommandContext getLastChild() { + return source.getLastChild(); + } + + public Command getCommand() { + return source.getCommand(); + } + + public CommandSourceStack getSource() { + return source.getSource(); + } + + public CommandSender getSender() { + return source.getSource().getSender(); + } + + public @NotNull V getArgument(final String name, final Class clazz) { + return source.getArgument(name, clazz); + } + + public int getInteger(final String name) { + return source.getArgument(name, Integer.class); + } + + public boolean getBoolean(final String name) { + return source.getArgument(name, Boolean.class); + } + + public String getString(final String name) { + return source.getArgument(name, String.class); + } + + @SuppressWarnings("unchecked") + public @NotNull V getArgument(final Class> nodeClass) { + String name = getNameForNode(nodeClass); + return (V) source.getArgument(name, Object.class); + } + + public V getArgumentOrDefault(final Class> nodeClass, final V defaultValue) { + try { + return getArgument(nodeClass); + } catch (IllegalArgumentException e) { + return defaultValue; + } + } + + public V getArgumentOrDefault(final String name, final Class clazz, final V defaultValue) { + try { + return source.getArgument(name, clazz); + } catch (IllegalArgumentException e) { + return defaultValue; + } + } + + public String getStringOrDefault(final String name, final String defaultValue) { + return getArgumentOrDefault(name, String.class, defaultValue); + } + + public int getIntegerOrDefault(final String name, final int defaultValue) { + return getArgumentOrDefault(name, Integer.class, defaultValue); + } + + public float getFloatOrDefault(final String name, final float defaultValue) { + return getArgumentOrDefault(name, Float.class, defaultValue); + } + + public RedirectModifier getRedirectModifier() { + return source.getRedirectModifier(); + } + + public StringRange getRange() { + return source.getRange(); + } + + public String getInput() { + return source.getInput(); + } + + public CommandNode getRootNode() { + return source.getRootNode(); + } + + public List> getNodes() { + return source.getNodes(); + } + + public boolean hasNodes() { + return source.hasNodes(); + } + + public boolean isForked() { + return source.isForked(); + } + + public com.mojang.brigadier.context.CommandContext getMojangContext() { + return source; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java new file mode 100644 index 00000000..3a640364 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandNode.java @@ -0,0 +1,79 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Stream; + +public abstract class CommandNode { + private static final Map, String> class2NameMap = new HashMap<>(); + + protected final String name; + protected final List children = new ArrayList<>(); + + protected CommandNode(String name) { + this.name = name; + class2NameMap.put(getClass(), name); + } + + @SafeVarargs + protected final void children(Supplier... childrenClasses) { + this.children.addAll(Stream.of(childrenClasses).map(Supplier::get).toList()); + } + + protected abstract ArgumentBuilder compileBase(); + + protected boolean execute(CommandContext context) throws CommandSyntaxException { + return true; + } + + public boolean requires(CommandSourceStack source) { + return true; + } + + public String getName() { + return this.name; + } + + protected ArgumentBuilder compile() { + ArgumentBuilder builder = compileBase().requires(this::requires); + + for (CommandNode child : children) { + builder = builder.then(child.compile()); + } + + if (canExecute()) { + builder = builder.executes(mojangCtx -> { + CommandContext ctx = new CommandContext(mojangCtx); + return execute(ctx) ? 1 : 0; + }); + } + + return builder; + } + + protected boolean canExecute() { + return isMethodOverridden("execute", CommandNode.class); + } + + protected boolean isMethodOverridden(String methodName, @NotNull Class baseClass) { + for (Method method : getClass().getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + return method.getDeclaringClass() != baseClass; + } + } + return false; + } + + public static String getNameForNode(Class nodeClass) { + return class2NameMap.get(nodeClass); + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java similarity index 59% rename from leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java index afb48b7e..bdf3d41c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommandUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/CommandUtils.java @@ -3,14 +3,17 @@ package org.leavesmc.leaves.command; import com.google.common.base.Functions; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import net.minecraft.resources.ResourceLocation; -import org.bukkit.command.CommandSender; +import org.bukkit.Bukkit; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; +import org.bukkit.plugin.PluginManager; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.framework.qual.DefaultQualifier; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -18,76 +21,31 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -@DefaultQualifier(NonNull.class) -public class LeavesCommandUtil { +public class CommandUtils { - private LeavesCommandUtil() { + public static void registerPermissions(String base, @NotNull List children) { + List permissions = new ArrayList<>(); + permissions.add(base); + permissions.addAll(children.stream().map((it) -> base + "." + it.getName()).toList()); + registerPermissions(permissions); } - // Code from Mojang - copyright them - public static List getListMatchingLast( - final CommandSender sender, - final String[] args, - final String... matches - ) { - return getListMatchingLast(sender, args, Arrays.asList(matches)); - } - - public static boolean matches(final String s, final String s1) { - return s1.regionMatches(true, 0, s, 0, s.length()); - } - - public static List getListMatchingLast( - final CommandSender sender, - final String[] strings, - final Collection collection - ) { - return getListMatchingLast(sender, strings, collection, LeavesCommand.BASE_PERM, "bukkit.command.leaves"); - } - - public static List getListMatchingLast( - final CommandSender sender, - final String[] strings, - final Collection collection, - final String basePermission, - final String overridePermission - ) { - String last = strings[strings.length - 1]; - ArrayList results = Lists.newArrayList(); - - if (!collection.isEmpty()) { - - for (String s1 : Iterables.transform(collection, Functions.toStringFunction())) { - if (matches(last, s1) && (sender.hasPermission(basePermission + s1) || sender.hasPermission(overridePermission))) { - results.add(s1); - } - } - - if (results.isEmpty()) { - for (Object object : collection) { - if (object instanceof ResourceLocation && matches(last, ((ResourceLocation) object).getPath())) { - results.add(String.valueOf(object)); - } - } + public static void registerPermissions(@NotNull List permissions) { + PluginManager pluginManager = Bukkit.getServer().getPluginManager(); + for (String perm : permissions) { + if (pluginManager.getPermission(perm) == null) { + pluginManager.addPermission(new Permission(perm, PermissionDefault.OP)); } } - - return results; } - // end copy stuff - public static List getListClosestMatchingLast( - final CommandSender sender, - final String last, - final Collection collection, - final String overridePermission - ) { - ArrayList candidates = Lists.newArrayList(); - - if (collection.isEmpty() || !sender.hasPermission(overridePermission)) { + @DefaultQualifier(NonNull.class) + public static List getListClosestMatchingLast(final String last, final Collection collection) { + if (collection.isEmpty()) { return Collections.emptyList(); } + ArrayList candidates = Lists.newArrayList(); String lastLower = last.toLowerCase(); for (String item : Iterables.transform(collection, Functions.toStringFunction())) { String itemLower = item.toLowerCase(); @@ -97,7 +55,7 @@ public class LeavesCommandUtil { candidates.add(Candidate.of(item, damerauLevenshteinDistance(lastLower, itemLower))); } } - candidates.sort(Comparator.comparingInt(c -> c.score)); + candidates.sort(Comparator.comparingInt(Candidate::score)); List results = new ArrayList<>(candidates.size()); for (Candidate candidate : candidates) { @@ -124,7 +82,7 @@ public class LeavesCommandUtil { if (s1 != null && s2 == null) { return s1.length(); } - if (s1 == null && s2 != null) { + if (s1 == null) { return s2.length(); } @@ -171,11 +129,10 @@ public class LeavesCommandUtil { return H[s1Len + 1][s2Len + 1]; } - // Copy from org/bukkit/command/defaults/HelpCommand.java - private record Candidate(String item, int score) { - private static Candidate of(String item, int score) { + @Contract("_, _ -> new") + private static @NotNull Candidate of(String item, int score) { return new Candidate(item, score); } } -} \ No newline at end of file +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java deleted file mode 100644 index caea88aa..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesCommand.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.leavesmc.leaves.command; - -import net.minecraft.Util; -import org.leavesmc.leaves.command.subcommands.BlockUpdateCommand; -import org.leavesmc.leaves.command.subcommands.ConfigCommand; -import org.leavesmc.leaves.command.subcommands.CounterCommand; -import org.leavesmc.leaves.command.subcommands.ReloadCommand; -import org.leavesmc.leaves.command.subcommands.ReportCommand; -import org.leavesmc.leaves.command.subcommands.UpdateCommand; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public final class LeavesCommand extends LeavesRootCommand { - - public static final String BASE_PERM = "bukkit.command.leaves."; - - // subcommand label -> subcommand - private static final Map SUBCOMMANDS = Util.make(() -> { - final Map, LeavesSubcommand> commands = new HashMap<>(); - commands.put(Set.of("config"), new ConfigCommand()); - commands.put(Set.of("update"), new UpdateCommand()); - commands.put(Set.of("counter"), new CounterCommand()); - commands.put(Set.of("reload"), new ReloadCommand()); - commands.put(Set.of("report"), new ReportCommand()); - commands.put(Set.of("blockupdate"), new BlockUpdateCommand()); - - return commands.entrySet().stream() - .flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue()))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - }); - - public LeavesCommand() { - super("leaves", "Leaves related commands", "bukkit.command.leaves", SUBCOMMANDS); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesRootCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesRootCommand.java deleted file mode 100644 index 90bda53e..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesRootCommand.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.leavesmc.leaves.command; - -import it.unimi.dsi.fastutil.Pair; -import net.kyori.adventure.text.Component; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.permissions.Permission; -import org.bukkit.permissions.PermissionDefault; -import org.bukkit.plugin.PluginManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.RED; - -public abstract class LeavesRootCommand extends Command implements LeavesSuggestionCommand { - - protected final String basePermission; - protected final Map subcommands; - - protected LeavesRootCommand( - @NotNull String name, - @NotNull String description, - @NotNull String basePermission, - @NotNull Map subCommands - ) { - super(name, description, String.format("/%s [%s]", name, String.join(" | ", subCommands.keySet())), Collections.emptyList()); - this.basePermission = basePermission; - this.subcommands = subCommands; - - final List permissions = new ArrayList<>(); - permissions.add(basePermission); - permissions.addAll(subCommands.keySet().stream().map(s -> basePermission + "." + s).toList()); - this.setPermission(String.join(";", permissions)); - final PluginManager pluginManager = Bukkit.getServer().getPluginManager(); - for (final String perm : permissions) { - if (pluginManager.getPermission(perm) == null) { - pluginManager.addPermission(new Permission(perm, PermissionDefault.OP)); - } - } - } - - protected boolean testPermission(final CommandSender sender, final String permission) { - if (sender.hasPermission(basePermission) || sender.hasPermission(basePermission + "." + permission)) { - return true; - } - sender.sendMessage(Bukkit.permissionMessage()); - return false; - } - - @Override - public boolean execute(@NotNull CommandSender sender, @NotNull String label, @NotNull String @NotNull [] args) { - if (!testPermission(sender) || !isEnabled()) { - return true; - } - - if (args.length == 0) { - sender.sendMessage(unknownMessage()); - return true; - } - final Pair subCommand = resolveCommand(args[0]); - - if (subCommand == null) { - sender.sendMessage(unknownMessage()); - return true; - } - - if (!testPermission(sender, subCommand.first())) { - return true; - } - final String[] choppedArgs = Arrays.copyOfRange(args, 1, args.length); - subCommand.second().execute(sender, subCommand.first(), choppedArgs); - return true; - } - - @Override - public void suggest(final @NotNull CommandSender sender, final @NotNull String alias, final @NotNull String @NotNull [] args, final @Nullable Location location, @NotNull LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (!testPermission(sender) || !isEnabled()) { - return; - } - if (args.length <= 1) { - LeavesCommandUtil.getListMatchingLast(sender, args, usableSubcommands(), basePermission + ".", basePermission).forEach(builder::suggest); - return; - } - final @Nullable Pair subCommand = resolveCommand(args[0]); - if (subCommand != null) { - subCommand.second().suggest(sender, subCommand.first(), Arrays.copyOfRange(args, 1, args.length), location, builder); - } - } - - public Component unknownMessage() { - return text(String.format("Usage: /%s [%s]", this.getName(), String.join(" | ", usableSubcommands())), RED); - } - - @Nullable - public Pair resolveCommand(String label) { - label = label.toLowerCase(Locale.ENGLISH); - LeavesSubcommand subCommand = subcommands.get(label); - - if (subCommand != null && subCommand.isEnabled()) { - return Pair.of(label, subCommand); - } - - return null; - } - - public Collection usableSubcommands() { - List subcommandList = new ArrayList<>(); - for (var entry : subcommands.entrySet()) { - if (entry.getValue().isEnabled()) { - subcommandList.add(entry.getKey()); - } - } - return subcommandList; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java deleted file mode 100644 index c026b634..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSubcommand.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.bukkit.command.CommandSender; - -public interface LeavesSubcommand extends LeavesSuggestionCommand { - void execute(CommandSender sender, String subCommand, String[] args); -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionBuilder.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionBuilder.java deleted file mode 100644 index 1eb02281..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionBuilder.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.leavesmc.leaves.command; - -import com.mojang.brigadier.Message; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; - -import java.util.concurrent.CompletableFuture; - -public class LeavesSuggestionBuilder { - - private SuggestionsBuilder vanillaBuilder; - - public LeavesSuggestionBuilder(SuggestionsBuilder builder) { - this.vanillaBuilder = builder; - } - - public CompletableFuture build() { - return vanillaBuilder.buildFuture(); - } - - public LeavesSuggestionBuilder suggest(String text) { - vanillaBuilder.suggest(text); - return this; - } - - public LeavesSuggestionBuilder suggest(String text, Message tooltip) { - vanillaBuilder.suggest(text, tooltip); - return this; - } - - public LeavesSuggestionBuilder suggest(int value) { - vanillaBuilder.suggest(value); - return this; - } - - public LeavesSuggestionBuilder suggest(int value, Message tooltip) { - vanillaBuilder.suggest(value, tooltip); - return this; - } - - public LeavesSuggestionBuilder createOffset(int start) { - vanillaBuilder = vanillaBuilder.createOffset(start); - return this; - } - - public String getInput() { - return vanillaBuilder.getInput(); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionCommand.java deleted file mode 100644 index ed0f1c5f..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/LeavesSuggestionCommand.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.leavesmc.leaves.command; - -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface LeavesSuggestionCommand { - default void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - } - - default boolean isEnabled() { - return true; - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java new file mode 100644 index 00000000..340f389c --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/LiteralNode.java @@ -0,0 +1,17 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; + +public class LiteralNode extends CommandNode { + + protected LiteralNode(String name) { + super(name); + } + + @Override + protected ArgumentBuilder compileBase() { + return Commands.literal(name); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java new file mode 100644 index 00000000..b2805c6e --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/RootNode.java @@ -0,0 +1,50 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.PaperCommands; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import static org.leavesmc.leaves.command.CommandUtils.registerPermissions; + +public abstract class RootNode extends LiteralNode { + private final String permissionBase; + + public RootNode(String name, String permissionBase) { + super(name); + this.permissionBase = permissionBase; + } + + @Override + protected ArgumentBuilder compile() { + registerPermissions(permissionBase, this.children); + return super.compile(); + } + + protected static boolean hasPermission(@NotNull CommandSender sender, String subcommand, String permissionBase) { + return sender.hasPermission(permissionBase) || sender.hasPermission(permissionBase + "." + subcommand); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return children.stream().anyMatch(child -> child.requires(source)); + } + + @SuppressWarnings("unchecked") + public void register() { + PaperCommands.INSTANCE.setValid(); + PaperCommands.INSTANCE.getDispatcher().register((LiteralArgumentBuilder) compile()); + PaperCommands.INSTANCE.invalidate(); + Bukkit.getOnlinePlayers().forEach(org.bukkit.entity.Player::updateCommands); + } + + public void unregister() { + PaperCommands.INSTANCE.setValid(); + PaperCommands.INSTANCE.getDispatcher().getRoot().removeCommand(name); + PaperCommands.INSTANCE.invalidate(); + Bukkit.getOnlinePlayers().forEach(org.bukkit.entity.Player::updateCommands); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java new file mode 100644 index 00000000..0c3326fb --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/WrappedArgument.java @@ -0,0 +1,68 @@ +package org.leavesmc.leaves.command; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; + +import java.util.concurrent.CompletableFuture; + +public class WrappedArgument { + private final String name; + private final ArgumentType type; + private AsyncSuggestionProvider asyncSuggestionProvider = null; + private SuggestionApplier suggestionApplier = null; + private boolean optional = false; + + public WrappedArgument(String name, ArgumentType type) { + this.name = name; + this.type = type; + } + + public WrappedArgument suggestsAsync(AsyncSuggestionProvider provider) { + this.asyncSuggestionProvider = provider; + return this; + } + + public WrappedArgument suggests(SuggestionApplier provider) { + this.suggestionApplier = provider; + return this; + } + + public WrappedArgument setOptional(boolean optional) { + this.optional = optional; + return this; + } + + public boolean isOptional() { + return optional; + } + + public RequiredArgumentBuilder compile() { + RequiredArgumentBuilder builder = Commands.argument(name, type); + if (asyncSuggestionProvider != null) { + builder.suggests((context, b) -> + asyncSuggestionProvider.getSuggestions(new CommandContext(context), b) + ); + } else if (suggestionApplier != null) { + builder.suggests((context, b) -> { + suggestionApplier.applySuggestions(new CommandContext(context), b); + return CompletableFuture.completedFuture(b.build()); + }); + } + return builder; + } + + @FunctionalInterface + public interface SuggestionApplier { + void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } + + @FunctionalInterface + public interface AsyncSuggestionProvider { + CompletableFuture getSuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java new file mode 100644 index 00000000..f4518812 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/BotArgumentType.java @@ -0,0 +1,54 @@ +package org.leavesmc.leaves.command.arguments; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.BotList; +import org.leavesmc.leaves.bot.ServerBot; + +import java.util.Collection; +import java.util.concurrent.CompletableFuture; + +public class BotArgumentType implements CustomArgumentType.Converted<@NotNull ServerBot, @NotNull String> { + + private BotArgumentType() { + } + + public static @NotNull BotArgumentType bot() { + return new BotArgumentType(); + } + + @Override + public @NotNull CompletableFuture listSuggestions(com.mojang.brigadier.context.@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + Collection bots = BotList.INSTANCE.bots; + if (bots.isEmpty()) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("There are no bots in the server, create one first.")) + .buildFuture(); + } + bots.stream().map(ServerBot::getScoreboardName).forEach(builder::suggest); + return builder.buildFuture(); + } + + @Override + public ServerBot convert(String nativeType) throws CommandSyntaxException { + ServerBot bot = BotList.INSTANCE.getBotByName(nativeType); + if (bot == null) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), + Component.literal("Bot with name '" + nativeType + "' does not exist") + ); + } + return bot; + } + + @Override + public @NotNull ArgumentType<@NotNull String> getNativeType() { + return StringArgumentType.word(); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/EnumArgumentType.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/EnumArgumentType.java new file mode 100644 index 00000000..ef90de03 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/arguments/EnumArgumentType.java @@ -0,0 +1,81 @@ +package org.leavesmc.leaves.command.arguments; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +@SuppressWarnings("ClassCanBeRecord") +public final class EnumArgumentType> implements CustomArgumentType.Converted<@NotNull T, @NotNull String> { + private final Class enumClass; + + @Contract(value = "_ -> new", pure = true) + public static > @NotNull EnumArgumentType fromEnum(Class enumClass) { + return new EnumArgumentType<>(enumClass); + } + + private EnumArgumentType(Class enumClass) { + this.enumClass = enumClass; + } + + @Override + public @NotNull T convert(@NotNull String nativeType) throws CommandSyntaxException { + try { + return Enum.valueOf(enumClass, nativeType.toUpperCase()); + } catch (IllegalArgumentException e) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + } + + @Override + public @NotNull CompletableFuture listSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + for (Enum value : enumClass.getEnumConstants()) { + String name = value.name().toLowerCase(); + if (name.startsWith(builder.getRemainingLowerCase())) { + builder.suggest(name); + } + } + return builder.buildFuture(); + } + + @Override + public @NotNull ArgumentType<@NotNull String> getNativeType() { + return StringArgumentType.word(); + } + + public Class enumClass() { + return enumClass; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + EnumArgumentType that = (EnumArgumentType) obj; + return Objects.equals(this.enumClass, that.enumClass); + } + + @Override + public int hashCode() { + return Objects.hash(enumClass); + } + + @Override + public String toString() { + return "EnumArgumentType[" + + "enumClass=" + enumClass + ']'; + } + +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java new file mode 100644 index 00000000..758fb015 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotCommand.java @@ -0,0 +1,48 @@ +package org.leavesmc.leaves.command.bot; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.RootNode; +import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; +import org.leavesmc.leaves.command.bot.subcommands.ConfigCommand; +import org.leavesmc.leaves.command.bot.subcommands.CreateCommand; +import org.leavesmc.leaves.command.bot.subcommands.ListCommand; +import org.leavesmc.leaves.command.bot.subcommands.LoadCommand; +import org.leavesmc.leaves.command.bot.subcommands.RemoveCommand; +import org.leavesmc.leaves.command.bot.subcommands.SaveCommand; + +import static org.leavesmc.leaves.command.CommandUtils.registerPermissions; + +public class BotCommand extends RootNode { + public static final BotCommand INSTANCE = new BotCommand(); + private static final String PERM_BASE = "bukkit.command.bot"; + + private BotCommand() { + super("bot", PERM_BASE); + this.children( + ListCommand::new, + ConfigCommand::new, + RemoveCommand::new, + LoadCommand::new, + SaveCommand::new, + ActionCommand::new, + CreateCommand::new + ); + } + + @Override + protected ArgumentBuilder compile() { + registerPermissions(PERM_BASE, this.children); + return super.compile(); + } + + public static boolean hasPermission(@NotNull CommandSender sender) { + return sender.hasPermission(PERM_BASE); + } + + public static boolean hasPermission(@NotNull CommandSender sender, String subcommand) { + return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java new file mode 100644 index 00000000..a46dfcc9 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/BotSubcommand.java @@ -0,0 +1,16 @@ +package org.leavesmc.leaves.command.bot; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.LiteralNode; + +public abstract class BotSubcommand extends LiteralNode { + protected BotSubcommand(String name) { + super(name); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return BotCommand.hasPermission(source.getSender(), this.name); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java new file mode 100644 index 00000000..d0736996 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ActionCommand.java @@ -0,0 +1,42 @@ +package org.leavesmc.leaves.command.bot.subcommands; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.arguments.BotArgumentType; +import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.command.bot.subcommands.action.ListCommand; +import org.leavesmc.leaves.command.bot.subcommands.action.StartCommand; +import org.leavesmc.leaves.command.bot.subcommands.action.StopCommand; + +public class ActionCommand extends BotSubcommand { + + public ActionCommand() { + super("action"); + children(BotArgument::new); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.fakeplayer.canUseAction && super.requires(source); + } + + public static class BotArgument extends ArgumentNode { + + private BotArgument() { + super("bot", BotArgumentType.bot()); + children( + StartCommand::new, + StopCommand::new, + ListCommand::new + ); + } + + public static @NotNull ServerBot getBot(@NotNull CommandContext context) { + return context.getArgument(BotArgument.class); + } + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java new file mode 100644 index 00000000..98fb98c4 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ConfigCommand.java @@ -0,0 +1,132 @@ +package org.leavesmc.leaves.command.bot.subcommands; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.Configs; +import org.leavesmc.leaves.bot.agent.configs.AbstractBotConfig; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.arguments.BotArgumentType; +import org.leavesmc.leaves.command.bot.BotSubcommand; + +import java.util.Collection; +import java.util.function.Supplier; + +import static io.papermc.paper.adventure.PaperAdventure.asAdventure; +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class ConfigCommand extends BotSubcommand { + + public ConfigCommand() { + super("config"); + children(BotArgument::new); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.fakeplayer.canModifyConfig && super.requires(source); + } + + private static class BotArgument extends ArgumentNode { + + private BotArgument() { + super("bot", BotArgumentType.bot()); + Configs.getConfigs().stream().map(this::configNodeCreator).forEach(this::children); + } + + @Contract(pure = true) + private @NotNull Supplier configNodeCreator(AbstractBotConfig config) { + return () -> new ConfigNode<>(config); + } + + public static @NotNull ServerBot getBot(@NotNull CommandContext context) { + return context.getArgument(BotArgument.class); + } + + @Override + protected boolean execute(CommandContext context) { + ServerBot bot = BotArgument.getBot(context); + CommandSender sender = context.getSender(); + Collection> botConfigs = bot.getAllConfigs(); + sender.sendMessage(join(spaces(), + text("Bot", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("configs:", GRAY) + )); + for (AbstractBotConfig botConfig : botConfigs) { + sender.sendMessage(join(spaces(), + botConfig.getNameComponent(), + text("=", GRAY), + text(String.valueOf(botConfig.getValue()), AQUA) + )); + } + return true; + } + } + + private static class ConfigNode extends LiteralNode { + private final AbstractBotConfig config; + + private ConfigNode(@NotNull AbstractBotConfig config) { + super(config.getName()); + this.config = config; + } + + @Override + protected ArgumentBuilder compileBase() { + RequiredArgumentBuilder argument = config.getArgument() + .compile() + .executes(mojangCtx -> { + CommandContext ctx = new CommandContext(mojangCtx); + return executeSet(ctx) ? 1 : 0; + }); + return super.compileBase().then(argument); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + ServerBot bot = BotArgument.getBot(context); + AbstractBotConfig botConfig = bot.getConfig(config); + context.getSender().sendMessage(join(spaces(), + text("Bot", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("config", GRAY), + botConfig.getNameComponent(), + text("is", GRAY), + text(String.valueOf(bot.getConfig(config).getValue()), AQUA) + )); + return true; + } + + private boolean executeSet(CommandContext context) throws CommandSyntaxException { + ServerBot bot = BotArgument.getBot(context); + AbstractBotConfig botConfig = bot.getConfig(config); + try { + botConfig.setValue(botConfig.loadFromCommand(context)); + } catch (ClassCastException e) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + context.getSender().sendMessage(join(spaces(), + text("Bot", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("config", GRAY), + botConfig.getNameComponent(), + text("changed to", GRAY), + text(String.valueOf(botConfig.getValue()), AQUA) + )); + return true; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java new file mode 100644 index 00000000..2101c001 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/CreateCommand.java @@ -0,0 +1,146 @@ +package org.leavesmc.leaves.command.bot.subcommands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.argument.ArgumentTypes; +import io.papermc.paper.command.brigadier.argument.resolvers.FinePositionResolver; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.BotCreateState; +import org.leavesmc.leaves.bot.BotList; +import org.leavesmc.leaves.bot.BotUtil; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.event.bot.BotCreateEvent; + +import static net.kyori.adventure.text.Component.text; + +public class CreateCommand extends BotSubcommand { + + public CreateCommand() { + super("create"); + children(NameArgument::new); + } + + protected static boolean handleCreateCommand(@NotNull CommandContext context) throws CommandSyntaxException { + CommandSender sender = context.getSender(); + + String rawName = context.getArgument(NameArgument.class); + String fullName = BotUtil.getFullName(rawName); + if (!canCreate(sender, fullName)) { // Check full name + return false; + } + String skinName = context.getArgumentOrDefault(SkinNameArgument.class, rawName); // Use raw name for correct skin + + World world; + try { + world = context.getArgument(WorldArgument.class); + } catch (IllegalArgumentException e) { + if (!(sender instanceof Entity entity)) { + sender.sendMessage(text("Must specify world and location when executed by console", NamedTextColor.RED)); + return false; + } + world = entity.getWorld(); + } + + Location location = Bukkit.getWorlds().getFirst().getSpawnLocation(); + FinePositionResolver positionResolver = context.getArgumentOrDefault(LocationArgument.class, null); + if (positionResolver != null) { + Vector vec3 = positionResolver.resolve(context.getSource()).toVector(); + location = new Location(world, vec3.getX(), vec3.getY(), vec3.getZ()); + } else if (sender instanceof Entity entity) { + location = entity.getLocation(); + } + + BotCreateState + .builder(rawName, location) + .createReason(BotCreateEvent.CreateReason.COMMAND) + .skinName(skinName) + .creator(sender) + .spawnWithSkin(null); + + return true; + } + + private static boolean canCreate(CommandSender sender, @NotNull String name) { + BotList botList = BotList.INSTANCE; + if (!name.matches("^[a-zA-Z0-9_]{4,16}$")) { + sender.sendMessage(text("This name is illegal, bot name must be 4-16 characters and contain only letters, numbers, and underscores.", NamedTextColor.RED)); + return false; + } + + if (Bukkit.getPlayerExact(name) != null || botList.getBotByName(name) != null) { + sender.sendMessage(text("This bot is already in server", NamedTextColor.RED)); + return false; + } + + if (LeavesConfig.modify.fakeplayer.unableNames.contains(name)) { + sender.sendMessage(text("This name is not allowed in this server", NamedTextColor.RED)); + return false; + } + + if (botList.bots.size() >= LeavesConfig.modify.fakeplayer.limit) { + sender.sendMessage(text("Bot number limit exceeded", NamedTextColor.RED)); + return false; + } + + return true; + } + + private static class NameArgument extends ArgumentNode { + private NameArgument() { + super("name", StringArgumentType.word()); + children(SkinNameArgument::new); + } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + return handleCreateCommand(context); + } + } + + private static class SkinNameArgument extends ArgumentNode { + private SkinNameArgument() { + super("skin_name", StringArgumentType.word()); + children(WorldArgument::new); + } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + return handleCreateCommand(context); + } + } + + private static class WorldArgument extends ArgumentNode { + private WorldArgument() { + super("world", ArgumentTypes.world()); + children(LocationArgument::new); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return source.getSender() instanceof ConsoleCommandSender; + } + } + + private static class LocationArgument extends ArgumentNode { + private LocationArgument() { + super("location", ArgumentTypes.finePosition()); + } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + return handleCreateCommand(context); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java new file mode 100644 index 00000000..3464717d --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/ListCommand.java @@ -0,0 +1,94 @@ +package org.leavesmc.leaves.command.bot.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.command.brigadier.argument.ArgumentTypes; +import net.kyori.adventure.text.Component; +import net.minecraft.world.entity.player.Player; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.CraftWorld; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.BotList; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.bot.BotSubcommand; + +import java.util.List; +import java.util.Objects; + +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.noSeparators; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.*; + +public class ListCommand extends BotSubcommand { + + public ListCommand() { + super("list"); + children(WorldArgument::new); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + Component msg = Bukkit.getWorlds().stream() + .map(ListCommand::getBotListMessage) + .filter(Objects::nonNull) + .reduce((a, b) -> a.append(text("\n")).append(b)) + .orElseGet(() -> text("No bots on the server", GRAY)); + context.getSender().sendMessage(join(noSeparators(), + text("Total bot number: ", GRAY), + text(BotList.INSTANCE.bots.size(), AQUA).hoverEvent(showText(text("current bot count"))), + text("/", GRAY), + text(LeavesConfig.modify.fakeplayer.limit, AQUA).hoverEvent(showText(text("bot count limit"))) + )); + context.getSender().sendMessage(msg); + return true; + } + + protected static @Nullable Component getBotListMessage(@NotNull World world) { + List botsInLevel = BotList.INSTANCE.bots.stream() + .filter((bot) -> bot.getBukkitEntity().getWorld().equals(world)) + .toList(); + if (botsInLevel.isEmpty()) { + return null; + } + + Component botsMsg = botsInLevel.stream() + .map(Player::getDisplayName) + .map(PaperAdventure::asAdventure) + .reduce((a, b) -> a.append(text(", ", GRAY)).append(b)) + .get(); + String worldLocation = ((CraftWorld) world).getHandle().dimension().location().toString(); + return join(noSeparators(), + text(world.getName(), AQUA).hoverEvent(showText(text(worldLocation))), + text(" (" + botsInLevel.size() + ")\n", GRAY), + botsMsg + ); + } + + private static class WorldArgument extends ArgumentNode { + + private WorldArgument() { + super("world", ArgumentTypes.world()); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + World world = context.getArgument(WorldArgument.class); + Component botListMessage = getBotListMessage(world); + CommandSender sender = context.getSender(); + if (botListMessage == null) { + sender.sendMessage(text("No bots in that world", RED)); + } else { + sender.sendMessage(text("Bot in ").append(botListMessage)); + } + return true; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java new file mode 100644 index 00000000..0dece054 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/LoadCommand.java @@ -0,0 +1,75 @@ +package org.leavesmc.leaves.command.bot.subcommands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.BotList; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.bot.BotSubcommand; + +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import static io.papermc.paper.adventure.PaperAdventure.asAdventure; +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; + +public class LoadCommand extends BotSubcommand { + + public LoadCommand() { + super("load"); + children(BotNameArgument::new); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad && super.requires(source); + } + + private static class BotNameArgument extends ArgumentNode { + + private BotNameArgument() { + super("bot_name", StringArgumentType.word()); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + String botName = context.getArgument(BotNameArgument.class); + BotList botList = BotList.INSTANCE; + CommandSender sender = context.getSender(); + if (!botList.getManualSavedBotList().contains(botName)) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + + ServerBot bot = botList.loadNewManualSavedBot(botName); + if (bot == null) { + sender.sendMessage(text("Failed to load bot, please check log", NamedTextColor.RED)); + return false; + } + sender.sendMessage(join(spaces(), text("Successfully loaded bot", NamedTextColor.GRAY), asAdventure(bot.getDisplayName()))); + return true; + } + + @Override + protected CompletableFuture getSuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) { + BotList botList = BotList.INSTANCE; + Set bots = botList.getManualSavedBotList().keySet(); + if (bots.isEmpty()) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("There are no bots saved before, save one first.")) + .buildFuture(); + } + bots.forEach(builder::suggest); + return builder.buildFuture(); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java new file mode 100644 index 00000000..9948ac4f --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/RemoveCommand.java @@ -0,0 +1,170 @@ +package org.leavesmc.leaves.command.bot.subcommands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.adventure.PaperAdventure; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.bot.BotList; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.arguments.BotArgumentType; +import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.event.bot.BotRemoveEvent; +import org.leavesmc.leaves.plugin.MinecraftInternalPlugin; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.minecraft.network.chat.Component.literal; + +public class RemoveCommand extends BotSubcommand { + + public RemoveCommand() { + super("remove"); + children(BotArgument::new); + } + + private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender sender) { + boolean success = BotList.INSTANCE.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, false, false); + if (!success) { + sender = sender == null ? Bukkit.getConsoleSender() : sender; + sender.sendMessage(text("Bot remove canceled by a plugin", RED)); + } + return success; + } + + private static class BotArgument extends ArgumentNode { + private BotArgument() { + super("bot", BotArgumentType.bot()); + children(RemoveTimeArgument::new); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + ServerBot bot = context.getArgument(BotArgument.class); + return removeBot(bot, context.getSender()); + } + } + + private static class RemoveTimeArgument extends ArgumentNode { + + private RemoveTimeArgument() { + super("remove_time", StringArgumentType.word()); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + String removeTimeStr = context.getArgument("remove_time", String.class); + int removeTimeSeconds = parseRemoveTime(removeTimeStr); + ServerBot bot = context.getArgument(BotArgument.class); + CommandSender sender = context.getSender(); + + boolean isReschedule = bot.removeTaskId != -1; + + if (isReschedule) { + Bukkit.getScheduler().cancelTask(bot.removeTaskId); + } + bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> { + bot.removeTaskId = -1; + removeBot(bot, sender); + }, removeTimeSeconds * 20L).getTaskId(); + + sender.sendMessage(join(spaces(), + text("Bot", GRAY), + PaperAdventure.asAdventure(bot.getDisplayName()), + text("scheduled for removal in", GRAY), + text(formatSeconds(removeTimeSeconds), AQUA), + text(isReschedule ? "(rescheduled)" : "", GRAY) + )); + return true; + } + + private static int parseRemoveTime(String timeStr) throws CommandSyntaxException { + if (timeStr == null || timeStr.trim().isEmpty()) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + + if (!timeStr.matches("^[\\d\\shmsHMS]+$")) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("Invalid time format: " + timeStr) + ); + } + + String remaining = timeStr.replaceAll("\\d+[hmsHMS]", "").trim(); + if (!remaining.isEmpty() && remaining.matches(".*\\d+.*")) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("Found trailing numbers without unit: " + timeStr) + ); + } + + Matcher matcher = Pattern.compile("(\\d+)([hmsHMS])").matcher(timeStr); + long seconds = 0; + boolean foundMatch = false; + + while (matcher.find()) { + foundMatch = true; + long value; + try { + value = Long.parseLong(matcher.group(1)); + } catch (NumberFormatException e) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("Number too large: " + matcher.group(1)) + ); + } + + switch (matcher.group(2).toLowerCase()) { + case "h" -> seconds += value * 3600; + case "m" -> seconds += value * 60; + case "s" -> seconds += value; + } + } + + if (!foundMatch) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("No valid time units found in: " + timeStr) + ); + } + + if (seconds > Integer.MAX_VALUE) { + throw new CommandSyntaxException( + CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException(), + literal("Total time exceeds maximum limit") + ); + } + + return (int) seconds; + } + + private static @NotNull String formatSeconds(int totalSeconds) { + int h = totalSeconds / 3600; + int m = (totalSeconds % 3600) / 60; + int s = totalSeconds % 60; + StringBuilder sb = new StringBuilder(); + if (h > 0) { + sb.append(h).append("h"); + } + if (m > 0) { + sb.append(m).append("m"); + } + if (s > 0) { + sb.append(s).append("s"); + } + if (sb.isEmpty()) { + sb.append("0s"); + } + return sb.toString(); + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java new file mode 100644 index 00000000..b45eda20 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/SaveCommand.java @@ -0,0 +1,58 @@ +package org.leavesmc.leaves.command.bot.subcommands; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.BotList; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.arguments.BotArgumentType; +import org.leavesmc.leaves.command.bot.BotSubcommand; +import org.leavesmc.leaves.event.bot.BotRemoveEvent; + +import static io.papermc.paper.adventure.PaperAdventure.asAdventure; +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; + +public class SaveCommand extends BotSubcommand { + + public SaveCommand() { + super("save"); + children(BotArgument::new); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.fakeplayer.canManualSaveAndLoad && super.requires(source); + } + + private static class BotArgument extends ArgumentNode { + + private BotArgument() { + super("bot", BotArgumentType.bot()); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + ServerBot bot = context.getArgument(BotArgument.class); + CommandSender sender = context.getSender(); + BotList botList = BotList.INSTANCE; + + boolean success = botList.removeBot(bot, BotRemoveEvent.RemoveReason.COMMAND, sender, true, false); + if (success) { + sender.sendMessage(join(spaces(), + text("Successfully saved bot", NamedTextColor.GRAY), + asAdventure(bot.getDisplayName()), + text("as " + bot.createState.fullName(), NamedTextColor.GRAY) + )); + } else { + sender.sendMessage(text("Bot save canceled by a plugin", NamedTextColor.RED)); + } + return success; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java new file mode 100644 index 00000000..1547891e --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/ListCommand.java @@ -0,0 +1,50 @@ +package org.leavesmc.leaves.command.bot.subcommands.action; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; + +import java.util.List; + +import static io.papermc.paper.adventure.PaperAdventure.asAdventure; +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class ListCommand extends LiteralNode { + + public ListCommand() { + super("list"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + + CommandSender sender = context.getSender(); + List> actions = bot.getBotActions(); + if (actions.isEmpty()) { + sender.sendMessage(text("This bot has no active actions", GRAY)); + return true; + } + + sender.sendMessage(asAdventure(bot.getDisplayName()).append(text("'s action list:", GRAY))); + for (int i = 0; i < actions.size(); i++) { + AbstractBotAction action = actions.get(i); + sender.sendMessage(join(spaces(), + text(i, GRAY), + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) + )); + } + + return true; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java new file mode 100644 index 00000000..126c8ea2 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StartCommand.java @@ -0,0 +1,112 @@ +package org.leavesmc.leaves.command.bot.subcommands.action; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.Actions; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.WrappedArgument; + +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import static io.papermc.paper.adventure.PaperAdventure.asAdventure; +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static org.leavesmc.leaves.command.bot.subcommands.ActionCommand.BotArgument.getBot; + +public class StartCommand extends LiteralNode { + + public StartCommand() { + super("start"); + Actions.getAll().stream().map(this::actionNodeCreator).forEach(this::children); + } + + private boolean handleStartCommand(CommandContext context, @NotNull AbstractBotAction action) throws CommandSyntaxException { + ServerBot bot = getBot(context); + CommandSender sender = context.getSender(); + + action.loadCommand(context); + if (bot.addBotAction(action, sender)) { + sender.sendMessage(join(spaces(), + text("Action", GRAY), + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))), + text("has been issued to", GRAY), + asAdventure(bot.getDisplayName()) + )); + } + + return true; + } + + @Contract(pure = true) + private @NotNull Supplier actionNodeCreator(AbstractBotAction action) { + return () -> new ActionLiteralNode(action); + } + + private class ActionLiteralNode extends LiteralNode { + private final AbstractBotAction action; + + private ActionLiteralNode(@NotNull AbstractBotAction action) { + super(action.getName()); + this.action = action; + } + + @Override + protected ArgumentBuilder compile() { + ArgumentBuilder builder = super.compile(); + + Map>>> arguments = action.getArguments(); + Command executor = context -> { + if (handleStartCommand(new CommandContext(context), action)) { + return Command.SINGLE_SUCCESS; + } else { + return 0; + } + }; + for (Map.Entry>>> entry : arguments.entrySet()) { + List>> value = entry.getValue(); + ArgumentBuilder branchArgumentBuilder = null; + + for (Pair> stringWrappedArgumentPair : value.reversed()) { + WrappedArgument argument = stringWrappedArgumentPair.getRight(); + if (branchArgumentBuilder == null) { + branchArgumentBuilder = argument.compile().executes(executor); + } else { + branchArgumentBuilder = argument.compile().then(branchArgumentBuilder); + if (argument.isOptional()) { + branchArgumentBuilder = branchArgumentBuilder.executes(executor); + } + } + } + + if (value.getFirst().getRight().isOptional() || value.isEmpty()) { + builder = builder.executes(executor); + } + + if (branchArgumentBuilder != null) { + builder = builder.then(branchArgumentBuilder); + } + } + + if (arguments.isEmpty()) { + builder = builder.executes(executor); + } + + return builder; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java new file mode 100644 index 00000000..16d75583 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/bot/subcommands/action/StopCommand.java @@ -0,0 +1,144 @@ +package org.leavesmc.leaves.command.bot.subcommands.action; + +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.network.chat.Component; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.bot.subcommands.ActionCommand; +import org.leavesmc.leaves.event.bot.BotActionStopEvent; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +import static io.papermc.paper.adventure.PaperAdventure.asAdventure; +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.event.HoverEvent.showText; +import static net.kyori.adventure.text.format.NamedTextColor.*; + +public class StopCommand extends LiteralNode { + + public StopCommand() { + super("stop"); + children(StopIndexArgument::new); + children(StopAll::new); + } + + private static class StopIndexArgument extends ArgumentNode { + + private StopIndexArgument() { + super("index", IntegerArgumentType.integer(0)); + } + + @Override + protected CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + + for (int i = 0; i < bot.getBotActions().size(); i++) { + AbstractBotAction action = bot.getBotActions().get(i); + builder.suggest(String.valueOf(i), Component.literal(action.getName())); + } + + return builder.buildFuture(); + } + + @Override + protected boolean execute(CommandContext context) throws CommandSyntaxException { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + CommandSender sender = context.getSender(); + + int index = context.getArgument(StopIndexArgument.class); + int maxIndex = bot.getBotActions().size() - 1; + if (maxIndex < 0) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create(); + } + if (index > maxIndex) { + throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.integerTooHigh().create(index, maxIndex); + } + + AbstractBotAction action = bot.getBotActions().get(index); + BotActionStopEvent event = new BotActionStopEvent( + bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender + ); + event.callEvent(); + if (!event.isCancelled()) { + action.stop(bot, BotActionStopEvent.Reason.COMMAND); + bot.getBotActions().remove(index); + sender.sendMessage(join(spaces(), + text("Already stopped", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("action", GRAY), + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) + )); + } else { + sender.sendMessage(text("Action stop cancelled by a plugin", RED)); + } + return true; + } + } + + private static class StopAll extends LiteralNode { + + private StopAll() { + super("all"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + ServerBot bot = ActionCommand.BotArgument.getBot(context); + + List> actions = bot.getBotActions(); + CommandSender sender = context.getSender(); + if (actions.isEmpty()) { + sender.sendMessage(text("This bot has no active actions", GRAY)); + return true; + } + + Set> canceled = new HashSet<>(); + Set> forRemoval = new HashSet<>(); + for (AbstractBotAction action : actions) { + BotActionStopEvent event = new BotActionStopEvent( + bot.getBukkitEntity(), action.getName(), action.getUUID(), BotActionStopEvent.Reason.COMMAND, sender + ); + event.callEvent(); + if (!event.isCancelled()) { + forRemoval.add(action); + action.stop(bot, BotActionStopEvent.Reason.COMMAND); + } else { + canceled.add(action); + } + } + bot.getBotActions().removeAll(forRemoval); + + if (canceled.isEmpty()) { + sender.sendMessage(join(spaces(), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("'s action list cleared", GRAY) + )); + } else { + sender.sendMessage(join(spaces(), + text("Tried to clear", GRAY), + asAdventure(bot.getDisplayName()).append(text("'s", GRAY)), + text("'s action list, but following actions' stop was canceled by plugin:", GRAY) + )); + for (AbstractBotAction action : canceled) { + context.getSender().sendMessage( + text(action.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))) + ); + } + } + return true; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java new file mode 100644 index 00000000..f30ec31d --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesCommand.java @@ -0,0 +1,33 @@ +package org.leavesmc.leaves.command.leaves; + +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.RootNode; +import org.leavesmc.leaves.command.leaves.subcommands.BlockUpdateCommand; +import org.leavesmc.leaves.command.leaves.subcommands.ConfigCommand; +import org.leavesmc.leaves.command.leaves.subcommands.CounterCommand; +import org.leavesmc.leaves.command.leaves.subcommands.ReloadCommand; +import org.leavesmc.leaves.command.leaves.subcommands.ReportCommand; +import org.leavesmc.leaves.command.leaves.subcommands.UpdateCommand; + +public class LeavesCommand extends RootNode { + + public static final LeavesCommand INSTANCE = new LeavesCommand(); + private static final String PERM_BASE = "bukkit.command.leaves"; + + private LeavesCommand() { + super("leaves", PERM_BASE); + children( + BlockUpdateCommand::new, + ConfigCommand::new, + CounterCommand::new, + ReloadCommand::new, + ReportCommand::new, + UpdateCommand::new + ); + } + + public static boolean hasPermission(@NotNull CommandSender sender, String subcommand) { + return sender.hasPermission(PERM_BASE) || sender.hasPermission(PERM_BASE + "." + subcommand); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java new file mode 100644 index 00000000..006b0f19 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/LeavesSubcommand.java @@ -0,0 +1,22 @@ +package org.leavesmc.leaves.command.leaves; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.LiteralNode; + +public abstract class LeavesSubcommand extends LiteralNode { + + protected LeavesSubcommand(String name) { + super(name); + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return hasPermission(source.getSender()); + } + + protected boolean hasPermission(CommandSender sender) { + return LeavesCommand.hasPermission(sender, this.name); + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java new file mode 100644 index 00000000..86aa3a54 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/BlockUpdateCommand.java @@ -0,0 +1,99 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; + +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class BlockUpdateCommand extends LeavesSubcommand { + private static boolean noBlockUpdate = false; + + public static boolean isNoBlockUpdate() { + return LeavesConfig.modify.noBlockUpdateCommand && noBlockUpdate; + } + + public BlockUpdateCommand() { + super("blockupdate"); + children( + EnableNode::new, + DisableNode::new + ); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + context.getSender().sendMessage(join(spaces(), + text("Block update is", GRAY), + text(noBlockUpdate ? "disabled" : "enabled", AQUA) + )); + return true; + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.noBlockUpdateCommand && super.requires(source); + } + + private class EnableNode extends LiteralNode { + private EnableNode() { + super("enable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (!noBlockUpdate) { + sender.sendMessage(join(spaces(), + text("Block update is already", GRAY), + text("enabled", AQUA) + )); + return true; + } + noBlockUpdate = false; + Bukkit.getOnlinePlayers().stream() + .filter(BlockUpdateCommand.this::hasPermission) + .forEach(player -> player.sendMessage(join(spaces(), + text("Block update is", GRAY), + text("enabled", AQUA) + ))); + return true; + } + } + + private class DisableNode extends LiteralNode { + private DisableNode() { + super("disable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (noBlockUpdate) { + sender.sendMessage(join(spaces(), + text("Block update is already", GRAY), + text("disabled", AQUA) + )); + return true; + } + noBlockUpdate = true; + Bukkit.getOnlinePlayers().stream() + .filter(BlockUpdateCommand.this::hasPermission) + .forEach(player -> player.sendMessage(join(spaces(), + text("Block update is", GRAY), + text("disabled", AQUA) + ))); + return true; + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java new file mode 100644 index 00000000..2d7505b2 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ConfigCommand.java @@ -0,0 +1,137 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.command.ArgumentNode; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.CommandUtils; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; +import org.leavesmc.leaves.config.GlobalConfigManager; +import org.leavesmc.leaves.config.VerifiedConfig; + +import java.util.concurrent.CompletableFuture; + +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.format.NamedTextColor.*; + +public class ConfigCommand extends LeavesSubcommand { + + public ConfigCommand() { + super("config"); + children(PathArgument::new); + } + + private static class PathArgument extends ArgumentNode { + + private PathArgument() { + super("path", StringArgumentType.string()); + children(ValueArgument::new); + } + + @Override + protected CompletableFuture getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + String path = context.getArgumentOrDefault(PathArgument.class, ""); + int dotIndex = path.lastIndexOf("."); + builder = builder.createOffset(builder.getInput().lastIndexOf(' ') + dotIndex + 2); + CommandUtils.getListClosestMatchingLast(path.substring(dotIndex + 1), GlobalConfigManager.getVerifiedConfigSubPaths(path)) + .forEach(builder::suggest); + return builder.buildFuture(); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + String path = context.getArgument(PathArgument.class); + VerifiedConfig verifiedConfig = getVerifiedConfig(context); + if (verifiedConfig == null) { + return false; + } + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, AQUA), + text("value is", GRAY), + text(verifiedConfig.getString(), AQUA) + )); + return true; + } + + private static @Nullable VerifiedConfig getVerifiedConfig(@NotNull CommandContext context) { + String path = context.getArgument(PathArgument.class); + VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); + if (verifiedConfig == null) { + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, RED), + text("is Not Found.", GRAY) + )); + return null; + } + return verifiedConfig; + } + } + + private static class ValueArgument extends ArgumentNode { + + private ValueArgument() { + super("value", StringArgumentType.greedyString()); + } + + @Override + protected CompletableFuture getSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + String path = context.getArgument(PathArgument.class); + VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(path); + if (verifiedConfig == null) { + return builder + .suggest("", net.minecraft.network.chat.Component.literal("This config path does not exist.")) + .buildFuture(); + } + verifiedConfig.validator().valueSuggest().forEach(builder::suggest); + return builder.buildFuture(); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + VerifiedConfig verifiedConfig = PathArgument.getVerifiedConfig(context); + String path = context.getArgument(PathArgument.class); + String value = context.getArgument(ValueArgument.class); + if (verifiedConfig == null) { + return false; + } + try { + verifiedConfig.set(value); + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, AQUA), + text("changed to", GRAY), + text(verifiedConfig.getString(), AQUA) + )); + Bukkit.getOnlinePlayers() + .stream() + .filter(player -> player.hasPermission("leaves.command.config.notify") && player != context.getSender()) + .forEach( + player -> player.sendMessage(join(spaces(), + text(context.getSender().getName() + ":", GRAY), + text("Config", GRAY), + text(path, AQUA), + text("changed to", GRAY), + text(verifiedConfig.getString(), AQUA) + )) + ); + return true; + } catch (IllegalArgumentException exception) { + context.getSender().sendMessage(join(spaces(), + text("Config", GRAY), + text(path, RED), + text("modify error by", GRAY), + text(exception.getMessage(), RED) + )); + return false; + } + } + } +} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java new file mode 100644 index 00000000..5c14da8e --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/CounterCommand.java @@ -0,0 +1,165 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.item.DyeColor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; +import org.leavesmc.leaves.util.HopperCounter; + +import static net.kyori.adventure.text.Component.join; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.spaces; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class CounterCommand extends LeavesSubcommand { + + public CounterCommand() { + super("counter"); + children( + EnableNode::new, + DisableNode::new, + ResetAllNode::new + ); + for (DyeColor color : DyeColor.values()) { + children(() -> new ColorNode(color)); + } + } + + @Override + public boolean requires(@NotNull CommandSourceStack source) { + return LeavesConfig.modify.hopperCounter.enable && super.requires(source); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + context.getSender().sendMessage(join(spaces(), + text("Hopper counter is", GRAY), + text(HopperCounter.isEnabled() ? "enabled" : "disabled", AQUA) + )); + return true; + } + + private static class EnableNode extends LiteralNode { + private EnableNode() { + super("enable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (HopperCounter.isEnabled()) { + sender.sendMessage(join(spaces(), + text("Hopper counter is already", GRAY), + text("enabled", AQUA) + )); + return true; + } + HopperCounter.setEnabled(true); + sender.sendMessage(join(spaces(), + text("Hopper counter is now", GRAY), + text("enabled", AQUA) + )); + return true; + } + } + + private static class DisableNode extends LiteralNode { + private DisableNode() { + super("disable"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + CommandSender sender = context.getSender(); + if (!HopperCounter.isEnabled()) { + sender.sendMessage(join(spaces(), + text("Hopper counter is already", GRAY), + text("disabled", AQUA) + )); + return true; + } + HopperCounter.setEnabled(false); + sender.sendMessage(join(spaces(), + text("Hopper counter is now", GRAY), + text("disabled", AQUA) + )); + return true; + } + } + + private static class ResetAllNode extends LiteralNode { + private ResetAllNode() { + super("reset"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + HopperCounter.resetAll(MinecraftServer.getServer(), false); + context.getSender().sendMessage(text("Restarted all counters", GRAY)); + return true; + } + } + + private static class ColorNode extends LiteralNode { + private final DyeColor color; + private final HopperCounter counter; + + private ColorNode(@NotNull DyeColor color) { + super(color.getName()); + this.color = color; + this.counter = HopperCounter.getCounter(color); + children( + ResetNode::new, + RealtimeNode::new + ); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + displayCounter(context.getSender(), false); + return true; + } + + private void displayCounter(CommandSender sender, boolean realTime) { + for (Component component : counter.format(MinecraftServer.getServer(), realTime)) { + sender.sendMessage(component); + } + } + + private class ResetNode extends LiteralNode { + private ResetNode() { + super("reset"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + counter.reset(MinecraftServer.getServer()); + context.getSender().sendMessage(join(spaces(), + text("Restarted counter", GRAY), + text(color.getName(), TextColor.color(color.getTextColor())) + )); + return true; + } + } + + private class RealtimeNode extends LiteralNode { + private RealtimeNode() { + super("realtime"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) { + displayCounter(context.getSender(), true); + return true; + } + } + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java new file mode 100644 index 00000000..bf4d4428 --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReloadCommand.java @@ -0,0 +1,29 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; + +public class ReloadCommand extends LeavesSubcommand { + public ReloadCommand() { + super("reload"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + LeavesConfig.reload(); + CommandSender sender = context.getSender(); + sender.sendMessage(text("Leaves config reload complete", GREEN)); + Bukkit.getOnlinePlayers().stream() + .filter(player -> player.hasPermission("leaves.command.config.notify") && player != sender) + .forEach(player -> player.sendMessage(text("Leaves config reloaded", GREEN))); + return true; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReportCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReportCommand.java similarity index 67% rename from leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReportCommand.java rename to leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReportCommand.java index 924fa03b..99984ee2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReportCommand.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/ReportCommand.java @@ -1,4 +1,4 @@ -package org.leavesmc.leaves.command.subcommands; +package org.leavesmc.leaves.command.leaves.subcommands; import io.papermc.paper.plugin.configuration.PluginMeta; import io.papermc.paper.plugin.entrypoint.Entrypoint; @@ -8,22 +8,18 @@ import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; import io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; import net.minecraft.server.MinecraftServer; import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.world.flag.FeatureFlagSet; import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.command.LeavesCommandUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.LiteralNode; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; import org.leavesmc.leaves.plugin.provider.configuration.LeavesPluginMeta; import java.net.URLEncoder; @@ -33,17 +29,43 @@ import java.util.List; import java.util.TreeMap; import java.util.concurrent.CompletableFuture; +import static net.kyori.adventure.text.Component.join; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.JoinConfiguration.noSeparators; +import static net.kyori.adventure.text.JoinConfiguration.spaces; import static net.kyori.adventure.text.format.NamedTextColor.AQUA; -import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.TextDecoration.UNDERLINED; -public class ReportCommand implements LeavesSubcommand { +public class ReportCommand extends LeavesSubcommand { + private static final String BASE_URL = "https://github.com/LeavesMC/Leaves/issues/new?template="; + private static final String BUG_REPORT_URL = BASE_URL + "1-bug-report.yml&leaves-version=${version}&plugin-list=${plugins}%0a%0a${datapacks}"; + private static final String NOT_VANILLA_URL = BASE_URL + "2-not-vanilla.yml&leaves-version=${version}"; - private static final String BUG_REPORT_URL = "https://github.com/LeavesMC/Leaves/issues/new?template=1-bug-report.yml&leaves-version=${version}&plugin-list=${plugins}%0a%0a${datapacks}"; - private static final String NOT_VANILLA_URL = "https://github.com/LeavesMC/Leaves/issues/new?template=2-not-vanilla.yml&leaves-version=${version}"; - private static final String COMMAND_PERM = "bukkit.command.leaves.report"; + public ReportCommand() { + super("report"); + children( + () -> new ReportTypeNode("bug-report", BUG_REPORT_URL), + () -> new ReportTypeNode("not-vanilla", NOT_VANILLA_URL) + ); + } - private static String generatePluginMessage() { + private static class ReportTypeNode extends LiteralNode { + private final String url; + + private ReportTypeNode(String type, String url) { + super(type); + this.url = url; + } + + @Override + protected boolean execute(CommandContext context) { + CompletableFuture.runAsync(() -> sendOnSuccess(context.getSender(), url, name)); + return true; + } + } + + private static @NotNull String generatePluginMessage() { final StringBuilder pluginList = new StringBuilder(); final TreeMap> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @@ -98,7 +120,7 @@ public class ReportCommand implements LeavesSubcommand { return pluginList.toString(); } - private static String generateDataPackMessage() { + private static @NotNull String generateDataPackMessage() { final StringBuilder dataPackList = new StringBuilder(); PackRepository packRepository = MinecraftServer.getServer().getPackRepository(); @@ -130,39 +152,30 @@ public class ReportCommand implements LeavesSubcommand { return dataPackList.toString(); } - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Please select a report template: \"bug-report\" or \"not-vanilla\"", RED)); - return; - } - if (args[0].equals("bug-report")) { - CompletableFuture.runAsync(() -> sendOnSuccess(sender, BUG_REPORT_URL, Component.text("Successfully generated report url for \"bug-report\"", AQUA))); - return; - } else if (args[0].equals("not-vanilla")) { - CompletableFuture.runAsync(() -> sendOnSuccess(sender, NOT_VANILLA_URL, Component.text("Successfully generated report url for \"not-vanilla\"", AQUA))); - return; - } - sender.sendMessage(text("The template" + args[0] + " does not exist! Please select a correct template: \"bug-report\" or \"not-vanilla\"", RED)); - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (args.length <= 1) { - LeavesCommandUtil.getListMatchingLast(sender, args, List.of("bug-report", "not-vanilla"), COMMAND_PERM + ".", COMMAND_PERM).forEach(builder::suggest); - } - } - - private void sendOnSuccess(CommandSender sender, String template, Component component) { + private static void sendOnSuccess(@NotNull CommandSender sender, @NotNull String template, String type) { String finalUrl = template .replace("${version}", URLEncoder.encode(Bukkit.getVersionMessage(), StandardCharsets.UTF_8)) .replace("${plugins}", URLEncoder.encode(generatePluginMessage(), StandardCharsets.UTF_8)) .replace("${datapacks}", URLEncoder.encode(generateDataPackMessage(), StandardCharsets.UTF_8)); + Component base = join(noSeparators(), + text("Successfully generated report url for ", GRAY), + text(type, AQUA), + text(",", GRAY) + ); if (sender instanceof ConsoleCommandSender) { - sender.sendMessage(component.append(text(", please copy it as you are running this command in console"))); - sender.sendMessage(text(finalUrl, AQUA).decorate(TextDecoration.UNDERLINED)); + sender.sendMessage(join(spaces(), + base, + text("please open it in your browser:", GRAY), + text(finalUrl, AQUA) + )); } else { - sender.sendMessage(component.append(text(", click this message to open")).decorate(TextDecoration.UNDERLINED).hoverEvent(Component.text("Click to open the report url", NamedTextColor.WHITE)).clickEvent(ClickEvent.openUrl(finalUrl))); + sender.sendMessage(join(spaces(), + base, + text("click here to continue", AQUA) + .decorate(UNDERLINED) + .hoverEvent(text("Open the report url")) + .clickEvent(ClickEvent.openUrl(finalUrl)) + )); } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/UpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/UpdateCommand.java new file mode 100644 index 00000000..0193466c --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/command/leaves/subcommands/UpdateCommand.java @@ -0,0 +1,31 @@ +package org.leavesmc.leaves.command.leaves.subcommands; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.command.CommandContext; +import org.leavesmc.leaves.command.leaves.LeavesSubcommand; +import org.leavesmc.leaves.util.LeavesUpdateHelper; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; + +public class UpdateCommand extends LeavesSubcommand { + + public UpdateCommand() { + super("update"); + } + + @Override + protected boolean execute(@NotNull CommandContext context) throws CommandSyntaxException { + CommandSender sender = context.getSender(); + if (sender instanceof ConsoleCommandSender) { + sender.sendMessage(text("Trying to update Leaves...", GRAY)); + } else { + sender.sendMessage(text("Trying to update Leaves, see the console for more info", GRAY)); + } + LeavesUpdateHelper.tryUpdateLeaves(); + return true; + } +} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/BlockUpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/BlockUpdateCommand.java deleted file mode 100644 index 18477f57..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/BlockUpdateCommand.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesSubcommand; - -public class BlockUpdateCommand implements LeavesSubcommand { - - private static boolean noBlockUpdate = false; - - public static boolean isNoBlockUpdate() { - return LeavesConfig.modify.noBlockUpdateCommand && noBlockUpdate; - } - - @Override - public void execute(@NotNull CommandSender sender, @NotNull String commandLabel, String @NotNull [] args) { - noBlockUpdate = !noBlockUpdate; - Bukkit.broadcast(Component.join(JoinConfiguration.noSeparators(), - Component.text("Block update status: ", NamedTextColor.GRAY), - Component.text(!noBlockUpdate, noBlockUpdate ? NamedTextColor.AQUA : NamedTextColor.GRAY) - ), "bukkit.command.leaves.blockupdate"); - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.noBlockUpdateCommand; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java deleted file mode 100644 index e5349244..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ConfigCommand.java +++ /dev/null @@ -1,92 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.command.LeavesCommandUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.config.GlobalConfigManager; -import org.leavesmc.leaves.config.VerifiedConfig; - -import static net.kyori.adventure.text.Component.text; - -public class ConfigCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(text("Leaves Config", NamedTextColor.GRAY)); - return; - } - - VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(args[0]); - if (verifiedConfig == null) { - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.RED), - text("is Not Found.", NamedTextColor.GRAY) - )); - return; - } - - if (args.length > 1) { - try { - verifiedConfig.set(args[1]); - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.AQUA), - text("changed to", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) - )); - Bukkit.getOnlinePlayers().stream().filter(player -> player.hasPermission("leaves.command.config.notify") && player != sender).forEach( - player -> player.sendMessage(Component.join(JoinConfiguration.spaces(), - text(sender.getName() + ":", NamedTextColor.GRAY), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.AQUA), - text("changed to", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) - )) - ); - } catch (IllegalArgumentException exception) { - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.RED), - text("modify error by", NamedTextColor.GRAY), - text(exception.getMessage(), NamedTextColor.RED) - )); - } - } else { - sender.sendMessage(Component.join(JoinConfiguration.spaces(), - text("Config", NamedTextColor.GRAY), - text(args[0], NamedTextColor.AQUA), - text("value is", NamedTextColor.GRAY), - text(verifiedConfig.getString(), NamedTextColor.AQUA) - )); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String subCommand, String @NotNull [] args, @Nullable Location location, @NotNull LeavesSuggestionBuilder builder) { - if (args.length <= 1) { - String arg = args[0]; - int dotIndex = arg.lastIndexOf("."); - builder.createOffset(builder.getInput().lastIndexOf(' ') + dotIndex + 2); - LeavesCommandUtil.getListClosestMatchingLast(sender, arg.substring(dotIndex + 1), GlobalConfigManager.getVerifiedConfigSubPaths(arg), "bukkit.command.leaves.config") - .forEach(builder::suggest); - } - if (args.length == 2) { - VerifiedConfig verifiedConfig = GlobalConfigManager.getVerifiedConfig(args[0]); - if (verifiedConfig != null) { - LeavesCommandUtil.getListMatchingLast(sender, args, verifiedConfig.validator().valueSuggest()).forEach(builder::suggest); - } else { - builder.suggest(""); - } - } - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/CounterCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/CounterCommand.java deleted file mode 100644 index f2f87cd9..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/CounterCommand.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.JoinConfiguration; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextColor; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.item.DyeColor; -import org.bukkit.Location; -import org.bukkit.command.CommandSender; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesCommandUtil; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.command.LeavesSuggestionBuilder; -import org.leavesmc.leaves.util.HopperCounter; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class CounterCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - if (args.length < 1) { - sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), - Component.text("Hopper Counter: ", NamedTextColor.GRAY), - Component.text(HopperCounter.isEnabled(), HopperCounter.isEnabled() ? NamedTextColor.AQUA : NamedTextColor.GRAY) - )); - } - - if (!HopperCounter.isEnabled()) { - if (args[0].equals("enable")) { - HopperCounter.setEnabled(true); - sender.sendMessage(Component.text("Hopper Counter now is enabled", NamedTextColor.AQUA)); - } else { - sender.sendMessage(Component.text("Hopper Counter is not enabled", NamedTextColor.RED)); - } - } - - DyeColor color = DyeColor.byName(args[0], null); - if (color != null) { - HopperCounter counter = HopperCounter.getCounter(color); - if (args.length < 2) { - displayCounter(sender, counter, false); - return; - } - switch (args[1]) { - case "reset" -> { - counter.reset(MinecraftServer.getServer()); - sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), - Component.text("Restarted "), - Component.text(color.getName(), TextColor.color(color.getTextColor())), - Component.text(" counter") - )); - } - case "realtime" -> displayCounter(sender, counter, true); - } - } - - switch (args[0]) { - case "reset" -> { - HopperCounter.resetAll(MinecraftServer.getServer(), false); - sender.sendMessage(Component.text("Restarted all counters")); - } - case "disable" -> { - HopperCounter.setEnabled(false); - HopperCounter.resetAll(MinecraftServer.getServer(), true); - sender.sendMessage(Component.text("Hopper Counter now is disabled", NamedTextColor.GRAY)); - } - } - } - - private void displayCounter(CommandSender sender, @NotNull HopperCounter counter, boolean realTime) { - for (Component component : counter.format(MinecraftServer.getServer(), realTime)) { - sender.sendMessage(component); - } - } - - @Override - public void suggest(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location, LeavesSuggestionBuilder builder) throws IllegalArgumentException { - if (args.length <= 1) { - if (!HopperCounter.isEnabled()) { - builder.suggest("enable"); - return; - } - - List list = new ArrayList<>(Arrays.stream(DyeColor.values()).map(DyeColor::getName).toList()); - list.add("reset"); - list.add("disable"); - LeavesCommandUtil.getListMatchingLast(sender, args, list).forEach(builder::suggest); - } - if (args.length == 2) { - if (DyeColor.byName(args[0], null) != null) { - LeavesCommandUtil.getListMatchingLast(sender, args, "reset", "realtime").forEach(builder::suggest); - } - } - } - - @Override - public boolean isEnabled() { - return LeavesConfig.modify.hopperCounter.enable; - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReloadCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReloadCommand.java deleted file mode 100644 index 4697c546..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/ReloadCommand.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; -import org.leavesmc.leaves.LeavesConfig; -import org.leavesmc.leaves.command.LeavesSubcommand; - -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.GREEN; - -public class ReloadCommand implements LeavesSubcommand { - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - LeavesConfig.reload(); - sender.sendMessage(text("Leaves config reload complete.", GREEN)); - Bukkit.getOnlinePlayers().stream().filter(player -> player.hasPermission("leaves.command.config.notify") && player != sender).forEach( - player -> player.sendMessage(text("Leaves config reload complete.", GREEN)) - ); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/UpdateCommand.java b/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/UpdateCommand.java deleted file mode 100644 index 4af4c88f..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/command/subcommands/UpdateCommand.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.leavesmc.leaves.command.subcommands; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.command.CommandSender; -import org.leavesmc.leaves.command.LeavesSubcommand; -import org.leavesmc.leaves.util.LeavesUpdateHelper; - -public class UpdateCommand implements LeavesSubcommand { - - @Override - public void execute(CommandSender sender, String subCommand, String[] args) { - sender.sendMessage(Component.text("Trying to update Leaves, see the console for more info.", NamedTextColor.GRAY)); - LeavesUpdateHelper.tryUpdateLeaves(); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java index de83f04c..97fa23e3 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBot.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; import org.leavesmc.leaves.entity.bot.actions.CraftBotAction; import org.leavesmc.leaves.event.bot.BotActionStopEvent; @@ -29,8 +29,8 @@ public class CraftBot extends CraftPlayer implements Bot { } @Override - public @NotNull String getRealName() { - return this.getHandle().createState.realName(); + public @NotNull String getRawName() { + return this.getHandle().createState.rawName(); } @Override @@ -40,12 +40,17 @@ public class CraftBot extends CraftPlayer implements Bot { @Override public > void addAction(@NotNull T action) { - switch (action) { - case CraftBotAction act -> this.getHandle().addBotAction(act.getHandle(), null); - default -> throw new IllegalArgumentException("Action " + action.getClass().getName() + " is not a valid BotAction type!"); + if (action instanceof CraftBotAction act) { + this.getHandle().addBotAction(act.getHandle(), null); + } else { + throw new IllegalArgumentException("Action " + action.getClass().getName() + " is not a valid BotAction type!"); } } + public void addAction(@NotNull AbstractBotAction action) { + this.getHandle().addBotAction(action, null); + } + @Override public BotAction getAction(int index) { return (BotAction) this.getHandle().getBotActions().get(index).asCraft(); @@ -63,15 +68,19 @@ public class CraftBot extends CraftPlayer implements Bot { @Override public void stopAllActions() { - for (ServerBotAction action : this.getHandle().getBotActions()) { + for (AbstractBotAction action : this.getHandle().getBotActions()) { action.stop(this.getHandle(), BotActionStopEvent.Reason.PLUGIN); } } @Override public boolean remove(boolean save) { - BotList.INSTANCE.removeBot(this.getHandle(), BotRemoveEvent.RemoveReason.PLUGIN, null, save); - return true; + return BotList.INSTANCE.removeBot(this.getHandle(), BotRemoveEvent.RemoveReason.PLUGIN, null, save, false); + } + + @Override + public boolean remove(boolean save, boolean resume) { + return BotList.INSTANCE.removeBot(this.getHandle(), BotRemoveEvent.RemoveReason.PLUGIN, null, save, resume); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java index dcbf2330..1fb5f33a 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/CraftBotManager.java @@ -9,7 +9,7 @@ import org.leavesmc.leaves.bot.BotCreateState; import org.leavesmc.leaves.bot.BotList; import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.bot.agent.Actions; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; import org.leavesmc.leaves.event.bot.BotCreateEvent; @@ -55,7 +55,7 @@ public class CraftBotManager implements BotManager { @SuppressWarnings("unchecked") @Override public > T newAction(@NotNull Class type) { - ServerBotAction action = Actions.getForClass(type); + AbstractBotAction action = Actions.getForClass(type); if (action == null) { throw new IllegalArgumentException("No action registered for type: " + type.getName()); } else { @@ -68,7 +68,7 @@ public class CraftBotManager implements BotManager { } @Override - public BotCreator botCreator(@NotNull String realName, @NotNull Location location) { - return BotCreateState.builder(realName, location).createReason(BotCreateEvent.CreateReason.PLUGIN); + public BotCreator botCreator(@NotNull String rawName, @NotNull Location location) { + return BotCreateState.builder(rawName, location).createReason(BotCreateEvent.CreateReason.PLUGIN); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java index f3fbd60e..b0c0c20c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftBotAction.java @@ -2,14 +2,14 @@ package org.leavesmc.leaves.entity.bot.actions; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.bot.ServerBot; -import org.leavesmc.leaves.bot.agent.actions.ServerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction; import org.leavesmc.leaves.entity.bot.action.BotAction; import java.util.UUID; import java.util.function.Consumer; import java.util.function.Function; -public abstract class CraftBotAction, S extends ServerBotAction> implements BotAction { +public abstract class CraftBotAction, S extends AbstractBotAction> implements BotAction { protected final S serverAction; protected final Function creator; @@ -23,7 +23,7 @@ public abstract class CraftBotAction, S extends ServerBot this.creator = creator; } - public ServerBotAction getHandle() { + public AbstractBotAction getHandle() { return serverAction; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java index 532c3e37..2ff20416 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/entity/bot/actions/CraftTimerBotAction.java @@ -1,11 +1,11 @@ package org.leavesmc.leaves.entity.bot.actions; -import org.leavesmc.leaves.bot.agent.actions.ServerTimerBotAction; +import org.leavesmc.leaves.bot.agent.actions.AbstractTimerBotAction; import org.leavesmc.leaves.entity.bot.action.TimerBotAction; import java.util.function.Function; -public class CraftTimerBotAction, S extends ServerTimerBotAction> extends CraftBotAction implements TimerBotAction { +public class CraftTimerBotAction, S extends AbstractTimerBotAction> extends CraftBotAction implements TimerBotAction { public CraftTimerBotAction(S serverAction, Function creator) { super(serverAction, creator); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/lithium/common/world/chunk/LithiumHashPalette.java b/leaves-server/src/main/java/org/leavesmc/leaves/lithium/common/world/chunk/LithiumHashPalette.java index e814196d..105eac4f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/lithium/common/world/chunk/LithiumHashPalette.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/lithium/common/world/chunk/LithiumHashPalette.java @@ -23,30 +23,24 @@ import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR; /** * Generally provides better performance over the vanilla {@link net.minecraft.world.level.chunk.HashMapPalette} when calling - * {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing. + * {@link LithiumHashPalette#idFor(Object, PaletteResize)} through using a faster backing map and reducing pointer chasing. */ public class LithiumHashPalette implements Palette { private static final int ABSENT_VALUE = -1; - - private final IdMap idList; - private final PaletteResize resizeHandler; private final int indexBits; - private final Reference2IntOpenHashMap table; private T[] entries; private int size = 0; - private LithiumHashPalette(IdMap idList, PaletteResize resizeHandler, int indexBits, T[] entries, Reference2IntOpenHashMap table, int size) { - this.idList = idList; - this.resizeHandler = resizeHandler; + private LithiumHashPalette(int indexBits, T[] entries, Reference2IntOpenHashMap table, int size) { this.indexBits = indexBits; this.entries = entries; this.table = table; this.size = size; } - public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler, List list) { - this(idList, bits, resizeHandler); + public LithiumHashPalette(int bits, List list) { + this(bits); for (T t : list) { this.addEntry(t); @@ -54,10 +48,8 @@ public class LithiumHashPalette implements Palette { } @SuppressWarnings("unchecked") - public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler) { - this.idList = idList; + public LithiumHashPalette(int bits) { this.indexBits = bits; - this.resizeHandler = resizeHandler; int capacity = 1 << bits; @@ -67,11 +59,11 @@ public class LithiumHashPalette implements Palette { } @Override - public int idFor(@NotNull T obj) { + public int idFor(@NotNull T obj, @NotNull PaletteResize resizeHandler) { int id = this.table.getInt(obj); if (id == ABSENT_VALUE) { - id = this.computeEntry(obj); + id = this.computeEntry(obj, resizeHandler); } return id; @@ -88,14 +80,14 @@ public class LithiumHashPalette implements Palette { return false; } - private int computeEntry(T obj) { + private int computeEntry(T obj, PaletteResize resizeHandler) { int id = this.addEntry(obj); if (id >= 1 << this.indexBits) { - if (this.resizeHandler == null) { + if (resizeHandler == null) { throw new IllegalStateException("Cannot grow"); } else { - id = this.resizeHandler.onResize(this.indexBits + 1, obj); + id = resizeHandler.onResize(this.indexBits + 1, obj); } } @@ -151,32 +143,32 @@ public class LithiumHashPalette implements Palette { } @Override - public void read(FriendlyByteBuf buf) { + public void read(FriendlyByteBuf buf, @NotNull IdMap idMap) { this.clear(); int entryCount = buf.readVarInt(); for (int i = 0; i < entryCount; ++i) { - this.addEntry(this.idList.byIdOrThrow(buf.readVarInt())); + this.addEntry(idMap.byIdOrThrow(buf.readVarInt())); } } @Override - public void write(FriendlyByteBuf buf) { + public void write(FriendlyByteBuf buf, @NotNull IdMap idMap) { int size = this.size; buf.writeVarInt(size); for (int i = 0; i < size; ++i) { - buf.writeVarInt(this.idList.getId(this.valueFor(i))); + buf.writeVarInt(idMap.getId(this.valueFor(i))); } } @Override - public int getSerializedSize() { + public int getSerializedSize(@NotNull IdMap idMap) { int size = VarInt.getByteSize(this.size); for (int i = 0; i < this.size; ++i) { - size += VarInt.getByteSize(this.idList.getId(this.valueFor(i))); + size += VarInt.getByteSize(idMap.getId(this.valueFor(i))); } return size; @@ -188,8 +180,8 @@ public class LithiumHashPalette implements Palette { } @Override - public @NotNull Palette copy(@NotNull PaletteResize resizeHandler) { - return new LithiumHashPalette<>(this.idList, resizeHandler, this.indexBits, this.entries.clone(), this.table.clone(), this.size); + public @NotNull Palette copy() { + return new LithiumHashPalette<>(this.indexBits, this.entries.clone(), this.table.clone(), this.size); } private void clear() { @@ -203,7 +195,7 @@ public class LithiumHashPalette implements Palette { return Arrays.asList(copy); } - public static Palette create(int bits, IdMap idList, PaletteResize listener, List list) { - return new LithiumHashPalette<>(idList, bits, listener, list); + public static Palette create(int bits, List list) { + return new LithiumHashPalette<>(bits, list); } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/profile/LeavesMinecraftSessionService.java b/leaves-server/src/main/java/org/leavesmc/leaves/profile/LeavesMinecraftSessionService.java index 49ef02e1..dc9045df 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/profile/LeavesMinecraftSessionService.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/profile/LeavesMinecraftSessionService.java @@ -11,8 +11,10 @@ import com.mojang.authlib.yggdrasil.ProfileResult; import com.mojang.authlib.yggdrasil.ServicesKeySet; import com.mojang.authlib.yggdrasil.response.HasJoinedMinecraftServerResponse; import com.mojang.authlib.yggdrasil.response.ProfileAction; +import io.papermc.paper.profile.MutablePropertyMap; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.NameAndId; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesConfig; import org.leavesmc.leaves.bot.ServerBot; @@ -63,9 +65,9 @@ public class LeavesMinecraftSessionService extends PaperMinecraftSessionService arguments.put("ip", address.getHostAddress()); } - GameProfile cache = null; + NameAndId cache = null; if (LeavesConfig.mics.yggdrasil.loginProtect) { - cache = MinecraftServer.getServer().services.profileCache().getProfileIfCached(profileName); + cache = MinecraftServer.getServer().services.nameToIdCache().getIfCached(profileName); } for (URL checkUrl : extraYggdrasilList) { @@ -74,14 +76,14 @@ public class LeavesMinecraftSessionService extends PaperMinecraftSessionService final HasJoinedMinecraftServerResponse response = client.get(url, HasJoinedMinecraftServerResponse.class); if (response != null && response.id() != null) { if (LeavesConfig.mics.yggdrasil.loginProtect && cache != null) { - if (!response.id().equals(cache.getId())) { + if (!response.id().equals(cache.id())) { continue; } } - final GameProfile result1 = new GameProfile(response.id(), profileName); + final GameProfile result1 = new GameProfile(response.id(), profileName, new MutablePropertyMap()); if (response.properties() != null) { - result1.getProperties().putAll(response.properties()); + result1.properties().putAll(response.properties()); } final Set profileActions = response.profileActions().stream() diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java index a6407b37..0879c96b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/AppleSkinProtocol.java @@ -38,7 +38,7 @@ public class AppleSkinProtocol implements LeavesProtocol { @Contract("_ -> new") public static ResourceLocation id(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID, path); } @ProtocolHandler.PlayerJoin @@ -54,7 +54,7 @@ public class AppleSkinProtocol implements LeavesProtocol { @ProtocolHandler.MinecraftRegister(onlyNamespace = true) public static void onPlayerSubscribed(@NotNull Context context, ResourceLocation id) { - subscribedChannels.computeIfAbsent(context.profile().getId(), k -> new HashSet<>()).add(id.getPath()); + subscribedChannels.computeIfAbsent(context.profile().id(), k -> new HashSet<>()).add(id.getPath()); } @ProtocolHandler.Ticker diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java index 6698d367..ec416c19 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/BBORProtocol.java @@ -45,7 +45,7 @@ public class BBORProtocol implements LeavesProtocol { @Contract("_ -> new") public static ResourceLocation id(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID, path); } @ProtocolHandler.Ticker @@ -69,8 +69,8 @@ public class BBORProtocol implements LeavesProtocol { ServerLevel overworld = MinecraftServer.getServer().overworld(); ProtocolUtils.sendBytebufPacket(player, INITIALIZE_CLIENT, buf -> { buf.writeLong(overworld.getSeed()); - buf.writeInt(overworld.levelData.getSpawnPos().getX()); - buf.writeInt(overworld.levelData.getSpawnPos().getZ()); + buf.writeInt(overworld.levelData.getRespawnData().pos().getX()); + buf.writeInt(overworld.levelData.getRespawnData().pos().getZ()); }); sendStructureList(player); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java index fa004637..54e27d82 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/CarpetServerProtocol.java @@ -30,7 +30,7 @@ public class CarpetServerProtocol implements LeavesProtocol { @Contract("_ -> new") public static ResourceLocation id(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID, path); } @ProtocolHandler.PlayerJoin diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java index 5a8483f1..b6b245a9 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/PcaSyncProtocol.java @@ -60,7 +60,7 @@ public class PcaSyncProtocol implements LeavesProtocol { @Contract("_ -> new") public static ResourceLocation id(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID, path); } @ProtocolHandler.PlayerJoin @@ -142,12 +142,12 @@ public class PcaSyncProtocol implements LeavesProtocol { } } case OPS -> { - if (!(entity instanceof ServerBot) && !server.getPlayerList().isOp(player.gameProfile)) { + if (!(entity instanceof ServerBot) && !server.getPlayerList().isOp(player.nameAndId())) { return; } } case OPS_AND_SELF -> { - if (!(entity instanceof ServerBot) && !server.getPlayerList().isOp(player.gameProfile) && entity != player) { + if (!(entity instanceof ServerBot) && !server.getPlayerList().isOp(player.nameAndId()) && entity != player) { return; } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java index 75c8fcec..3c2e6137 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/XaeroMapProtocol.java @@ -19,12 +19,12 @@ public class XaeroMapProtocol implements LeavesProtocol { @Contract("_ -> new") public static ResourceLocation idMini(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID_MINI, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID_MINI, path); } @Contract("_ -> new") public static ResourceLocation idWorld(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID_WORLD, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID_WORLD, path); } public static void onSendWorldInfo(@NotNull ServerPlayer player) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java index 2985e993..5415b1da 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/chatimage/ChatImageProtocol.java @@ -24,7 +24,7 @@ public class ChatImageProtocol implements LeavesProtocol { @Contract("_ -> new") public static ResourceLocation id(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID, path); } @ProtocolHandler.PayloadReceiver(payload = FileChannelPayload.class) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java index f6300c8e..87eb1cf2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/LeavesProtocolManager.java @@ -205,7 +205,12 @@ public class LeavesProtocolManager { if (codec == null) { return null; } - return codec.decode(ProtocolUtils.decorate(buf)); + try { + return codec.decode(ProtocolUtils.decorate(buf)); + } catch (Exception e) { + LOGGER.severe("Failed to decode payload " + location, e); + throw e; + } } public static void encode(FriendlyByteBuf buf, LeavesCustomPayload payload) { @@ -214,8 +219,13 @@ public class LeavesProtocolManager { if (location == null || codec == null) { throw new IllegalArgumentException("Payload " + payload.getClass() + " is not configured correctly " + location + " " + codec); } - buf.writeResourceLocation(location); - codec.encode(ProtocolUtils.decorate(buf), payload); + try { + buf.writeResourceLocation(location); + codec.encode(ProtocolUtils.decorate(buf), payload); + } catch (Exception e) { + LOGGER.severe("Failed to encode payload " + location, e); + throw e; + } } public static void handlePayload(IdentifierSelector selector, LeavesCustomPayload payload) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java index ec6771d7..93b61305 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/ProtocolUtils.java @@ -1,5 +1,7 @@ package org.leavesmc.leaves.protocol.core; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; @@ -16,12 +18,14 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; public class ProtocolUtils { - private static final Function bufDecorator = buf -> buf instanceof RegistryFriendlyByteBuf registry ? registry : new RegistryFriendlyByteBuf(buf, MinecraftServer.getServer().registryAccess()); + private static final Cache SELECTOR_CACHE = CacheBuilder.newBuilder().expireAfterAccess(30, TimeUnit.SECONDS).build(); + private static final Function BUF_DECORATOR = buf -> buf instanceof RegistryFriendlyByteBuf registry ? registry : new RegistryFriendlyByteBuf(buf, MinecraftServer.getServer().registryAccess()); private static final byte[] EMPTY = new byte[0]; public static String buildProtocolVersion(String protocol) { @@ -57,12 +61,20 @@ public class ProtocolUtils { } public static RegistryFriendlyByteBuf decorate(ByteBuf buf) { - return bufDecorator.apply(buf); + return BUF_DECORATOR.apply(buf); } public static IdentifierSelector createSelector(ServerCommonPacketListenerImpl common) { + IdentifierSelector selector = SELECTOR_CACHE.getIfPresent(common); + if (selector != null) { + return selector; + } ServerPlayer player = common instanceof ServerGamePacketListenerImpl game ? game.getPlayer() : null; - return new IdentifierSelector(new Context(common.profile, common.connection), player); + selector = new IdentifierSelector(new Context(common.profile, common.connection), player); + if (player != null) { + SELECTOR_CACHE.put(common, selector); + } + return selector; } public static ByteBuf wrapNullable(byte @Nullable [] data) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java index 906b7264..b34f5448 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/core/invoker/AbstractInvokerHolder.java @@ -6,7 +6,6 @@ import org.leavesmc.leaves.protocol.core.LeavesProtocol; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; public abstract class AbstractInvokerHolder { @@ -15,7 +14,6 @@ public abstract class AbstractInvokerHolder { protected final T handler; protected final Class returnType; protected final Class[] parameterTypes; - protected final boolean isStatic; protected AbstractInvokerHolder(LeavesProtocol owner, Method invoker, T handler, @Nullable Class returnType, @NotNull Class... parameterTypes) { this.owner = owner; @@ -23,7 +21,6 @@ public abstract class AbstractInvokerHolder { this.handler = handler; this.returnType = returnType; this.parameterTypes = parameterTypes; - this.isStatic = Modifier.isStatic(invoker.getModifiers()); validateMethodSignature(); } @@ -61,11 +58,7 @@ public abstract class AbstractInvokerHolder { return null; } try { - if (isStatic) { - return invoker.invoke(null, args); - } else { - return invoker.invoke(owner, args); - } + return invoker.invoke(owner, args); } catch (InvocationTargetException e) { throw new RuntimeException(e.getCause()); } catch (Exception e) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java index 42d6fb5e..3d833302 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/JadeProtocol.java @@ -41,9 +41,9 @@ import org.leavesmc.leaves.protocol.jade.payload.ReceiveDataPayload; import org.leavesmc.leaves.protocol.jade.payload.RequestBlockPayload; import org.leavesmc.leaves.protocol.jade.payload.RequestEntityPayload; import org.leavesmc.leaves.protocol.jade.payload.ServerHandshakePayload; -import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; -import org.leavesmc.leaves.protocol.jade.provider.IServerDataProvider; -import org.leavesmc.leaves.protocol.jade.provider.IServerExtensionProvider; +import org.leavesmc.leaves.protocol.jade.provider.JadeProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerDataProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerExtensionProvider; import org.leavesmc.leaves.protocol.jade.provider.ItemStorageExtensionProvider; import org.leavesmc.leaves.protocol.jade.provider.ItemStorageProvider; import org.leavesmc.leaves.protocol.jade.provider.block.*; @@ -70,18 +70,18 @@ import java.util.Set; public class JadeProtocol implements LeavesProtocol { public static final String PROTOCOL_ID = "jade"; - public static final String PROTOCOL_VERSION = "8"; - public static final HierarchyLookup> entityDataProviders = new HierarchyLookup<>(Entity.class); - public static final PairHierarchyLookup> blockDataProviders = new PairHierarchyLookup<>(new HierarchyLookup<>(Block.class), new HierarchyLookup<>(BlockEntity.class)); - public static final WrappedHierarchyLookup> itemStorageProviders = WrappedHierarchyLookup.forAccessor(); + public static final String PROTOCOL_VERSION = "9"; + public static final HierarchyLookup> entityDataProviders = new HierarchyLookup<>(Entity.class); + public static final PairHierarchyLookup> blockDataProviders = new PairHierarchyLookup<>(new HierarchyLookup<>(Block.class), new HierarchyLookup<>(BlockEntity.class)); + public static final WrappedHierarchyLookup> itemStorageProviders = WrappedHierarchyLookup.forAccessor(); private static final Set enabledPlayers = new HashSet<>(); - public static PriorityStore priorities; + public static PriorityStore priorities; private static List shearableBlocks = null; @Contract("_ -> new") public static ResourceLocation id(String path) { - return ResourceLocation.tryBuild(PROTOCOL_ID, path); + return ResourceLocation.fromNamespaceAndPath(PROTOCOL_ID, path); } @Contract("_ -> new") @@ -91,7 +91,7 @@ public class JadeProtocol implements LeavesProtocol { @ProtocolHandler.Init public static void init() { - priorities = new PriorityStore<>(IJadeProvider::getDefaultPriority, IJadeProvider::getUid); + priorities = new PriorityStore<>(JadeProvider::getDefaultPriority, JadeProvider::getUid); // core plugin blockDataProviders.register(BlockEntity.class, BlockNameProvider.INSTANCE); @@ -173,13 +173,13 @@ public class JadeProtocol implements LeavesProtocol { return; } - List> providers = entityDataProviders.get(entity); + List> providers = entityDataProviders.get(entity); if (providers.isEmpty()) { return; } CompoundTag tag = new CompoundTag(); - for (IServerDataProvider provider : providers) { + for (ServerDataProvider provider : providers) { if (!payload.dataProviders().contains(provider)) { continue; } @@ -211,7 +211,7 @@ public class JadeProtocol implements LeavesProtocol { return; } - List> providers; + List> providers; if (blockEntity != null) { providers = blockDataProviders.getMerged(block, blockEntity); } else { @@ -223,7 +223,7 @@ public class JadeProtocol implements LeavesProtocol { } CompoundTag tag = new CompoundTag(); - for (IServerDataProvider provider : providers) { + for (ServerDataProvider provider : providers) { if (!payload.dataProviders().contains(provider)) { continue; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java index 7ea35779..567033af 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/Accessor.java @@ -1,22 +1,60 @@ package org.leavesmc.leaves.protocol.jade.accessor; +import io.netty.buffer.Unpooled; +import net.minecraft.nbt.ByteArrayTag; import net.minecraft.nbt.Tag; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamEncoder; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.HitResult; +import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.Nullable; -public interface Accessor { - ServerLevel getLevel(); +import java.util.function.Supplier; - Player getPlayer(); +public abstract class Accessor { - Tag encodeAsNbt(StreamEncoder codec, D value); + private final ServerLevel level; + private final Player player; + private final Supplier hit; + protected boolean verify; + private RegistryFriendlyByteBuf buffer; - T getHitResult(); + public Accessor(ServerLevel level, Player player, Supplier hit) { + this.level = level; + this.player = player; + this.hit = hit; + } + + public ServerLevel getLevel() { + return level; + } + + public Player getPlayer() { + return player; + } + + private RegistryFriendlyByteBuf buffer() { + if (buffer == null) { + buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), level.registryAccess()); + } + buffer.clear(); + return buffer; + } + + public Tag encodeAsNbt(StreamEncoder streamCodec, D value) { + RegistryFriendlyByteBuf buffer = buffer(); + streamCodec.encode(buffer, value); + ByteArrayTag tag = new ByteArrayTag(ArrayUtils.subarray(buffer.array(), 0, buffer.readableBytes())); + buffer.clear(); + return tag; + } + + public T getHitResult() { + return hit.get(); + } @Nullable - Object getTarget(); + public abstract Object getTarget(); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java deleted file mode 100644 index c6e7829a..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/AccessorImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.leavesmc.leaves.protocol.jade.accessor; - -import io.netty.buffer.Unpooled; -import net.minecraft.nbt.ByteArrayTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.StreamEncoder; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.HitResult; -import org.apache.commons.lang3.ArrayUtils; - -import java.util.function.Supplier; - -public abstract class AccessorImpl implements Accessor { - - private final ServerLevel level; - private final Player player; - private final Supplier hit; - protected boolean verify; - private RegistryFriendlyByteBuf buffer; - - public AccessorImpl(ServerLevel level, Player player, Supplier hit) { - this.level = level; - this.player = player; - this.hit = hit; - } - - @Override - public ServerLevel getLevel() { - return level; - } - - @Override - public Player getPlayer() { - return player; - } - - private RegistryFriendlyByteBuf buffer() { - if (buffer == null) { - buffer = new RegistryFriendlyByteBuf(Unpooled.buffer(), level.registryAccess()); - } - buffer.clear(); - return buffer; - } - - @Override - public Tag encodeAsNbt(StreamEncoder streamCodec, D value) { - RegistryFriendlyByteBuf buffer = buffer(); - streamCodec.encode(buffer, value); - ByteArrayTag tag = new ByteArrayTag(ArrayUtils.subarray(buffer.array(), 0, buffer.readableBytes())); - buffer.clear(); - return tag; - } - - @Override - public T getHitResult() { - return hit.get(); - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java index b981cdd0..943e11dc 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessor.java @@ -1,44 +1,134 @@ package org.leavesmc.leaves.protocol.jade.accessor; +import com.google.common.base.Suppliers; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; -import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.util.function.Supplier; -public interface BlockAccessor extends Accessor { +/** + * Class to get information of block target and context. + */ +public class BlockAccessor extends Accessor { - Block getBlock(); + private final BlockState blockState; + @Nullable + private final Supplier blockEntity; - BlockState getBlockState(); + private BlockAccessor(Builder builder) { + super(builder.level, builder.player, Suppliers.ofInstance(builder.hit)); + blockState = builder.blockState; + blockEntity = builder.blockEntity; + } - BlockEntity getBlockEntity(); + public Block getBlock() { + return getBlockState().getBlock(); + } - BlockPos getPosition(); + public BlockState getBlockState() { + return blockState; + } - @ApiStatus.NonExtendable - interface Builder { - Builder level(ServerLevel level); + public BlockEntity getBlockEntity() { + return blockEntity == null ? null : blockEntity.get(); + } - Builder player(Player player); + public BlockPos getPosition() { + return getHitResult().getBlockPos(); + } - Builder hit(BlockHitResult hit); + @Nullable + @Override + public Object getTarget() { + return getBlockEntity(); + } - Builder blockState(BlockState state); + public static class Builder { + private ServerLevel level; + private Player player; + private BlockHitResult hit; + private BlockState blockState = Blocks.AIR.defaultBlockState(); + private Supplier blockEntity; - default Builder blockEntity(BlockEntity blockEntity) { - return blockEntity(() -> blockEntity); + public Builder level(ServerLevel level) { + this.level = level; + return this; } - Builder blockEntity(Supplier blockEntity); + public Builder player(Player player) { + this.player = player; + return this; + } - Builder from(BlockAccessor accessor); + public Builder hit(BlockHitResult hit) { + this.hit = hit; + return this; + } - BlockAccessor build(); + public Builder blockState(BlockState blockState) { + this.blockState = blockState; + return this; + } + + public Builder blockEntity(Supplier blockEntity) { + this.blockEntity = blockEntity; + return this; + } + + public Builder from(BlockAccessor accessor) { + level = accessor.getLevel(); + player = accessor.getPlayer(); + hit = accessor.getHitResult(); + blockEntity = accessor::getBlockEntity; + blockState = accessor.getBlockState(); + return this; + } + + public BlockAccessor build() { + return new BlockAccessor(this); + } + } + + public record SyncData(boolean showDetails, BlockHitResult hit, ItemStack serversideRep, CompoundTag data) { + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.BOOL, + SyncData::showDetails, + StreamCodec.of(FriendlyByteBuf::writeBlockHitResult, FriendlyByteBuf::readBlockHitResult), + SyncData::hit, + ItemStack.OPTIONAL_STREAM_CODEC, + SyncData::serversideRep, + ByteBufCodecs.COMPOUND_TAG, + SyncData::data, + SyncData::new + ); + + public BlockAccessor unpack(ServerPlayer player) { + Supplier blockEntity = null; + BlockState blockState = player.level().getBlockState(hit.getBlockPos()); + if (blockState.hasBlockEntity()) { + blockEntity = Suppliers.memoize(() -> player.level().getBlockEntity(hit.getBlockPos())); + } + return new Builder() + .level(player.level()) + .player(player) + .hit(hit) + .blockState(blockState) + .blockEntity(blockEntity) + .build(); + } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java deleted file mode 100644 index cfcf71b1..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/BlockAccessorImpl.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.leavesmc.leaves.protocol.jade.accessor; - -import com.google.common.base.Suppliers; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; - -/** - * Class to get information of block target and context. - */ -public class BlockAccessorImpl extends AccessorImpl implements BlockAccessor { - - private final BlockState blockState; - @Nullable - private final Supplier blockEntity; - - private BlockAccessorImpl(Builder builder) { - super(builder.level, builder.player, Suppliers.ofInstance(builder.hit)); - blockState = builder.blockState; - blockEntity = builder.blockEntity; - } - - @Override - public Block getBlock() { - return getBlockState().getBlock(); - } - - @Override - public BlockState getBlockState() { - return blockState; - } - - @Override - public BlockEntity getBlockEntity() { - return blockEntity == null ? null : blockEntity.get(); - } - - @Override - public BlockPos getPosition() { - return getHitResult().getBlockPos(); - } - - @Nullable - @Override - public Object getTarget() { - return getBlockEntity(); - } - - public static class Builder implements BlockAccessor.Builder { - private ServerLevel level; - private Player player; - private BlockHitResult hit; - private BlockState blockState = Blocks.AIR.defaultBlockState(); - private Supplier blockEntity; - - @Override - public Builder level(ServerLevel level) { - this.level = level; - return this; - } - - @Override - public Builder player(Player player) { - this.player = player; - return this; - } - - @Override - public Builder hit(BlockHitResult hit) { - this.hit = hit; - return this; - } - - @Override - public Builder blockState(BlockState blockState) { - this.blockState = blockState; - return this; - } - - @Override - public Builder blockEntity(Supplier blockEntity) { - this.blockEntity = blockEntity; - return this; - } - - @Override - public Builder from(BlockAccessor accessor) { - level = accessor.getLevel(); - player = accessor.getPlayer(); - hit = accessor.getHitResult(); - blockEntity = accessor::getBlockEntity; - blockState = accessor.getBlockState(); - return this; - } - - @Override - public BlockAccessor build() { - return new BlockAccessorImpl(this); - } - } - - public record SyncData(boolean showDetails, BlockHitResult hit, BlockState blockState, ItemStack fakeBlock) { - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.BOOL, - SyncData::showDetails, - StreamCodec.of(FriendlyByteBuf::writeBlockHitResult, FriendlyByteBuf::readBlockHitResult), - SyncData::hit, - ByteBufCodecs.idMapper(Block.BLOCK_STATE_REGISTRY), - SyncData::blockState, - ItemStack.OPTIONAL_STREAM_CODEC, - SyncData::fakeBlock, - SyncData::new - ); - - public BlockAccessor unpack(ServerPlayer player) { - Supplier blockEntity = null; - if (blockState.hasBlockEntity()) { - blockEntity = Suppliers.memoize(() -> player.level().getBlockEntity(hit.getBlockPos())); - } - return new Builder() - .level(player.level()) - .player(player) - .hit(hit) - .blockState(blockState) - .blockEntity(blockEntity) - .build(); - } - } -} diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java index f46108cf..bd174792 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessor.java @@ -1,42 +1,106 @@ package org.leavesmc.leaves.protocol.jade.accessor; +import com.google.common.base.Suppliers; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.EntityHitResult; -import org.jetbrains.annotations.ApiStatus; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.protocol.jade.util.CommonUtil; import java.util.function.Supplier; -public interface EntityAccessor extends Accessor { +public class EntityAccessor extends Accessor { - Entity getEntity(); + private final Supplier entity; - /** - * For part entity like ender dragon's, getEntity() will return the parent entity. - */ - Entity getRawEntity(); + public EntityAccessor(Builder builder) { + super(builder.level, builder.player, builder.hit); + entity = builder.entity; + } - @ApiStatus.NonExtendable - interface Builder { - Builder level(ServerLevel level); + public Entity getEntity() { + return CommonUtil.wrapPartEntityParent(getRawEntity()); + } - Builder player(Player player); + public Entity getRawEntity() { + return entity.get(); + } - default Builder hit(EntityHitResult hit) { - return hit(() -> hit); + @NotNull + @Override + public Object getTarget() { + return getEntity(); + } + + public static class Builder { + private ServerLevel level; + private Player player; + private Supplier hit; + private Supplier entity; + + public Builder level(ServerLevel level) { + this.level = level; + return this; } - Builder hit(Supplier hit); - - default Builder entity(Entity entity) { - return entity(() -> entity); + public Builder player(Player player) { + this.player = player; + return this; } - Builder entity(Supplier entity); + public Builder hit(Supplier hit) { + this.hit = hit; + return this; + } - Builder from(EntityAccessor accessor); + public Builder entity(Supplier entity) { + this.entity = entity; + return this; + } - EntityAccessor build(); + public Builder from(EntityAccessor accessor) { + level = accessor.getLevel(); + player = accessor.getPlayer(); + hit = accessor::getHitResult; + entity = accessor::getEntity; + return this; + } + + public EntityAccessor build() { + return new EntityAccessor(this); + } + } + + public record SyncData(boolean showDetails, int id, int partIndex, Vec3 hitVec, CompoundTag data) { + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.BOOL, + SyncData::showDetails, + ByteBufCodecs.VAR_INT, + SyncData::id, + ByteBufCodecs.VAR_INT, + SyncData::partIndex, + ByteBufCodecs.VECTOR3F.map(Vec3::new, Vec3::toVector3f), + SyncData::hitVec, + ByteBufCodecs.COMPOUND_TAG, + SyncData::data, + SyncData::new + ); + + public EntityAccessor unpack(ServerPlayer player) { + Supplier entity = Suppliers.memoize(() -> CommonUtil.getPartEntity(player.level().getEntity(id), partIndex)); + return new EntityAccessor.Builder() + .level(player.level()) + .player(player) + .entity(entity) + .hit(Suppliers.memoize(() -> new EntityHitResult(entity.get(), hitVec))) + .build(); + } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java deleted file mode 100644 index 6486f4e9..00000000 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/accessor/EntityAccessorImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.leavesmc.leaves.protocol.jade.accessor; - -import com.google.common.base.Suppliers; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.EntityHitResult; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.NotNull; -import org.leavesmc.leaves.protocol.jade.util.CommonUtil; - -import java.util.function.Supplier; - -public class EntityAccessorImpl extends AccessorImpl implements EntityAccessor { - - private final Supplier entity; - - public EntityAccessorImpl(Builder builder) { - super(builder.level, builder.player, builder.hit); - entity = builder.entity; - } - - @Override - public Entity getEntity() { - return CommonUtil.wrapPartEntityParent(getRawEntity()); - } - - @Override - public Entity getRawEntity() { - return entity.get(); - } - - @NotNull - @Override - public Object getTarget() { - return getEntity(); - } - - public static class Builder implements EntityAccessor.Builder { - private ServerLevel level; - private Player player; - private Supplier hit; - private Supplier entity; - - @Override - public Builder level(ServerLevel level) { - this.level = level; - return this; - } - - @Override - public Builder player(Player player) { - this.player = player; - return this; - } - - - @Override - public Builder hit(Supplier hit) { - this.hit = hit; - return this; - } - - @Override - public Builder entity(Supplier entity) { - this.entity = entity; - return this; - } - - @Override - public Builder from(EntityAccessor accessor) { - level = accessor.getLevel(); - player = accessor.getPlayer(); - hit = accessor::getHitResult; - entity = accessor::getEntity; - return this; - } - - @Override - public EntityAccessor build() { - return new EntityAccessorImpl(this); - } - } - - public record SyncData(boolean showDetails, int id, int partIndex, Vec3 hitVec) { - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.BOOL, - SyncData::showDetails, - ByteBufCodecs.VAR_INT, - SyncData::id, - ByteBufCodecs.VAR_INT, - SyncData::partIndex, - ByteBufCodecs.VECTOR3F.map(Vec3::new, Vec3::toVector3f), - SyncData::hitVec, - SyncData::new - ); - - public EntityAccessor unpack(ServerPlayer player) { - Supplier entity = Suppliers.memoize(() -> CommonUtil.getPartEntity(player.level().getEntity(id), partIndex)); - return new EntityAccessorImpl.Builder() - .level(player.level()) - .player(player) - .entity(entity) - .hit(Suppliers.memoize(() -> new EntityHitResult(entity.get(), hitVec))) - .build(); - } - } -} \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java index 9d32bf29..8a5be184 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestBlockPayload.java @@ -9,24 +9,23 @@ import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; -import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessorImpl; -import org.leavesmc.leaves.protocol.jade.provider.IServerDataProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerDataProvider; import java.util.List; import java.util.Objects; import static org.leavesmc.leaves.protocol.jade.JadeProtocol.blockDataProviders; -public record RequestBlockPayload(BlockAccessorImpl.SyncData data, List<@Nullable IServerDataProvider> dataProviders) implements LeavesCustomPayload { +public record RequestBlockPayload(BlockAccessor.SyncData data, List<@Nullable ServerDataProvider> dataProviders) implements LeavesCustomPayload { @ID private static final ResourceLocation PACKET_REQUEST_BLOCK = JadeProtocol.id("request_block"); @Codec private static final StreamCodec CODEC = StreamCodec.composite( - BlockAccessorImpl.SyncData.STREAM_CODEC, + BlockAccessor.SyncData.STREAM_CODEC, RequestBlockPayload::data, - ByteBufCodecs.>list() + ByteBufCodecs.>list() .apply(ByteBufCodecs.idMapper( $ -> Objects.requireNonNull(blockDataProviders.idMapper()).byId($), $ -> Objects.requireNonNull(blockDataProviders.idMapper()).getIdOrThrow($))), diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java index 70dd289a..5b0e3660 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/payload/RequestEntityPayload.java @@ -9,24 +9,23 @@ import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.core.LeavesCustomPayload; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; -import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessorImpl; -import org.leavesmc.leaves.protocol.jade.provider.IServerDataProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerDataProvider; import java.util.List; import java.util.Objects; import static org.leavesmc.leaves.protocol.jade.JadeProtocol.entityDataProviders; -public record RequestEntityPayload(EntityAccessorImpl.SyncData data, List<@Nullable IServerDataProvider> dataProviders) implements LeavesCustomPayload { +public record RequestEntityPayload(EntityAccessor.SyncData data, List<@Nullable ServerDataProvider> dataProviders) implements LeavesCustomPayload { @ID private static final ResourceLocation PACKET_REQUEST_ENTITY = JadeProtocol.id("request_entity"); @Codec private static final StreamCodec CODEC = StreamCodec.composite( - EntityAccessorImpl.SyncData.STREAM_CODEC, + EntityAccessor.SyncData.STREAM_CODEC, RequestEntityPayload::data, - ByteBufCodecs.>list() + ByteBufCodecs.>list() .apply(ByteBufCodecs.idMapper( $ -> Objects.requireNonNull(entityDataProviders.idMapper()).byId($), $ -> Objects.requireNonNull(entityDataProviders.idMapper()).getIdOrThrow($) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java index 24f88873..b18132f8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageExtensionProvider.java @@ -30,7 +30,7 @@ import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -public enum ItemStorageExtensionProvider implements IServerExtensionProvider { +public enum ItemStorageExtensionProvider implements ServerExtensionProvider { INSTANCE; public static final Cache> targetCache = CacheBuilder.newBuilder().weakKeys().expireAfterAccess(60, TimeUnit.SECONDS).build(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java index 7d6cd6dd..35f13c31 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ItemStorageProvider.java @@ -22,7 +22,7 @@ import org.leavesmc.leaves.protocol.jade.util.ViewGroup; import java.util.List; import java.util.Map; -public abstract class ItemStorageProvider> implements IServerDataProvider { +public abstract class ItemStorageProvider> implements ServerDataProvider { private static final StreamCodec>>> STREAM_CODEC = ViewGroup.listCodec(ItemStack.OPTIONAL_STREAM_CODEC); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IJadeProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/JadeProvider.java similarity index 85% rename from leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IJadeProvider.java rename to leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/JadeProvider.java index d62fc8f9..b87da56f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IJadeProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/JadeProvider.java @@ -2,7 +2,7 @@ package org.leavesmc.leaves.protocol.jade.provider; import net.minecraft.resources.ResourceLocation; -public interface IJadeProvider { +public interface JadeProvider { ResourceLocation getUid(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerDataProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ServerDataProvider.java similarity index 71% rename from leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerDataProvider.java rename to leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ServerDataProvider.java index 7d839f17..1be607f8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerDataProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ServerDataProvider.java @@ -3,6 +3,6 @@ package org.leavesmc.leaves.protocol.jade.provider; import net.minecraft.nbt.CompoundTag; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; -public interface IServerDataProvider> extends IJadeProvider { +public interface ServerDataProvider> extends JadeProvider { void appendServerData(CompoundTag data, T accessor); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerExtensionProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ServerExtensionProvider.java similarity index 78% rename from leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerExtensionProvider.java rename to leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ServerExtensionProvider.java index 6e32eed1..301d33a7 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/IServerExtensionProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/ServerExtensionProvider.java @@ -5,6 +5,6 @@ import org.leavesmc.leaves.protocol.jade.util.ViewGroup; import java.util.List; -public interface IServerExtensionProvider extends IJadeProvider { +public interface ServerExtensionProvider extends JadeProvider { List> getGroups(Accessor request); } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/StreamServerDataProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/StreamServerDataProvider.java index fde7c8e6..f987432b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/StreamServerDataProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/StreamServerDataProvider.java @@ -6,7 +6,7 @@ import net.minecraft.network.codec.StreamCodec; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; -public interface StreamServerDataProvider, D> extends IServerDataProvider { +public interface StreamServerDataProvider, D> extends ServerDataProvider { @Override default void appendServerData(CompoundTag data, T accessor) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/CampfireProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/CampfireProvider.java index 2deb3777..27cc13ce 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/CampfireProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/CampfireProvider.java @@ -1,10 +1,7 @@ package org.leavesmc.leaves.protocol.jade.provider.block; import com.google.common.collect.Lists; -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.NbtOps; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.CustomData; @@ -14,15 +11,14 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; -import org.leavesmc.leaves.protocol.jade.provider.IServerExtensionProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerExtensionProvider; import org.leavesmc.leaves.protocol.jade.util.ViewGroup; import java.util.List; -public enum CampfireProvider implements IServerExtensionProvider { +public enum CampfireProvider implements ServerExtensionProvider { INSTANCE; - private static final MapCodec COOKING_TIME_CODEC = Codec.INT.fieldOf("jade:cooking"); private static final ResourceLocation MC_CAMPFIRE = JadeProtocol.mc_id("campfire"); @Override @@ -36,9 +32,8 @@ public enum CampfireProvider implements IServerExtensionProvider { } stack = stack.copy(); - CustomData customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY) - .update(NbtOps.INSTANCE, COOKING_TIME_CODEC, campfire.cookingTime[i] - campfire.cookingProgress[i]) - .getOrThrow(); + int time = campfire.cookingTime[i] - campfire.cookingProgress[i]; + CustomData customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).update(tag -> tag.putInt("jade:cooking", time)); stack.set(DataComponents.CUSTOM_DATA, customData); list.add(stack); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java index 12fdbc3c..ad1bcc28 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/ChiseledBookshelfProvider.java @@ -13,14 +13,16 @@ import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; import org.leavesmc.leaves.protocol.jade.provider.ItemStorageProvider; import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; +import static net.minecraft.world.level.block.CampfireBlock.FACING; + public enum ChiseledBookshelfProvider implements StreamServerDataProvider { INSTANCE; - private static final ResourceLocation MC_CHISELED_BOOKSHELF = JadeProtocol.mc_id("chiseled_bookshelf"); + private static final ResourceLocation MC_CHISELED_BOOKSHELF = JadeProtocol.mc_id("shelf"); @Override public @Nullable ItemStack streamData(@NotNull BlockAccessor accessor) { - int slot = ((ChiseledBookShelfBlock) accessor.getBlock()).getHitSlot(accessor.getHitResult(), accessor.getBlockState()).orElse(-1); + int slot = ((ChiseledBookShelfBlock) accessor.getBlock()).getHitSlot(accessor.getHitResult(), accessor.getBlockState().getValue(FACING)).orElse(-1); if (slot == -1) { return null; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/RedstoneProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/RedstoneProvider.java index 1cdcf21e..0bad6b2f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/RedstoneProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/block/RedstoneProvider.java @@ -10,9 +10,9 @@ import net.minecraft.world.level.block.entity.ComparatorBlockEntity; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; -import org.leavesmc.leaves.protocol.jade.provider.IServerDataProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerDataProvider; -public enum RedstoneProvider implements IServerDataProvider { +public enum RedstoneProvider implements ServerDataProvider { INSTANCE; private static final ResourceLocation MC_REDSTONE = JadeProtocol.mc_id("redstone"); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java index 495815a2..ab26adc0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/AnimalOwnerProvider.java @@ -1,22 +1,27 @@ package org.leavesmc.leaves.protocol.jade.provider.entity; +import com.mojang.authlib.GameProfile; import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.Services; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.players.NameAndId; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityReference; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.OwnableEntity; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; import org.leavesmc.leaves.protocol.jade.provider.StreamServerDataProvider; -import org.leavesmc.leaves.protocol.jade.util.CommonUtil; import java.util.UUID; -public enum AnimalOwnerProvider implements StreamServerDataProvider { +public enum AnimalOwnerProvider implements StreamServerDataProvider { INSTANCE; private static final ResourceLocation MC_ANIMAL_OWNER = JadeProtocol.mc_id("animal_owner"); @@ -32,13 +37,33 @@ public enum AnimalOwnerProvider implements StreamServerDataProvider streamCodec() { - return ByteBufCodecs.STRING_UTF8.cast(); + public @NotNull StreamCodec streamCodec() { + return ComponentSerialization.STREAM_CODEC; } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/NextEntityDropProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/NextEntityDropProvider.java index f7d24fd2..af6be8ba 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/NextEntityDropProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/provider/entity/NextEntityDropProvider.java @@ -9,9 +9,9 @@ import net.minecraft.world.entity.animal.sniffer.Sniffer; import org.jetbrains.annotations.NotNull; import org.leavesmc.leaves.protocol.jade.JadeProtocol; import org.leavesmc.leaves.protocol.jade.accessor.EntityAccessor; -import org.leavesmc.leaves.protocol.jade.provider.IServerDataProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerDataProvider; -public enum NextEntityDropProvider implements IServerDataProvider { +public enum NextEntityDropProvider implements ServerDataProvider { INSTANCE; private static final ResourceLocation MC_NEXT_ENTITY_DROP = JadeProtocol.mc_id("next_entity_drop"); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java index 4e48a268..d774c83f 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/CommonUtil.java @@ -1,20 +1,15 @@ package org.leavesmc.leaves.protocol.jade.util; -import com.mojang.authlib.GameProfile; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -import net.minecraft.world.level.block.entity.SkullBlockEntity; -import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; -import org.leavesmc.leaves.protocol.jade.provider.IServerExtensionProvider; +import org.leavesmc.leaves.protocol.jade.provider.ServerExtensionProvider; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.UUID; public class CommonUtil { @@ -42,19 +37,9 @@ public class CommonUtil { } - @Nullable - public static String getLastKnownUsername(@Nullable UUID uuid) { - if (uuid == null) { - return null; - } - Optional optional = SkullBlockEntity.fetchGameProfile(String.valueOf(uuid)).getNow(Optional.empty()); - return optional.map(GameProfile::getName).orElse(null); - } - - public static Map.Entry>> getServerExtensionData( Accessor accessor, - WrappedHierarchyLookup> lookup) { + WrappedHierarchyLookup> lookup) { for (var provider : lookup.wrappedGet(accessor)) { List> groups; try { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java index b2736d7d..63e399a2 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/HierarchyLookup.java @@ -14,7 +14,7 @@ import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesLogger; import org.leavesmc.leaves.protocol.jade.JadeProtocol; -import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; +import org.leavesmc.leaves.protocol.jade.provider.JadeProvider; import java.util.Collection; import java.util.Comparator; @@ -25,7 +25,7 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Stream; -public class HierarchyLookup implements IHierarchyLookup { +public class HierarchyLookup implements IHierarchyLookup { private final Class baseClass; private final Cache, List> resultCache = CacheBuilder.newBuilder().build(); private final boolean singleton; @@ -108,7 +108,7 @@ public class HierarchyLookup implements IHierarchyLooku } @Override - public void loadComplete(PriorityStore priorityStore) { + public void loadComplete(PriorityStore priorityStore) { objects.asMap().forEach((clazz, list) -> { if (list.size() < 2) { return; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java index c160eaa7..405afc40 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/IHierarchyLookup.java @@ -5,7 +5,7 @@ import net.minecraft.core.IdMapper; import net.minecraft.resources.ResourceLocation; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.jade.JadeProtocol; -import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; +import org.leavesmc.leaves.protocol.jade.provider.JadeProvider; import java.util.Collection; import java.util.Comparator; @@ -14,9 +14,9 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Stream; -public interface IHierarchyLookup { +public interface IHierarchyLookup { - Comparator COMPARATOR = Comparator.comparingInt(provider -> JadeProtocol.priorities.byValue(provider)); + Comparator COMPARATOR = Comparator.comparingInt(provider -> JadeProtocol.priorities.byValue(provider)); default IHierarchyLookup cast() { return this; @@ -29,7 +29,7 @@ public interface IHierarchyLookup { default List mappedIds() { return Streams.stream(Objects.requireNonNull(idMapper())) - .map(IJadeProvider::getUid) + .map(JadeProvider::getUid) .toList(); } @@ -52,7 +52,7 @@ public interface IHierarchyLookup { void invalidate(); - void loadComplete(PriorityStore priorityStore); + void loadComplete(PriorityStore priorityStore); default IdMapper createIdMapper() { List list = entries().flatMap(entry -> entry.getValue().stream()).toList(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java index 8ad85ca7..30b57703 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/ItemCollector.java @@ -11,13 +11,13 @@ import net.minecraft.world.item.component.TooltipDisplay; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; import java.util.List; -import java.util.Locale; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; public class ItemCollector { public static final int MAX_SIZE = 54; public static final ItemCollector EMPTY = new ItemCollector<>(null); + private static final CompoundTag IGNORED_TAG = new CompoundTag(); private static final Predicate SHOWN = stack -> { if (stack.isEmpty()) { return false; @@ -26,12 +26,8 @@ public class ItemCollector { return false; } if (stack.hasNonDefault(DataComponents.CUSTOM_MODEL_DATA) || stack.hasNonDefault(DataComponents.ITEM_MODEL)) { - CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); - for (String key : tag.keySet()) { - if (key.toLowerCase(Locale.ENGLISH).endsWith("clear") && tag.getBooleanOr(key, true)) { - return false; - } - } + CustomData data = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY); + return !data.matchedBy(IGNORED_TAG); } return true; }; @@ -42,6 +38,10 @@ public class ItemCollector { public boolean lastTimeIsEmpty; public List> mergedResult; + static { + IGNORED_TAG.putBoolean("__JadeClear", true); + } + public ItemCollector(ItemIterator iterator) { this.iterator = iterator; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java index 9e0dd9cc..e6660001 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/PairHierarchyLookup.java @@ -9,7 +9,7 @@ import net.minecraft.resources.ResourceLocation; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesLogger; -import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; +import org.leavesmc.leaves.protocol.jade.provider.JadeProvider; import java.util.Collection; import java.util.List; @@ -18,7 +18,7 @@ import java.util.Objects; import java.util.concurrent.ExecutionException; import java.util.stream.Stream; -public class PairHierarchyLookup implements IHierarchyLookup { +public class PairHierarchyLookup implements IHierarchyLookup { public final IHierarchyLookup first; public final IHierarchyLookup second; private final Cache, Class>, List> mergedCache = CacheBuilder.newBuilder().build(); @@ -105,7 +105,7 @@ public class PairHierarchyLookup implements IHierarchyL } @Override - public void loadComplete(PriorityStore priorityStore) { + public void loadComplete(PriorityStore priorityStore) { first.loadComplete(priorityStore); second.loadComplete(priorityStore); if (idMapped) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java index be8abe21..5c249c68 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/jade/util/WrappedHierarchyLookup.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.jade.accessor.Accessor; import org.leavesmc.leaves.protocol.jade.accessor.BlockAccessor; -import org.leavesmc.leaves.protocol.jade.provider.IJadeProvider; +import org.leavesmc.leaves.protocol.jade.provider.JadeProvider; import java.util.Collection; import java.util.List; @@ -19,7 +19,7 @@ import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; -public class WrappedHierarchyLookup extends HierarchyLookup { +public class WrappedHierarchyLookup extends HierarchyLookup { public final List, Function, @Nullable Object>>> overrides = Lists.newArrayList(); private boolean empty = true; @@ -28,7 +28,7 @@ public class WrappedHierarchyLookup extends HierarchyLo } @NotNull - public static WrappedHierarchyLookup forAccessor() { + public static WrappedHierarchyLookup forAccessor() { WrappedHierarchyLookup lookup = new WrappedHierarchyLookup<>(); lookup.overrides.add(Pair.of( new HierarchyLookup<>(Block.class), accessor -> { @@ -84,7 +84,7 @@ public class WrappedHierarchyLookup extends HierarchyLo } @Override - public void loadComplete(PriorityStore priorityStore) { + public void loadComplete(PriorityStore priorityStore) { for (var override : overrides) { override.getLeft().loadComplete(priorityStore); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java index 444aadec..52b21c1c 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/rei/REIServerProtocol.java @@ -193,7 +193,7 @@ public class REIServerProtocol implements LeavesProtocol { } } else if (channel.equals("ci_msg")) { // cheat rei-client into using "delete_item" packet - if (MinecraftServer.getServer().getProfilePermissions(player.getGameProfile()) < 1) { + if (MinecraftServer.getServer().getProfilePermissions(player.nameAndId()) < 1) { player.getBukkitEntity().sendOpLevel((byte) 1); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java index 70325ded..e5b11ade 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxHudDataProtocol.java @@ -101,7 +101,7 @@ public class ServuxHudDataProtocol implements LeavesProtocol { sendPacket(player, new HudDataPayload(HudDataPayloadType.PACKET_S2C_METADATA, metadata)); } - public static void refreshSpawnMetadata(ServerPlayer player) { + public static void refreshSpawnMetadata(ServerPlayer player) { // TODO: 1.21.9 removed spawn chunk, should we keep this? CompoundTag metadata = new CompoundTag(); metadata.putString("id", HudDataPayload.CHANNEL.toString()); metadata.putString("servux", ServuxProtocol.SERVUX_STRING); @@ -164,11 +164,11 @@ public class ServuxHudDataProtocol implements LeavesProtocol { private static void putWorldData(@NotNull CompoundTag metadata) { ServerLevel level = MinecraftServer.getServer().overworld(); - BlockPos spawnPos = level.levelData.getSpawnPos(); + BlockPos spawnPos = level.levelData.getRespawnData().pos(); metadata.putInt("spawnPosX", spawnPos.getX()); metadata.putInt("spawnPosY", spawnPos.getY()); metadata.putInt("spawnPosZ", spawnPos.getZ()); - metadata.putInt("spawnChunkRadius", level.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); + // metadata.putInt("spawnChunkRadius", level.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS)); // TODO: 1.21.9 removed spawn chunk, should we keep this? if (LeavesConfig.protocol.servux.hudMetadataShareSeed) { metadata.putLong("worldSeed", level.getSeed()); @@ -234,20 +234,17 @@ public class ServuxHudDataProtocol implements LeavesProtocol { }); } - for (ServerPlayer player : loggerPlayers.keySet()) { - List list = loggerPlayers.get(player); - if (list.isEmpty()) { - return; - } - + loggerPlayers.forEach((player, list) -> { CompoundTag nbt = new CompoundTag(); for (DataLogger.Type type : list) { if (DATA.containsKey(type)) { nbt.put(type.getSerializedName(), DATA.get(type)); } } - sendPacket(player, new HudDataPayload(HudDataPayloadType.PACKET_S2C_DATA_LOGGER_TICK, nbt)); - } + if (!nbt.isEmpty()) { + sendPacket(player, new HudDataPayload(HudDataPayloadType.PACKET_S2C_DATA_LOGGER_TICK, nbt)); + } + }); } @Override diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java index 6b4421f9..af57e659 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/ServuxStructuresProtocol.java @@ -35,6 +35,8 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import static net.minecraft.server.MinecraftServer.getServer; + // Powered by Servux(https://github.com/sakura-ryoko/servux) @LeavesProtocol.Register(namespace = "servux") @@ -69,7 +71,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol { @ProtocolHandler.Ticker public static void tick() { - MinecraftServer server = MinecraftServer.getServer(); + MinecraftServer server = getServer(); int tickCounter = server.getTickCount(); retainDistance = server.getPlayerList().getViewDistance() + 2; for (ServerPlayer player : players.values()) { @@ -79,8 +81,8 @@ public class ServuxStructuresProtocol implements LeavesProtocol { } public static void onStartedWatchingChunk(ServerPlayer player, LevelChunk chunk) { - MinecraftServer server = player.getServer(); - if (players.containsKey(player.getId()) && server != null) { + MinecraftServer server = getServer(); + if (players.containsKey(player.getId())) { addChunkTimeoutIfHasReferences(player.getUUID(), chunk, server.getTickCount()); } } @@ -119,7 +121,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol { LeavesLogger.LOGGER.warning(player.getScoreboardName() + " re-register servux:structures"); } - MinecraftServer server = MinecraftServer.getServer(); + MinecraftServer server = getServer(); sendMetaData(player); initialSyncStructures(player, player.moonrise$getViewDistanceHolder().getViewDistances().sendViewDistance() + 2, server.getTickCount()); } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java index 7f744bab..925a0e96 100755 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/ServuxLitematicsProtocol.java @@ -104,7 +104,7 @@ public class ServuxLitematicsProtocol implements LeavesProtocol { case PACKET_C2S_BLOCK_ENTITY_REQUEST -> onBlockEntityRequest(player, payload.getPos()); case PACKET_C2S_ENTITY_REQUEST -> onEntityRequest(player, payload.getEntityId()); - + case PACKET_C2S_BULK_ENTITY_NBT_REQUEST -> onBulkEntityRequest(player, payload.getChunkPos(), payload.getCompound()); case PACKET_C2S_NBT_RESPONSE_DATA -> { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java index c031382d..e9c9a77b 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/EntityUtils.java @@ -53,7 +53,7 @@ public class EntityUtils { Entity passenger = createEntityAndPassengersFromNBT(tagList.getCompoundOrEmpty(i), world); if (passenger != null) { - passenger.startRiding(entity, true); + passenger.startRiding(entity, true, true); } } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java index b5370f69..5ea66405 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/litematics/utils/Schema.java @@ -6,6 +6,16 @@ public enum Schema { // TODO --> Add Schema Versions to this as versions get released // Minecraft Data Versions SCHEMA_FUTURE(9999, "FUTURE"), + SCHEMA_25W41A(4657, "25w41a"), + SCHEMA_1_21_10(4556, "1.21.10"), + SCHEMA_1_21_09(4554, "1.21.9"), + SCHEMA_25W36B(4546, "25w36b"), + SCHEMA_25W31A(4534, "25w31a"), + SCHEMA_1_21_08(4440, "1.21.8"), + SCHEMA_1_21_07(4438, "1.21.7"), + SCHEMA_1_21_06(4435, "1.21.6"), + SCHEMA_25W21A(4429, "25w21a"), + SCHEMA_25W16A(4423, "25w16a"), SCHEMA_1_21_05(4325, "1.21.5"), SCHEMA_25W10A(4319, "25w10a"), SCHEMA_25W03A(4304, "25w03a"), // Entity Data Components ( https://www.minecraft.net/en-us/article/minecraft-snapshot-25w03a ) diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/logger/DataLogger.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/logger/DataLogger.java index dbff3b0a..29d03ab5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/logger/DataLogger.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/servux/logger/DataLogger.java @@ -12,6 +12,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.StringRepresentable; import net.minecraft.world.entity.MobCategory; import net.minecraft.world.level.NaturalSpawner; +import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.protocol.servux.logger.data.MobCapData; @@ -100,7 +101,7 @@ public abstract class DataLogger { ServerTickRateManager tickManager = server.tickRateManager(); boolean frozen = tickManager.isFrozen(); boolean sprinting = tickManager.isSprinting(); - final double mspt = server.tickTimes5s.getAverage(); + final double mspt = Bukkit.getAverageTickTime(); double tps = 1000.0D / Math.max(sprinting ? 0.0 : tickManager.millisecondsPerTick(), mspt); if (frozen) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java index e19ec8fe..4e009397 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/CommunicationManager.java @@ -55,7 +55,7 @@ public class CommunicationManager implements LeavesProtocol { final VersionHandshakeServer hi = new VersionHandshakeServer(newPlayer); playerMap.put(newPlayer, player); final GameProfile profile = player.getGameProfile(); - SyncmaticaProtocol.getPlayerIdentifierProvider().updateName(profile.getId(), profile.getName()); + SyncmaticaProtocol.getPlayerIdentifierProvider().updateName(profile.id(), profile.name()); startExchangeUnchecked(hi); } @@ -149,7 +149,7 @@ public class CommunicationManager implements LeavesProtocol { final UUID placementId = packetBuf.readUUID(); final ServerPlacement placement = SyncmaticaProtocol.getSyncmaticManager().getPlacement(placementId); if (placement != null) { - if (!getGameProfile(source).getId().equals(placement.getOwner().uuid)) { + if (!getGameProfile(source).id().equals(placement.getOwner().uuid)) { return; } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PacketType.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PacketType.java index d3643823..00266430 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PacketType.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PacketType.java @@ -25,6 +25,6 @@ public enum PacketType { public final ResourceLocation identifier; PacketType(final String id) { - identifier = ResourceLocation.tryBuild(SyncmaticaProtocol.PROTOCOL_ID, id); + identifier = ResourceLocation.fromNamespaceAndPath(SyncmaticaProtocol.PROTOCOL_ID, id); } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PlayerIdentifierProvider.java b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PlayerIdentifierProvider.java index 4a6248fc..a4f983a5 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PlayerIdentifierProvider.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/protocol/syncmatica/PlayerIdentifierProvider.java @@ -22,7 +22,7 @@ public class PlayerIdentifierProvider { } public PlayerIdentifier createOrGet(final @NotNull GameProfile gameProfile) { - return createOrGet(gameProfile.getId(), gameProfile.getName()); + return createOrGet(gameProfile.id(), gameProfile.name()); } public PlayerIdentifier createOrGet(final UUID uuid, final String playerName) { diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/replay/ServerPhotographer.java b/leaves-server/src/main/java/org/leavesmc/leaves/replay/ServerPhotographer.java index d9d8ef31..240afb93 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/replay/ServerPhotographer.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/replay/ServerPhotographer.java @@ -24,6 +24,8 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; +import static net.minecraft.server.MinecraftServer.getServer; + public class ServerPhotographer extends ServerPlayer { private static final List photographers = new CopyOnWriteArrayList<>(); @@ -49,7 +51,7 @@ public class ServerPhotographer extends ServerPlayer { throw new IllegalArgumentException(state.id + " is a invalid photographer id"); } - MinecraftServer server = MinecraftServer.getServer(); + MinecraftServer server = getServer(); ServerLevel world = ((CraftWorld) state.loc.getWorld()).getHandle(); GameProfile profile = new GameProfile(UUID.randomUUID(), state.id); @@ -62,7 +64,7 @@ public class ServerPhotographer extends ServerPlayer { photographer.createState = state; photographer.recorder.start(); - MinecraftServer.getServer().getPlayerList().placeNewPhotographer(photographer.recorder, photographer, world); + getServer().getPlayerList().placeNewPhotographer(photographer.recorder, photographer, world); photographer.level().chunkSource.move(photographer); photographer.setInvisible(true); photographers.add(photographer); @@ -79,7 +81,7 @@ public class ServerPhotographer extends ServerPlayer { this.lastPos = this.blockPosition(); super.tick(); - if (this.getServer().getTickCount() % 10 == 0) { + if (getServer().getTickCount() % 10 == 0) { connection.resetPosition(); this.level().chunkSource.move(this); } @@ -131,7 +133,7 @@ public class ServerPhotographer extends ServerPlayer { super.remove(RemovalReason.KILLED); photographers.remove(this); this.recorder.stop(); - this.getServer().getPlayerList().removePhotographer(this); + getServer().getPlayerList().removePhotographer(this); LeavesLogger.LOGGER.info("Photographer " + createState.id + " removed"); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java index f1b50d9a..737be4d0 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/ItemOverstackUtils.java @@ -28,7 +28,7 @@ public class ItemOverstackUtils { public static int getItemStackMaxCount(ItemStack stack) { int size; for (ItemUtil util : overstackUtils) { - if ((size = util.getMaxServerStackCount(stack)) != -1) { + if (util.isEnabled() && (size = util.getMaxServerStackCount(stack)) != -1) { return size; } } @@ -38,7 +38,7 @@ public class ItemOverstackUtils { public static int getNetworkMaxCount(ItemStack stack) { int size; for (ItemUtil util : overstackUtils) { - if ((size = util.getMaxClientStackCount(stack)) != -1) { + if (util.isEnabled() && (size = util.getMaxClientStackCount(stack)) != -1) { return size; } } @@ -47,7 +47,7 @@ public class ItemOverstackUtils { public static boolean tryStackItems(ItemEntity self, ItemEntity other) { for (ItemUtil util : overstackUtils) { - if (util.tryStackItems(self, other)) { + if (util.isEnabled() && util.tryStackItems(self, other)) { return true; } } @@ -55,7 +55,12 @@ public class ItemOverstackUtils { } public static boolean hasOverstackingItem() { - return overstackUtils.stream().anyMatch(ItemUtil::isEnabled); + for (ItemUtil util : overstackUtils) { + if (util.isEnabled()) { + return true; + } + } + return false; } public static int getItemStackMaxCountReal(ItemStack stack) { @@ -102,7 +107,6 @@ public class ItemOverstackUtils { return getItemStackMaxCount(itemStack) > 1 && (!itemStack.isDamageableItem() || !itemStack.isDamaged()); } - private interface ItemUtil { boolean isEnabled(); @@ -137,10 +141,7 @@ public class ItemOverstackUtils { @Override public boolean tryStackItems(ItemEntity self, ItemEntity other) { ItemStack selfStack = self.getItem(); - if (!isEnabled() || - !(selfStack.getItem() instanceof net.minecraft.world.item.BlockItem blockItem) || - !(blockItem.getBlock() instanceof net.minecraft.world.level.block.ShulkerBoxBlock) - ) { + if (!(selfStack.getItem() instanceof BlockItem blockItem) || !(blockItem.getBlock() instanceof ShulkerBoxBlock)) { return false; } @@ -169,7 +170,7 @@ public class ItemOverstackUtils { @Override public int getMaxServerStackCount(ItemStack stack) { - if (isEnabled() && stack.getItem() instanceof BlockItem bi && + if (stack.getItem() instanceof BlockItem bi && bi.getBlock() instanceof ShulkerBoxBlock && (LeavesConfig.modify.shulkerBox.sameNbtStackable || shulkerBoxNoItem(stack))) { return LeavesConfig.modify.shulkerBox.stackableShulkerBoxes; } @@ -204,10 +205,7 @@ public class ItemOverstackUtils { @Override public int getMaxClientStackCount(ItemStack stack) { - if (isEnabled() && isCursedEnchantedBook(stack)) { - return 2; - } - return -1; + return isCursedEnchantedBook(stack) ? 2 : -1; } } } \ No newline at end of file diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ServerI18nUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ServerI18nUtil.java index 11bbe3fd..affc7a98 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ServerI18nUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/ServerI18nUtil.java @@ -5,7 +5,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.mojang.logging.LogUtils; -import net.minecraft.DetectedVersion; +import io.papermc.paper.ServerBuildInfo; import net.minecraft.locale.DeprecatedTranslationsInfo; import net.minecraft.locale.Language; import net.minecraft.network.chat.FormattedText; @@ -42,7 +42,7 @@ import java.util.regex.Pattern; public class ServerI18nUtil { private static final Logger logger = LogUtils.getClassLogger(); - private static final String VERSION = DetectedVersion.BUILT_IN.name(); + private static final String VERSION = ServerBuildInfo.buildInfo().minecraftVersionId(); private static final String BASE_PATH = "cache/leaves/" + VERSION + "/"; private static final String defaultLeavesLangPath = "/assets/leaves/lang/en_us.json"; private static final String manifestUrl = "https://launchermeta.mojang.com/mc/game/version_manifest.json"; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java b/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java index 07fb9a13..217d6ceb 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/util/ShearsWrenchUtil.java @@ -7,8 +7,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.*;