From 72415ee5f287b8f782af73f45a7deddedbb84851 Mon Sep 17 00:00:00 2001 From: AlphaKR93 Date: Tue, 22 Oct 2024 07:47:40 +0900 Subject: [PATCH] API patches --- initDev | 0 libs/api.versions.toml | 4 +- libs/common.versions.toml | 2 +- .../0003-Use-Gradle-Version-Catalogs.patch | 30 ++- patches/api/0004-Rebrand.patch | 12 +- patches/api/0005-Plazma-Configurations.patch | 4 +- .../0011-LivingEntity-safeFallDistance.patch | 35 +++ ...0016-LivingEntity-broadcastItemBreak.patch | 24 ++ .../0032-Potion-NamespacedKey.patch | 204 ++++++++++++++++ ...0041-Add-item-packet-serialize-event.patch | 60 +++++ .../0049-Add-hover-lines-API.patch | 44 ++++ .../0013-LivingEntity-safeFallDistance.patch | 27 +++ ...hould-check-if-entity-can-use-portal.patch | 18 ++ ...0082-LivingEntity-broadcastItemBreak.patch | 23 ++ ...te-and-mending-enchantments-together.patch | 39 +++ .../0142-Allow-infinity-on-crossbows.patch | 39 +++ .../0220-Potion-NamespacedKey.patch | 223 ++++++++++++++++++ .../0236-Configurable-food-attributes.patch | 149 ++++++++++++ .../0255-Send-client-custom-name-of-BE.patch | 36 +++ .../0263-Allay-respect-item-NBT.patch | 64 +++++ ...0271-Add-item-packet-serialize-event.patch | 80 +++++++ .../0282-Add-mending-multiplier.patch | 48 ++++ .../0292-Add-hover-lines-API.patch | 28 +++ 23 files changed, 1172 insertions(+), 21 deletions(-) mode change 100644 => 100755 initDev create mode 100644 patches/purpur-drops/dropped-api/0011-LivingEntity-safeFallDistance.patch create mode 100644 patches/purpur-drops/dropped-api/0016-LivingEntity-broadcastItemBreak.patch create mode 100644 patches/purpur-drops/dropped-api/0032-Potion-NamespacedKey.patch create mode 100644 patches/purpur-drops/dropped-api/0041-Add-item-packet-serialize-event.patch create mode 100644 patches/purpur-drops/dropped-api/0049-Add-hover-lines-API.patch create mode 100644 patches/purpur-drops/dropped-server/0013-LivingEntity-safeFallDistance.patch create mode 100644 patches/purpur-drops/dropped-server/0040-End-gateway-should-check-if-entity-can-use-portal.patch create mode 100644 patches/purpur-drops/dropped-server/0082-LivingEntity-broadcastItemBreak.patch create mode 100644 patches/purpur-drops/dropped-server/0094-Allow-infinite-and-mending-enchantments-together.patch create mode 100644 patches/purpur-drops/dropped-server/0142-Allow-infinity-on-crossbows.patch create mode 100644 patches/purpur-drops/dropped-server/0220-Potion-NamespacedKey.patch create mode 100644 patches/purpur-drops/dropped-server/0236-Configurable-food-attributes.patch create mode 100644 patches/purpur-drops/dropped-server/0255-Send-client-custom-name-of-BE.patch create mode 100644 patches/purpur-drops/dropped-server/0263-Allay-respect-item-NBT.patch create mode 100644 patches/purpur-drops/dropped-server/0271-Add-item-packet-serialize-event.patch create mode 100644 patches/purpur-drops/dropped-server/0282-Add-mending-multiplier.patch create mode 100644 patches/purpur-drops/dropped-server/0292-Add-hover-lines-API.patch diff --git a/initDev b/initDev old mode 100644 new mode 100755 diff --git a/libs/api.versions.toml b/libs/api.versions.toml index 830c512..29a8665 100644 --- a/libs/api.versions.toml +++ b/libs/api.versions.toml @@ -3,6 +3,7 @@ gson = "2.10.1" joml = "1.10.5" guava = "32.1.2-jre" sentry = "5.4.0" +jspecify = "1.0.0" fastutil = "8.5.6" findbugs = "1.3.9" slf4j-api = "2.0.9" @@ -17,6 +18,7 @@ joml = { group = "org.joml", name = "joml", version.ref = "joml" } gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } sentry = { group = "io.sentry", name = "sentry", version.ref = "sentry" } +jspecify = { group = "org.jspecify", name = "jspecify", version.ref = "jspecify" } fastutil = { group = "it.unimi.dsi", name = "fastutil", version.ref = "fastutil" } findbugs = { group = "com.google.code.findbugs", name = "jsr305", version.ref = "findbugs" } brigadier = { group = "com.mojang", name = "brigadier", version.ref = "brigadier" } @@ -27,5 +29,5 @@ annotations = { group = "org.jetbrains", name = "annotations", version.ref = "an checkerqual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checkerqual" } [bundles] -api = [ "guava", "gson", "joml", "fastutil", "slf4j-api", "sentry", "brigadier" ] +api = [ "jspecify", "guava", "gson", "joml", "fastutil", "slf4j-api", "sentry", "brigadier" ] annotations = [ "annotations", "checkerqual" ] diff --git a/libs/common.versions.toml b/libs/common.versions.toml index 269bd5b..9d86fc9 100644 --- a/libs/common.versions.toml +++ b/libs/common.versions.toml @@ -1,5 +1,5 @@ [versions] -asm = "9.6" +asm = "9.6.1" log4j = "2.19.0" mockito = "5.5.0" jupiter = "5.10.0" diff --git a/patches/api/0003-Use-Gradle-Version-Catalogs.patch b/patches/api/0003-Use-Gradle-Version-Catalogs.patch index 466a341..56a36c4 100644 --- a/patches/api/0003-Use-Gradle-Version-Catalogs.patch +++ b/patches/api/0003-Use-Gradle-Version-Catalogs.patch @@ -5,24 +5,24 @@ Subject: [PATCH] Use Gradle Version Catalogs diff --git a/build.gradle.kts b/build.gradle.kts -index 7aa138f7123dcfb7d1d9ae9efcf2359522f5d2fd..67324689a65e8ed65c9d27c9b50073488c235c51 100644 +index f536f8f42b99e4b7dc2e25785617837fbc405b5b..51ef37146672e17ac140d260fbc229bcbd4ad049 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,11 +9,13 @@ java { withJavadocJar() } -+/* // Plazma - Use Gradle Version Catalogs ++/* // Plazma - Use Gradle Versuib Catalogs val annotationsVersion = "24.1.0" val bungeeCordChatVersion = "1.20-R0.2" val adventureVersion = "4.17.0" val slf4jVersion = "2.0.9" val log4jVersion = "2.17.1" -+ */ // Plazma - Use Gradle Version Catalogs ++ */ val apiAndDocs: Configuration by configurations.creating { attributes { attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION)) -@@ -27,56 +29,31 @@ configurations.api { +@@ -27,57 +29,29 @@ configurations.api { } dependencies { @@ -53,8 +53,8 @@ index 7aa138f7123dcfb7d1d9ae9efcf2359522f5d2fd..67324689a65e8ed65c9d27c9b5007348 - api("org.slf4j:slf4j-api:$slf4jVersion") - api("io.sentry:sentry:5.4.0") // Pufferfish - -- implementation("org.ow2.asm:asm:9.7") -- implementation("org.ow2.asm:asm-commons:9.7") +- implementation("org.ow2.asm:asm:9.7.1") +- implementation("org.ow2.asm:asm-commons:9.7.1") - // Paper end - - api("org.apache.maven:maven-resolver-provider:3.9.6") // Paper - make API dependency for Paper Plugins @@ -70,13 +70,13 @@ index 7aa138f7123dcfb7d1d9ae9efcf2359522f5d2fd..67324689a65e8ed65c9d27c9b5007348 - compileOnlyApi(checkerQual) - testCompileOnly(checkerQual) - // Paper end +- api("org.jspecify:jspecify:1.0.0") // Paper - add jspecify - - testImplementation("org.apache.commons:commons-lang3:3.12.0") - testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") - testImplementation("org.hamcrest:hamcrest:2.2") -- testImplementation("org.mockito:mockito-core:5.11.0") -- testImplementation("org.ow2.asm:asm-tree:9.7") -+ +- testImplementation("org.mockito:mockito-core:5.14.1") +- testImplementation("org.ow2.asm:asm-tree:9.7.1") + // Plazma start - Use Gradle Version Catalogs + implementation(common.bundles.asm) + @@ -100,11 +100,10 @@ index 7aa138f7123dcfb7d1d9ae9efcf2359522f5d2fd..67324689a65e8ed65c9d27c9b5007348 + testCompileOnly(api.annotations) + testCompileOnly(api.checkerqual) + // Plazma end -+ } // Paper start -@@ -157,25 +134,16 @@ tasks.withType { +@@ -158,27 +132,24 @@ tasks.withType { options.use() options.isDocFilesSubDirs = true options.links( @@ -115,9 +114,11 @@ index 7aa138f7123dcfb7d1d9ae9efcf2359522f5d2fd..67324689a65e8ed65c9d27c9b5007348 - // Paper start - add missing javadoc links - "https://javadoc.io/doc/org.joml/joml/1.10.5/index.html", - "https://www.javadoc.io/doc/com.google.code.gson/gson/2.10.1", + "https://jspecify.dev/docs/api/", - // Paper end - // Paper start - "https://jd.advntr.dev/api/$adventureVersion/", +- "https://jd.advntr.dev/key/$adventureVersion/", - "https://jd.advntr.dev/text-minimessage/$adventureVersion/", - "https://jd.advntr.dev/text-serializer-gson/$adventureVersion/", - "https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/", @@ -128,6 +129,13 @@ index 7aa138f7123dcfb7d1d9ae9efcf2359522f5d2fd..67324689a65e8ed65c9d27c9b5007348 - // Paper end - "https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", // Paper + // Plazma start - Use Gradle Version Catalogs ++ "https://jd.advntr.dev/api/${common.adventure.api.orNull?.version}/", ++ "https://jd.advntr.dev/key/${common.adventure.api.orNull?.version}/", ++ "https://jd.advntr.dev/text-minimessage/${common.adventure.api.orNull?.version}/", ++ "https://jd.advntr.dev/text-serializer-gson/${common.adventure.api.orNull?.version}/", ++ "https://jd.advntr.dev/text-serializer-legacy/${common.adventure.api.orNull?.version}/", ++ "https://jd.advntr.dev/text-serializer-plain/${common.adventure.api.orNull?.version}/", ++ "https://jd.advntr.dev/text-logger-slf4j/${common.adventure.api.orNull?.version}/", + "https://guava.dev/releases/${api.guava.orNull?.version}/api/docs/", + "https://javadoc.io/doc/org.yaml/snakeyaml/${common.snakeyaml.orNull?.version}/", + "https://javadoc.io/doc/org.jetbrains/annotations/${api.annotations.orNull?.version}/", diff --git a/patches/api/0004-Rebrand.patch b/patches/api/0004-Rebrand.patch index 7a28fd0..5ebdcc1 100644 --- a/patches/api/0004-Rebrand.patch +++ b/patches/api/0004-Rebrand.patch @@ -45,10 +45,10 @@ index 199789d56d22fcb1b77ebd56805cc28aa5a5ab0a..3b3bcfa6fa2dbcc7fef899cc7570da09 Logger.getGlobal().log(Level.SEVERE, "TIMING_STACK_CORRUPTION - Report this to the plugin " + last.identifier.group + " (Look for errors above this in the logs) (" + last.identifier + " did not stopTiming)", new Throwable()); } diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java -index fe23268c418cccbd45caf2870f7931cfed978d28..bcf09f735e98f8bbce7c7dfab802ad20e2f17548 100644 +index 7196594e07af19a14c320d77df893978525fe386..843283cfee6e481addea1f1c18147639c70ddfe0 100644 --- a/src/main/java/io/papermc/paper/ServerBuildInfo.java +++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java -@@ -32,6 +32,29 @@ public interface ServerBuildInfo { +@@ -33,6 +33,29 @@ public interface ServerBuildInfo { Key BRAND_PURPUR_ID = Key.key("purpurmc", "purpur"); // Purpur end @@ -79,10 +79,10 @@ index fe23268c418cccbd45caf2870f7931cfed978d28..bcf09f735e98f8bbce7c7dfab802ad20 * Gets the {@code ServerBuildInfo}. * diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java -index 3d29c47ac0620af82d990faf5dfc266c6f0235f1..0dd22efb7f318867d0f099e336505d2830883745 100644 +index c880d0010849ab733ad13bbd18fab3c864d0cf61..e7d7bcbd3dbaf69fd7b9375d4f53ef9420c6b46a 100644 --- a/src/main/java/org/bukkit/command/defaults/VersionCommand.java +++ b/src/main/java/org/bukkit/command/defaults/VersionCommand.java -@@ -258,7 +258,7 @@ public class VersionCommand extends BukkitCommand { +@@ -259,7 +259,7 @@ public class VersionCommand extends BukkitCommand { // Purpur start int distance = getVersionFetcher().distance(); final Component message = Component.join(net.kyori.adventure.text.JoinConfiguration.separator(Component.newline()), @@ -91,7 +91,7 @@ index 3d29c47ac0620af82d990faf5dfc266c6f0235f1..0dd22efb7f318867d0f099e336505d28 // Purpur end msg ); -@@ -281,6 +281,7 @@ public class VersionCommand extends BukkitCommand { +@@ -282,6 +282,7 @@ public class VersionCommand extends BukkitCommand { } } @@ -99,7 +99,7 @@ index 3d29c47ac0620af82d990faf5dfc266c6f0235f1..0dd22efb7f318867d0f099e336505d28 private static int getDistance(@NotNull String repo, @NotNull String hash) { try { BufferedReader reader = Resources.asCharSource( -@@ -301,4 +302,5 @@ public class VersionCommand extends BukkitCommand { +@@ -302,4 +303,5 @@ public class VersionCommand extends BukkitCommand { return -1; } } diff --git a/patches/api/0005-Plazma-Configurations.patch b/patches/api/0005-Plazma-Configurations.patch index 31720c0..41105d1 100644 --- a/patches/api/0005-Plazma-Configurations.patch +++ b/patches/api/0005-Plazma-Configurations.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Plazma Configurations diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index ec8b9b2cbe65838a194281f7d76d0e17defc5211..0062b2d4dc7a64d1e4da240bf8dc5b428eb242ee 100644 +index eb29794f6ca2efc9cde4dd1685822f9a3a73f3b9..d84c788fe1183833c86cde0ba8e174418cede950 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2269,6 +2269,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2277,6 +2277,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi } // Purpur end diff --git a/patches/purpur-drops/dropped-api/0011-LivingEntity-safeFallDistance.patch b/patches/purpur-drops/dropped-api/0011-LivingEntity-safeFallDistance.patch new file mode 100644 index 0000000..a858bf8 --- /dev/null +++ b/patches/purpur-drops/dropped-api/0011-LivingEntity-safeFallDistance.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 May 2019 12:58:19 -0500 +Subject: [PATCH] LivingEntity safeFallDistance + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index b777e530122549455dcce6fac8d4a151c1c0af42..57a3e330043077f042a284c99e2631e1582cb32c 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -1447,4 +1447,24 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + void setBodyYaw(float bodyYaw); + // Paper end - body yaw API ++ ++ // Purpur start ++ /** ++ * Gets the distance (in blocks) this entity can safely fall without taking damage ++ * ++ * @return Safe fall distance ++ * @deprecated use {@link org.bukkit.attribute.Attribute#GENERIC_SAFE_FALL_DISTANCE} instead ++ */ ++ @Deprecated ++ float getSafeFallDistance(); ++ ++ /** ++ * Set the distance (in blocks) this entity can safely fall without taking damage ++ * ++ * @param safeFallDistance Safe fall distance ++ * @deprecated use {@link org.bukkit.attribute.Attribute#GENERIC_SAFE_FALL_DISTANCE} instead ++ */ ++ @Deprecated ++ void setSafeFallDistance(float safeFallDistance); ++ // Purpur end + } diff --git a/patches/purpur-drops/dropped-api/0016-LivingEntity-broadcastItemBreak.patch b/patches/purpur-drops/dropped-api/0016-LivingEntity-broadcastItemBreak.patch new file mode 100644 index 0000000..7157d3d --- /dev/null +++ b/patches/purpur-drops/dropped-api/0016-LivingEntity-broadcastItemBreak.patch @@ -0,0 +1,24 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 17 Aug 2020 21:50:32 -0500 +Subject: [PATCH] LivingEntity#broadcastItemBreak + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index 5c29956c6db53440322330ff723c7087193641f1..e1079c5c4be99e75a646c090189678dd131f210e 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -1447,4 +1447,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + void setBodyYaw(float bodyYaw); + // Paper end - body yaw API ++ ++ // Purpur start ++ /** ++ * Play item break animation for the item in specified equipment slot ++ * ++ * @param slot Equipment slot to play break animation for ++ */ ++ void broadcastItemBreak(@NotNull org.bukkit.inventory.EquipmentSlot slot); ++ // Purpur end + } diff --git a/patches/purpur-drops/dropped-api/0032-Potion-NamespacedKey.patch b/patches/purpur-drops/dropped-api/0032-Potion-NamespacedKey.patch new file mode 100644 index 0000000..b26f177 --- /dev/null +++ b/patches/purpur-drops/dropped-api/0032-Potion-NamespacedKey.patch @@ -0,0 +1,204 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Racci +Date: Fri, 3 Dec 2021 23:48:26 +1100 +Subject: [PATCH] Potion NamespacedKey + + +diff --git a/src/main/java/org/bukkit/potion/PotionEffect.java b/src/main/java/org/bukkit/potion/PotionEffect.java +index c8ab330ef171795d08fa201cf8320703c7f1c66b..93e2ea220dc03c122f82af65d5e9fda5b582290c 100644 +--- a/src/main/java/org/bukkit/potion/PotionEffect.java ++++ b/src/main/java/org/bukkit/potion/PotionEffect.java +@@ -33,6 +33,7 @@ public class PotionEffect implements ConfigurationSerializable { + private static final String AMBIENT = "ambient"; + private static final String PARTICLES = "has-particles"; + private static final String ICON = "has-icon"; ++ private static final String KEY = "namespacedKey"; // Purpur + private final int amplifier; + private final int duration; + private final PotionEffectType type; +@@ -40,6 +41,7 @@ public class PotionEffect implements ConfigurationSerializable { + private final boolean particles; + private final boolean icon; + private final PotionEffect hiddenEffect; // Paper ++ @Nullable private final NamespacedKey key; // Purpur + + /** + * Creates a potion effect. +@@ -50,11 +52,12 @@ public class PotionEffect implements ConfigurationSerializable { + * @param ambient the ambient status, see {@link PotionEffect#isAmbient()} + * @param particles the particle status, see {@link PotionEffect#hasParticles()} + * @param icon the icon status, see {@link PotionEffect#hasIcon()} ++ * @param key the namespacedKey, see {@link PotionEffect#getKey()} + * @param hiddenEffect the hidden PotionEffect + * @hidden Internal-- hidden effects are only shown internally + */ + @org.jetbrains.annotations.ApiStatus.Internal // Paper +- public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable PotionEffect hiddenEffect) { // Paper ++ public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable PotionEffect hiddenEffect, @Nullable NamespacedKey key) { // Paper // Purpur + Preconditions.checkArgument(type != null, "effect type cannot be null"); + this.type = type; + this.duration = duration; +@@ -62,6 +65,7 @@ public class PotionEffect implements ConfigurationSerializable { + this.ambient = ambient; + this.particles = particles; + this.icon = icon; ++ this.key = key; // Purpur + // Paper start + this.hiddenEffect = hiddenEffect; + } +@@ -77,10 +81,27 @@ public class PotionEffect implements ConfigurationSerializable { + * @param icon the icon status, see {@link PotionEffect#hasIcon()} + */ + public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon) { +- this(type, duration, amplifier, ambient, particles, icon, null); ++ this(type, duration, amplifier, ambient, particles, icon, null, null); // Purpur + // Paper end + } + ++ // Purpur start ++ /** ++ * Creates a potion effect. ++ * @param type effect type ++ * @param duration measured in ticks, see {@link ++ * PotionEffect#getDuration()} ++ * @param amplifier the amplifier, see {@link PotionEffect#getAmplifier()} ++ * @param ambient the ambient status, see {@link PotionEffect#isAmbient()} ++ * @param particles the particle status, see {@link PotionEffect#hasParticles()} ++ * @param icon the icon status, see {@link PotionEffect#hasIcon()} ++ * @param key the namespacedKey, see {@link PotionEffect#getKey()} ++ */ ++ public PotionEffect(@NotNull PotionEffectType type, int duration, int amplifier, boolean ambient, boolean particles, boolean icon, @Nullable NamespacedKey key) { ++ this(type, duration, amplifier, ambient, particles, icon, null, key); ++ } ++ // Purpur end ++ + /** + * Creates a potion effect with no defined color. + * +@@ -126,33 +147,33 @@ public class PotionEffect implements ConfigurationSerializable { + * @param map the map to deserialize from + */ + public PotionEffect(@NotNull Map map) { +- this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)), (PotionEffect) map.get(HIDDEN_EFFECT)); // Paper ++ this(getEffectType(map), getInt(map, DURATION), getInt(map, AMPLIFIER), getBool(map, AMBIENT, false), getBool(map, PARTICLES, true), getBool(map, ICON, getBool(map, PARTICLES, true)), (PotionEffect) map.get(HIDDEN_EFFECT), getKey(map)); // Paper // Purpur - getKey + } + + // Paper start + @NotNull + public PotionEffect withType(@NotNull PotionEffectType type) { +- return new PotionEffect(type, duration, amplifier, ambient, particles, icon); ++ return new PotionEffect(type, duration, amplifier, ambient, particles, icon, key); // Purpur - add key + } + @NotNull + public PotionEffect withDuration(int duration) { +- return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon, key); // Purpur - add key + } + @NotNull + public PotionEffect withAmplifier(int amplifier) { +- return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon, key); // Purpur - add key + } + @NotNull + public PotionEffect withAmbient(boolean ambient) { +- return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon, key); // Purpur - add key + } + @NotNull + public PotionEffect withParticles(boolean particles) { +- return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon, key); // Purpur - add key + } + @NotNull + public PotionEffect withIcon(boolean icon) { +- return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon); ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon, key); // Purpur - add key + } + + /** +@@ -169,6 +190,13 @@ public class PotionEffect implements ConfigurationSerializable { + } + // Paper end + ++ // Purpur start ++ @NotNull ++ public PotionEffect withKey(@Nullable NamespacedKey key) { ++ return new PotionEffect(this.type, duration, amplifier, ambient, particles, icon, key); ++ } ++ // Purpur end ++ + @NotNull + private static PotionEffectType getEffectType(@NotNull Map map) { + PotionEffectType effect; +@@ -201,6 +229,17 @@ public class PotionEffect implements ConfigurationSerializable { + return def; + } + ++ // Purpur start ++ @Nullable ++ private static NamespacedKey getKey(@NotNull Map map) { ++ Object key = map.get(KEY); ++ if (key instanceof String stringKey) { ++ return NamespacedKey.fromString(stringKey); ++ } ++ return null; ++ } ++ // Purpur end ++ + @Override + @NotNull + public Map serialize() { +@@ -215,6 +254,11 @@ public class PotionEffect implements ConfigurationSerializable { + if (this.hiddenEffect != null) { + builder.put(HIDDEN_EFFECT, this.hiddenEffect); + } ++ // Purpur start ++ if (key != null) { ++ builder.put(KEY, key.toString()); ++ } ++ // Purpur end + return builder.build(); + // Paper end + } +@@ -243,7 +287,7 @@ public class PotionEffect implements ConfigurationSerializable { + return false; + } + PotionEffect that = (PotionEffect) obj; +- return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon && java.util.Objects.equals(this.hiddenEffect, that.hiddenEffect); // Paper ++ return this.type.equals(that.type) && this.ambient == that.ambient && this.amplifier == that.amplifier && this.duration == that.duration && this.particles == that.particles && this.icon == that.icon && java.util.Objects.equals(this.hiddenEffect, that.hiddenEffect) && this.key == that.key; // Paper // Purpur - add key + } + + /** +@@ -339,6 +383,24 @@ public class PotionEffect implements ConfigurationSerializable { + return icon; + } + ++ ++ // Purpur start ++ /** ++ * @return if the key isn't the default namespacedKey ++ */ ++ public boolean hasKey() { ++ return key != null; ++ } ++ ++ /** ++ * @return the key attached to the potion ++ */ ++ @Nullable ++ public NamespacedKey getKey() { ++ return key; ++ } ++ // Purpur end ++ + @Override + public int hashCode() { + int hash = 1; +@@ -354,6 +416,6 @@ public class PotionEffect implements ConfigurationSerializable { + + @Override + public String toString() { +- return "PotionEffect{" + "amplifier=" + amplifier + ", duration=" + duration + ", type=" + type + ", ambient=" + ambient + ", particles=" + particles + ", icon=" + icon + ", hiddenEffect=" + hiddenEffect + '}'; // Paper ++ return "PotionEffect{" + "amplifier=" + amplifier + ", duration=" + duration + ", type=" + type + ", ambient=" + ambient + ", particles=" + particles + ", icon=" + icon + ", hiddenEffect=" + hiddenEffect + ", key=" + key + '}'; // Paper // Purpur - add key + } + } diff --git a/patches/purpur-drops/dropped-api/0041-Add-item-packet-serialize-event.patch b/patches/purpur-drops/dropped-api/0041-Add-item-packet-serialize-event.patch new file mode 100644 index 0000000..633be50 --- /dev/null +++ b/patches/purpur-drops/dropped-api/0041-Add-item-packet-serialize-event.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MelnCat +Date: Sat, 24 Sep 2022 10:50:33 -0700 +Subject: [PATCH] Add item packet serialize event + + +diff --git a/src/main/java/org/purpurmc/purpur/event/packet/NetworkItemSerializeEvent.java b/src/main/java/org/purpurmc/purpur/event/packet/NetworkItemSerializeEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0da73d2ea83a6055e34894ba1c7506fc8667712 +--- /dev/null ++++ b/src/main/java/org/purpurmc/purpur/event/packet/NetworkItemSerializeEvent.java +@@ -0,0 +1,48 @@ ++package org.purpurmc.purpur.event.packet; ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * Called when an item is about to be written to a packet. ++ */ ++public class NetworkItemSerializeEvent extends Event { ++ private ItemStack itemStack; ++ ++ public NetworkItemSerializeEvent(@NotNull ItemStack itemStack) { ++ super(!org.bukkit.Bukkit.isPrimaryThread()); ++ this.itemStack = itemStack; ++ } ++ ++ /** ++ * @return The item that is about to be serialized. Not mutable ++ */ ++ @NotNull ++ public ItemStack getItemStack() { ++ return itemStack; ++ } ++ ++ /** ++ * Sets the item that will be serialized. ++ * ++ * @param itemStack The item ++ */ ++ public void setItemStack(@Nullable ItemStack itemStack) { ++ this.itemStack = itemStack; ++ } ++ ++ private static final HandlerList handlers = new HandlerList(); ++ ++ @NotNull ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/purpur-drops/dropped-api/0049-Add-hover-lines-API.patch b/patches/purpur-drops/dropped-api/0049-Add-hover-lines-API.patch new file mode 100644 index 0000000..052712a --- /dev/null +++ b/patches/purpur-drops/dropped-api/0049-Add-hover-lines-API.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Meln Cat +Date: Mon, 2 Oct 2023 17:42:19 -0700 +Subject: [PATCH] Add hover lines API + + +diff --git a/src/main/java/org/bukkit/inventory/ItemFactory.java b/src/main/java/org/bukkit/inventory/ItemFactory.java +index 98a970a6582dca22e719a31559c7becea4725cb2..1cd2962ceb4fa0a0a3e28a09fa4ccef5802cd5c4 100644 +--- a/src/main/java/org/bukkit/inventory/ItemFactory.java ++++ b/src/main/java/org/bukkit/inventory/ItemFactory.java +@@ -353,4 +353,14 @@ public interface ItemFactory { + */ + @NotNull ItemStack enchantWithLevels(@NotNull ItemStack itemStack, @org.jetbrains.annotations.Range(from = 1, to = 30) int levels, boolean allowTreasure, @NotNull java.util.Random random); + // Paper end - enchantWithLevels API ++ ++ // Purpur start ++ /** ++ * Returns the lines of text shown when hovering over an item ++ * @param itemStack The ItemStack ++ * @param advanced Whether advanced tooltips are shown ++ * @return the list of Components ++ */ ++ @NotNull java.util.List getHoverLines(@NotNull ItemStack itemStack, boolean advanced); ++ // Purpur end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java +index 6e9b4cbc81878616b1c48add5db534286d267b05..e497575b2f44bb8b3bb6fdda3ae2f5247cbb4679 100644 +--- a/src/main/java/org/bukkit/inventory/ItemStack.java ++++ b/src/main/java/org/bukkit/inventory/ItemStack.java +@@ -1644,5 +1644,14 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat + } + return random.nextInt(unbreaking + 1) > 0; + } ++ ++ /** ++ * Returns the lines of text shown when hovering over the item ++ * @param advanced Whether advanced tooltips are shown ++ * @return the list of Components ++ */ ++ public @NotNull List getHoverLines(boolean advanced) { ++ return Bukkit.getItemFactory().getHoverLines(this, advanced); ++ } + // Purpur end + } diff --git a/patches/purpur-drops/dropped-server/0013-LivingEntity-safeFallDistance.patch b/patches/purpur-drops/dropped-server/0013-LivingEntity-safeFallDistance.patch new file mode 100644 index 0000000..4991196 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0013-LivingEntity-safeFallDistance.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sun, 5 May 2019 12:58:45 -0500 +Subject: [PATCH] LivingEntity safeFallDistance + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index aa351df679f300018367244c7ccb3e5a59e9276f..39c2a9f732b8e2452fd2dca07193a173d0c2ba1c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1173,4 +1173,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + this.getHandle().setYBodyRot(bodyYaw); + } + // Paper end - body yaw API ++ ++ // Purpur start ++ @Override ++ public float getSafeFallDistance() { ++ return (float) getHandle().getAttributeValue(Attributes.SAFE_FALL_DISTANCE); ++ } ++ ++ @Override ++ public void setSafeFallDistance(float safeFallDistance) { ++ getHandle().getAttribute(Attributes.SAFE_FALL_DISTANCE).setBaseValue(safeFallDistance); ++ } ++ // Purpur end + } diff --git a/patches/purpur-drops/dropped-server/0040-End-gateway-should-check-if-entity-can-use-portal.patch b/patches/purpur-drops/dropped-server/0040-End-gateway-should-check-if-entity-can-use-portal.patch new file mode 100644 index 0000000..d5bd1de --- /dev/null +++ b/patches/purpur-drops/dropped-server/0040-End-gateway-should-check-if-entity-can-use-portal.patch @@ -0,0 +1,18 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Sat, 21 Mar 2020 18:33:05 -0500 +Subject: [PATCH] End gateway should check if entity can use portal + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +index 93bd70c1dc2ba8b893a6087730071c81fb1132f4..60b343edc4383c8bc450f106f483349850432fa3 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +@@ -167,6 +167,7 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { + + public static void teleportEntity(Level world, BlockPos pos, BlockState state, Entity entity, TheEndGatewayBlockEntity blockEntity) { + if (world instanceof ServerLevel worldserver && !blockEntity.isCoolingDown()) { ++ if (!entity.canChangeDimensions()) return; // Purpur + blockEntity.teleportCooldown = 100; + BlockPos blockposition1; + diff --git a/patches/purpur-drops/dropped-server/0082-LivingEntity-broadcastItemBreak.patch b/patches/purpur-drops/dropped-server/0082-LivingEntity-broadcastItemBreak.patch new file mode 100644 index 0000000..1e339ef --- /dev/null +++ b/patches/purpur-drops/dropped-server/0082-LivingEntity-broadcastItemBreak.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Mon, 17 Aug 2020 21:50:39 -0500 +Subject: [PATCH] LivingEntity#broadcastItemBreak + + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index a1e715629313346f670bce92483996122b0f1d7b..386647f6000c71c59ab8d7875219eefdc5a3d7ef 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1181,4 +1181,12 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + this.getHandle().setYBodyRot(bodyYaw); + } + // Paper end - body yaw API ++ ++ // Purpur start ++ @Override ++ public void broadcastItemBreak(org.bukkit.inventory.EquipmentSlot slot) { ++ if (slot == null) return; ++ getHandle().broadcastBreakEvent(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); ++ } ++ // Purpur end + } diff --git a/patches/purpur-drops/dropped-server/0094-Allow-infinite-and-mending-enchantments-together.patch b/patches/purpur-drops/dropped-server/0094-Allow-infinite-and-mending-enchantments-together.patch new file mode 100644 index 0000000..b5f4be4 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0094-Allow-infinite-and-mending-enchantments-together.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +Date: Tue, 13 Oct 2020 20:04:33 -0500 +Subject: [PATCH] Allow infinite and mending enchantments together + + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/ArrowInfiniteEnchantment.java b/src/main/java/net/minecraft/world/item/enchantment/ArrowInfiniteEnchantment.java +index 81cc05c929d612898609965d82454b89cd18f9f5..fa73c3d4b58ad8379963a9866d8f09e1d6abd663 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/ArrowInfiniteEnchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/ArrowInfiniteEnchantment.java +@@ -7,6 +7,6 @@ public class ArrowInfiniteEnchantment extends Enchantment { + + @Override + public boolean checkCompatibility(Enchantment other) { +- return !(other instanceof MendingEnchantment) && super.checkCompatibility(other); ++ return !(other instanceof MendingEnchantment) && super.checkCompatibility(other) || other instanceof MendingEnchantment && org.purpurmc.purpur.PurpurConfig.allowInfinityMending; // Purpur + } + } +diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +index 2f68cf2fc064a38ca059504a39d563d95d01643e..6d621a93aaf94927fa6c73e649dcdb8bbbaadd2a 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +@@ -246,6 +246,16 @@ public class PurpurConfig { + cryingObsidianValidForPortalFrame = getBoolean("settings.blocks.crying_obsidian.valid-for-portal-frame", cryingObsidianValidForPortalFrame); + } + ++ public static boolean allowInfinityMending = false; ++ private static void enchantmentSettings() { ++ if (version < 5) { ++ boolean oldValue = getBoolean("settings.enchantment.allow-infinite-and-mending-together", false); ++ set("settings.enchantment.allow-infinity-and-mending-together", oldValue); ++ set("settings.enchantment.allow-infinite-and-mending-together", null); ++ } ++ allowInfinityMending = getBoolean("settings.enchantment.allow-infinity-and-mending-together", allowInfinityMending); ++ } ++ + public static boolean endermanShortHeight = false; + private static void entitySettings() { + endermanShortHeight = getBoolean("settings.entity.enderman.short-height", endermanShortHeight); diff --git a/patches/purpur-drops/dropped-server/0142-Allow-infinity-on-crossbows.patch b/patches/purpur-drops/dropped-server/0142-Allow-infinity-on-crossbows.patch new file mode 100644 index 0000000..5f50b3a --- /dev/null +++ b/patches/purpur-drops/dropped-server/0142-Allow-infinity-on-crossbows.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Kerllenevich +Date: Thu, 18 Mar 2021 12:25:29 -0400 +Subject: [PATCH] Allow infinity on crossbows + + +diff --git a/src/main/java/net/minecraft/world/item/CrossbowItem.java b/src/main/java/net/minecraft/world/item/CrossbowItem.java +index 1f52feb5684ee1bab710e1557cf69b43b4d4dfd4..d2bb5c84e1895f28afed03d1868a79338e4f3e58 100644 +--- a/src/main/java/net/minecraft/world/item/CrossbowItem.java ++++ b/src/main/java/net/minecraft/world/item/CrossbowItem.java +@@ -107,7 +107,7 @@ public class CrossbowItem extends ProjectileWeaponItem { + return CrossbowItem.tryLoadProjectiles(shooter, crossbow, true); + } + private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow, boolean consume) { +- List list = draw(crossbow, shooter.getProjectile(crossbow), shooter, consume); ++ List list = draw(crossbow, shooter.getProjectile(crossbow), shooter, (org.purpurmc.purpur.PurpurConfig.allowCrossbowInfinity && EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY, crossbow) > 0) || consume); + // Paper end - Add EntityLoadCrossbowEvent + if (!list.isEmpty()) { + crossbow.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(list)); +diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +index 0587b0c7f34ae90f0d06f29d58fafbcf5b80ff13..c60d0d1861fd24b74bfa93228357f27d524f4ce7 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +@@ -284,6 +284,7 @@ public class PurpurConfig { + } + + public static boolean allowInfinityMending = false; ++ public static boolean allowCrossbowInfinity = true; + private static void enchantmentSettings() { + if (version < 5) { + boolean oldValue = getBoolean("settings.enchantment.allow-infinite-and-mending-together", false); +@@ -291,6 +292,7 @@ public class PurpurConfig { + set("settings.enchantment.allow-infinite-and-mending-together", null); + } + allowInfinityMending = getBoolean("settings.enchantment.allow-infinity-and-mending-together", allowInfinityMending); ++ allowCrossbowInfinity = getBoolean("settings.enchantment.allow-infinity-on-crossbow", allowCrossbowInfinity); + } + + public static boolean endermanShortHeight = false; diff --git a/patches/purpur-drops/dropped-server/0220-Potion-NamespacedKey.patch b/patches/purpur-drops/dropped-server/0220-Potion-NamespacedKey.patch new file mode 100644 index 0000000..7b8d0b1 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0220-Potion-NamespacedKey.patch @@ -0,0 +1,223 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Racci +Date: Sat, 4 Dec 2021 00:07:05 +1100 +Subject: [PATCH] Potion NamespacedKey + + +diff --git a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java +index 32cf6ea96aaa2e6bd0cc28fa88492ceea3d34052..9787dd4fc6ca2ed8aba3db7674ad2dc26a529a7a 100644 +--- a/src/main/java/net/minecraft/world/effect/MobEffectInstance.java ++++ b/src/main/java/net/minecraft/world/effect/MobEffectInstance.java +@@ -53,6 +53,7 @@ public class MobEffectInstance implements Comparable { + private boolean showIcon; + @Nullable + public MobEffectInstance hiddenEffect; ++ private org.bukkit.NamespacedKey key; // Purpur - add key + private final MobEffectInstance.BlendState blendState = new MobEffectInstance.BlendState(); + + public MobEffectInstance(Holder effect) { +@@ -71,8 +72,14 @@ public class MobEffectInstance implements Comparable { + this(effect, duration, amplifier, ambient, visible, visible); + } + ++ // Purpur start ++ public MobEffectInstance(Holder effect, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon, @Nullable org.bukkit.NamespacedKey key) { ++ this(effect, duration, amplifier, ambient, showParticles, showIcon, null, key); ++ // Purpur end ++ } ++ + public MobEffectInstance(Holder effect, int duration, int amplifier, boolean ambient, boolean showParticles, boolean showIcon) { +- this(effect, duration, amplifier, ambient, showParticles, showIcon, null); ++ this(effect, duration, amplifier, ambient, showParticles, showIcon, null, null); // Purpur + } + + public MobEffectInstance( +@@ -82,7 +89,8 @@ public class MobEffectInstance implements Comparable { + boolean ambient, + boolean showParticles, + boolean showIcon, +- @Nullable MobEffectInstance hiddenEffect ++ @Nullable MobEffectInstance hiddenEffect, ++ @Nullable org.bukkit.NamespacedKey key // Purpur + ) { + this.effect = effect; + this.duration = duration; +@@ -90,6 +98,7 @@ public class MobEffectInstance implements Comparable { + this.ambient = ambient; + this.visible = showParticles; + this.showIcon = showIcon; ++ this.key = key; // Purpur - add key + this.hiddenEffect = hiddenEffect; + } + +@@ -135,6 +144,7 @@ public class MobEffectInstance implements Comparable { + this.ambient = that.ambient; + this.visible = that.visible; + this.showIcon = that.showIcon; ++ this.key = that.key; // Purpur - add key + } + + public boolean update(MobEffectInstance that) { +@@ -179,6 +189,13 @@ public class MobEffectInstance implements Comparable { + bl = true; + } + ++ // Purpur start ++ if (that.key != this.key) { ++ this.key = that.key; ++ bl = true; ++ } ++ // Purpur end ++ + return bl; + } + +@@ -222,6 +239,17 @@ public class MobEffectInstance implements Comparable { + return this.showIcon; + } + ++ // Purpur start ++ public boolean hasKey() { ++ return this.key != null; ++ } ++ ++ @Nullable ++ public org.bukkit.NamespacedKey getKey() { ++ return this.key; ++ } ++ // Purpur end ++ + public boolean tick(LivingEntity entity, Runnable overwriteCallback) { + if (this.hasRemainingDuration()) { + int i = this.isInfiniteDuration() ? entity.tickCount : this.duration; +@@ -286,6 +314,12 @@ public class MobEffectInstance implements Comparable { + string = string + ", Show Icon: false"; + } + ++ // Purpur start ++ if (this.hasKey()) { ++ string = string + ", Key: " + this.key; ++ } ++ // Purpur end ++ + return string; + } + +@@ -300,6 +334,7 @@ public class MobEffectInstance implements Comparable { + && this.duration == mobEffectInstance.duration + && this.amplifier == mobEffectInstance.amplifier + && this.ambient == mobEffectInstance.ambient ++ && this.key == mobEffectInstance.key // Purpur - add key + && this.effect.equals(mobEffectInstance.effect); + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java +index 4a9e6a679530025caa710a152c5249299ceffdf9..ea4f3f606aad69965384c73eb1273ed0644297b8 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java +@@ -42,6 +42,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta { + static final ItemMetaKey POTION_EFFECTS = new ItemMetaKey("custom-effects"); + static final ItemMetaKey POTION_COLOR = new ItemMetaKey("custom-color"); + static final ItemMetaKey DEFAULT_POTION = new ItemMetaKey("potion-type"); ++ static final ItemMetaKey KEY = new ItemMetaKey("key", "namespacedkey"); // Purpur - add key + + private PotionType type; + private List customEffects; +@@ -91,7 +92,13 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta { + boolean ambient = effect.isAmbient(); + boolean particles = effect.isVisible(); + boolean icon = effect.showIcon(); +- this.customEffects.add(new PotionEffect(type, duration, amp, ambient, particles, icon)); ++ // Purpur start ++ NamespacedKey key = null; ++ if (tag.contains(CraftMetaPotion.KEY.NBT)) { ++ key = NamespacedKey.fromString(effect.getString(CraftMetaPotion.KEY.NBT)); ++ } ++ this.customEffects.add(new PotionEffect(type, duration, amp, ambient, particles, icon, key)); ++ // Purpur end + } + }); + } +@@ -130,6 +137,11 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta { + if (this.customEffects != null) { + for (PotionEffect effect : this.customEffects) { + effectList.add(new MobEffectInstance(CraftPotionEffectType.bukkitToMinecraftHolder(effect.getType()), effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon())); ++ // Purpur start ++ if (effect.hasKey()) { ++ effectData.putString(CraftMetaPotion.KEY.NBT, effect.getKey().toString()); ++ } ++ // Purpur end + } + } + +@@ -196,7 +208,7 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta { + if (index != -1) { + if (overwrite) { + PotionEffect old = this.customEffects.get(index); +- if (old.getAmplifier() == effect.getAmplifier() && old.getDuration() == effect.getDuration() && old.isAmbient() == effect.isAmbient()) { ++ if (old.getAmplifier() == effect.getAmplifier() && old.getDuration() == effect.getDuration() && old.isAmbient() == effect.isAmbient() && old.getKey() == effect.getKey()) { // Purpur - add key + return false; + } + this.customEffects.set(index, effect); +diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java +index 14c58cf8d255c51473fd3d0092faeaf5a3c1ae0c..3ee9c14440046872b83de628b7f460d0782e9315 100644 +--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java ++++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java +@@ -11,7 +11,7 @@ public class CraftPotionUtil { + public static MobEffectInstance fromBukkit(PotionEffect effect) { + Holder type = CraftPotionEffectType.bukkitToMinecraftHolder(effect.getType()); + // Paper - Note: do not copy over the hidden effect, as this method is only used for applying to entities which we do not want to convert over. +- return new MobEffectInstance(type, effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon()); // Paper ++ return new MobEffectInstance(type, effect.getDuration(), effect.getAmplifier(), effect.isAmbient(), effect.hasParticles(), effect.hasIcon(), effect.getKey()); // Paper // Purpur - add key + } + + public static PotionEffect toBukkit(MobEffectInstance effect) { +@@ -20,7 +20,7 @@ public class CraftPotionUtil { + int duration = effect.getDuration(); + boolean ambient = effect.isAmbient(); + boolean particles = effect.isVisible(); +- return new PotionEffect(type, duration, amp, ambient, particles, effect.showIcon(), effect.hiddenEffect == null ? null : toBukkit(effect.hiddenEffect)); // Paper ++ return new PotionEffect(type, duration, amp, ambient, particles, effect.showIcon(), effect.hiddenEffect == null ? null : toBukkit(effect.hiddenEffect), effect.getKey()); // Paper // Purpur - add key + } + + public static boolean equals(Holder mobEffect, PotionEffectType type) { +diff --git a/src/test/java/org/bukkit/potion/PotionTest.java b/src/test/java/org/bukkit/potion/PotionTest.java +index cbcd1c21646308b2a9706095e2e12177ca06734d..b3ccaea713e858e334cc91d1ae498e589e3daafa 100644 +--- a/src/test/java/org/bukkit/potion/PotionTest.java ++++ b/src/test/java/org/bukkit/potion/PotionTest.java +@@ -10,6 +10,7 @@ import net.minecraft.world.effect.MobEffect; + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.item.alchemy.Potion; + import org.bukkit.craftbukkit.legacy.FieldRename; ++import org.bukkit.NamespacedKey; // Purpur + import org.bukkit.craftbukkit.potion.CraftPotionEffectType; + import org.bukkit.support.AbstractTestingBase; + import org.junit.jupiter.api.Test; +@@ -47,4 +48,27 @@ public class PotionTest extends AbstractTestingBase { + assertEquals(bukkit, byName, "Same type not returned by name " + key); + } + } ++ ++ // Purpur start ++ @Test ++ public void testNamespacedKey() { ++ NamespacedKey key = new NamespacedKey("testnamespace", "testkey"); ++ PotionEffect namedSpacedEffect = new PotionEffect(PotionEffectType.DOLPHINS_GRACE, 20, 0, true, true, true, key); ++ assertNotNull(namedSpacedEffect.getKey()); ++ assertTrue(namedSpacedEffect.hasKey()); ++ assertFalse(namedSpacedEffect.withKey(null).hasKey()); ++ ++ PotionEffect effect = new PotionEffect(PotionEffectType.DOLPHINS_GRACE, 20, 0, true, true, true); ++ assertNull(effect.getKey()); ++ assertFalse(effect.hasKey()); ++ assertTrue(namedSpacedEffect.withKey(key).hasKey()); ++ ++ Map s1 = namedSpacedEffect.serialize(); ++ Map s2 = effect.serialize(); ++ assertTrue(s1.containsKey("namespacedKey")); ++ assertFalse(s2.containsKey("namespacedKey")); ++ assertNotNull(new PotionEffect(s1).getKey()); ++ assertNull(new PotionEffect(s2).getKey()); ++ } ++ // Purpur end + } diff --git a/patches/purpur-drops/dropped-server/0236-Configurable-food-attributes.patch b/patches/purpur-drops/dropped-server/0236-Configurable-food-attributes.patch new file mode 100644 index 0000000..cc0c5a9 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0236-Configurable-food-attributes.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 18 Jan 2022 04:51:51 -0600 +Subject: [PATCH] Configurable food attributes + + +diff --git a/src/main/java/net/minecraft/world/food/FoodProperties.java b/src/main/java/net/minecraft/world/food/FoodProperties.java +index 9967ba762567631f2bdb1e4f8fe16a13ea927b46..6c945ae8fe8b1517e312c688f829fab41f12d9f4 100644 +--- a/src/main/java/net/minecraft/world/food/FoodProperties.java ++++ b/src/main/java/net/minecraft/world/food/FoodProperties.java +@@ -2,15 +2,22 @@ package net.minecraft.world.food; + + import com.google.common.collect.Lists; + import com.mojang.datafixers.util.Pair; ++ ++import java.util.ArrayList; + import java.util.List; + import net.minecraft.world.effect.MobEffectInstance; + + public class FoodProperties { +- private final int nutrition; +- private final float saturationModifier; +- private final boolean isMeat; +- private final boolean canAlwaysEat; +- private final boolean fastFood; ++ // Purpur start ++ private int nutrition; public void setNutrition(int nutrition) { this.nutrition = nutrition; } ++ private float saturationModifier; public void setSaturationModifier(float saturation) { this.saturationModifier = saturation; } ++ private boolean isMeat; public void setIsMeat(boolean isMeat) { this.isMeat = isMeat; } ++ private boolean canAlwaysEat; public void setCanAlwaysEat(boolean canAlwaysEat) { this.canAlwaysEat = canAlwaysEat; } ++ private boolean fastFood; public void setFastFood(boolean isFastFood) { this.fastFood = isFastFood; } ++ public FoodProperties copy() { ++ return new FoodProperties(this.nutrition, this.saturationModifier, this.isMeat, this.canAlwaysEat, this.fastFood, new ArrayList<>(this.effects)); ++ } ++ // Purpur end + private final List> effects; + + FoodProperties(int hunger, float saturationModifier, boolean meat, boolean alwaysEdible, boolean snack, List> statusEffects) { +diff --git a/src/main/java/net/minecraft/world/food/Foods.java b/src/main/java/net/minecraft/world/food/Foods.java +index 4569cf30b33167a415256a8542820557ad38f89e..9c65eefa855f3622b6c9ae2a698cf332ba225c7f 100644 +--- a/src/main/java/net/minecraft/world/food/Foods.java ++++ b/src/main/java/net/minecraft/world/food/Foods.java +@@ -4,6 +4,8 @@ import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.effect.MobEffects; + + public class Foods { ++ public static final java.util.Map ALL_PROPERTIES = new java.util.HashMap<>(); // Purpur ++ public static final java.util.Map DEFAULT_PROPERTIES = new java.util.HashMap<>(); // Purpur + public static final FoodProperties APPLE = new FoodProperties.Builder().nutrition(4).saturationMod(0.3F).build(); + public static final FoodProperties BAKED_POTATO = new FoodProperties.Builder().nutrition(5).saturationMod(0.6F).build(); + public static final FoodProperties BEEF = new FoodProperties.Builder().nutrition(3).saturationMod(0.3F).meat().build(); +diff --git a/src/main/java/net/minecraft/world/item/Items.java b/src/main/java/net/minecraft/world/item/Items.java +index bb2103a488964f25335393fa91e8ae5749eca333..249c887af68f56739c3609bad2405ba2cbe11762 100644 +--- a/src/main/java/net/minecraft/world/item/Items.java ++++ b/src/main/java/net/minecraft/world/item/Items.java +@@ -1715,6 +1715,13 @@ public class Items { + ((BlockItem)item).registerBlocks(Item.BY_BLOCK, item); + } + ++ // Purpur start ++ if (item.getFoodProperties() != null) { ++ Foods.ALL_PROPERTIES.put(key.location().getPath(), item.getFoodProperties()); ++ Foods.DEFAULT_PROPERTIES.put(key.location().getPath(), item.getFoodProperties().copy()); ++ } ++ // Purpur end ++ + return Registry.register(BuiltInRegistries.ITEM, key, item); + } + } +diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +index 0e28cf20a870f3f3662bd1d8f7a4f2cbf13c48bf..ce3ab604e6ed6669f38abf83d40b500148277b9d 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +@@ -466,4 +466,75 @@ public class PurpurConfig { + String setPattern = getString("settings.username-valid-characters", defaultPattern); + usernameValidCharactersPattern = java.util.regex.Pattern.compile(setPattern == null || setPattern.isBlank() ? defaultPattern : setPattern); + } ++ ++ private static void foodSettings() { ++ ConfigurationSection properties = config.getConfigurationSection("settings.food-properties"); ++ if (properties == null) { ++ config.addDefault("settings.food-properties", new HashMap<>()); ++ return; ++ } ++ ++ Map> effectDefaults = new HashMap<>(); ++ Map EFFECT_DEFAULT = Map.of( ++ "chance", 0.0F, ++ "duration", 0, ++ "amplifier", 0, ++ "ambient", false, ++ "visible", true, ++ "show-icon", true ++ ); ++ ++ properties.getKeys(false).forEach(foodKey -> { ++ FoodProperties food = Foods.ALL_PROPERTIES.get(foodKey); ++ if (food == null) { ++ PurpurConfig.log(Level.SEVERE, "Invalid food property: " + foodKey); ++ return; ++ } ++ FoodProperties foodDefaults = Foods.DEFAULT_PROPERTIES.get(foodKey); ++ food.setNutrition(properties.getInt(foodKey + ".nutrition", foodDefaults.getNutrition())); ++ food.setSaturationModifier((float) properties.getDouble(foodKey + ".saturation-modifier", foodDefaults.getSaturationModifier())); ++ food.setIsMeat(properties.getBoolean(foodKey + ".is-meat", foodDefaults.isMeat())); ++ food.setCanAlwaysEat(properties.getBoolean(foodKey + ".can-always-eat", foodDefaults.canAlwaysEat())); ++ food.setFastFood(properties.getBoolean(foodKey + ".fast-food", foodDefaults.isFastFood())); ++ ConfigurationSection effects = properties.getConfigurationSection(foodKey + ".effects"); ++ if (effects != null) { ++ effectDefaults.clear(); ++ foodDefaults.getEffects().forEach(pair -> { ++ MobEffectInstance effect = pair.getFirst(); ++ effectDefaults.put(effect.getEffect(), Map.of( ++ "chance", pair.getSecond(), ++ "duration", effect.getDuration(), ++ "amplifier", effect.getAmplifier(), ++ "ambient", effect.isAmbient(), ++ "visible", effect.isVisible(), ++ "show-icon", effect.showIcon() ++ )); ++ }); ++ effects.getKeys(false).forEach(effectKey -> { ++ MobEffect effect = BuiltInRegistries.MOB_EFFECT.get(new ResourceLocation(effectKey)); ++ if (effect == null) { ++ PurpurConfig.log(Level.SEVERE, "Invalid food property effect for " + foodKey + ": " + effectKey); ++ return; ++ } ++ ++ Map effectDefault = effectDefaults.get(effect); ++ if (effectDefault == null) { ++ effectDefault = EFFECT_DEFAULT; ++ } ++ ++ food.getEffects().removeIf(pair -> pair.getFirst().getEffect() == effect); ++ float chance = (float) effects.getDouble(effectKey + ".chance", ((Float) effectDefault.get("chance")).doubleValue()); ++ int duration = effects.getInt(effectKey + ".duration", (int) effectDefault.get("duration")); ++ if (chance <= 0.0F || duration < 0) { ++ return; ++ } ++ int amplifier = effects.getInt(effectKey + ".amplifier", (int) effectDefault.get("amplifier")); ++ boolean ambient = effects.getBoolean(effectKey + ".ambient", (boolean) effectDefault.get("ambient")); ++ boolean visible = effects.getBoolean(effectKey + ".visible", (boolean) effectDefault.get("visible")); ++ boolean showIcon = effects.getBoolean(effectKey + ".show-icon", (boolean) effectDefault.get("show-icon")); ++ food.getEffects().add(Pair.of(new MobEffectInstance(effect, duration, amplifier, ambient, visible, showIcon), chance)); ++ }); ++ } ++ }); ++ } + } diff --git a/patches/purpur-drops/dropped-server/0255-Send-client-custom-name-of-BE.patch b/patches/purpur-drops/dropped-server/0255-Send-client-custom-name-of-BE.patch new file mode 100644 index 0000000..30f7486 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0255-Send-client-custom-name-of-BE.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ben Kerllenevich +Date: Wed, 13 Jul 2022 16:27:43 -0400 +Subject: [PATCH] Send client custom name of BE + +https://modrinth.com/mod/know-my-name + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 4ea15e17a1393864422edb6d5c57962651abf69a..a78ed43288cfefaeb2592ed0a33fd11565dea2b2 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -256,10 +256,24 @@ public abstract class BlockEntity { + + @Nullable + public Packet getUpdatePacket() { ++ // Purpur start ++ if (this instanceof net.minecraft.world.Nameable nameable && nameable.hasCustomName()) { ++ CompoundTag nbt = this.saveWithoutMetadata(); ++ nbt.remove("Items"); ++ return net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket.create(this, $ -> nbt); ++ } ++ // Purpur end + return null; + } + + public CompoundTag getUpdateTag(HolderLookup.Provider registryLookup) { ++ // Purpur start ++ if (this instanceof net.minecraft.world.Nameable nameable && nameable.hasCustomName()) { ++ CompoundTag nbt = this.saveWithoutMetadata(); ++ nbt.remove("Items"); ++ return nbt; ++ } ++ // Purpur end + return new CompoundTag(); + } + diff --git a/patches/purpur-drops/dropped-server/0263-Allay-respect-item-NBT.patch b/patches/purpur-drops/dropped-server/0263-Allay-respect-item-NBT.patch new file mode 100644 index 0000000..4e5e97b --- /dev/null +++ b/patches/purpur-drops/dropped-server/0263-Allay-respect-item-NBT.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: BillyGalbreath +Date: Tue, 20 Sep 2022 17:56:21 -0500 +Subject: [PATCH] Allay respect item NBT + +https://github.com/PurpurMC/Purpur/discussions/1127 + +diff --git a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java +index bca7b7192debb3a34a08047010a2438e7b7e2a78..53765198483e137d411e227119e4f912964aefe3 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java ++++ b/src/main/java/net/minecraft/world/entity/animal/allay/Allay.java +@@ -399,9 +399,31 @@ public class Allay extends PathfinderMob implements InventoryCarrier, VibrationS + + @Override + public boolean wantsToPickUp(ItemStack stack) { +- ItemStack itemstack1 = this.getItemInHand(InteractionHand.MAIN_HAND); +- +- return !itemstack1.isEmpty() && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && this.inventory.canAddItem(stack) && this.allayConsidersItemEqual(itemstack1, stack); ++ // Purpur start ++ if (!this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ return false; ++ } ++ ItemStack itemStack = this.getItemInHand(InteractionHand.MAIN_HAND); ++ if (itemStack.isEmpty()) { ++ return false; ++ } ++ if (!allayConsidersItemEqual(itemStack, stack)) { ++ return false; ++ } ++ if (!this.inventory.canAddItem(stack)) { ++ return false; ++ } ++ for (String tag : this.level().purpurConfig.allayRespectNBT) { ++ if (stack.hasTag() && itemStack.hasTag()) { ++ Tag tag1 = stack.getTag().get(tag); ++ Tag tag2 = itemStack.getTag().get(tag); ++ if (!Objects.equals(tag1, tag2)) { ++ return false; ++ } ++ } ++ } ++ return true; ++ // Purpur end + } + + private boolean allayConsidersItemEqual(ItemStack stack, ItemStack stack2) { +diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +index 5b12c08a1d8e6f62c5653c95071a1d36d735d039..94e29919ddc7f507d54e14c3360f7a3e8bb831a7 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +@@ -1138,10 +1138,13 @@ public class PurpurWorldConfig { + public boolean allayRidable = false; + public boolean allayRidableInWater = true; + public boolean allayControllable = true; ++ public List allayRespectNBT = new ArrayList<>(); + private void allaySettings() { + allayRidable = getBoolean("mobs.allay.ridable", allayRidable); + allayRidableInWater = getBoolean("mobs.allay.ridable-in-water", allayRidableInWater); + allayControllable = getBoolean("mobs.allay.controllable", allayControllable); ++ allayRespectNBT.clear(); ++ getList("mobs.allay.respect-nbt", new ArrayList<>()).forEach(key -> allayRespectNBT.add(key.toString())); + } + + public boolean axolotlRidable = false; diff --git a/patches/purpur-drops/dropped-server/0271-Add-item-packet-serialize-event.patch b/patches/purpur-drops/dropped-server/0271-Add-item-packet-serialize-event.patch new file mode 100644 index 0000000..81f4367 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0271-Add-item-packet-serialize-event.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MelnCat +Date: Sat, 24 Sep 2022 09:56:28 -0700 +Subject: [PATCH] Add item packet serialize event + + +diff --git a/src/main/java/net/minecraft/network/FriendlyByteBuf.java b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +index b863249ff7e13cf4939c8961601f0564c62fd661..bdcfd80f937c34956911373905d66424bbff8e1d 100644 +--- a/src/main/java/net/minecraft/network/FriendlyByteBuf.java ++++ b/src/main/java/net/minecraft/network/FriendlyByteBuf.java +@@ -95,6 +95,8 @@ public class FriendlyByteBuf extends ByteBuf { + private static final int MAX_PUBLIC_KEY_LENGTH = 512; + private static final Gson GSON = new Gson(); + ++ public static boolean hasItemSerializeEvent = false; // Purpur ++ + public FriendlyByteBuf(ByteBuf parent) { + this.source = parent; + } +@@ -640,6 +642,17 @@ public class FriendlyByteBuf extends ByteBuf { + this.writeBoolean(false); + } else { + this.writeBoolean(true); ++ // Purpur start ++ if (hasItemSerializeEvent) { ++ var event = new org.purpurmc.purpur.event.packet.NetworkItemSerializeEvent(stack.asBukkitCopy()); ++ event.callEvent(); ++ ItemStack newStack = ItemStack.fromBukkitCopy(event.getItemStack()); ++ if (org.purpurmc.purpur.PurpurConfig.fixNetworkSerializedItemsInCreative && !ItemStack.matches(stack, newStack)) { ++ stack.save(newStack.getOrCreateTagElement("Purpur.OriginalItem")); ++ } ++ stack = newStack; ++ } ++ // Purpur end + Item item = stack.getItem(); + + this.writeId(BuiltInRegistries.ITEM, item); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 4611116f3328c0f8d5b37c8765feca36b2448ffe..60b5e0643d933393b5473681ac9261db29fe2416 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1731,6 +1731,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Purpur + Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; move down + while (iterator.hasNext()) { + ServerLevel worldserver = (ServerLevel) iterator.next(); +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 872be72e24017fdcb3060f6e4e9a92c342d59fc1..f7ac60e1aa188ec25a4c5d326cdd4a109a54101c 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -3382,6 +3382,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + } + } ++ // Purpur start ++ if (org.purpurmc.purpur.PurpurConfig.fixNetworkSerializedItemsInCreative) { ++ var tag = itemstack.getTagElement("Purpur.OriginalItem"); ++ if (tag != null) itemstack = ItemStack.of(tag); ++ } ++ // Purpur end + + boolean flag1 = packet.getSlotNum() >= 1 && packet.getSlotNum() <= 45; + boolean flag2 = itemstack.isEmpty() || itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty(); +diff --git a/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +index 5313ba91ffc625b27d5bb99395f0e719829f6bda..5329ad6493950a561bd46045e35a9bd70ac4405f 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurConfig.java +@@ -568,4 +568,9 @@ public class PurpurConfig { + } + }); + } ++ ++ public static boolean fixNetworkSerializedItemsInCreative = false; ++ private static void fixNetworkSerializedCreativeItems() { ++ fixNetworkSerializedItemsInCreative = getBoolean("settings.fix-network-serialized-items-in-creative", fixNetworkSerializedItemsInCreative); ++ } + } diff --git a/patches/purpur-drops/dropped-server/0282-Add-mending-multiplier.patch b/patches/purpur-drops/dropped-server/0282-Add-mending-multiplier.patch new file mode 100644 index 0000000..53fb2e5 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0282-Add-mending-multiplier.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: rafaelflromao <12960698+rafaelflromao@users.noreply.github.com> +Date: Mon, 8 May 2023 20:43:29 +0100 +Subject: [PATCH] Add mending multiplier + + +diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +index 7130d483ccdce26526e715bd7e68d2e896e6215f..40d168d225932717b8ac8bdd27dfe2a202bc2808 100644 +--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java ++++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java +@@ -372,13 +372,15 @@ public class ExperienceOrb extends Entity { + } + } + ++ // Purpur start + public int durabilityToXp(int repairAmount) { +- return repairAmount / 2; ++ return (int) (repairAmount / (2 * level().purpurConfig.mendingMultiplier)); + } + + public int xpToDurability(int experienceAmount) { +- return experienceAmount * 2; ++ return (int) ((experienceAmount * 2) * level().purpurConfig.mendingMultiplier); + } ++ // Purpur end + + public int getValue() { + return this.value; +diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +index 02b8333222668c3419296ec5513c1c4e8e8d1a79..3c614b8f62c0d3839ebc4e948c952d52c4f66819 100644 +--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java ++++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +@@ -119,6 +119,7 @@ public class PurpurWorldConfig { + } + + public boolean useBetterMending = false; ++ public double mendingMultiplier = 1.0; + public boolean alwaysTameInCreative = false; + public boolean boatEjectPlayersOnLand = false; + public boolean boatsDoFallDamage = false; +@@ -147,6 +148,7 @@ public class PurpurWorldConfig { + public int mobLastHurtByPlayerTime = 100; + private void miscGameplayMechanicsSettings() { + useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending); ++ mendingMultiplier = getDouble("gameplay-mechanics.mending-multiplier", mendingMultiplier); + alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative); + boatEjectPlayersOnLand = getBoolean("gameplay-mechanics.boat.eject-players-on-land", boatEjectPlayersOnLand); + boatsDoFallDamage = getBoolean("gameplay-mechanics.boat.do-fall-damage", boatsDoFallDamage); diff --git a/patches/purpur-drops/dropped-server/0292-Add-hover-lines-API.patch b/patches/purpur-drops/dropped-server/0292-Add-hover-lines-API.patch new file mode 100644 index 0000000..47c1dd6 --- /dev/null +++ b/patches/purpur-drops/dropped-server/0292-Add-hover-lines-API.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Meln Cat +Date: Mon, 2 Oct 2023 17:42:26 -0700 +Subject: [PATCH] Add hover lines API + + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +index 6e2a6ce5cf456bd9f6c8c18a58f08e2285dc77ed..b27d16e74c3f99aa693b38590c1fb62db8204509 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +@@ -619,4 +619,17 @@ public final class CraftItemFactory implements ItemFactory { + return CraftItemStack.asCraftMirror(enchanted); + } + // Paper end - enchantWithLevels API ++ ++ // Purpur start ++ @Override ++ public @org.jetbrains.annotations.NotNull java.util.List getHoverLines(@org.jetbrains.annotations.NotNull ItemStack itemStack, boolean advanced) { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure( ++ CraftItemStack.asNMSCopy(itemStack).getTooltipLines( ++ null, ++ advanced ? net.minecraft.world.item.TooltipFlag.ADVANCED ++ : net.minecraft.world.item.TooltipFlag.NORMAL ++ ) ++ ); ++ } ++ // Purpur end + }