diff --git a/Spigot-API-Patches/More-Enchantment-API.patch b/Spigot-API-Patches/More-Enchantment-API.patch new file mode 100644 index 0000000000..2f0bd9ed01 --- /dev/null +++ b/Spigot-API-Patches/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..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/enchantments/EnchantmentRarity.java +@@ -0,0 +0,0 @@ ++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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/enchantments/Enchantment.java ++++ b/src/main/java/org/bukkit/enchantments/Enchantment.java +@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java ++++ b/src/main/java/org/bukkit/enchantments/EnchantmentWrapper.java +@@ -0,0 +0,0 @@ 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/More-Enchantment-API.patch b/Spigot-Server-Patches/More-Enchantment-API.patch new file mode 100644 index 0000000000..daa2a62d77 --- /dev/null +++ b/Spigot-Server-Patches/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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java ++++ b/src/main/java/net/minecraft/world/item/enchantment/Enchantment.java +@@ -0,0 +0,0 @@ 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 +@@ -0,0 +0,0 @@ public abstract class Enchantment { + return map; + } + ++ public Enchantment.Rarity getRarity() { return d(); } // Paper - OBFHELPER + public Enchantment.Rarity d() { + return this.d; + } +@@ -0,0 +0,0 @@ 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; + } +@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java ++++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +@@ -0,0 +0,0 @@ public class CraftEnchantment extends Enchantment { + + @Override + public boolean isCursed() { +- return target instanceof EnchantmentBinding || target instanceof EnchantmentVanishing; ++ return target.isCursed(); // Paper + } + + @Override +@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -0,0 +0,0 @@ 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..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/enchantments/EnchantmentRarityTest.java +@@ -0,0 +0,0 @@ ++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..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/entity/EntityCategoryTest.java +@@ -0,0 +0,0 @@ ++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); ++ } ++}