浏览代码

Cache ItemMeta instead of creating a new ItemMeta for each potion check (#5075)

* Cache ItemMeta instead of creating a new ItemMeta for each potion check

* Check if the item has item meta and, if it doesn't, bail out

* Also cache the potion item meta too

* Add requireNonNull to the potionItemMeta
MrPowerGamerBR 11 月之前
父节点
当前提交
dcf83a8d20

+ 7 - 1
src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java

@@ -9,6 +9,7 @@ import org.bukkit.Color;
 import org.bukkit.Material;
 import org.bukkit.Material;
 import org.bukkit.configuration.ConfigurationSection;
 import org.bukkit.configuration.ConfigurationSection;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
 import org.bukkit.inventory.meta.PotionMeta;
 import org.bukkit.inventory.meta.PotionMeta;
 import org.bukkit.potion.PotionEffect;
 import org.bukkit.potion.PotionEffect;
 import org.bukkit.potion.PotionEffectType;
 import org.bukkit.potion.PotionEffectType;
@@ -334,9 +335,14 @@ public class PotionConfig extends LegacyConfigLoader {
      * @return AlchemyPotion that corresponds to the given ItemStack.
      * @return AlchemyPotion that corresponds to the given ItemStack.
      */
      */
     public AlchemyPotion getPotion(ItemStack item) {
     public AlchemyPotion getPotion(ItemStack item) {
+        // Fast return if the item does not have any item meta to avoid initializing an unnecessary ItemMeta instance
+        if (!item.hasItemMeta())
+            return null;
+
+        ItemMeta itemMeta = item.getItemMeta();
         final List<AlchemyPotion> potionList = alchemyPotions.values()
         final List<AlchemyPotion> potionList = alchemyPotions.values()
                 .stream()
                 .stream()
-                .filter(potion -> potion.isSimilarPotion(item))
+                .filter(potion -> potion.isSimilarPotion(item, itemMeta))
                 .toList();
                 .toList();
         if(potionList.size() > 1) {
         if(potionList.size() > 1) {
             mcMMO.p.getLogger().severe("Multiple potions defined in config have matched this potion, for mcMMO to behave" +
             mcMMO.p.getLogger().severe("Multiple potions defined in config have matched this potion, for mcMMO to behave" +

+ 11 - 3
src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/AlchemyPotion.java

@@ -4,6 +4,7 @@ import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.util.PotionUtil;
 import com.gmail.nossr50.util.PotionUtil;
 import org.bukkit.Material;
 import org.bukkit.Material;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
 import org.bukkit.inventory.meta.PotionMeta;
 import org.bukkit.inventory.meta.PotionMeta;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.annotations.Nullable;
@@ -18,6 +19,7 @@ import static java.util.Objects.requireNonNull;
 public class AlchemyPotion {
 public class AlchemyPotion {
     private final @NotNull String potionConfigName;
     private final @NotNull String potionConfigName;
     private final @NotNull ItemStack potionItemStack;
     private final @NotNull ItemStack potionItemStack;
+    private final @NotNull ItemMeta potionItemMeta;
     private final @NotNull Map<ItemStack, String> alchemyPotionChildren;
     private final @NotNull Map<ItemStack, String> alchemyPotionChildren;
 
 
     public AlchemyPotion(@NotNull String potionConfigName, @NotNull ItemStack potionItemStack,
     public AlchemyPotion(@NotNull String potionConfigName, @NotNull ItemStack potionItemStack,
@@ -25,6 +27,7 @@ public class AlchemyPotion {
         this.potionConfigName = requireNonNull(potionConfigName, "potionConfigName cannot be null");
         this.potionConfigName = requireNonNull(potionConfigName, "potionConfigName cannot be null");
         this.potionItemStack = requireNonNull(potionItemStack, "potionItemStack cannot be null");
         this.potionItemStack = requireNonNull(potionItemStack, "potionItemStack cannot be null");
         this.alchemyPotionChildren = requireNonNull(alchemyPotionChildren, "alchemyPotionChildren cannot be null");
         this.alchemyPotionChildren = requireNonNull(alchemyPotionChildren, "alchemyPotionChildren cannot be null");
+        this.potionItemMeta = requireNonNull(potionItemStack.getItemMeta(), "potionItemMeta cannot be null"); // The potion item meta should never be null because it is a potion, but if it is null, then something went terribly wrong
     }
     }
 
 
     public @NotNull ItemStack toItemStack(int amount) {
     public @NotNull ItemStack toItemStack(int amount) {
@@ -49,13 +52,18 @@ public class AlchemyPotion {
     }
     }
 
 
     public boolean isSimilarPotion(@NotNull ItemStack otherPotion) {
     public boolean isSimilarPotion(@NotNull ItemStack otherPotion) {
+        return isSimilarPotion(otherPotion, otherPotion.getItemMeta());
+    }
+
+    public boolean isSimilarPotion(@NotNull ItemStack otherPotion, @Nullable ItemMeta otherMeta) {
         requireNonNull(otherPotion, "otherPotion cannot be null");
         requireNonNull(otherPotion, "otherPotion cannot be null");
+
         if (otherPotion.getType() != potionItemStack.getType()) {
         if (otherPotion.getType() != potionItemStack.getType()) {
             return false;
             return false;
         }
         }
 
 
         // no potion meta, no match
         // no potion meta, no match
-        if (!otherPotion.hasItemMeta()) {
+        if (otherMeta == null) {
             return false;
             return false;
         }
         }
 
 
@@ -63,7 +71,7 @@ public class AlchemyPotion {
          * Compare custom effects on both potions.
          * Compare custom effects on both potions.
          */
          */
 
 
-        final PotionMeta otherPotionMeta = (PotionMeta) otherPotion.getItemMeta();
+        final PotionMeta otherPotionMeta = (PotionMeta) otherMeta;
         // compare custom effects on both potions, this has to be done in two traversals
         // compare custom effects on both potions, this has to be done in two traversals
         // comparing thisPotionMeta -> otherPotionMeta and otherPotionMeta -> thisPotionMeta
         // comparing thisPotionMeta -> otherPotionMeta and otherPotionMeta -> thisPotionMeta
         if (hasDifferingCustomEffects(getAlchemyPotionMeta(), otherPotionMeta)
         if (hasDifferingCustomEffects(getAlchemyPotionMeta(), otherPotionMeta)
@@ -114,7 +122,7 @@ public class AlchemyPotion {
     }
     }
 
 
     public PotionMeta getAlchemyPotionMeta() {
     public PotionMeta getAlchemyPotionMeta() {
-        return (PotionMeta) potionItemStack.getItemMeta();
+        return (PotionMeta) potionItemMeta;
     }
     }
 
 
     public boolean isSplash() {
     public boolean isSplash() {