diff --git a/Spigot-API-Patches/0303-More-Enchantment-API.patch b/Spigot-API-Patches/0303-More-Enchantment-API.patch new file mode 100644 index 000000000..dda68575c --- /dev/null +++ b/Spigot-API-Patches/0303-More-Enchantment-API.patch @@ -0,0 +1,124 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 6 May 2021 19:58:03 -0700 +Subject: [PATCH] More Enchantment API + + +diff --git a/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e6a40c1fcea761bd66743b50e3da3d14797d05b0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java +@@ -0,0 +1,24 @@ ++package io.papermc.paper.enchantments; ++ ++public enum EnchantmentRarity { ++ ++ COMMON(10), ++ UNCOMMON(5), ++ RARE(2), ++ VERY_RARE(1); ++ ++ private final int weight; ++ ++ EnchantmentRarity(int weight) { ++ this.weight = weight; ++ } ++ ++ /** ++ * Gets the weight for the rarity. ++ * ++ * @return the weight ++ */ ++ public int getWeight() { ++ return weight; ++ } ++} +diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java +index 8eb0497c81744874809ebc4bc2e28b128e66a926..799813410f40589ba1d7d530a47d87f609764705 100644 +--- a/src/main/java/org/bukkit/enchantments/Enchantment.java ++++ b/src/main/java/org/bukkit/enchantments/Enchantment.java +@@ -306,6 +306,46 @@ public abstract class Enchantment implements Keyed { + * @return the name of the enchantment with {@code level} applied + */ + public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); ++ ++ /** ++ * Checks if this enchantment can be found in villager trades. ++ * ++ * @return true if the enchantment can be found in trades ++ */ ++ public abstract boolean isTradeable(); ++ ++ /** ++ * Checks if this enchantment can be found in an enchanting table ++ * or use to enchant items generated by loot tables. ++ * ++ * @return true if the enchantment can be found in a table or by loot tables ++ */ ++ public abstract boolean isDiscoverable(); ++ ++ /** ++ * Gets the rarity of this enchantment. ++ * ++ * @return the rarity ++ */ ++ @NotNull ++ public abstract io.papermc.paper.enchantments.EnchantmentRarity getRarity(); ++ ++ /** ++ * Gets the damage increase as a result of the level and entity category specified ++ * ++ * @param level the level of enchantment ++ * @param entityCategory the category of entity ++ * @return the damage increase ++ */ ++ public abstract float getDamageIncrease(int level, @NotNull org.bukkit.entity.EntityCategory entityCategory); ++ ++ /** ++ * Gets the equipment slots where this enchantment is considered "active". ++ * ++ * @return the equipment slots ++ */ ++ @NotNull ++ public abstract java.util.Set getActiveSlots(); + // Paper end + + @Override +diff --git a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +index 4d5f0837bd0e02a30c943d8969fb6b13452322e0..ca097db904db96e81c0ea4b06b445a13e9333cfe 100644 +--- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java ++++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +@@ -69,5 +69,32 @@ public class EnchantmentWrapper extends Enchantment { + public net.kyori.adventure.text.Component displayName(int level) { + return getEnchantment().displayName(level); + } ++ ++ @Override ++ public boolean isTradeable() { ++ return getEnchantment().isTradeable(); ++ } ++ ++ @Override ++ public boolean isDiscoverable() { ++ return getEnchantment().isDiscoverable(); ++ } ++ ++ @NotNull ++ @Override ++ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { ++ return getEnchantment().getRarity(); ++ } ++ ++ @Override ++ public float getDamageIncrease(int level, @NotNull org.bukkit.entity.EntityCategory entityCategory) { ++ return getEnchantment().getDamageIncrease(level, entityCategory); ++ } ++ ++ @NotNull ++ @Override ++ public java.util.Set getActiveSlots() { ++ return getEnchantment().getActiveSlots(); ++ } + // Paper end + } diff --git a/Spigot-Server-Patches/0735-More-Enchantment-API.patch b/Spigot-Server-Patches/0735-More-Enchantment-API.patch new file mode 100644 index 000000000..6314953da --- /dev/null +++ b/Spigot-Server-Patches/0735-More-Enchantment-API.patch @@ -0,0 +1,202 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 6 May 2021 19:57:58 -0700 +Subject: [PATCH] More Enchantment API + + +diff --git a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +index b76ef55145336cc8dc4857b79767f5a738ad5144..c719c1c1f837753f61eb7be83b6ec2a214ab6819 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -17,7 +17,7 @@ import net.minecraft.world.item.ItemStack; + + public abstract class Enchantment { + +- private final EnumItemSlot[] a; ++ private final EnumItemSlot[] a; public final EnumItemSlot[] getSlots() { return this.a; } // Paper - OBFHELPER + private final Enchantment.Rarity d; + public final EnchantmentSlotType itemTarget; + @Nullable +@@ -46,6 +46,7 @@ public abstract class Enchantment { + return map; + } + ++ public Enchantment.Rarity getRarity() { return d(); } // Paper - OBFHELPER + public Enchantment.Rarity d() { + return this.d; + } +@@ -70,6 +71,7 @@ public abstract class Enchantment { + return 0; + } + ++ public float getDamageIncrease(int level, EnumMonsterType enumMonsterType) { return a(level, enumMonsterType); } // Paper - OBFHELPER + public float a(int i, EnumMonsterType enummonstertype) { + return 0.0F; + } +@@ -123,14 +125,17 @@ public abstract class Enchantment { + return false; + } + ++ public boolean isCursed() { return c(); } // Paper - OBFHELPER + public boolean c() { + return false; + } + ++ public boolean isTradeable() { return h(); } // Paper - OBFHELPER + public boolean h() { + return true; + } + ++ public boolean isDiscoverable() { return i(); } // Paper - OBFHELPER + public boolean i() { + return true; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +index 5a14430f63894bbe9daa42900cf5a6519bea4f45..3b83852249e56609074ef1e8cdad6416db66007b 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -71,7 +71,7 @@ public class CraftEnchantment extends Enchantment { + + @Override + public boolean isCursed() { +- return target instanceof EnchantmentBinding || target instanceof EnchantmentVanishing; ++ return target.isCursed(); // Paper + } + + @Override +@@ -192,6 +192,45 @@ public class CraftEnchantment extends Enchantment { + public net.kyori.adventure.text.Component displayName(int level) { + return io.papermc.paper.adventure.PaperAdventure.asAdventure(getHandle().getTranslationComponentForLevel(level)); + } ++ ++ @Override ++ public boolean isTradeable() { ++ return target.isTradeable(); ++ } ++ ++ @Override ++ public boolean isDiscoverable() { ++ return target.isDiscoverable(); ++ } ++ ++ @Override ++ public io.papermc.paper.enchantments.EnchantmentRarity getRarity() { ++ return fromNMSRarity(target.getRarity()); ++ } ++ ++ @Override ++ public float getDamageIncrease(int level, org.bukkit.entity.EntityCategory entityCategory) { ++ return target.getDamageIncrease(level, org.bukkit.craftbukkit.entity.CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ ++ @Override ++ public java.util.Set getActiveSlots() { ++ return java.util.stream.Stream.of(target.getSlots()).map(org.bukkit.craftbukkit.CraftEquipmentSlot::getSlot).collect(java.util.stream.Collectors.toSet()); ++ } ++ ++ public static io.papermc.paper.enchantments.EnchantmentRarity fromNMSRarity(net.minecraft.world.item.enchantment.Enchantment.Rarity nmsRarity) { ++ if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.COMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.COMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.UNCOMMON) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.UNCOMMON; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.RARE; ++ } else if (nmsRarity == net.minecraft.world.item.enchantment.Enchantment.Rarity.VERY_RARE) { ++ return io.papermc.paper.enchantments.EnchantmentRarity.VERY_RARE; ++ } ++ ++ throw new IllegalArgumentException(String.format("Unable to convert %s to a enum value of %s.", nmsRarity, io.papermc.paper.enchantments.EnchantmentRarity.class)); ++ } + // Paper end + + public net.minecraft.world.item.enchantment.Enchantment getHandle() { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index 3d497f69f89455b88fba423de8effb3db83e7af4..4545bac9309f5a3aad617f48f7808d8ae829602d 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -842,5 +842,21 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + public void setHurtDirection(float hurtDirection) { + getHandle().setHurtDirection(hurtDirection); + } ++ ++ public static EnumMonsterType fromBukkitEntityCategory(EntityCategory entityCategory) { ++ switch (entityCategory) { ++ case NONE: ++ return EnumMonsterType.UNDEFINED; ++ case UNDEAD: ++ return EnumMonsterType.UNDEAD; ++ case ARTHROPOD: ++ return EnumMonsterType.ARTHROPOD; ++ case ILLAGER: ++ return EnumMonsterType.ILLAGER; ++ case WATER: ++ return EnumMonsterType.WATER_MOB; ++ } ++ throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category"); ++ } + // Paper end + } +diff --git a/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..62b56b5b43696b03fc72cac59f986d006edc3f76 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.enchantments; ++ ++import net.minecraft.world.item.enchantment.Enchantment.Rarity; ++import org.bukkit.craftbukkit.enchantments.CraftEnchantment; ++import org.junit.Test; ++ ++import static org.junit.Assert.assertNotNull; ++ ++public class EnchantmentRarityTest { ++ ++ @Test ++ public void test() { ++ for (Rarity nmsRarity : Rarity.values()) { ++ // Will throw exception if a bukkit counterpart is not found ++ CraftEnchantment.fromNMSRarity(nmsRarity); ++ } ++ } ++} +diff --git a/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..adb0e5b4268fa115b814143cf29d9a3688e4bc17 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +@@ -0,0 +1,34 @@ ++package io.papermc.paper.entity; ++ ++import com.google.common.base.Joiner; ++import com.google.common.collect.Maps; ++import com.google.common.collect.Sets; ++import net.minecraft.world.entity.EnumMonsterType; ++import org.bukkit.craftbukkit.entity.CraftLivingEntity; ++import org.bukkit.entity.EntityCategory; ++import org.junit.Test; ++ ++import java.lang.reflect.Field; ++import java.util.Map; ++import java.util.Set; ++ ++import static org.junit.Assert.assertTrue; ++ ++public class EntityCategoryTest { ++ ++ @Test ++ public void test() throws IllegalAccessException { ++ ++ Map enumMonsterTypeFieldMap = Maps.newHashMap(); ++ for (Field field : EnumMonsterType.class.getDeclaredFields()) { ++ if (field.getType() == EnumMonsterType.class) { ++ enumMonsterTypeFieldMap.put( (EnumMonsterType) field.get(null), field.getName()); ++ } ++ } ++ ++ for (EntityCategory entityCategory : EntityCategory.values()) { ++ enumMonsterTypeFieldMap.remove(CraftLivingEntity.fromBukkitEntityCategory(entityCategory)); ++ } ++ assertTrue(EnumMonsterType.class.getName() + " instance(s): " + Joiner.on(", ").join(enumMonsterTypeFieldMap.values()) + " do not have bukkit equivalents", enumMonsterTypeFieldMap.size() == 0); ++ } ++}