From fc66c9f3fd67f1501a13e786a21b1cd1004f2e22 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Wed, 15 May 2024 15:56:50 -0700 Subject: [PATCH] 2.2.010 --- Changelog.txt | 6 ++-- pom.xml | 2 +- .../config/skills/alchemy/PotionConfig.java | 22 ++++++++----- .../skills/alchemy/AlchemyPotion.java | 33 +++++++++++-------- .../datatypes/skills/alchemy/PotionStage.java | 1 + .../nossr50/util/PotionCompatibilityType.java | 2 +- .../com/gmail/nossr50/util/PotionUtil.java | 23 +++++++++---- .../gmail/nossr50/util/PotionUtilTest.java | 31 +++++++++++++++++ 8 files changed, 87 insertions(+), 33 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 0cd3c8ce6..9f85db54e 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,8 +1,7 @@ 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 - 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 a NPE that could happen when damaging armor with Axes Fixed a bug where Alchemy brewing would be cancelled if the player died @@ -40,6 +39,7 @@ Version 2.2.010 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 + 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. Version 2.2.009 diff --git a/pom.xml b/pom.xml index 38bb18f62..8567d1d1b 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.gmail.nossr50.mcMMO mcMMO - 2.2.010-SNAPSHOT + 2.2.010 mcMMO https://github.com/mcMMO-Dev/mcMMO diff --git a/src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java b/src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java index 9aadac89f..5c9e023b7 100644 --- a/src/main/java/com/gmail/nossr50/config/skills/alchemy/PotionConfig.java +++ b/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.List; import java.util.Map; +import java.util.stream.Collectors; import static com.gmail.nossr50.util.ItemUtils.setItemName; import static com.gmail.nossr50.util.PotionUtil.matchPotionType; @@ -39,7 +40,7 @@ public class PotionConfig extends LegacyConfigLoader { /** * Map of potion names to AlchemyPotion objects. */ - private final Map loadedPotions = new HashMap<>(); + private final Map alchemyPotions = new HashMap<>(); public PotionConfig() { super("potions.yml"); @@ -106,7 +107,7 @@ public class PotionConfig extends LegacyConfigLoader { AlchemyPotion potion = loadPotion(potionSection.getConfigurationSection(potionName)); if (potion != null) { - loadedPotions.put(potionName, potion); + alchemyPotions.put(potionName, potion); potionsLoaded++; } else { failures++; @@ -250,7 +251,7 @@ public class PotionConfig extends LegacyConfigLoader { // TODO: Might not need to .setItemMeta itemStack.setItemMeta(potionMeta); - return new AlchemyPotion(itemStack, children); + return new AlchemyPotion(potion_section.getName(), itemStack, children); } catch (Exception e) { mcMMO.p.getLogger().warning("PotionConfig: Failed to load Alchemy potion: " + potion_section.getName()); return null; @@ -325,7 +326,7 @@ public class PotionConfig extends LegacyConfigLoader { * @return AlchemyPotion that corresponds to the given 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. */ public AlchemyPotion getPotion(ItemStack item) { - for (AlchemyPotion potion : loadedPotions.values()) { - if (potion.isSimilarPotion(item)) { - return potion; - } + final List 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 effects) { diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/AlchemyPotion.java b/src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/AlchemyPotion.java index fb5ea7899..51be1cde9 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/AlchemyPotion.java +++ b/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; public class AlchemyPotion { - private final @NotNull ItemStack potionItemstack; + private final @NotNull String potionConfigName; + private final @NotNull ItemStack potionItemStack; private final @NotNull Map alchemyPotionChildren; - public AlchemyPotion(@NotNull ItemStack potionItemStack, @NotNull Map alchemyPotionChildren) { - this.potionItemstack = requireNonNull(potionItemStack, "potionItemStack cannot be null"); + public AlchemyPotion(@NotNull String potionConfigName, @NotNull ItemStack potionItemStack, @NotNull Map 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"); + // mcMMO.p.getLogger().info("AlchemyPotion created: " + potionConfigName + ", with children: " + alchemyPotionChildren); } public @NotNull ItemStack toItemStack(int amount) { - final ItemStack clone = potionItemstack.clone(); + final ItemStack clone = potionItemStack.clone(); clone.setAmount(Math.max(1, amount)); return clone; } @@ -46,9 +49,12 @@ public class AlchemyPotion { public boolean isSimilarPotion(@NotNull ItemStack otherPotion) { 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; } @@ -97,15 +103,15 @@ public class AlchemyPotion { } public PotionMeta getAlchemyPotionMeta() { - return (PotionMeta) potionItemstack.getItemMeta(); + return (PotionMeta) potionItemStack.getItemMeta(); } public boolean isSplash() { - return potionItemstack.getType() == Material.SPLASH_POTION; + return potionItemStack.getType() == Material.SPLASH_POTION; } public boolean isLingering() { - return potionItemstack.getType() == Material.LINGERING_POTION; + return potionItemStack.getType() == Material.LINGERING_POTION; } @Override @@ -113,18 +119,19 @@ public class AlchemyPotion { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; 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 public int hashCode() { - return Objects.hash(potionItemstack, alchemyPotionChildren); + return Objects.hash(potionConfigName, potionItemStack, alchemyPotionChildren); } @Override public String toString() { return "AlchemyPotion{" + - "potion=" + potionItemstack + + "potionConfigName='" + potionConfigName + '\'' + + ", potionItemStack=" + potionItemStack + ", alchemyPotionChildren=" + alchemyPotionChildren + '}'; } diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/PotionStage.java b/src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/PotionStage.java index 7825c717f..64bf65009 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/PotionStage.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/alchemy/PotionStage.java @@ -1,6 +1,7 @@ package com.gmail.nossr50.datatypes.skills.alchemy; import com.gmail.nossr50.util.PotionUtil; +import org.bukkit.Bukkit; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.potion.PotionEffect; diff --git a/src/main/java/com/gmail/nossr50/util/PotionCompatibilityType.java b/src/main/java/com/gmail/nossr50/util/PotionCompatibilityType.java index ea070814d..0b19748a5 100644 --- a/src/main/java/com/gmail/nossr50/util/PotionCompatibilityType.java +++ b/src/main/java/com/gmail/nossr50/util/PotionCompatibilityType.java @@ -2,5 +2,5 @@ package com.gmail.nossr50.util; public enum PotionCompatibilityType { PRE_1_20_5, - POST_1_20_5 + POST_1_20_6 } diff --git a/src/main/java/com/gmail/nossr50/util/PotionUtil.java b/src/main/java/com/gmail/nossr50/util/PotionUtil.java index 739059787..0debc5ab8 100644 --- a/src/main/java/com/gmail/nossr50/util/PotionUtil.java +++ b/src/main/java/com/gmail/nossr50/util/PotionUtil.java @@ -58,10 +58,11 @@ public class PotionUtil { methodPotionTypeGetPotionEffects = getPotionTypeGetPotionEffects(); methodSetBasePotionData = getSetBasePotionData(); - if (potionDataClass != null) { + if (potionDataClass != null + && !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 20, 5)) { COMPATIBILITY_MODE = PotionCompatibilityType.PRE_1_20_5; } 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 */ 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) { - return matchLegacyPotionType(updatedName); + return matchLegacyPotionType(partialName); } else { + String updatedName = convertLegacyNames(partialName).toUpperCase(); 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 -> !isExtended || potionType.name().toUpperCase().contains(LONG)) .findAny().orElse(null); @@ -99,6 +100,16 @@ public class PotionUtil { .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) { try { if (getKeyMethod() != null) { diff --git a/src/test/java/com/gmail/nossr50/util/PotionUtilTest.java b/src/test/java/com/gmail/nossr50/util/PotionUtilTest.java index e3e5dae20..299496320 100644 --- a/src/test/java/com/gmail/nossr50/util/PotionUtilTest.java +++ b/src/test/java/com/gmail/nossr50/util/PotionUtilTest.java @@ -1,14 +1,45 @@ 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.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; 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.matchPotionType; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; class PotionUtilTest { + MockedStatic 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 void testMatchPotionTypeRegen() { final String potionTypeStr = "REGEN";