nossr50 1 年之前
父節點
當前提交
fc66c9f3fd

+ 3 - 3
Changelog.txt

@@ -1,8 +1,7 @@
 Version 2.2.010
 Version 2.2.010
-    # TODO: Fix not moving mcMMO custom ingredients from hopper -> brewing stand
-    # TODO: Fix some potions are not rewarding XP ( strength 2, etc )
     Fixed being unable to load REGEN potion type on new versions of Paper/Spigot 1.20.6
     Fixed being unable to load REGEN potion type on new versions of Paper/Spigot 1.20.6
-    BrewingStand now remember who owns them, this persists across restarts (see notes)
+    Fixed some potions not gaining XP when brewed (Level 2 potions, etc)
+    BrewingStands will now remember who owns them, this persists across restarts (see notes)
     Fixed rare NPE in mcMMO events when player data was unable to be retrieved
     Fixed rare NPE in mcMMO events when player data was unable to be retrieved
     Fixed a NPE that could happen when damaging armor with Axes
     Fixed a NPE that could happen when damaging armor with Axes
     Fixed a bug where Alchemy brewing would be cancelled if the player died
     Fixed a bug where Alchemy brewing would be cancelled if the player died
@@ -40,6 +39,7 @@ Version 2.2.010
 
 
     NOTES:
     NOTES:
     You can now use hoppers and brewing stands and not have to worry about having to re-interact with the brewing stand over and over again
     You can now use hoppers and brewing stands and not have to worry about having to re-interact with the brewing stand over and over again
+    Ownership of a brewing stand is whoever last interacted with it, this persists across restarts
     This is not an exhaustive list of API changes in this update, but most of the important ones should be documented here.
     This is not an exhaustive list of API changes in this update, but most of the important ones should be documented here.
 
 
 Version 2.2.009
 Version 2.2.009

+ 1 - 1
pom.xml

@@ -2,7 +2,7 @@
     <modelVersion>4.0.0</modelVersion>
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.gmail.nossr50.mcMMO</groupId>
     <groupId>com.gmail.nossr50.mcMMO</groupId>
     <artifactId>mcMMO</artifactId>
     <artifactId>mcMMO</artifactId>
-    <version>2.2.010-SNAPSHOT</version>
+    <version>2.2.010</version>
     <name>mcMMO</name>
     <name>mcMMO</name>
     <url>https://github.com/mcMMO-Dev/mcMMO</url>
     <url>https://github.com/mcMMO-Dev/mcMMO</url>
     <scm>
     <scm>

+ 13 - 9
src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java

@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 
 import static com.gmail.nossr50.util.ItemUtils.setItemName;
 import static com.gmail.nossr50.util.ItemUtils.setItemName;
 import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
 import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
@@ -39,7 +40,7 @@ public class PotionConfig extends LegacyConfigLoader {
     /**
     /**
      * Map of potion names to AlchemyPotion objects.
      * Map of potion names to AlchemyPotion objects.
      */
      */
-    private final Map<String, AlchemyPotion> loadedPotions = new HashMap<>();
+    private final Map<String, AlchemyPotion> alchemyPotions = new HashMap<>();
 
 
     public PotionConfig() {
     public PotionConfig() {
         super("potions.yml");
         super("potions.yml");
@@ -106,7 +107,7 @@ public class PotionConfig extends LegacyConfigLoader {
             AlchemyPotion potion = loadPotion(potionSection.getConfigurationSection(potionName));
             AlchemyPotion potion = loadPotion(potionSection.getConfigurationSection(potionName));
 
 
             if (potion != null) {
             if (potion != null) {
-                loadedPotions.put(potionName, potion);
+                alchemyPotions.put(potionName, potion);
                 potionsLoaded++;
                 potionsLoaded++;
             } else {
             } else {
                 failures++;
                 failures++;
@@ -250,7 +251,7 @@ public class PotionConfig extends LegacyConfigLoader {
 
 
             // TODO: Might not need to .setItemMeta
             // TODO: Might not need to .setItemMeta
             itemStack.setItemMeta(potionMeta);
             itemStack.setItemMeta(potionMeta);
-            return new AlchemyPotion(itemStack, children);
+            return new AlchemyPotion(potion_section.getName(), itemStack, children);
         } catch (Exception e) {
         } catch (Exception e) {
             mcMMO.p.getLogger().warning("PotionConfig: Failed to load Alchemy potion: " + potion_section.getName());
             mcMMO.p.getLogger().warning("PotionConfig: Failed to load Alchemy potion: " + potion_section.getName());
             return null;
             return null;
@@ -325,7 +326,7 @@ public class PotionConfig extends LegacyConfigLoader {
      * @return AlchemyPotion that corresponds to the given name.
      * @return AlchemyPotion that corresponds to the given name.
      */
      */
     public AlchemyPotion getPotion(String name) {
     public AlchemyPotion getPotion(String name) {
-        return loadedPotions.get(name);
+        return alchemyPotions.get(name);
     }
     }
 
 
     /**
     /**
@@ -336,12 +337,15 @@ 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) {
-        for (AlchemyPotion potion : loadedPotions.values()) {
-            if (potion.isSimilarPotion(item)) {
-                return potion;
-            }
+        final List<AlchemyPotion> potionList = alchemyPotions.values()
+                .stream()
+                .filter(potion -> potion.isSimilarPotion(item))
+                .toList();
+        if(potionList.size() > 1) {
+            mcMMO.p.getLogger().severe("Multiple child potions matched for item, when there should only be one: " + item);
         }
         }
-        return null;
+
+        return potionList.isEmpty() ? null : potionList.get(0);
     }
     }
 
 
     public Color generateColor(List<PotionEffect> effects) {
     public Color generateColor(List<PotionEffect> effects) {

+ 20 - 13
src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/AlchemyPotion.java

@@ -15,16 +15,19 @@ import static com.gmail.nossr50.util.PotionUtil.samePotionType;
 import static java.util.Objects.requireNonNull;
 import static java.util.Objects.requireNonNull;
 
 
 public class AlchemyPotion {
 public class AlchemyPotion {
-    private final @NotNull ItemStack potionItemstack;
+    private final @NotNull String potionConfigName;
+    private final @NotNull ItemStack potionItemStack;
     private final @NotNull Map<ItemStack, String> alchemyPotionChildren;
     private final @NotNull Map<ItemStack, String> alchemyPotionChildren;
 
 
-    public AlchemyPotion(@NotNull ItemStack potionItemStack, @NotNull Map<ItemStack, String> alchemyPotionChildren) {
-        this.potionItemstack = requireNonNull(potionItemStack, "potionItemStack cannot be null");
+    public AlchemyPotion(@NotNull String potionConfigName, @NotNull ItemStack potionItemStack, @NotNull Map<ItemStack, String> alchemyPotionChildren) {
+        this.potionConfigName = requireNonNull(potionConfigName, "potionConfigName 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");
+        // mcMMO.p.getLogger().info("AlchemyPotion created: " + potionConfigName + ", with children: " + alchemyPotionChildren);
     }
     }
 
 
     public @NotNull ItemStack toItemStack(int amount) {
     public @NotNull ItemStack toItemStack(int amount) {
-        final ItemStack clone = potionItemstack.clone();
+        final ItemStack clone = potionItemStack.clone();
         clone.setAmount(Math.max(1, amount));
         clone.setAmount(Math.max(1, amount));
         return clone;
         return clone;
     }
     }
@@ -46,9 +49,12 @@ public class AlchemyPotion {
 
 
     public boolean isSimilarPotion(@NotNull ItemStack otherPotion) {
     public boolean isSimilarPotion(@NotNull ItemStack otherPotion) {
         requireNonNull(otherPotion, "otherPotion cannot be null");
         requireNonNull(otherPotion, "otherPotion cannot be null");
-        // TODO: Investigate?
-        // We currently don't compare base potion effects, likely because they are derived from the potion type
-        if (otherPotion.getType() != potionItemstack.getType() || !otherPotion.hasItemMeta()) {
+        if (otherPotion.getType() != potionItemStack.getType()) {
+            return false;
+        }
+
+        // no potion meta, no match
+        if (!otherPotion.hasItemMeta()) {
             return false;
             return false;
         }
         }
 
 
@@ -97,15 +103,15 @@ public class AlchemyPotion {
     }
     }
 
 
     public PotionMeta getAlchemyPotionMeta() {
     public PotionMeta getAlchemyPotionMeta() {
-        return (PotionMeta) potionItemstack.getItemMeta();
+        return (PotionMeta) potionItemStack.getItemMeta();
     }
     }
 
 
     public boolean isSplash() {
     public boolean isSplash() {
-        return potionItemstack.getType() == Material.SPLASH_POTION;
+        return potionItemStack.getType() == Material.SPLASH_POTION;
     }
     }
 
 
     public boolean isLingering() {
     public boolean isLingering() {
-        return potionItemstack.getType() == Material.LINGERING_POTION;
+        return potionItemStack.getType() == Material.LINGERING_POTION;
     }
     }
 
 
     @Override
     @Override
@@ -113,18 +119,19 @@ public class AlchemyPotion {
         if (this == o) return true;
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         if (o == null || getClass() != o.getClass()) return false;
         AlchemyPotion that = (AlchemyPotion) o;
         AlchemyPotion that = (AlchemyPotion) o;
-        return Objects.equals(potionItemstack, that.potionItemstack) && Objects.equals(alchemyPotionChildren, that.alchemyPotionChildren);
+        return Objects.equals(potionConfigName, that.potionConfigName) && Objects.equals(potionItemStack, that.potionItemStack) && Objects.equals(alchemyPotionChildren, that.alchemyPotionChildren);
     }
     }
 
 
     @Override
     @Override
     public int hashCode() {
     public int hashCode() {
-        return Objects.hash(potionItemstack, alchemyPotionChildren);
+        return Objects.hash(potionConfigName, potionItemStack, alchemyPotionChildren);
     }
     }
 
 
     @Override
     @Override
     public String toString() {
     public String toString() {
         return "AlchemyPotion{" +
         return "AlchemyPotion{" +
-                "potion=" + potionItemstack +
+                "potionConfigName='" + potionConfigName + '\'' +
+                ", potionItemStack=" + potionItemStack +
                 ", alchemyPotionChildren=" + alchemyPotionChildren +
                 ", alchemyPotionChildren=" + alchemyPotionChildren +
                 '}';
                 '}';
     }
     }

+ 1 - 0
src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/PotionStage.java

@@ -1,6 +1,7 @@
 package com.gmail.nossr50.datatypes.skills.alchemy;
 package com.gmail.nossr50.datatypes.skills.alchemy;
 
 
 import com.gmail.nossr50.util.PotionUtil;
 import com.gmail.nossr50.util.PotionUtil;
+import org.bukkit.Bukkit;
 import org.bukkit.inventory.meta.PotionMeta;
 import org.bukkit.inventory.meta.PotionMeta;
 import org.bukkit.potion.PotionEffect;
 import org.bukkit.potion.PotionEffect;
 
 

+ 1 - 1
src/main/java/com/gmail/nossr50/util/PotionCompatibilityType.java

@@ -2,5 +2,5 @@ package com.gmail.nossr50.util;
 
 
 public enum PotionCompatibilityType {
 public enum PotionCompatibilityType {
     PRE_1_20_5,
     PRE_1_20_5,
-    POST_1_20_5
+    POST_1_20_6
 }
 }

+ 17 - 6
src/main/java/com/gmail/nossr50/util/PotionUtil.java

@@ -58,10 +58,11 @@ public class PotionUtil {
         methodPotionTypeGetPotionEffects = getPotionTypeGetPotionEffects();
         methodPotionTypeGetPotionEffects = getPotionTypeGetPotionEffects();
         methodSetBasePotionData = getSetBasePotionData();
         methodSetBasePotionData = getSetBasePotionData();
 
 
-        if (potionDataClass != null) {
+        if (potionDataClass != null
+                && !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 20, 5)) {
             COMPATIBILITY_MODE = PotionCompatibilityType.PRE_1_20_5;
             COMPATIBILITY_MODE = PotionCompatibilityType.PRE_1_20_5;
         } else {
         } else {
-            COMPATIBILITY_MODE = PotionCompatibilityType.POST_1_20_5;
+            COMPATIBILITY_MODE = PotionCompatibilityType.POST_1_20_6;
         }
         }
     }
     }
 
 
@@ -71,13 +72,13 @@ public class PotionUtil {
      * @return The potion type
      * @return The potion type
      */
      */
     public static PotionType matchPotionType(String partialName, boolean isUpgraded, boolean isExtended) {
     public static PotionType matchPotionType(String partialName, boolean isUpgraded, boolean isExtended) {
-        String updatedName = convertLegacyNames(partialName).toUpperCase();
+        // updatedName = convertUpgradedOrExtended(updatedName, isUpgraded, isExtended);
         if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
         if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
-            return matchLegacyPotionType(updatedName);
+            return matchLegacyPotionType(partialName);
         } else {
         } else {
+            String updatedName = convertLegacyNames(partialName).toUpperCase();
             return Arrays.stream(PotionType.values())
             return Arrays.stream(PotionType.values())
-                    .filter(potionType -> getKeyGetKey(potionType).toUpperCase().contains(partialName)
-                                || getKeyGetKey(potionType).toUpperCase().contains(convertLegacyNames(updatedName)))
+                    .filter(potionType -> getKeyGetKey(potionType).toUpperCase().contains(updatedName))
                     .filter(potionType -> !isUpgraded || potionType.name().toUpperCase().contains(STRONG))
                     .filter(potionType -> !isUpgraded || potionType.name().toUpperCase().contains(STRONG))
                     .filter(potionType -> !isExtended || potionType.name().toUpperCase().contains(LONG))
                     .filter(potionType -> !isExtended || potionType.name().toUpperCase().contains(LONG))
                     .findAny().orElse(null);
                     .findAny().orElse(null);
@@ -99,6 +100,16 @@ public class PotionUtil {
                 .findAny().orElse(null);
                 .findAny().orElse(null);
     }
     }
 
 
+    private static String convertUpgradedOrExtended(String potionType, boolean isUpgraded, boolean isExtended) {
+        if (isUpgraded) {
+            potionType = STRONG + "_" + potionType;
+        }
+        if (isExtended) {
+            potionType = LONG + "_" + potionType;
+        }
+        return potionType;
+    }
+
     public static String getKeyGetKey(PotionType potionType) {
     public static String getKeyGetKey(PotionType potionType) {
         try {
         try {
             if (getKeyMethod() != null) {
             if (getKeyMethod() != null) {

+ 31 - 0
src/test/java/com/gmail/nossr50/util/PotionUtilTest.java

@@ -1,14 +1,45 @@
 package com.gmail.nossr50.util;
 package com.gmail.nossr50.util;
 
 
+import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.util.compat.CompatibilityManager;
+import com.gmail.nossr50.util.platform.MinecraftGameVersion;
 import org.bukkit.potion.PotionType;
 import org.bukkit.potion.PotionType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
 
 
 import static com.gmail.nossr50.util.PotionUtil.convertLegacyNames;
 import static com.gmail.nossr50.util.PotionUtil.convertLegacyNames;
 import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
 import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.*;
 
 
 class PotionUtilTest {
 class PotionUtilTest {
 
 
+    MockedStatic<mcMMO> mockedStaticMcMMO;
+
+    @BeforeEach
+    void setUp() {
+        mockedStaticMcMMO = mockStatic(mcMMO.class);
+        CompatibilityManager compatibilityManager = mock(CompatibilityManager.class);
+        MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class);
+        when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion);
+        when(minecraftGameVersion.isAtLeast(1, 20, 5)).thenReturn(true);
+        when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
+    }
+
+    @AfterEach
+    void tearDown() {
+        mockedStaticMcMMO.close();
+    }
+
+    @Test
+    void testMatchPotionTypeStrengthII() {
+        final String potionTypeStr = "STRENGTH";
+        final PotionType potionType = matchPotionType(potionTypeStr, true, false);
+        assertEquals(PotionType.STRONG_STRENGTH, potionType);
+    }
+
     @Test
     @Test
     void testMatchPotionTypeRegen() {
     void testMatchPotionTypeRegen() {
         final String potionTypeStr = "REGEN";
         final String potionTypeStr = "REGEN";