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,56 @@
//package com.gmail.nossr50.commands.skills;
//
//import com.gmail.nossr50.datatypes.player.McMMOPlayer;
//import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
//import com.gmail.nossr50.util.player.UserManager;
//import com.gmail.nossr50.util.skills.CombatUtils;
//import com.gmail.nossr50.util.skills.SkillUtils;
//import com.gmail.nossr50.util.text.TextComponentFactory;
//import net.kyori.adventure.text.Component;
//import org.bukkit.ChatColor;
//import org.bukkit.entity.Player;
//
//import java.util.ArrayList;
//import java.util.List;
//
//import static com.gmail.nossr50.datatypes.skills.SubSkillType.MACES_MACES_LIMIT_BREAK;
//
//public class MacesCommand extends SkillCommand {
//
// public MacesCommand() {
// super(PrimarySkillType.MACES);
// }
//
// @Override
// protected void dataCalculations(Player player, float skillValue) {}
//
// @Override
// protected void permissionsCheck(Player player) {}
//
// @Override
// protected List<String> statsDisplay(Player player, float skillValue, boolean hasEndurance, boolean isLucky) {
// List<String> messages = new ArrayList<>();
// McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
// if (mmoPlayer == null) {
// return messages;
// }
//
// if(SkillUtils.canUseSubskill(player, MACES_MACES_LIMIT_BREAK)) {
// messages.add(getStatMessage(MACES_MACES_LIMIT_BREAK,
// String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player, MACES_MACES_LIMIT_BREAK, 1000))));
// }
//
// messages.add(ChatColor.GRAY + "The Maces skill is a work in progress and is still being developed," +
// " feedback would be appreciated in the mcMMO discord server.");
// return messages;
// }
//
// @Override
// protected List<Component> getTextComponents(Player player) {
// List<Component> textComponents = new ArrayList<>();
//
// TextComponentFactory.getSubSkillTextComponents(player, textComponents, PrimarySkillType.MACES);
//
// return textComponents;
// }
//}

View File

@ -4,31 +4,40 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.LogUtils;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.VisibleForTesting;
import java.io.File;
import java.util.List;
@Deprecated
public abstract class LegacyConfigLoader {
protected final File configFile;
protected final @NotNull File configFile;
protected final @NotNull File dataFolder;
protected String fileName;
protected @NotNull String fileName;
protected YamlConfiguration config;
public LegacyConfigLoader(String relativePath, String fileName, @NotNull File dataFolder) {
public LegacyConfigLoader(@NotNull String relativePath, @NotNull String fileName, @NotNull File dataFolder) {
this.fileName = fileName;
this.dataFolder = dataFolder;
configFile = new File(dataFolder, relativePath + File.separator + fileName);
loadFile();
}
public LegacyConfigLoader(String fileName, @NotNull File dataFolder) {
public LegacyConfigLoader(@NotNull String fileName, @NotNull File dataFolder) {
this.fileName = fileName;
this.dataFolder = dataFolder;
configFile = new File(dataFolder, fileName);
loadFile();
}
@VisibleForTesting
public LegacyConfigLoader(@NotNull File file) {
this.fileName = file.getName();
this.dataFolder = file.getParentFile();
configFile = new File(dataFolder, fileName);
loadFile();
}
@Deprecated
public LegacyConfigLoader(String relativePath, String fileName) {
this.fileName = fileName;

View File

@ -2,22 +2,30 @@ package com.gmail.nossr50.config.skills.alchemy;
import com.gmail.nossr50.config.LegacyConfigLoader;
import com.gmail.nossr50.datatypes.skills.alchemy.AlchemyPotion;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.LogUtils;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.PotionUtil;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.*;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.VisibleForTesting;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.gmail.nossr50.util.PotionUtil.*;
public class PotionConfig extends LegacyConfigLoader {
private static PotionConfig instance;
private final List<ItemStack> concoctionsIngredientsTierOne = new ArrayList<>();
private final List<ItemStack> concoctionsIngredientsTierTwo = new ArrayList<>();
@ -28,30 +36,34 @@ public class PotionConfig extends LegacyConfigLoader {
private final List<ItemStack> concoctionsIngredientsTierSeven = new ArrayList<>();
private final List<ItemStack> concoctionsIngredientsTierEight = new ArrayList<>();
private final Map<String, AlchemyPotion> potionMap = new HashMap<>();
/**
* Map of potion names to AlchemyPotion objects.
*/
private final Map<String, AlchemyPotion> loadedPotions = new HashMap<>();
private PotionConfig() {
public PotionConfig() {
super("potions.yml");
loadKeys();
}
public static PotionConfig getInstance() {
if (instance == null) {
instance = new PotionConfig();
}
return instance;
@VisibleForTesting
PotionConfig(File file) {
super(file);
}
@Override
protected void loadKeys() {
}
public void loadPotions() {
loadConcoctions();
loadPotionMap();
}
private void loadConcoctions() {
ConfigurationSection concoctionSection = config.getConfigurationSection("Concoctions");
@VisibleForTesting
void loadConcoctions() {
final ConfigurationSection concoctionSection = config.getConfigurationSection("Concoctions");
// Load the ingredients for each tier
loadConcoctionsTier(concoctionsIngredientsTierOne, concoctionSection.getStringList("Tier_One_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierTwo, concoctionSection.getStringList("Tier_Two_Ingredients"));
loadConcoctionsTier(concoctionsIngredientsTierThree, concoctionSection.getStringList("Tier_Three_Ingredients"));
@ -71,7 +83,7 @@ public class PotionConfig extends LegacyConfigLoader {
}
private void loadConcoctionsTier(List<ItemStack> ingredientList, List<String> ingredientStrings) {
if (ingredientStrings != null && ingredientStrings.size() > 0) {
if (ingredientStrings != null && !ingredientStrings.isEmpty()) {
for (String ingredientString : ingredientStrings) {
ItemStack ingredient = loadIngredient(ingredientString);
@ -85,23 +97,24 @@ public class PotionConfig extends LegacyConfigLoader {
/**
* Find the Potions configuration section and load all defined potions.
*/
private void loadPotionMap() {
int loadPotionMap() {
ConfigurationSection potionSection = config.getConfigurationSection("Potions");
int pass = 0;
int fail = 0;
int potionsLoaded = 0;
int failures = 0;
for (String potionName : potionSection.getKeys(false)) {
AlchemyPotion potion = loadPotion(potionSection.getConfigurationSection(potionName));
if (potion != null) {
potionMap.put(potionName, potion);
pass++;
loadedPotions.put(potionName, potion);
potionsLoaded++;
} else {
fail++;
failures++;
}
}
LogUtils.debug(mcMMO.p.getLogger(), "Loaded " + pass + " Alchemy potions, skipped " + fail + ".");
mcMMO.p.getLogger().info("Loaded " + potionsLoaded + " Alchemy potions, skipped " + failures + ".");
return potionsLoaded;
}
/**
@ -114,37 +127,88 @@ public class PotionConfig extends LegacyConfigLoader {
*/
private AlchemyPotion loadPotion(ConfigurationSection potion_section) {
try {
final String key = potion_section.getName();
final String displayName = potion_section.getString("Name") != null
? LocaleLoader.addColors(potion_section.getString("Name"))
: null;
final ConfigurationSection potionData = potion_section.getConfigurationSection("PotionData");
boolean extended = false;
boolean upgraded = false;
String name = potion_section.getString("Name");
if (name != null) {
name = ChatColor.translateAlternateColorCodes('&', name);
if (potionData != null) {
extended = potionData.getBoolean("Extended", false);
upgraded = potionData.getBoolean("Upgraded", false);
}
PotionData data;
if (!potion_section.contains("PotionData")) { // Backwards config compatability
short dataValue = Short.parseShort(potion_section.getName());
Potion potion = Potion.fromDamage(dataValue);
data = new PotionData(potion.getType(), potion.hasExtendedDuration(), potion.getLevel() == 2);
Material material;
final String materialString = potion_section.getString("Material", null);
if (materialString != null) {
material = ItemUtils.exhaustiveMaterialLookup(materialString);
if (material == null) {
mcMMO.p.getLogger().warning("PotionConfig: Failed to parse material for potion " + key + ": " + materialString);
mcMMO.p.getLogger().warning("PotionConfig: Defaulting to POTION");
material = Material.POTION;
}
} else {
ConfigurationSection potionData = potion_section.getConfigurationSection("PotionData");
data = new PotionData(PotionType.valueOf(potionData.getString("PotionType", "WATER")), potionData.getBoolean("Extended", false), potionData.getBoolean("Upgraded", false));
mcMMO.p.getLogger().warning("PotionConfig: Missing Material config entry for potion " + key + "," +
" from configuration section: " + potion_section + ", defaulting to POTION");
material = Material.POTION;
}
Material material = Material.POTION;
String mat = potion_section.getString("Material", null);
if (mat != null) {
material = Material.valueOf(mat);
final ItemStack itemStack = new ItemStack(material, 1);
final PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta();
if (potionMeta == null) {
mcMMO.p.getLogger().severe("PotionConfig: Failed to get PotionMeta for " + displayName + ", from configuration section:" +
" " + potion_section);
return null;
}
// extended and upgraded seem to be mutually exclusive
if (extended && upgraded) {
mcMMO.p.getLogger().warning("Potion " + key + " has both Extended and Upgraded set to true," +
" defaulting to Extended.");
upgraded = false;
}
String potionTypeStr = potionData.getString("PotionType", null);
if (potionTypeStr == null) {
mcMMO.p.getLogger().severe("PotionConfig: Missing PotionType for " + displayName + ", from configuration section:" +
" " + potion_section);
return null;
}
PotionType potionType = matchPotionType(potionTypeStr, upgraded, extended);
if (potionType == null) {
// try matching to key
mcMMO.p.getLogger().warning("Failed to match potion type, trying to match with config key...");
matchPotionType(key, upgraded, extended);
}
if (potionType == null) {
mcMMO.p.getLogger().severe("PotionConfig: Failed to parse potion type for: " + potionTypeStr);
return null;
}
// Set base potion type
// NOTE: extended/ignored are effectively ignored here on 1.20.5 and later
PotionUtil.setBasePotionType(potionMeta, potionType, extended, upgraded);
// // Use the name of the potion to indicate upgrade status if not set in PotionData
// if(convertPotionConfigName(key).toUpperCase().contains("STRONG"))
// upgraded = true;
//
// if(convertPotionConfigName(key).toUpperCase().contains("LONG"))
// extended = true;
List<String> lore = new ArrayList<>();
if (potion_section.contains("Lore")) {
for (String line : potion_section.getStringList("Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', line));
}
}
potionMeta.setLore(lore);
List<PotionEffect> effects = new ArrayList<>();
if (potion_section.contains("Effects")) {
for (String effect : potion_section.getStringList("Effects")) {
String[] parts = effect.split(" ");
@ -154,9 +218,9 @@ public class PotionConfig extends LegacyConfigLoader {
int duration = parts.length > 2 ? Integer.parseInt(parts[2]) : 0;
if (type != null) {
effects.add(new PotionEffect(type, duration, amplifier));
potionMeta.addCustomEffect(new PotionEffect(type, duration, amplifier), true);
} else {
mcMMO.p.getLogger().warning("Failed to parse effect for potion " + name + ": " + effect);
mcMMO.p.getLogger().severe("PotionConfig: Failed to parse effect for potion " + displayName + ": " + effect);
}
}
}
@ -165,8 +229,9 @@ public class PotionConfig extends LegacyConfigLoader {
if (potion_section.contains("Color")) {
color = Color.fromRGB(potion_section.getInt("Color"));
} else {
color = this.generateColor(effects);
color = this.generateColor(potionMeta.getCustomEffects());
}
potionMeta.setColor(color);
Map<ItemStack, String> children = new HashMap<>();
if (potion_section.contains("Children")) {
@ -175,14 +240,15 @@ public class PotionConfig extends LegacyConfigLoader {
if (ingredient != null) {
children.put(ingredient, potion_section.getConfigurationSection("Children").getString(child));
} else {
mcMMO.p.getLogger().warning("Failed to parse child for potion " + name + ": " + child);
mcMMO.p.getLogger().severe("PotionConfig: Failed to parse child for potion " + displayName + ": " + child);
}
}
}
return new AlchemyPotion(material, data, name, lore, effects, color, children);
// TODO: Might not need to .setItemMeta
itemStack.setItemMeta(potionMeta);
return new AlchemyPotion(itemStack, children);
} catch (Exception e) {
mcMMO.p.getLogger().warning("Failed to load Alchemy potion: " + potion_section.getName());
mcMMO.p.getLogger().warning("PotionConfig: Failed to load Alchemy potion: " + potion_section.getName());
return null;
}
}
@ -210,39 +276,52 @@ public class PotionConfig extends LegacyConfigLoader {
return null;
}
/**
* Get the ingredients for the given tier.
* @param tier Tier to get ingredients for.
* @return List of ingredients for the given tier.
*/
public List<ItemStack> getIngredients(int tier) {
switch (tier) {
case 8:
return concoctionsIngredientsTierEight;
case 7:
return concoctionsIngredientsTierSeven;
case 6:
return concoctionsIngredientsTierSix;
case 5:
return concoctionsIngredientsTierFive;
case 4:
return concoctionsIngredientsTierFour;
case 3:
return concoctionsIngredientsTierThree;
case 2:
return concoctionsIngredientsTierTwo;
case 1:
default:
return concoctionsIngredientsTierOne;
}
return switch (tier) {
case 8 -> concoctionsIngredientsTierEight;
case 7 -> concoctionsIngredientsTierSeven;
case 6 -> concoctionsIngredientsTierSix;
case 5 -> concoctionsIngredientsTierFive;
case 4 -> concoctionsIngredientsTierFour;
case 3 -> concoctionsIngredientsTierThree;
case 2 -> concoctionsIngredientsTierTwo;
default -> concoctionsIngredientsTierOne;
};
}
/**
* Check if the given ItemStack is a valid potion.
* @param item ItemStack to be checked.
* @return True if the given ItemStack is a valid potion, false otherwise.
*/
public boolean isValidPotion(ItemStack item) {
return getPotion(item) != null;
}
/**
* Get the AlchemyPotion that corresponds to the given name.
* @param name Name of the potion to be checked.
* @return AlchemyPotion that corresponds to the given name.
*/
public AlchemyPotion getPotion(String name) {
return potionMap.get(name);
return loadedPotions.get(name);
}
/**
* Get the AlchemyPotion that corresponds to the given ItemStack.
*
* @param item ItemStack to be checked.
*
* @return AlchemyPotion that corresponds to the given ItemStack.
*/
public AlchemyPotion getPotion(ItemStack item) {
for (AlchemyPotion potion : potionMap.values()) {
if (potion.isSimilar(item)) {
for (AlchemyPotion potion : loadedPotions.values()) {
if (potion.isSimilarPotion(item)) {
return potion;
}
}

View File

@ -5,6 +5,7 @@ import com.gmail.nossr50.datatypes.treasure.*;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.EnchantmentUtils;
import com.gmail.nossr50.util.LogUtils;
import com.gmail.nossr50.util.PotionUtil;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
@ -13,12 +14,13 @@ import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
public class FishingTreasureConfig extends BukkitConfig {
public static final String FILENAME = "fishing_treasures.yml";
@ -204,30 +206,40 @@ public class FishingTreasureConfig extends BukkitConfig {
}
if (materialName.contains("POTION")) {
// Update for 1.20.5
Material mat = Material.matchMaterial(materialName);
if (mat == null) {
reason.add("Potion format for " + FILENAME + " has changed");
continue;
} else {
item = new ItemStack(mat, amount, data);
PotionMeta itemMeta = (PotionMeta) item.getItemMeta();
PotionMeta potionMeta = (PotionMeta) item.getItemMeta();
if (itemMeta == null) {
mcMMO.p.getLogger().severe("Item meta when adding potion to fishing treasure was null, contact the mcMMO devs!");
if (potionMeta == null) {
mcMMO.p.getLogger().severe("FishingConfig: Item meta when adding potion to fishing treasure was null," +
" contact the mcMMO devs!");
reason.add("FishingConfig: Item meta when adding potion to fishing treasure was null");
continue;
}
PotionType potionType = null;
try {
potionType = PotionType.valueOf(config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
} catch (IllegalArgumentException ex) {
reason.add("Invalid Potion_Type: " + config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
}
String potionTypeStr;
potionTypeStr = config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER");
boolean extended = config.getBoolean(type + "." + treasureName + ".PotionData.Extended", false);
boolean upgraded = config.getBoolean(type + "." + treasureName + ".PotionData.Upgraded", false);
itemMeta.setBasePotionData(new PotionData(potionType, extended, upgraded));
final PotionType potionType = matchPotionType(potionTypeStr, extended, upgraded);
if (potionType == null) {
reason.add("FishingConfig: Could not derive potion type from: " + potionTypeStr +", " + extended + ", " + upgraded);
continue;
}
// Set the base potion type
// NOTE: Upgraded/Extended are ignored in 1.20.5 and later
PotionUtil.setBasePotionType(potionMeta, potionType, upgraded, extended);
if (customName != null) {
itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', customName));
potionMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', customName));
}
if (config.contains(type + "." + treasureName + ".Lore")) {
@ -235,9 +247,9 @@ public class FishingTreasureConfig extends BukkitConfig {
for (String s : config.getStringList(type + "." + treasureName + ".Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', s));
}
itemMeta.setLore(lore);
potionMeta.setLore(lore);
}
item.setItemMeta(itemMeta);
item.setItemMeta(potionMeta);
}
} else if (material == Material.ENCHANTED_BOOK) {
//If any whitelisted enchants exist we use whitelist-based matching
@ -355,7 +367,8 @@ public class FishingTreasureConfig extends BukkitConfig {
Enchantment enchantment = EnchantmentUtils.getByName(enchantmentName);
if (enchantment == null) {
mcMMO.p.getLogger().warning("Skipping invalid enchantment in " + FILENAME + ": " + enchantmentName);
mcMMO.p.getLogger().info("Skipping invalid enchantment in '" + FILENAME + "', named:"
+ enchantmentName);
continue;
}

View File

@ -6,6 +6,7 @@ import com.gmail.nossr50.datatypes.treasure.HylianTreasure;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.LogUtils;
import com.gmail.nossr50.util.PotionUtil;
import com.gmail.nossr50.util.text.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -14,7 +15,6 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionType;
import java.io.IOException;
@ -165,22 +165,33 @@ public class TreasureConfig extends BukkitConfig {
Material mat = Material.matchMaterial(materialName);
if (mat == null) {
reason.add("Potion format for " + FILENAME + " has changed");
continue;
} else {
item = new ItemStack(mat, amount, data);
PotionMeta itemMeta = (PotionMeta) item.getItemMeta();
PotionType potionType = null;
try {
potionType = PotionType.valueOf(config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
} catch (IllegalArgumentException ex) {
reason.add("Invalid Potion_Type: " + config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER"));
PotionMeta potionMeta = (PotionMeta) item.getItemMeta();
if (potionMeta == null) {
mcMMO.p.getLogger().severe("Item meta when adding potion to treasure was null, contact the mcMMO devs!");
reason.add("Item meta when adding potion to treasure was null, contact the mcMMO devs!");
continue;
}
String potionTypeStr;
potionTypeStr = config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER");
boolean extended = config.getBoolean(type + "." + treasureName + ".PotionData.Extended", false);
boolean upgraded = config.getBoolean(type + "." + treasureName + ".PotionData.Upgraded", false);
itemMeta.setBasePotionData(new PotionData(potionType, extended, upgraded));
PotionType potionType = PotionUtil.matchPotionType(potionTypeStr, extended, upgraded);
if (potionType == null) {
reason.add("Could not derive potion type from: " + potionTypeStr +", " + extended + ", " + upgraded);
continue;
}
// Set the base potion type
// NOTE: extended/upgraded are ignored in 1.20.5 and later
PotionUtil.setBasePotionType(potionMeta, potionType, extended, upgraded);
if (config.contains(type + "." + treasureName + ".Custom_Name")) {
itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString(type + "." + treasureName + ".Custom_Name")));
potionMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString(type + "." + treasureName + ".Custom_Name")));
}
if (config.contains(type + "." + treasureName + ".Lore")) {
@ -188,9 +199,9 @@ public class TreasureConfig extends BukkitConfig {
for (String s : config.getStringList(type + "." + treasureName + ".Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', s));
}
itemMeta.setLore(lore);
potionMeta.setLore(lore);
}
item.setItemMeta(itemMeta);
item.setItemMeta(potionMeta);
}
} else if (material != null) {
item = new ItemStack(material, amount, data);

View File

@ -253,68 +253,26 @@ public class FlatFileDataProcessor {
}
public static @NotNull ExpectedType getExpectedValueType(int dataIndex) throws IndexOutOfBoundsException {
switch(dataIndex) {
case USERNAME_INDEX:
return ExpectedType.STRING;
case 2: //Assumption: Used to be for something, no longer used
case 3: //Assumption: Used to be for something, no longer used
case 23: //Assumption: Used to be used for something, no longer used
case 33: //Assumption: Used to be used for something, no longer used
case HEALTHBAR:
case LEGACY_LAST_LOGIN:
return ExpectedType.IGNORED;
case SKILLS_MINING:
case SKILLS_REPAIR:
case SKILLS_UNARMED:
case SKILLS_HERBALISM:
case SKILLS_EXCAVATION:
case SKILLS_ARCHERY:
case SKILLS_SWORDS:
case SKILLS_AXES:
case SKILLS_WOODCUTTING:
case SKILLS_ACROBATICS:
case SKILLS_TAMING:
case SKILLS_FISHING:
case SKILLS_ALCHEMY:
case SKILLS_CROSSBOWS:
case SKILLS_TRIDENTS:
case COOLDOWN_BERSERK:
case COOLDOWN_GIGA_DRILL_BREAKER:
case COOLDOWN_TREE_FELLER:
case COOLDOWN_GREEN_TERRA:
case COOLDOWN_SERRATED_STRIKES:
case COOLDOWN_SKULL_SPLITTER:
case COOLDOWN_SUPER_BREAKER:
case COOLDOWN_BLAST_MINING:
case SCOREBOARD_TIPS:
case COOLDOWN_CHIMAERA_WING:
case COOLDOWN_SUPER_SHOTGUN:
case COOLDOWN_TRIDENTS:
case COOLDOWN_ARCHERY:
return ExpectedType.INTEGER;
case EXP_MINING:
case EXP_WOODCUTTING:
case EXP_REPAIR:
case EXP_UNARMED:
case EXP_HERBALISM:
case EXP_EXCAVATION:
case EXP_ARCHERY:
case EXP_SWORDS:
case EXP_AXES:
case EXP_ACROBATICS:
case EXP_TAMING:
case EXP_FISHING:
case EXP_ALCHEMY:
case EXP_CROSSBOWS:
case EXP_TRIDENTS:
return ExpectedType.FLOAT;
case UUID_INDEX:
return ExpectedType.UUID;
case OVERHAUL_LAST_LOGIN:
return ExpectedType.LONG;
}
throw new IndexOutOfBoundsException();
return switch (dataIndex) {
case USERNAME_INDEX -> ExpectedType.STRING; //Assumption: Used to be for something, no longer used
//Assumption: Used to be for something, no longer used
//Assumption: Used to be used for something, no longer used
//Assumption: Used to be used for something, no longer used
case 2, 3, 23, 33, HEALTHBAR, LEGACY_LAST_LOGIN -> ExpectedType.IGNORED;
case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION, SKILLS_ARCHERY,
SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING, SKILLS_FISHING,
SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES, COOLDOWN_BERSERK,
COOLDOWN_GIGA_DRILL_BREAKER, COOLDOWN_TREE_FELLER, COOLDOWN_GREEN_TERRA, COOLDOWN_SERRATED_STRIKES,
COOLDOWN_SKULL_SPLITTER, COOLDOWN_SUPER_BREAKER, COOLDOWN_BLAST_MINING, SCOREBOARD_TIPS,
COOLDOWN_CHIMAERA_WING, COOLDOWN_SUPER_SHOTGUN, COOLDOWN_TRIDENTS, COOLDOWN_ARCHERY, COOLDOWN_MACES ->
ExpectedType.INTEGER;
case EXP_MINING, EXP_WOODCUTTING, EXP_REPAIR, EXP_UNARMED, EXP_HERBALISM, EXP_EXCAVATION, EXP_ARCHERY,
EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY, EXP_CROSSBOWS,
EXP_TRIDENTS, EXP_MACES -> ExpectedType.FLOAT;
case UUID_INDEX -> ExpectedType.UUID;
case OVERHAUL_LAST_LOGIN -> ExpectedType.LONG;
default -> throw new IndexOutOfBoundsException();
};
}
public @NotNull List<FlatFileDataContainer> getFlatFileDataContainers() {

View File

@ -87,8 +87,11 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
public static final int COOLDOWN_SUPER_SHOTGUN = 49;
public static final int COOLDOWN_TRIDENTS = 50;
public static final int COOLDOWN_ARCHERY = 51;
public static final int EXP_MACES = 52;
public static final int SKILLS_MACES = 53;
public static final int COOLDOWN_MACES = 54;
//Update this everytime new data is added
public static final int DATA_ENTRY_COUNT = COOLDOWN_ARCHERY + 1;
public static final int DATA_ENTRY_COUNT = COOLDOWN_MACES + 1;
FlatFileDatabaseManager(@NotNull File usersFile, @NotNull Logger logger, long purgeTime, int startingLevel, boolean testing) {
this.usersFile = usersFile;
@ -478,6 +481,18 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
appendable.append(String.valueOf(profile.getSkillLevel(PrimarySkillType.CROSSBOWS))).append(":");
appendable.append(String.valueOf(profile.getSkillXpLevel(PrimarySkillType.TRIDENTS))).append(":");
appendable.append(String.valueOf(profile.getSkillLevel(PrimarySkillType.TRIDENTS))).append(":");
// public static final int COOLDOWN_SUPER_SHOTGUN = 49;
appendable.append(String.valueOf(profile.getAbilityDATS(SuperAbilityType.SUPER_SHOTGUN))).append(":");
// public static final int COOLDOWN_TRIDENTS = 50;
appendable.append(String.valueOf(profile.getAbilityDATS(SuperAbilityType.TRIDENTS_SUPER_ABILITY))).append(":");
// public static final int COOLDOWN_ARCHERY = 51;
appendable.append(String.valueOf(profile.getAbilityDATS(SuperAbilityType.EXPLOSIVE_SHOT))).append(":");
// public static final int EXP_MACES = 52;
appendable.append(String.valueOf(profile.getSkillXpLevel(PrimarySkillType.MACES))).append(":");
// public static final int SKILLS_MACES = 53;
appendable.append(String.valueOf(profile.getSkillLevel(PrimarySkillType.MACES))).append(":");
// public static final int COOLDOWN_MACES = 54;
appendable.append(String.valueOf(profile.getAbilityDATS(SuperAbilityType.MACES_SUPER_ABILITY))).append(":");
appendable.append("\r\n");
}
@ -987,6 +1002,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
List<PlayerStat> alchemy = new ArrayList<>();
List<PlayerStat> crossbows = new ArrayList<>();
List<PlayerStat> tridents = new ArrayList<>();
List<PlayerStat> maces = new ArrayList<>();
BufferedReader in = null;
String playerName = null;
@ -1022,6 +1038,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
powerLevel += putStat(woodcutting, playerName, skills.get(PrimarySkillType.WOODCUTTING));
powerLevel += putStat(crossbows, playerName, skills.get(PrimarySkillType.CROSSBOWS));
powerLevel += putStat(tridents, playerName, skills.get(PrimarySkillType.TRIDENTS));
powerLevel += putStat(maces, playerName, skills.get(PrimarySkillType.MACES));
putStat(powerLevels, playerName, powerLevel);
}
@ -1059,6 +1076,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
alchemy.sort(c);
crossbows.sort(c);
tridents.sort(c);
maces.sort(c);
powerLevels.sort(c);
playerStatHash.put(PrimarySkillType.MINING, mining);
@ -1076,6 +1094,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
playerStatHash.put(PrimarySkillType.ALCHEMY, alchemy);
playerStatHash.put(PrimarySkillType.CROSSBOWS, crossbows);
playerStatHash.put(PrimarySkillType.TRIDENTS, tridents);
playerStatHash.put(PrimarySkillType.MACES, maces);
return LeaderboardStatus.UPDATED;
}
@ -1239,6 +1258,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
tryLoadSkillFloatValuesFromRawData(skillsXp, character, PrimarySkillType.ALCHEMY, EXP_ALCHEMY, username);
tryLoadSkillFloatValuesFromRawData(skillsXp, character, PrimarySkillType.CROSSBOWS, EXP_CROSSBOWS, username);
tryLoadSkillFloatValuesFromRawData(skillsXp, character, PrimarySkillType.TRIDENTS, EXP_TRIDENTS, username);
tryLoadSkillFloatValuesFromRawData(skillsXp, character, PrimarySkillType.MACES, EXP_MACES, username);
// Taming - Unused
tryLoadSkillCooldownFromRawData(skillsDATS, character, SuperAbilityType.SUPER_BREAKER, COOLDOWN_SUPER_BREAKER, username);
@ -1254,6 +1274,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
tryLoadSkillCooldownFromRawData(skillsDATS, character, SuperAbilityType.BLAST_MINING, COOLDOWN_BLAST_MINING, username);
tryLoadSkillCooldownFromRawData(skillsDATS, character, SuperAbilityType.SUPER_SHOTGUN, COOLDOWN_SUPER_SHOTGUN, username);
tryLoadSkillCooldownFromRawData(skillsDATS, character, SuperAbilityType.TRIDENTS_SUPER_ABILITY, COOLDOWN_TRIDENTS, username);
tryLoadSkillCooldownFromRawData(skillsDATS, character, SuperAbilityType.MACES_SUPER_ABILITY, COOLDOWN_MACES, username);
UUID uuid;
try {
@ -1343,6 +1364,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
tryLoadSkillIntValuesFromRawData(skills, character, PrimarySkillType.ALCHEMY, SKILLS_ALCHEMY, username);
tryLoadSkillIntValuesFromRawData(skills, character, PrimarySkillType.CROSSBOWS, SKILLS_CROSSBOWS, username);
tryLoadSkillIntValuesFromRawData(skills, character, PrimarySkillType.TRIDENTS, SKILLS_TRIDENTS, username);
tryLoadSkillIntValuesFromRawData(skills, character, PrimarySkillType.MACES, SKILLS_MACES, username);
return skills;
}

View File

@ -169,7 +169,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "taming = 0 AND mining = 0 AND woodcutting = 0 AND repair = 0 "
+ "AND unarmed = 0 AND herbalism = 0 AND excavation = 0 AND "
+ "archery = 0 AND swords = 0 AND axes = 0 AND acrobatics = 0 "
+ "AND fishing = 0 AND alchemy = 0 AND crossbows = 0 AND tridents = 0;");
+ "AND fishing = 0 AND alchemy = 0 AND crossbows = 0 AND tridents = 0 AND maces = 0;");
statement.executeUpdate("DELETE FROM `" + tablePrefix + "experience` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "skills` `s` WHERE `" + tablePrefix + "experience`.`user_id` = `s`.`user_id`)");
statement.executeUpdate("DELETE FROM `" + tablePrefix + "huds` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "skills` `s` WHERE `" + tablePrefix + "huds`.`user_id` = `s`.`user_id`)");
@ -291,7 +291,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
+ ", unarmed = ?, herbalism = ?, excavation = ?"
+ ", archery = ?, swords = ?, axes = ?, acrobatics = ?"
+ ", fishing = ?, alchemy = ?, crossbows = ?, tridents = ?, total = ? WHERE user_id = ?");
+ ", fishing = ?, alchemy = ?, crossbows = ?, tridents = ?, maces = ?, total = ? WHERE user_id = ?");
statement.setInt(1, profile.getSkillLevel(PrimarySkillType.TAMING));
statement.setInt(2, profile.getSkillLevel(PrimarySkillType.MINING));
statement.setInt(3, profile.getSkillLevel(PrimarySkillType.REPAIR));
@ -307,11 +307,12 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setInt(13, profile.getSkillLevel(PrimarySkillType.ALCHEMY));
statement.setInt(14, profile.getSkillLevel(PrimarySkillType.CROSSBOWS));
statement.setInt(15, profile.getSkillLevel(PrimarySkillType.TRIDENTS));
statement.setInt(16, profile.getSkillLevel(PrimarySkillType.MACES));
int total = 0;
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS)
total += profile.getSkillLevel(primarySkillType);
statement.setInt(16, total);
statement.setInt(17, id);
statement.setInt(17, total);
statement.setInt(18, id);
success &= (statement.executeUpdate() != 0);
statement.close();
if (!success) {
@ -323,7 +324,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
+ ", unarmed = ?, herbalism = ?, excavation = ?"
+ ", archery = ?, swords = ?, axes = ?, acrobatics = ?"
+ ", fishing = ?, alchemy = ?, crossbows = ?, tridents = ? WHERE user_id = ?");
+ ", fishing = ?, alchemy = ?, crossbows = ?, tridents = ?, maces = ? WHERE user_id = ?");
statement.setInt(1, profile.getSkillXpLevel(PrimarySkillType.TAMING));
statement.setInt(2, profile.getSkillXpLevel(PrimarySkillType.MINING));
statement.setInt(3, profile.getSkillXpLevel(PrimarySkillType.REPAIR));
@ -339,7 +340,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setInt(13, profile.getSkillXpLevel(PrimarySkillType.ALCHEMY));
statement.setInt(14, profile.getSkillXpLevel(PrimarySkillType.CROSSBOWS));
statement.setInt(15, profile.getSkillXpLevel(PrimarySkillType.TRIDENTS));
statement.setInt(16, id);
statement.setInt(16, profile.getSkillXpLevel(PrimarySkillType.MACES));
statement.setInt(17, id);
success &= (statement.executeUpdate() != 0);
statement.close();
if (!success) {
@ -350,7 +352,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement = connection.prepareStatement("UPDATE " + tablePrefix + "cooldowns SET "
+ " mining = ?, woodcutting = ?, unarmed = ?"
+ ", herbalism = ?, excavation = ?, swords = ?"
+ ", axes = ?, blast_mining = ?, chimaera_wing = ?, crossbows = ?, tridents = ? WHERE user_id = ?");
+ ", axes = ?, blast_mining = ?, chimaera_wing = ?, crossbows = ?"
+ ", tridents = ?, maces = ? WHERE user_id = ?");
statement.setLong(1, profile.getAbilityDATS(SuperAbilityType.SUPER_BREAKER));
statement.setLong(2, profile.getAbilityDATS(SuperAbilityType.TREE_FELLER));
statement.setLong(3, profile.getAbilityDATS(SuperAbilityType.BERSERK));
@ -362,7 +365,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setLong(9, profile.getUniqueData(UniqueDataType.CHIMAERA_WING_DATS));
statement.setLong(10, profile.getAbilityDATS(SuperAbilityType.SUPER_SHOTGUN));
statement.setLong(11, profile.getAbilityDATS(SuperAbilityType.TRIDENTS_SUPER_ABILITY));
statement.setInt(12, id);
statement.setLong(12, profile.getAbilityDATS(SuperAbilityType.MACES_SUPER_ABILITY));
statement.setInt(13, id);
success = (statement.executeUpdate() != 0);
statement.close();
if (!success) {
@ -648,9 +652,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement = connection.prepareStatement(
"SELECT " +
"s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, s.crossbows, s.tridents, " +
"e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, e.crossbows, e.tridents, " +
"c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, c.chimaera_wing, c.crossbows, c.tridents, " +
"s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, s.crossbows, s.tridents, s.maces, " +
"e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, e.crossbows, e.tridents, e.maces, " +
"c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, c.chimaera_wing, c.crossbows, c.tridents, c.maces, " +
"h.mobhealthbar, h.scoreboardtips, u.uuid, u.`user` "
+ "FROM " + tablePrefix + "users u "
+ "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) "
@ -922,6 +926,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`chimaera_wing` int(32) unsigned NOT NULL DEFAULT '0',"
+ "`crossbows` int(32) unsigned NOT NULL DEFAULT '0',"
+ "`tridents` int(32) unsigned NOT NULL DEFAULT '0',"
+ "`maces` int(32) unsigned NOT NULL DEFAULT '0',"
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=" + CHARSET_SQL + ";");
tryClose(createStatement);
@ -950,6 +955,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`alchemy` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
+ "`crossbows` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
+ "`tridents` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
+ "`maces` int(10) unsigned NOT NULL DEFAULT "+startingLevel+","
+ "`total` int(10) unsigned NOT NULL DEFAULT "+totalLevel+","
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=" + CHARSET_SQL + ";");
@ -1017,20 +1023,24 @@ public final class SQLDatabaseManager implements DatabaseManager {
tryClose(connection);
}
String skills = "skills";
String crossbows = "crossbows";
String tridents = "tridents";
String experience = "experience";
String cooldowns = "cooldowns";
final String skills = "skills";
final String crossbows = "crossbows";
final String tridents = "tridents";
final String maces = "maces";
final String experience = "experience";
final String cooldowns = "cooldowns";
updateStructure(skills, crossbows, String.valueOf(32));
updateStructure(skills, tridents, String.valueOf(32));
updateStructure(skills, maces, String.valueOf(32));
updateStructure(experience, crossbows, String.valueOf(10));
updateStructure(experience, tridents, String.valueOf(10));
updateStructure(experience, maces, String.valueOf(10));
updateStructure(cooldowns, crossbows, String.valueOf(10));
updateStructure(cooldowns, tridents, String.valueOf(10));
updateStructure(cooldowns, maces, String.valueOf(10));
}
private void updateStructure(String tableName, String columnName, String columnSize) {
@ -1213,15 +1223,14 @@ public final class SQLDatabaseManager implements DatabaseManager {
Map<PrimarySkillType, Float> skillsXp = new EnumMap<>(PrimarySkillType.class); // Skill & XP
Map<SuperAbilityType, Integer> skillsDATS = new EnumMap<>(SuperAbilityType.class); // Ability & Cooldown
Map<UniqueDataType, Integer> uniqueData = new EnumMap<>(UniqueDataType.class); //Chimaera wing cooldown and other misc info
MobHealthbarType mobHealthbarType;
UUID uuid;
int scoreboardTipsShown;
final int OFFSET_SKILLS = 0; // TODO update these numbers when the query
// changes (a new skill is added)
final int OFFSET_XP = 15;
final int OFFSET_DATS = 28;
final int OFFSET_OTHER = 41;
final int OFFSET_XP = 16;
final int OFFSET_DATS = 29;
final int OFFSET_OTHER = 42;
skills.put(PrimarySkillType.TAMING, result.getInt(OFFSET_SKILLS + 1));
skills.put(PrimarySkillType.MINING, result.getInt(OFFSET_SKILLS + 2));
@ -1238,6 +1247,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
skills.put(PrimarySkillType.ALCHEMY, result.getInt(OFFSET_SKILLS + 13));
skills.put(PrimarySkillType.CROSSBOWS, result.getInt(OFFSET_SKILLS + 14));
skills.put(PrimarySkillType.TRIDENTS, result.getInt(OFFSET_SKILLS + 15));
skills.put(PrimarySkillType.MACES, result.getInt(OFFSET_SKILLS + 16));
skillsXp.put(PrimarySkillType.TAMING, result.getFloat(OFFSET_XP + 1));
skillsXp.put(PrimarySkillType.MINING, result.getFloat(OFFSET_XP + 2));
@ -1254,6 +1264,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
skillsXp.put(PrimarySkillType.ALCHEMY, result.getFloat(OFFSET_XP + 13));
skillsXp.put(PrimarySkillType.CROSSBOWS, result.getFloat(OFFSET_XP + 14));
skillsXp.put(PrimarySkillType.TRIDENTS, result.getFloat(OFFSET_XP + 15));
skillsXp.put(PrimarySkillType.MACES, result.getFloat(OFFSET_XP + 16));
// Taming - Unused - result.getInt(OFFSET_DATS + 1)
skillsDATS.put(SuperAbilityType.SUPER_BREAKER, result.getInt(OFFSET_DATS + 2));
@ -1270,6 +1281,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
uniqueData.put(UniqueDataType.CHIMAERA_WING_DATS, result.getInt(OFFSET_DATS + 13));
skillsDATS.put(SuperAbilityType.SUPER_SHOTGUN, result.getInt(OFFSET_DATS + 14));
skillsDATS.put(SuperAbilityType.TRIDENTS_SUPER_ABILITY, result.getInt(OFFSET_DATS + 15));
skillsDATS.put(SuperAbilityType.MACES_SUPER_ABILITY, result.getInt(OFFSET_DATS + 16));
try {
scoreboardTipsShown = result.getInt(OFFSET_OTHER + 2);

View File

@ -56,67 +56,29 @@ public class FlatFileDataUtil {
* @return the "zero" initialized data corresponding to the index
*/
public static @NotNull String getZeroInitialisedData(int index, int startingLevel) throws IndexOutOfBoundsException {
switch(index) {
case USERNAME_INDEX:
return LEGACY_INVALID_OLD_USERNAME; //We'll keep using this value for legacy compatibility reasons (not sure if needed but don't care)
case 2: //Assumption: Used to be for something, no longer used
case 3: //Assumption: Used to be for something, no longer used
case 23: //Assumption: Used to be used for something, no longer used
case 33: //Assumption: Used to be used for something, no longer used
case LEGACY_LAST_LOGIN:
case HEALTHBAR:
return "IGNORED";
case SKILLS_MINING:
case SKILLS_REPAIR:
case SKILLS_UNARMED:
case SKILLS_HERBALISM:
case SKILLS_EXCAVATION:
case SKILLS_ARCHERY:
case SKILLS_SWORDS:
case SKILLS_AXES:
case SKILLS_WOODCUTTING:
case SKILLS_ACROBATICS:
case SKILLS_TAMING:
case SKILLS_FISHING:
case SKILLS_ALCHEMY:
case SKILLS_CROSSBOWS:
case SKILLS_TRIDENTS:
return String.valueOf(startingLevel);
case OVERHAUL_LAST_LOGIN:
return String.valueOf(-1L);
case COOLDOWN_BERSERK:
case COOLDOWN_GIGA_DRILL_BREAKER:
case COOLDOWN_TREE_FELLER:
case COOLDOWN_GREEN_TERRA:
case COOLDOWN_SERRATED_STRIKES:
case COOLDOWN_SKULL_SPLITTER:
case COOLDOWN_SUPER_BREAKER:
case COOLDOWN_BLAST_MINING:
case COOLDOWN_SUPER_SHOTGUN:
case COOLDOWN_TRIDENTS:
case COOLDOWN_ARCHERY:
case SCOREBOARD_TIPS:
case COOLDOWN_CHIMAERA_WING:
case EXP_MINING:
case EXP_WOODCUTTING:
case EXP_REPAIR:
case EXP_UNARMED:
case EXP_HERBALISM:
case EXP_EXCAVATION:
case EXP_ARCHERY:
case EXP_SWORDS:
case EXP_AXES:
case EXP_ACROBATICS:
case EXP_TAMING:
case EXP_FISHING:
case EXP_ALCHEMY:
case EXP_CROSSBOWS:
case EXP_TRIDENTS:
return "0";
case UUID_INDEX:
throw new IndexOutOfBoundsException(); //TODO: Add UUID recovery? Might not even be worth it.
}
//TODO: Add UUID recovery? Might not even be worth it.
return switch (index) {
case USERNAME_INDEX ->
LEGACY_INVALID_OLD_USERNAME; //We'll keep using this value for legacy compatibility reasons (not sure if needed but don't care)
//Assumption: Used to be for something, no longer used
//Assumption: Used to be for something, no longer used
//Assumption: Used to be used for something, no longer used
//Assumption: Used to be used for something, no longer used
case 2, 3, 23, 33, LEGACY_LAST_LOGIN, HEALTHBAR -> "IGNORED";
case SKILLS_MINING, SKILLS_REPAIR, SKILLS_UNARMED, SKILLS_HERBALISM, SKILLS_EXCAVATION, SKILLS_ARCHERY,
SKILLS_SWORDS, SKILLS_AXES, SKILLS_WOODCUTTING, SKILLS_ACROBATICS, SKILLS_TAMING, SKILLS_FISHING,
SKILLS_ALCHEMY, SKILLS_CROSSBOWS, SKILLS_TRIDENTS, SKILLS_MACES -> String.valueOf(startingLevel);
case OVERHAUL_LAST_LOGIN -> String.valueOf(-1L);
case COOLDOWN_BERSERK, COOLDOWN_GIGA_DRILL_BREAKER, COOLDOWN_TREE_FELLER, COOLDOWN_GREEN_TERRA,
COOLDOWN_SERRATED_STRIKES, COOLDOWN_SKULL_SPLITTER, COOLDOWN_SUPER_BREAKER, COOLDOWN_BLAST_MINING,
COOLDOWN_SUPER_SHOTGUN, COOLDOWN_TRIDENTS, COOLDOWN_ARCHERY, COOLDOWN_MACES, SCOREBOARD_TIPS, COOLDOWN_CHIMAERA_WING,
EXP_MINING, EXP_WOODCUTTING, EXP_REPAIR, EXP_UNARMED, EXP_HERBALISM, EXP_EXCAVATION, EXP_ARCHERY,
EXP_SWORDS, EXP_AXES, EXP_ACROBATICS, EXP_TAMING, EXP_FISHING, EXP_ALCHEMY, EXP_CROSSBOWS,
EXP_TRIDENTS, EXP_MACES -> "0";
case UUID_INDEX ->
throw new IndexOutOfBoundsException(); //TODO: Add UUID recovery? Might not even be worth it.
default -> throw new IndexOutOfBoundsException();
};
throw new IndexOutOfBoundsException();
}
}

View File

@ -32,6 +32,7 @@ import com.gmail.nossr50.skills.crossbows.CrossbowsManager;
import com.gmail.nossr50.skills.excavation.ExcavationManager;
import com.gmail.nossr50.skills.fishing.FishingManager;
import com.gmail.nossr50.skills.herbalism.HerbalismManager;
import com.gmail.nossr50.skills.maces.MacesManager;
import com.gmail.nossr50.skills.mining.MiningManager;
import com.gmail.nossr50.skills.repair.RepairManager;
import com.gmail.nossr50.skills.salvage.SalvageManager;
@ -220,6 +221,9 @@ public class McMMOPlayer implements Identified {
case WOODCUTTING:
skillManagers.put(primarySkillType, new WoodcuttingManager(this));
break;
case MACES:
skillManagers.put(primarySkillType, new MacesManager(this));
break;
default:
throw new InvalidSkillException("The skill named has no manager! Contact the devs!");
}
@ -313,6 +317,10 @@ public class McMMOPlayer implements Identified {
return (TridentsManager) skillManagers.get(PrimarySkillType.TRIDENTS);
}
public MacesManager getMacesManager() {
return (MacesManager) skillManagers.get(PrimarySkillType.MACES);
}
public ExcavationManager getExcavationManager() {
return (ExcavationManager) skillManagers.get(PrimarySkillType.EXCAVATION);
}

View File

@ -20,6 +20,7 @@ public enum PrimarySkillType {
EXCAVATION,
FISHING,
HERBALISM,
MACES,
MINING,
REPAIR,
SALVAGE,

View File

@ -57,6 +57,9 @@ public enum SubSkillType {
HERBALISM_HYLIAN_LUCK,
HERBALISM_SHROOM_THUMB,
/* Maces */
MACES_MACES_LIMIT_BREAK(10),
/* Mining */
MINING_BIGGER_BOMBS(1),
MINING_BLAST_MINING(8),

View File

@ -72,19 +72,26 @@ public enum SuperAbilityType {
"Swords.Skills.SS.Other.Off",
"Swords.SubSkill.SerratedStrikes.Name"),
SUPER_SHOTGUN(
null,
null,
"Crossbows.Skills.SSG.Other.On",
"Crossbows.Skills.SSG.Refresh",
null,
"Crossbows.SubSkill.SuperShotgun.Name"),
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder"),
TRIDENTS_SUPER_ABILITY(
"Tridents.Skills.TA.On",
"Tridents.Skills.TA.Off",
"Tridents.Skills.TA.Other.On",
"Tridents.Skills.TA.Refresh",
"Tridents.Skills.TA.Other.Off",
"Tridents.SubSkill.TridentAbility.Name"),
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder"),
MACES_SUPER_ABILITY(
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder",
"Placeholder"),
/**
* Has cooldown - but has to share a skill with Super Breaker, so needs special treatment
@ -209,6 +216,7 @@ public enum SuperAbilityType {
case SUPER_SHOTGUN -> Permissions.superShotgun(player);
case TREE_FELLER -> Permissions.treeFeller(player);
case TRIDENTS_SUPER_ABILITY -> Permissions.tridentsSuper(player);
case MACES_SUPER_ABILITY -> Permissions.macesSuper(player);
};
}

View File

@ -13,7 +13,8 @@ public enum ToolType {
SWORD("Swords.Ability.Lower", "Swords.Ability.Ready"),
CROSSBOW("Crossbows.Ability.Lower", "Crossbows.Ability.Ready"),
BOW("Archery.Ability.Lower", "Archery.Ability.Ready"),
TRIDENTS("Tridents.Ability.Lower", "Tridents.Ability.Ready");
TRIDENTS("Tridents.Ability.Lower", "Tridents.Ability.Ready"),
MACES("Maces.Ability.Lower", "Maces.Ability.Ready");
private final String lowerTool;
private final String raiseTool;
@ -45,6 +46,8 @@ public enum ToolType {
return ItemUtils.isCrossbow(itemStack);
case TRIDENTS:
return ItemUtils.isTrident(itemStack);
case MACES:
return ItemUtils.isMace(itemStack);
case FISTS:
return itemStack.getType() == Material.AIR;

View File

@ -1,167 +1,120 @@
package com.gmail.nossr50.datatypes.skills.alchemy;
import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
import org.bukkit.Color;
import com.gmail.nossr50.mcMMO;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import static com.gmail.nossr50.util.PotionUtil.samePotionType;
import static java.util.Objects.requireNonNull;
public class AlchemyPotion {
private final Material material;
private PotionData data;
private String name;
private List<String> lore;
private List<PotionEffect> effects;
private Color color;
private Map<ItemStack, String> children;
private final ItemStack potion;
private final Map<ItemStack, String> alchemyPotionChildren;
public AlchemyPotion(Material material, PotionData data, String name, List<String> lore, List<PotionEffect> effects, Color color, Map<ItemStack, String> children) {
this.material = material;
this.data = data;
this.lore = lore;
this.name = name;
this.effects = effects;
this.children = children;
this.color = color;
public AlchemyPotion(ItemStack potion, Map<ItemStack, String> alchemyPotionChildren) {
this.potion = requireNonNull(potion, "potion cannot be null");
this.alchemyPotionChildren = requireNonNull(alchemyPotionChildren, "alchemyPotionChildren cannot be null");
}
public String toString() {
return "AlchemyPotion{" + data + ", " + name + ", Effects[" + effects.size() + "], Children[" + children.size() + "]}";
}
public ItemStack toItemStack(int amount) {
ItemStack potion = new ItemStack(material, amount);
PotionMeta meta = (PotionMeta) potion.getItemMeta();
meta.setBasePotionData(data);
if (this.getName() != null) {
meta.setDisplayName(this.getName());
}
if (this.getLore() != null && !this.getLore().isEmpty()) {
meta.setLore(this.getLore());
}
if (!this.getEffects().isEmpty()) {
for (PotionEffect effect : this.getEffects()) {
meta.addCustomEffect(effect, true);
}
}
if (this.getColor() != null) {
meta.setColor(this.getColor());
}
potion.setItemMeta(meta);
public @NotNull ItemStack toItemStack(int amount) {
final ItemStack potion = new ItemStack(this.potion);
potion.setAmount(Math.max(1, amount));
return potion;
}
public Material getMaterial() {
return material;
public Map<ItemStack, String> getAlchemyPotionChildren() {
return alchemyPotionChildren;
}
public Potion toPotion(int amount) {
return Potion.fromItemStack(this.toItemStack(amount));
}
public PotionData getData() {
return data;
}
public void setData(PotionData data) {
this.data = data;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getLore() {
return lore;
}
public void setLore(List<String> lore) {
this.lore = lore;
}
public List<PotionEffect> getEffects() {
return effects;
}
public void setEffects(List<PotionEffect> effects) {
this.effects = effects;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public Map<ItemStack, String> getChildren() {
return children;
}
public void setChildren(Map<ItemStack, String> children) {
this.children = children;
}
public AlchemyPotion getChild(ItemStack ingredient) {
if (!children.isEmpty()) {
for (Entry<ItemStack, String> child : children.entrySet()) {
public @Nullable AlchemyPotion getChild(@NotNull ItemStack ingredient) {
if (!alchemyPotionChildren.isEmpty()) {
for (Entry<ItemStack, String> child : alchemyPotionChildren.entrySet()) {
if (ingredient.isSimilar(child.getKey())) {
return PotionConfig.getInstance().getPotion(child.getValue());
return mcMMO.p.getPotionConfig().getPotion(child.getValue());
}
}
}
return null;
}
public boolean isSimilar(ItemStack item) {
if (item.getType() != material) {
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() != potion.getType() || !otherPotion.hasItemMeta()) {
return false;
}
if (!item.hasItemMeta()) {
return false;
}
PotionMeta meta = (PotionMeta) item.getItemMeta();
PotionData that = meta.getBasePotionData();
if (data.getType() != that.getType()) {
return false;
}
if (data.isExtended() != that.isExtended()) {
return false;
}
if (data.isUpgraded() != that.isUpgraded()) {
return false;
}
for (PotionEffect effect : effects) {
if (!meta.hasCustomEffect(effect.getType())) {
final PotionMeta otherPotionMeta = (PotionMeta) otherPotion.getItemMeta();
// all custom effects must be present
for (var effect : getAlchemyPotionMeta().getCustomEffects()) {
if (!otherPotionMeta.hasCustomEffect(effect.getType())) {
return false;
}
}
if (!meta.hasLore() && !lore.isEmpty()) {
if (!samePotionType(getAlchemyPotionMeta(), otherPotionMeta)) {
return false;
}
if (!(lore.isEmpty() && !meta.hasLore()) && !meta.getLore().equals(lore)) {
if (!otherPotionMeta.hasLore() && getAlchemyPotionMeta().hasLore()
|| !getAlchemyPotionMeta().hasLore() && otherPotionMeta.hasLore()) {
return false;
}
if (!meta.hasDisplayName() && name != null) {
if (otherPotionMeta.hasLore() && getAlchemyPotionMeta().hasLore()
&& !otherPotionMeta.getLore().equals(getAlchemyPotionMeta().getLore())) {
return false;
}
return (name == null && !meta.hasDisplayName()) || meta.getDisplayName().equals(name);
if (!otherPotionMeta.hasDisplayName() && getAlchemyPotionMeta().hasDisplayName()) {
return false;
}
var alchemyPotionName = getAlchemyPotionMeta().hasDisplayName() ? getAlchemyPotionMeta().getDisplayName() : null;
return (alchemyPotionName == null && !otherPotionMeta.hasDisplayName()) || otherPotionMeta.getDisplayName().equals(alchemyPotionName);
}
public PotionMeta getAlchemyPotionMeta() {
return (PotionMeta) potion.getItemMeta();
}
public boolean isSplash() {
return potion.getType() == Material.SPLASH_POTION;
}
public boolean isLingering() {
return potion.getType() == Material.LINGERING_POTION;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AlchemyPotion that = (AlchemyPotion) o;
return Objects.equals(potion, that.potion) && Objects.equals(alchemyPotionChildren, that.alchemyPotionChildren);
}
@Override
public int hashCode() {
return Objects.hash(potion, alchemyPotionChildren);
}
@Override
public String toString() {
return "AlchemyPotion{" +
"potion=" + potion +
", alchemyPotionChildren=" + alchemyPotionChildren +
'}';
}
}

View File

@ -1,11 +1,10 @@
package com.gmail.nossr50.datatypes.skills.alchemy;
import org.bukkit.Material;
import org.bukkit.potion.PotionData;
import com.gmail.nossr50.util.PotionUtil;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionType;
import java.util.List;
import static com.gmail.nossr50.util.PotionUtil.*;
public enum PotionStage {
FIVE(5),
@ -43,27 +42,27 @@ public enum PotionStage {
return potionStage;
}
private static boolean isWaterBottle(AlchemyPotion input) {
return input.getData().getType() == PotionType.WATER;
private static boolean isWaterBottle(AlchemyPotion alchemyPotion) {
return isPotionTypeWater(alchemyPotion.getAlchemyPotionMeta());
}
public static PotionStage getPotionStage(AlchemyPotion alchemyPotion) {
PotionData data = alchemyPotion.getData();
List<PotionEffect> effects = alchemyPotion.getEffects();
final PotionMeta potionMeta = alchemyPotion.getAlchemyPotionMeta();
int stage = 1;
// Check if potion has an effect of any sort
if (data.getType().getEffectType() != null || !effects.isEmpty()) {
if (!potionMeta.getCustomEffects().isEmpty()
|| PotionUtil.hasBasePotionEffects(potionMeta)) {
stage++;
}
// Check if potion has a glowstone dust amplifier
// Else check if the potion has a custom effect with an amplifier added by mcMMO
if (data.isUpgraded()) {
if (isStrong(potionMeta)) {
stage++;
} else if(!effects.isEmpty()) {
for (PotionEffect effect : effects){
} else if (!potionMeta.getCustomEffects().isEmpty()) {
for (PotionEffect effect : potionMeta.getCustomEffects()){
if(effect.getAmplifier() > 0){
stage++;
break;
@ -72,12 +71,12 @@ public enum PotionStage {
}
// Check if potion has a redstone dust amplifier
if (data.isExtended()) {
if (isLong(potionMeta)) {
stage++;
}
// Check if potion has a gunpowder amplifier
if (alchemyPotion.getMaterial() == Material.SPLASH_POTION || alchemyPotion.getMaterial() == Material.LINGERING_POTION) {
if (alchemyPotion.isSplash() || alchemyPotion.isLingering()) {
stage++;
}

View File

@ -26,7 +26,6 @@ import net.kyori.adventure.text.TextComponent;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.SoundCategory;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventPriority;
@ -317,7 +316,7 @@ public class Roll extends AcrobaticsSubSkill {
ItemStack boots = player.getInventory().getBoots();
float xp = (float) (damage * (isRoll ? ExperienceConfig.getInstance().getRollXPModifier() : ExperienceConfig.getInstance().getFallXPModifier()));
if (boots != null && boots.containsEnchantment(Enchantment.PROTECTION_FALL)) {
if (boots != null && boots.containsEnchantment(mcMMO.p.getEnchantmentMapper().getFeatherFalling())) {
xp *= ExperienceConfig.getInstance().getFeatherFallXPModifier();
}

View File

@ -120,7 +120,7 @@ public class EntityListener implements Listener {
if (bow == null)
return;
if (bow.containsEnchantment(Enchantment.ARROW_INFINITE)) {
if (bow.containsEnchantment(mcMMO.p.getEnchantmentMapper().getInfinity())) {
projectile.setMetadata(MetadataConstants.METADATA_KEY_INF_ARROW, MetadataConstants.MCMMO_METADATA_VALUE);
}

View File

@ -78,8 +78,6 @@ import java.util.ArrayList;
import java.util.List;
public class mcMMO extends JavaPlugin {
/* Managers & Services */
private static PlatformManager platformManager;
private static MetadataService metadataService;
@ -140,21 +138,14 @@ public class mcMMO extends JavaPlugin {
private GeneralConfig generalConfig;
private AdvancedConfig advancedConfig;
private PartyConfig partyConfig;
private PotionConfig potionConfig;
private CustomItemSupportConfig customItemSupportConfig;
private EnchantmentMapper enchantmentMapper;
private AttributeMapper attributeMapper;
private FoliaLib foliaLib;
private PartyManager partyManager;
// private RepairConfig repairConfig;
// private SalvageConfig salvageConfig;
// private PersistentDataConfig persistentDataConfig;
// private ChatConfig chatConfig;
// private CoreSkillsConfig coreSkillsConfig;
// private RankConfig rankConfig;
// private TreasureConfig treasureConfig;
// private FishingTreasureConfig fishingTreasureConfig;
// private SoundConfig soundConfig;
public mcMMO() {
p = this;
}
@ -207,8 +198,11 @@ public class mcMMO extends JavaPlugin {
modManager = new ModManager();
//Init Material Maps
// Init Material Maps
materialMapStore = new MaterialMapStore();
// Init compatibility mappers
enchantmentMapper = new EnchantmentMapper(this);
attributeMapper = new AttributeMapper(this);
loadConfigFiles();
@ -567,7 +561,11 @@ public class mcMMO extends JavaPlugin {
FishingTreasureConfig.getInstance();
HiddenConfig.getInstance();
mcMMO.p.getAdvancedConfig();
PotionConfig.getInstance();
// init potion config
potionConfig = new PotionConfig();
potionConfig.loadPotions();
CoreSkillsConfig.getInstance();
SoundConfig.getInstance();
RankConfig.getInstance();
@ -812,6 +810,18 @@ public class mcMMO extends JavaPlugin {
return customItemSupportConfig;
}
public PotionConfig getPotionConfig() {
return potionConfig;
}
public EnchantmentMapper getEnchantmentMapper() {
return enchantmentMapper;
}
public AttributeMapper getAttributeMapper() {
return attributeMapper;
}
public @NotNull FoliaLib getFoliaLib() {
return foliaLib;
}

View File

@ -1,7 +1,6 @@
package com.gmail.nossr50.metadata;
import com.gmail.nossr50.mcMMO;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
@ -74,12 +73,12 @@ public class ItemMetadataService {
if(itemMeta != null) {
//TODO: can be optimized
if (itemMeta.hasEnchant(Enchantment.DIG_SPEED)) {
itemMeta.removeEnchant(Enchantment.DIG_SPEED);
if (itemMeta.hasEnchant(mcMMO.p.getEnchantmentMapper().getEfficiency())) {
itemMeta.removeEnchant(mcMMO.p.getEnchantmentMapper().getEfficiency());
}
if (originalSpeed > 0) {
itemMeta.addEnchant(Enchantment.DIG_SPEED, originalSpeed, true);
itemMeta.addEnchant(mcMMO.p.getEnchantmentMapper().getEfficiency(), originalSpeed, true);
}
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();

View File

@ -1,13 +1,13 @@
package com.gmail.nossr50.skills.alchemy;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
import com.gmail.nossr50.datatypes.experience.XPGainReason;
import com.gmail.nossr50.datatypes.experience.XPGainSource;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.alchemy.PotionStage;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.text.StringUtils;
@ -27,7 +27,7 @@ public class AlchemyManager extends SkillManager {
}
public List<ItemStack> getIngredients() {
return PotionConfig.getInstance().getIngredients(getTier());
return mcMMO.p.getPotionConfig().getIngredients(getTier());
}
public String getIngredientList() {

View File

@ -1,6 +1,5 @@
package com.gmail.nossr50.skills.alchemy;
import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.alchemy.AlchemyPotion;
import com.gmail.nossr50.datatypes.skills.alchemy.PotionStage;
@ -36,7 +35,7 @@ public final class AlchemyPotionBrewer {
continue;
}
if (getChildPotion(PotionConfig.getInstance().getPotion(contents[i]), contents[Alchemy.INGREDIENT_SLOT]) != null) {
if (getChildPotion(mcMMO.p.getPotionConfig().getPotion(contents[i]), contents[Alchemy.INGREDIENT_SLOT]) != null) {
return true;
}
}
@ -94,12 +93,11 @@ public final class AlchemyPotionBrewer {
}
private static List<ItemStack> getValidIngredients(Player player) {
if(player == null || UserManager.getPlayer(player) == null)
{
return PotionConfig.getInstance().getIngredients(1);
if(player == null || UserManager.getPlayer(player) == null) {
return mcMMO.p.getPotionConfig().getIngredients(1);
}
return PotionConfig.getInstance().getIngredients(!Permissions.isSubSkillEnabled(player, SubSkillType.ALCHEMY_CONCOCTIONS) ? 1 : UserManager.getPlayer(player).getAlchemyManager().getTier());
return mcMMO.p.getPotionConfig().getIngredients(!Permissions.isSubSkillEnabled(player, SubSkillType.ALCHEMY_CONCOCTIONS) ? 1 : UserManager.getPlayer(player).getAlchemyManager().getTier());
}
public static void finishBrewing(BlockState brewingStand, Player player, boolean forced) {
@ -120,11 +118,11 @@ public final class AlchemyPotionBrewer {
for (int i = 0; i < 3; i++) {
ItemStack item = inventory.getItem(i);
if (isEmpty(item) || item.getType() == Material.GLASS_BOTTLE || !PotionConfig.getInstance().isValidPotion(item)) {
if (isEmpty(item) || item.getType() == Material.GLASS_BOTTLE || !mcMMO.p.getPotionConfig().isValidPotion(item)) {
continue;
}
AlchemyPotion input = PotionConfig.getInstance().getPotion(item);
AlchemyPotion input = mcMMO.p.getPotionConfig().getPotion(item);
AlchemyPotion output = input.getChild(ingredient);
inputList.set(i, input);

View File

@ -18,7 +18,8 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import static com.gmail.nossr50.util.PotionEffectMapper.getNausea;
public class ArcheryManager extends SkillManager {
public ArcheryManager(McMMOPlayer mcMMOPlayer) {
@ -95,10 +96,8 @@ public class ArcheryManager extends SkillManager {
Location dazedLocation = defender.getLocation();
dazedLocation.setPitch(90 - Misc.getRandom().nextInt(181));
// defender.teleport(dazedLocation);
mcMMO.p.getFoliaLib().getImpl().teleportAsync(defender, dazedLocation);
defender.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, 20 * 10, 10));
defender.addPotionEffect(new PotionEffect(getNausea(), 20 * 10, 10));
if (NotificationManager.doesPlayerUseNotifications(defender)) {
NotificationManager.sendPlayerInformation(defender, NotificationType.SUBSKILL_MESSAGE, "Combat.TouchedFuzzy");

View File

@ -573,11 +573,13 @@ public class FishingManager extends SkillManager {
int luck;
if (getPlayer().getInventory().getItemInMainHand().getType() == Material.FISHING_ROD) {
luck = getPlayer().getInventory().getItemInMainHand().getEnchantmentLevel(Enchantment.LUCK);
luck = getPlayer().getInventory().getItemInMainHand().getEnchantmentLevel(
mcMMO.p.getEnchantmentMapper().getLuckOfTheSea());
}
else {
// We know something was caught, so if the rod wasn't in the main hand it must be in the offhand
luck = getPlayer().getInventory().getItemInOffHand().getEnchantmentLevel(Enchantment.LUCK);
luck = getPlayer().getInventory().getItemInOffHand().getEnchantmentLevel(
mcMMO.p.getEnchantmentMapper().getLuckOfTheSea());
}
// Rather than subtracting luck (and causing a minimum 3% chance for every drop), scale by luck.

View File

@ -0,0 +1,21 @@
package com.gmail.nossr50.skills.maces;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.Permissions;
public class MacesManager extends SkillManager {
public MacesManager(McMMOPlayer mmoPlayer) {
super(mmoPlayer, PrimarySkillType.MACES);
}
/**
* Checks if the player can activate the Super Ability for Maces
* @return true if the player can activate the Super Ability, false otherwise
*/
public boolean canActivateAbility() {
return mmoPlayer.getToolPreparationMode(ToolType.MACES) && Permissions.macesSuper(getPlayer());
}
}

View File

@ -233,7 +233,7 @@ public class TamingManager extends SkillManager {
// Bred mules & donkeys can actually have horse-like stats, but llamas cannot.
if (beast instanceof AbstractHorse horseLikeCreature && !(beast instanceof Llama)) {
AttributeInstance jumpAttribute = horseLikeCreature.getAttribute(Attribute.HORSE_JUMP_STRENGTH);
AttributeInstance jumpAttribute = horseLikeCreature.getAttribute(mcMMO.p.getAttributeMapper().getHorseJumpStrength());
if(jumpAttribute != null) {
double jumpStrength = jumpAttribute.getValue();

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));
}