WIP 1.20.6 support

This commit is contained in:
nossr50
2024-05-02 06:28:20 -07:00
parent 5628df988f
commit 78558107b3
51 changed files with 1874 additions and 736 deletions

View File

@ -0,0 +1,45 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.mcMMO;
import org.bukkit.Registry;
import org.bukkit.attribute.Attribute;
public class AttributeMapper {
private final mcMMO pluginRef;
private static final String GENERIC_JUMP_STRENGTH = "generic.jump_strength";
private static final String HORSE_JUMP_STRENGTH = "horse.jump_strength";
private final Attribute horseJumpStrength;
public AttributeMapper(mcMMO pluginRef) {
this.pluginRef = pluginRef;
this.horseJumpStrength = initHorseJumpStrength();
}
private Attribute initHorseJumpStrength() {
// TODO: Use modern matching?
// if (Registry.ATTRIBUTE.match(GENERIC_JUMP_STRENGTH) != null) {
// return Registry.ATTRIBUTE.match(GENERIC_JUMP_STRENGTH);
// }
//
// if (Registry.ATTRIBUTE.match(HORSE_JUMP_STRENGTH) != null) {
// return Registry.ATTRIBUTE.match(HORSE_JUMP_STRENGTH);
// }
for (Attribute attr : Registry.ATTRIBUTE) {
if (attr.getKey().getKey().equalsIgnoreCase(HORSE_JUMP_STRENGTH)
|| attr.getKey().getKey().equalsIgnoreCase(GENERIC_JUMP_STRENGTH)
|| attr.name().equalsIgnoreCase(HORSE_JUMP_STRENGTH)
|| attr.name().equalsIgnoreCase(GENERIC_JUMP_STRENGTH)) {
return attr;
}
}
pluginRef.getLogger().severe("Unable to find the Generic Jump Strength or Horse Jump Strength attribute, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Generic Jump Strength or Horse Jump Strength attribute");
}
public Attribute getHorseJumpStrength() {
return horseJumpStrength;
}
}

View File

@ -0,0 +1,149 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.mcMMO;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
public class EnchantmentMapper {
private final mcMMO pluginRef;
private final Enchantment efficiency;
private final Enchantment unbreaking;
private final Enchantment infinity;
private final Enchantment featherFalling;
private final Enchantment luckOfTheSea;
public EnchantmentMapper(mcMMO pluginRef) {
this.pluginRef = pluginRef;
this.efficiency = initEfficiency();
this.unbreaking = initUnbreaking();
this.infinity = initInfinity();
this.featherFalling = initFeatherFalling();
this.luckOfTheSea = initLuckOfTheSea();
}
private Enchantment initLuckOfTheSea() {
// TODO: Make use of match if present
// if (Registry.ENCHANTMENT.match("luck_of_the_sea") != null) {
// return Registry.ENCHANTMENT.match("luck_of_the_sea");
// }
// Look for the enchantment by name
for (Enchantment enchantment : Registry.ENCHANTMENT) {
if (enchantment.getKey().getKey().equalsIgnoreCase("LUCK_OF_THE_SEA")
|| enchantment.getKey().getKey().equalsIgnoreCase("LUCK")
|| enchantment.getName().equalsIgnoreCase("LUCK_OF_THE_SEA")
|| enchantment.getName().equalsIgnoreCase("LUCK")) {
return enchantment;
}
}
pluginRef.getLogger().severe("Unable to find the Luck of the Sea enchantment, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Luck of the Sea enchantment");
}
private Enchantment initFeatherFalling() {
// if (Registry.ENCHANTMENT.match("feather_falling") != null) {
// return Registry.ENCHANTMENT.match("feather_falling");
// }
// Look for the enchantment by name
for (Enchantment enchantment : Registry.ENCHANTMENT) {
if (enchantment.getKey().getKey().equalsIgnoreCase("FEATHER_FALLING")
|| enchantment.getKey().getKey().equalsIgnoreCase("PROTECTION_FALL")
|| enchantment.getName().equalsIgnoreCase("FEATHER_FALLING")
|| enchantment.getName().equalsIgnoreCase("PROTECTION_FALL")) {
return enchantment;
}
}
pluginRef.getLogger().severe("Unable to find the Feather Falling enchantment, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Feather Falling enchantment");
}
private Enchantment initInfinity() {
// if(Registry.ENCHANTMENT.match("infinity") != null) {
// return Registry.ENCHANTMENT.match("infinity");
// }
// Look for the enchantment by name
for (Enchantment enchantment : Registry.ENCHANTMENT) {
if (enchantment.getKey().getKey().equalsIgnoreCase("INFINITY")
|| enchantment.getKey().getKey().equalsIgnoreCase("ARROW_INFINITE")
|| enchantment.getName().equalsIgnoreCase("INFINITY")
|| enchantment.getName().equalsIgnoreCase("ARROW_INFINITE")) {
return enchantment;
}
}
pluginRef.getLogger().severe("Unable to find the Infinity enchantment, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Infinity enchantment");
}
private Enchantment initEfficiency() {
// if (Registry.ENCHANTMENT.match("efficiency") != null) {
// return Registry.ENCHANTMENT.match("efficiency");
// }
// Look for the enchantment by name
for (Enchantment enchantment : Registry.ENCHANTMENT) {
if (enchantment.getKey().getKey().equalsIgnoreCase("EFFICIENCY")
|| enchantment.getKey().getKey().equalsIgnoreCase("DIG_SPEED")
|| enchantment.getName().equalsIgnoreCase("EFFICIENCY")
|| enchantment.getName().equalsIgnoreCase("DIG_SPEED")) {
return enchantment;
}
}
pluginRef.getLogger().severe("Unable to find the Efficiency enchantment, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Efficiency enchantment");
}
private Enchantment initUnbreaking() {
// if (Registry.ENCHANTMENT.match("unbreaking") != null) {
// return Registry.ENCHANTMENT.match("unbreaking");
// }
// Look for the enchantment by name
for (Enchantment enchantment : Registry.ENCHANTMENT) {
if (enchantment.getKey().getKey().equalsIgnoreCase("UNBREAKING")
|| enchantment.getKey().getKey().equalsIgnoreCase("DURABILITY")
|| enchantment.getName().equalsIgnoreCase("UNBREAKING")
|| enchantment.getName().equalsIgnoreCase("DURABILITY")) {
return enchantment;
}
}
pluginRef.getLogger().severe("Unable to find the Unbreaking enchantment, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Unbreaking enchantment");
}
/**
* Get the efficiency enchantment
*
* @return The efficiency enchantment
*/
public Enchantment getEfficiency() {
return efficiency;
}
public Enchantment getUnbreaking() {
return unbreaking;
}
public Enchantment getInfinity() {
return infinity;
}
public Enchantment getFeatherFalling() {
return featherFalling;
}
public Enchantment getLuckOfTheSea() {
return luckOfTheSea;
}
}

View File

@ -1,39 +1,34 @@
package com.gmail.nossr50.util;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
public class EnchantmentUtils {
private static final HashMap<String, Enchantment> enchants = new HashMap<>();
private static final HashMap<String, Enchantment> legacyEnchantments = new HashMap<>();
static {
enchants.put("SHARPNESS", Enchantment.DAMAGE_ALL);
enchants.put("POWER", Enchantment.ARROW_DAMAGE);
enchants.put("FIRE_PROTECTION", Enchantment.PROTECTION_FIRE);
enchants.put("FEATHER_FALLING", Enchantment.PROTECTION_FALL);
enchants.put("PROTECTION", Enchantment.PROTECTION_ENVIRONMENTAL);
enchants.put("BLAST_PROTECTION", Enchantment.PROTECTION_EXPLOSIONS);
enchants.put("PROJECTILE_PROTECTION", Enchantment.PROTECTION_PROJECTILE);
enchants.put("RESPIRATION", Enchantment.OXYGEN);
enchants.put("INFINITY", Enchantment.ARROW_INFINITE);
enchants.put("AQUA_AFFINITY", Enchantment.WATER_WORKER);
enchants.put("UNBREAKING", Enchantment.DURABILITY);
enchants.put("SMITE", Enchantment.DAMAGE_UNDEAD);
enchants.put("BANE_OF_ARTHROPODS", Enchantment.DAMAGE_ARTHROPODS);
enchants.put("EFFICIENCY", Enchantment.DIG_SPEED);
enchants.put("FIRE_ASPECT", Enchantment.FIRE_ASPECT);
enchants.put("SILK_TOUCH", Enchantment.SILK_TOUCH);
enchants.put("FORTUNE", Enchantment.LOOT_BONUS_BLOCKS);
enchants.put("LOOTING", Enchantment.LOOT_BONUS_MOBS);
enchants.put("PUNCH", Enchantment.ARROW_KNOCKBACK);
enchants.put("FLAME", Enchantment.ARROW_FIRE);
enchants.put("KNOCKBACK", Enchantment.KNOCKBACK);
enchants.put("THORNS", Enchantment.THORNS);
enchants.put("MENDING", Enchantment.MENDING);
enchants.put("DEPTH_STRIDER", Enchantment.DEPTH_STRIDER);
enchants.put("FROST_WALKER", Enchantment.FROST_WALKER);
// backwards compatibility for looking up legacy bukkit enums
addLegacyEnchantmentLookup("SHARPNESS", "DAMAGE_ALL");
addLegacyEnchantmentLookup("POWER", "ARROW_DAMAGE");
addLegacyEnchantmentLookup("FIRE_PROTECTION", "PROTECTION_FIRE");
addLegacyEnchantmentLookup("FEATHER_FALLING", "PROTECTION_FALL");
addLegacyEnchantmentLookup("PROTECTION", "PROTECTION_ENVIRONMENTAL");
addLegacyEnchantmentLookup("BLAST_PROTECTION", "PROTECTION_EXPLOSIONS");
addLegacyEnchantmentLookup("PROJECTILE_PROTECTION", "PROTECTION_PROJECTILE");
addLegacyEnchantmentLookup("RESPIRATION", "OXYGEN");
addLegacyEnchantmentLookup("INFINITY", "ARROW_INFINITE");
addLegacyEnchantmentLookup("AQUA_AFFINITY", "WATER_WORKER");
addLegacyEnchantmentLookup("UNBREAKING", "DURABILITY");
addLegacyEnchantmentLookup("SMITE", "DAMAGE_UNDEAD");
addLegacyEnchantmentLookup("BANE_OF_ARTHROPODS", "DAMAGE_ARTHROPODS");
addLegacyEnchantmentLookup("EFFICIENCY", "DIG_SPEED");
addLegacyEnchantmentLookup("FORTUNE", "LOOT_BONUS_BLOCKS");
addLegacyEnchantmentLookup("LOOTING", "LOOT_BONUS_MOBS");
addLegacyEnchantmentLookup("PUNCH", "ARROW_KNOCKBACK");
addLegacyEnchantmentLookup("FLAME", "ARROW_FIRE");
}
/**
@ -43,11 +38,19 @@ public class EnchantmentUtils {
*
* @return Enchantment or null if no enchantment was found
*/
public static Enchantment getByName(String enchantmentName) {
if (enchants.containsKey(enchantmentName)) {
return enchants.get(enchantmentName);
@SuppressWarnings("deprecation")
public static @Nullable Enchantment getByName(String enchantmentName) {
if (legacyEnchantments.containsKey(enchantmentName)) {
return legacyEnchantments.get(enchantmentName);
}
return Enchantment.getByName(enchantmentName);
}
@SuppressWarnings("deprecation")
private static void addLegacyEnchantmentLookup(String enchantmentName, String legacyBukkitName) {
if (Enchantment.getByName(legacyBukkitName) != null) {
legacyEnchantments.put(enchantmentName, Enchantment.getByName(legacyBukkitName));
}
}
}

View File

@ -23,6 +23,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
import static java.util.Objects.requireNonNull;
public final class ItemUtils {
/**
* This is a static utility class, therefore we don't want any instances of
@ -41,6 +43,37 @@ public final class ItemUtils {
return mcMMO.getMaterialMapStore().isBow(item.getType().getKey().getKey());
}
/**
* Exhaustive lookup for a Material by name.
* <p>
* This method will first try a normal lookup, then a legacy lookup, then a lookup by ENUM name,
* and finally a lookup by ENUM name with legacy name.
* @param materialName The name of the material to lookup
* @return The Material if found, or null if not found
*/
public static @Nullable Material exhaustiveMaterialLookup(@NotNull String materialName) {
requireNonNull(materialName, "materialName cannot be null");
// First try a normal lookup
Material material = Material.matchMaterial(materialName);
// If that fails, try a legacy lookup
if (material == null) {
material = Material.matchMaterial(materialName, true);
}
// try to match to Material ENUM
if (material == null) {
material = Material.getMaterial(materialName.toUpperCase());
}
// try to match to Material ENUM with legacy name
if (material == null) {
material = Material.getMaterial(materialName.toUpperCase(), true);
}
return material;
}
/**
* Checks if a player has an item in their inventory or offhand.
*
@ -100,6 +133,10 @@ public final class ItemUtils {
return mcMMO.getMaterialMapStore().isTrident(item.getType().getKey().getKey());
}
public static boolean isMace(@NotNull ItemStack item) {
return mcMMO.getMaterialMapStore().isMace(item.getType().getKey().getKey());
}
public static boolean hasItemInEitherHand(@NotNull Player player, Material material) {
return player.getInventory().getItemInMainHand().getType() == material || player.getInventory().getItemInOffHand().getType() == material;
}
@ -681,7 +718,8 @@ public final class ItemUtils {
if(itemMeta == null)
return;
itemMeta.addEnchant(Enchantment.DIG_SPEED, existingEnchantLevel + mcMMO.p.getAdvancedConfig().getEnchantBuff(), true);
itemMeta.addEnchant(mcMMO.p.getEnchantmentMapper().getEfficiency(),
existingEnchantLevel + mcMMO.p.getAdvancedConfig().getEnchantBuff(), true);
itemStack.setItemMeta(itemMeta);
}

View File

@ -50,6 +50,7 @@ public class MaterialMapStore {
private final @NotNull HashSet<String> crossbows;
private final @NotNull HashSet<String> tools;
private final @NotNull HashSet<String> enchantables;
private final @NotNull HashSet<String> maces;
private final @NotNull HashSet<String> ores;
private final @NotNull HashSet<String> intendedToolPickAxe;
@ -97,6 +98,7 @@ public class MaterialMapStore {
shovels = new HashSet<>();
hoes = new HashSet<>();
tridents = new HashSet<>();
maces = new HashSet<>();
enchantables = new HashSet<>();
@ -453,6 +455,7 @@ public class MaterialMapStore {
enchantables.addAll(tridents);
enchantables.addAll(bows);
enchantables.addAll(crossbows);
enchantables.addAll(maces);
enchantables.add("shears");
enchantables.add("fishing_rod");
@ -476,6 +479,7 @@ public class MaterialMapStore {
fillHoes();
fillShovels();
fillTridents();
fillMaces();
fillStringTools();
fillBows();
fillCrossbows();
@ -491,6 +495,7 @@ public class MaterialMapStore {
tools.addAll(stringTools);
tools.addAll(bows);
tools.addAll(crossbows);
tools.addAll(maces);
}
private void fillBows() {
@ -507,6 +512,10 @@ public class MaterialMapStore {
stringTools.add("carrot_on_a_stick");
}
private void fillMaces() {
maces.add("mace");
}
private void fillTridents() {
tridents.add("trident");
}
@ -824,6 +833,14 @@ public class MaterialMapStore {
return tridents.contains(id);
}
public boolean isMace(@NotNull Material material) {
return isMace(material.getKey().getKey());
}
public boolean isMace(@NotNull String id) {
return maces.contains(id);
}
public boolean isLeatherArmor(@NotNull Material material) {
return isLeatherArmor(material.getKey().getKey());
}

View File

@ -246,6 +246,14 @@ public final class Permissions {
}
public static boolean tridentsLimitBreak(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.tridents.superability"); }
/* MACES */
public static boolean macesSuper(Permissible permissible) {
// TODO: When a super is added, change this
return false;
}
public static boolean macesLimitBreak(Permissible permissible) { return permissible.hasPermission("mcmmo.ability.maces.limitbreak"); }
/*
* PARTY
*/

View File

@ -0,0 +1,6 @@
package com.gmail.nossr50.util;
public enum PotionCompatibilityType {
PRE_1_20_5,
POST_1_20_5
}

View File

@ -0,0 +1,142 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.mcMMO;
import org.bukkit.potion.PotionEffectType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
final public class PotionEffectMapper {
private static final PotionEffectType haste;
private static final PotionEffectType nausea;
private static final Method potionEffectTypeWrapperGetPotionEffectType;
private static final Class<?> classPotionEffectTypeWrapper;
private PotionEffectMapper() {
// Utility class
}
static {
potionEffectTypeWrapperGetPotionEffectType = getPotionEffectTypeWrapperGetPotionEffectType();
classPotionEffectTypeWrapper = getClassPotionEffectTypeWrapper();
haste = initHaste();
nausea = initNausea();
}
private static Method getPotionEffectTypeWrapperGetPotionEffectType() {
try {
return classPotionEffectTypeWrapper.getMethod("getType");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Class<?> getClassPotionEffectTypeWrapper() {
try {
return Class.forName("org.bukkit.potion.PotionEffectTypeWrapper");
} catch (ClassNotFoundException e) {
return null;
}
}
private static PotionEffectType initNausea() {
if (classPotionEffectTypeWrapper != null) {
return getNauseaLegacy();
} else {
return getNauseaModern();
}
}
private static PotionEffectType getNauseaModern() {
// PotionEffectType potionEffectType = Registry.EFFECT.match("nausea");
// if (potionEffectType != null) {
// return potionEffectType;
// }
//
// // Look for the potion effect type by name
// for (PotionEffectType pet : Registry.EFFECT) {
// if (pet.getKey().getKey().equalsIgnoreCase("CONFUSION")
// || pet.getKey().getKey().equalsIgnoreCase("NAUSEA")
// || pet.getName().equalsIgnoreCase("CONFUSION")
// || pet.getName().equalsIgnoreCase("NAUSEA")) {
// return pet;
// }
// }
try {
return (PotionEffectType) PotionEffectType.class.getField("NAUSEA").get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
mcMMO.p.getLogger().severe("Unable to find the Nausea potion effect type, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Nausea potion effect type");
}
}
private static PotionEffectType getNauseaLegacy() {
try {
Object potionEffectTypeWrapper = PotionEffectType.class.getField("CONFUSION").get(null);
PotionEffectType potionEffectType = (PotionEffectType) potionEffectTypeWrapperGetPotionEffectType
.invoke(potionEffectTypeWrapper);
return potionEffectType;
} catch (IllegalAccessException | NoSuchFieldException | InvocationTargetException e) {
mcMMO.p.getLogger().severe("Unable to find the Nausea potion effect type, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Nausea potion effect type");
}
}
private static PotionEffectType initHaste() {
mcMMO.p.getLogger().severe("Unable to find the Haste potion effect type, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Haste potion effect type");
}
private static PotionEffectType getHasteLegacy() {
try {
Object potionEffectTypeWrapper = PotionEffectType.class.getField("FAST_DIGGING").get(null);
PotionEffectType potionEffectType = (PotionEffectType) potionEffectTypeWrapperGetPotionEffectType
.invoke(potionEffectTypeWrapper);
return potionEffectType;
} catch (IllegalAccessException | NoSuchFieldException | InvocationTargetException e) {
mcMMO.p.getLogger().severe("Unable to find the Haste potion effect type, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Haste potion effect type");
}
}
private static PotionEffectType getHasteModern() {
// PotionEffectType potionEffectType = Registry.EFFECT.match("haste");
// if (potionEffectType != null) {
// return potionEffectType;
// }
//
// // Look for the potion effect type by name
// for (PotionEffectType pet : Registry.EFFECT) {
// if (pet.getKey().getKey().equalsIgnoreCase("HASTE")
// || pet.getKey().getKey().equalsIgnoreCase("FAST_DIGGING")
// || pet.getName().equalsIgnoreCase("HASTE")
// || pet.getName().equalsIgnoreCase("FAST_DIGGING")) {
// return pet;
// }
// }
try {
return (PotionEffectType) PotionEffectType.class.getField("HASTE").get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
mcMMO.p.getLogger().severe("Unable to find the Haste potion effect type, " +
"mcMMO will not function properly.");
throw new IllegalStateException("Unable to find the Haste potion effect type");
}
}
public static PotionEffectType getHaste() {
return haste;
}
public static PotionEffectType getNausea() {
return nausea;
}
}

View File

@ -0,0 +1,447 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.mcMMO;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PotionUtil {
// Some of the old potion types got renamed, our configs can still contain these old names
private static final Map<String, String> legacyPotionTypes = new HashMap<>();
private static final Method methodPotionTypeGetKey;
private static final Method methodPotionTypeGetEffectType;
private static final Method methodPotionTypeGetPotionEffects;
private static final Method methodPotionDataIsUpgraded;
private static final Method methodPotionDataIsExtended;
private static final Method methodPotionDataGetType;
private static final Method methodPotionMetaGetBasePotionData;
private static final Method methodPotionMetaGetBasePotionType;
private static final Method methodPotionMetaSetBasePotionType;
private static final Method methodSetBasePotionData;
private static final Class<?> potionDataClass;
public static final String STRONG = "STRONG";
public static final String LONG = "LONG";
public static final String LEGACY_WATER_POTION_TYPE = "WATER";
private static final PotionCompatibilityType COMPATIBILITY_MODE;
static {
// We used to use uncraftable as the potion type
// this type isn't available anymore, so water will do
legacyPotionTypes.put("UNCRAFTABLE", "WATER");
legacyPotionTypes.put("JUMP", "LEAPING");
legacyPotionTypes.put("SPEED", "SWIFTNESS");
legacyPotionTypes.put("INSTANT_HEAL", "HEALING");
legacyPotionTypes.put("INSTANT_DAMAGE", "HARMING");
legacyPotionTypes.put("REGEN", "REGENERATION");
methodPotionTypeGetKey = getKeyMethod();
methodPotionDataIsUpgraded = getPotionDataIsUpgraded();
methodPotionDataIsExtended = getIsExtended();
methodPotionMetaGetBasePotionData = getBasePotionData();
methodPotionMetaGetBasePotionType = getBasePotionType();
methodPotionMetaSetBasePotionType = getMethodPotionMetaSetBasePotionType();
methodPotionDataGetType = getPotionDataGetType();
methodPotionTypeGetEffectType = getPotionTypeEffectType();
methodPotionTypeGetPotionEffects = getPotionTypeGetPotionEffects();
methodSetBasePotionData = getSetBasePotionData();
potionDataClass = getPotionDataClass();
if (methodPotionMetaGetBasePotionData != null) {
COMPATIBILITY_MODE = PotionCompatibilityType.PRE_1_20_5;
} else {
COMPATIBILITY_MODE = PotionCompatibilityType.POST_1_20_5;
}
}
/**
* Derive a potion from a partial name, and whether it should be upgraded or extended.
* @param partialName potion type as a string, can be a substring of the potion type but must match exactly
* @return The potion type
*/
public static PotionType matchPotionType(String partialName, boolean isUpgraded, boolean isExtended) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return matchLegacyPotionType(partialName);
} else {
String updatedName = convertLegacyNames(partialName);
return Arrays.stream(PotionType.values())
.filter(potionType -> getKeyGetKey(potionType).toUpperCase().contains(partialName)
|| getKeyGetKey(potionType).toUpperCase().contains(convertLegacyNames(updatedName)))
.filter(potionType -> !isUpgraded || potionType.name().toUpperCase().contains(STRONG))
.filter(potionType -> !isExtended || potionType.name().toUpperCase().contains(LONG))
.findAny().orElse(null);
}
}
public static String getKeyGetKey(PotionType potionType) {
try {
if (getKeyMethod() != null) {
NamespacedKey key = (NamespacedKey) methodPotionTypeGetKey.invoke(potionType);
return key.getKey();
} else {
return potionType.name();
}
} catch (InvocationTargetException | IllegalAccessException e) {
mcMMO.p.getLogger().warning("Failed to get potion key for " + potionType.name());
return potionType.name();
}
}
private static Class<?> getPotionDataClass() {
try {
return Class.forName("org.bukkit.potion.PotionData");
} catch (ClassNotFoundException e) {
return null;
}
}
/**
* Older versions of Spigot do not have getKey() in PotionType
* We need to check for the existence of this method before calling it
* @return The getKey method
*/
private static @Nullable Method getKeyMethod() {
try {
return PotionType.class.getMethod("getKey");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getMethodPotionMetaSetBasePotionType() {
try {
return PotionMeta.class.getMethod("setBasePotionType", PotionType.class);
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getSetBasePotionData() {
try {
return PotionMeta.class.getMethod("setBasePotionData", potionDataClass);
} catch (NoSuchMethodException e) {
return null;
}
}
private static @Nullable Method getPotionDataIsUpgraded() {
try {
// TODO: <?> Needed?
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
return clazz.getMethod("isUpgraded");
} catch (NoSuchMethodException | ClassNotFoundException e) {
return null;
}
}
private static @Nullable Method getIsExtended() {
try {
// TODO: <?> Needed?
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
return clazz.getMethod("isExtended");
} catch (NoSuchMethodException | ClassNotFoundException e) {
return null;
}
}
/**
* Newer versions of Spigot do not have getBasePotionData() in PotionMeta
*
* @return the getBasePotionData method, or null if it does not exist
*/
private static @Nullable Method getBasePotionData() {
try {
return PotionType.class.getMethod("getBasePotionData");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getBasePotionType() {
try {
return PotionMeta.class.getMethod("getBasePotionType");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getPotionDataGetType() {
try {
final Class<?> clazz = Class.forName("org.bukkit.potion.PotionData");
return clazz.getMethod("getType");
} catch (NoSuchMethodException | ClassNotFoundException e) {
return null;
}
}
private static Method getPotionTypeEffectType() {
try {
return PotionType.class.getMethod("getEffectType");
} catch (NoSuchMethodException e) {
return null;
}
}
private static Method getPotionTypeGetPotionEffects() {
try {
return PotionType.class.getMethod("getPotionEffects");
} catch (NoSuchMethodException e) {
return null;
}
}
/**
* Legacy matching for {@link PotionType}
*
* @param partialName The partial name of the potion
* @return The potion type
*/
private static PotionType matchLegacyPotionType(String partialName) {
String updatedName = convertLegacyNames(partialName);
return Arrays.stream(PotionType.values())
.filter(potionType -> getKeyGetKey(potionType).equalsIgnoreCase(partialName)
|| getKeyGetKey(potionType).equalsIgnoreCase(convertLegacyNames(updatedName))
|| potionType.name().equalsIgnoreCase(partialName)
|| potionType.name().equalsIgnoreCase(convertLegacyNames(updatedName)))
.findAny().orElse(null);
}
public static String convertPotionConfigName(String legacyName) {
String replacementName = legacyName;
// Remove generated potions.yml config naming convention
if (replacementName.contains("POTION_OF_")) {
replacementName = replacementName.replace("POTION_OF_", "");
}
if (replacementName.contains("_II")) {
replacementName = replacementName.replace("_II", "");
replacementName = "STRONG_" + replacementName;
} else if (replacementName.contains("_EXTENDED")) {
replacementName = replacementName.replace("_EXTENDED", "");
replacementName = "LONG_" + replacementName;
}
return replacementName;
}
public static String convertLegacyNames(String legacyPotionType) {
String modernized = legacyPotionType;
// check for legacy names
for (var key : legacyPotionTypes.keySet()) {
if (modernized.contains(key)) {
// Replace the legacy name with the new name
modernized = modernized.replace(key, legacyPotionTypes.get(key));
break;
}
}
return modernized;
}
public static boolean hasLegacyName(String potionType) {
for (var key : legacyPotionTypes.keySet()) {
if (potionType.contains(key)) {
return true;
}
}
return false;
}
public static boolean isStrong(PotionMeta potionMeta) {
if (methodPotionMetaGetBasePotionData == null) {
return isStrongModern(potionMeta);
} else {
return isStrongLegacy(potionMeta);
}
}
public static boolean isLong(PotionMeta potionMeta) {
if (methodPotionMetaGetBasePotionData == null) {
return isLongModern(potionMeta);
} else {
return isLongLegacy(potionMeta);
}
}
private static boolean isLongLegacy(PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
return (boolean) methodPotionDataIsExtended.invoke(potionData);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static boolean isLongModern(PotionMeta potionMeta) {
try {
return getModernPotionTypeKey(potionMeta).getKey().startsWith(LONG);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static boolean isStrongLegacy(PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
return (boolean) methodPotionDataIsUpgraded.invoke(potionData);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static boolean isStrongModern(PotionMeta potionMeta) {
try {
return getModernPotionTypeKey(potionMeta).getKey().startsWith(STRONG);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
private static NamespacedKey getModernPotionTypeKey(PotionMeta potionMeta) throws IllegalAccessException, InvocationTargetException {
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(potionMeta);
return (NamespacedKey) methodPotionTypeGetKey.invoke(potionType);
}
public static boolean isPotionTypeWater(@NotNull PotionMeta potionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return isPotionTypeWaterLegacy(potionMeta);
} else {
return isPotionTypeWaterModern(potionMeta);
}
}
private static boolean isPotionTypeWaterLegacy(@NotNull PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
return potionType.name().equalsIgnoreCase(LEGACY_WATER_POTION_TYPE)
|| PotionType.valueOf(LEGACY_WATER_POTION_TYPE) == potionType;
} catch (InvocationTargetException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
private static boolean isPotionTypeWaterModern(@NotNull PotionMeta potionMeta) {
try {
return getModernPotionTypeKey(potionMeta).getKey().equalsIgnoreCase(LEGACY_WATER_POTION_TYPE);
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
public static boolean samePotionType(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return samePotionTypeLegacy(potionMeta, otherPotionMeta);
} else {
return samePotionTypeModern(potionMeta, otherPotionMeta);
}
}
private static boolean samePotionTypeLegacy(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
Object otherPotionData = methodPotionMetaGetBasePotionData.invoke(otherPotionMeta);
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
PotionType otherPotionType = (PotionType) methodPotionDataGetType.invoke(otherPotionData);
return potionType == otherPotionType;
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
private static boolean samePotionTypeModern(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
try {
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(potionMeta);
PotionType otherPotionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(otherPotionMeta);
return potionType == otherPotionType;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public static boolean samePotionEffects(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return true;
} else {
return samePotionEffectsModern(potionMeta, otherPotionMeta);
}
}
private static boolean samePotionEffectsModern(PotionMeta potionMeta, PotionMeta otherPotionMeta) {
return potionMeta.getCustomEffects().equals(otherPotionMeta.getCustomEffects());
}
public static boolean hasBasePotionEffects(PotionMeta potionMeta) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
return hasBasePotionEffectsLegacy(potionMeta);
} else {
return hasBasePotionEffectsModern(potionMeta);
}
}
private static boolean hasBasePotionEffectsLegacy(PotionMeta potionMeta) {
try {
Object potionData = methodPotionMetaGetBasePotionData.invoke(potionMeta);
PotionType potionType = (PotionType) methodPotionDataGetType.invoke(potionData);
return methodPotionTypeGetEffectType.invoke(potionType) != null;
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
private static boolean hasBasePotionEffectsModern(PotionMeta potionMeta) {
try {
PotionType potionType = (PotionType) methodPotionMetaGetBasePotionType.invoke(potionMeta);
List<PotionEffectType> potionEffectTypeList = (List<PotionEffectType>) methodPotionTypeGetPotionEffects.invoke(potionType);
return potionEffectTypeList != null || !potionEffectTypeList.isEmpty();
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
/**
* Set the base potion type of a potion meta.
* Note that extended/upgraded are ignored in 1.20.5 and later.
*
* @param potionMeta the potion meta
* @param extended true if the potion is extended
* @param upgraded true if the potion is upgraded
*/
public static void setBasePotionType(PotionMeta potionMeta, PotionType potionType, boolean extended, boolean upgraded) {
if (COMPATIBILITY_MODE == PotionCompatibilityType.PRE_1_20_5) {
setBasePotionTypeLegacy(potionMeta, potionType, extended, upgraded);
} else {
setBasePotionTypeModern(potionMeta, potionType);
}
}
private static void setBasePotionTypeLegacy(PotionMeta potionMeta, PotionType potionType, boolean extended,
boolean upgraded) {
try {
Object potionData = potionDataClass.getConstructor(PotionType.class, boolean.class, boolean.class)
.newInstance(potionType, extended, upgraded);
methodSetBasePotionData.invoke(potionMeta, potionData);
} catch (IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
}
private static void setBasePotionTypeModern(PotionMeta potionMeta, PotionType potionType) {
try {
methodPotionMetaSetBasePotionType.invoke(potionMeta, potionType);
} catch (IllegalAccessException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
}

View File

@ -33,6 +33,9 @@ public final class CommandRegistrationManager {
private static void registerSkillCommands() {
for (PrimarySkillType skill : PrimarySkillType.values()) {
if (skill == PrimarySkillType.MACES)
continue;
String commandName = skill.toString().toLowerCase(Locale.ENGLISH);
String localizedName = mcMMO.p.getSkillTools().getLocalizedSkillName(skill).toLowerCase(Locale.ENGLISH);
@ -77,6 +80,10 @@ public final class CommandRegistrationManager {
command.setExecutor(new HerbalismCommand());
break;
case MACES:
// command.setExecutor(new MacesCommand());
break;
case MINING:
command.setExecutor(new MiningCommand());
break;
@ -113,7 +120,7 @@ public final class CommandRegistrationManager {
break;
default:
break;
throw new IllegalStateException("Unexpected value: " + skill);
}
}
}

View File

@ -23,7 +23,6 @@ import java.util.HashMap;
* In 2.2 we are switching to modules and that will clean things up significantly
*
*/
//TODO: I need to delete this crap
public class CompatibilityManager {
private @NotNull HashMap<CompatibilityType, Boolean> supportedLayers;
private boolean isFullyCompatibleServerSoftware = true; //true if all compatibility layers load successfully
@ -159,7 +158,7 @@ public class CompatibilityManager {
return masterAnglerCompatibility;
}
public @Nullable MinecraftGameVersion getMinecraftGameVersion() {
public @NotNull MinecraftGameVersion getMinecraftGameVersion() {
return minecraftGameVersion;
}
}

View File

@ -111,6 +111,7 @@ public final class CombatUtils {
}
}
}
private static void processTridentCombatMelee(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) {
return;
@ -214,6 +215,32 @@ public final class CombatUtils {
delayArrowMetaCleanup(arrow);
}
private static void processMacesCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) {
return;
}
double boostedDamage = event.getDamage();
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
//Make sure the profiles been loaded
if(mcMMOPlayer == null) {
return;
}
// MacesManager macesManager = mcMMOPlayer.getMacesManager();
if(canUseLimitBreak(player, target, SubSkillType.MACES_MACES_LIMIT_BREAK)) {
boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.MACES_MACES_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength());
}
event.setDamage(boostedDamage);
processCombatXP(mcMMOPlayer, target, PrimarySkillType.MACES);
printFinalDamageDebug(player, event, mcMMOPlayer);
}
private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
if (event.getCause() == DamageCause.THORNS) {
return;
@ -498,6 +525,15 @@ public final class CombatUtils {
processTridentCombatMelee(target, player, event);
}
}
else if (ItemUtils.isMace(heldItem)) {
if (!mcMMO.p.getSkillTools().canCombatSkillsTrigger(PrimarySkillType.MACES, target)) {
return;
}
if (mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, PrimarySkillType.MACES)) {
processMacesCombat(target, player, event);
}
}
}
else if (entityType == EntityType.WOLF) {

View File

@ -198,6 +198,7 @@ public class SkillTools {
case SUPER_SHOTGUN -> PrimarySkillType.CROSSBOWS;
case TRIDENTS_SUPER_ABILITY -> PrimarySkillType.TRIDENTS;
case EXPLOSIVE_SHOT -> PrimarySkillType.ARCHERY;
case MACES_SUPER_ABILITY -> PrimarySkillType.MACES;
};
}

View File

@ -20,7 +20,6 @@ import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
@ -28,12 +27,13 @@ import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import static com.gmail.nossr50.util.PotionEffectMapper.getHaste;
public final class SkillUtils {
/**
* This is a static utility class, therefore we don't want any instances of
@ -148,13 +148,8 @@ public final class SkillUtils {
return;
}
int originalDigSpeed = heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED);
//Add dig speed
//Lore no longer gets added, no point to it afaik
//ItemUtils.addAbilityLore(heldItem); //lore can be a secondary failsafe for 1.13 and below
ItemUtils.addDigSpeedToItem(heldItem, heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED));
int originalDigSpeed = heldItem.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getEfficiency());
ItemUtils.addDigSpeedToItem(heldItem, heldItem.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getEfficiency()));
//1.13.2+ will have persistent metadata for this item
mcMMO.getMetadataService().getItemMetadataService().setSuperAbilityBoostedItem(heldItem, originalDigSpeed);
@ -162,9 +157,9 @@ public final class SkillUtils {
int duration = 0;
int amplifier = 0;
if (player.hasPotionEffect(PotionEffectType.FAST_DIGGING)) {
if (player.hasPotionEffect(getHaste())) {
for (PotionEffect effect : player.getActivePotionEffects()) {
if (effect.getType() == PotionEffectType.FAST_DIGGING) {
if (effect.getType() == getHaste()) {
duration = effect.getDuration();
amplifier = effect.getAmplifier();
break;
@ -194,7 +189,7 @@ public final class SkillUtils {
mcMMO.p.getSkillTools().getSuperAbilityMaxLength(mcMMO.p.getSkillTools().getSuperAbility(skill))) * Misc.TICK_CONVERSION_FACTOR;
}
PotionEffect abilityBuff = new PotionEffect(PotionEffectType.FAST_DIGGING, duration + ticks, amplifier + 10);
PotionEffect abilityBuff = new PotionEffect(getHaste(), duration + ticks, amplifier + 10);
player.addPotionEffect(abilityBuff, true);
}
}
@ -221,7 +216,7 @@ public final class SkillUtils {
if(itemMeta != null) {
// This is safe to call without prior checks.
itemMeta.removeEnchant(Enchantment.DIG_SPEED);
itemMeta.removeEnchant(mcMMO.p.getEnchantmentMapper().getEfficiency());
itemStack.setItemMeta(itemMeta);
ItemUtils.removeAbilityLore(itemStack);
@ -251,7 +246,7 @@ public final class SkillUtils {
Material type = itemStack.getType();
short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1), maxDurability * maxDamageModifier);
durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getUnbreaking()) + 1), maxDurability * maxDamageModifier);
itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
}
@ -281,7 +276,7 @@ public final class SkillUtils {
Material type = itemStack.getType();
short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
durabilityModifier = (int) Math.min(durabilityModifier * (0.6 + 0.4/ (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1)), maxDurability * maxDamageModifier);
durabilityModifier = (int) Math.min(durabilityModifier * (0.6 + 0.4/ (itemStack.getEnchantmentLevel(mcMMO.p.getEnchantmentMapper().getUnbreaking()) + 1)), maxDurability * maxDamageModifier);
itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
}