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

@ -1,6 +1,13 @@
Version 2.2.007
Compatibility with the 1.20.5 MC Update
Alchemy now has more warning/errors that will print out to help debug
Fixed bug where Green Thumb did not replant if seed was in the off hand
NOTES:
I did my best to keep mcMMO compatible with older versions of Minecraft for this update.
This update to MC was quite large, with breaking changes to a lot of code relating to Alchemy, and some other things.
I expect there to be bugs, please report them on GitHub or Discord, but preferably GitHub.
I will be working on fixing these bugs as they come in, so please be patient.
Version 2.2.006
Added new config custom_item_support.yml
Added support for hex color codes in the locale file, uses the format &#RRGGBB (see notes)

33
pom.xml
View File

@ -254,8 +254,11 @@
<id>devmart-other</id>
<url>https://nexuslite.gcnt.net/repos/other/</url>
</repository>
<!-- ... -->
<!-- ... -->
<!-- MockBukkit -->
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
@ -361,7 +364,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.4-R0.1-SNAPSHOT</version>
<version>1.20.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@ -435,5 +438,29 @@
<version>0.3.1</version>
<scope>compile</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-core</artifactId>-->
<!-- <version>2.22.1</version> &lt;!&ndash; Make sure this version matches the other log4j dependencies &ndash;&gt;-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-api</artifactId>-->
<!-- <version>2.22.1</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.logging.log4j</groupId>-->
<!-- <artifactId>log4j-slf4j-impl</artifactId>-->
<!-- <version>2.22.1</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.github.seeseemelk</groupId>-->
<!-- <artifactId>MockBukkit-v1.19</artifactId>-->
<!-- <version>LATEST</version>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
</dependencies>
</project>

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:
//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;
}
@ -209,6 +200,9 @@ public class mcMMO extends JavaPlugin {
// 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));
}

View File

@ -1,13 +1,3 @@
#
# Experience configuration
# Last updated on ${project.version}-b${BUILD_NUMBER}
#
# Configure the experience formula and experience settings here.
#
#####
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarColor.html
# These are the only valid colors for Experience Bars, use the exact name found here
# BLUE, GREEN, PINK, PURPLE, RED, WHITE, YELLOW (As of the time of this update these are the only Bar colors available, this could change in the future so check the BarColor enum to see if it has)
@ -48,7 +38,7 @@ Fishing_ExploitFix_Options:
MoveRange: 3
OverFishLimit: 10
Experience_Bars:
# Turn this to false if you wanna disable XP bars
# Turn this to false if you want to disable XP bars
Enable: true
Update:
# XP that you gained from your party but not yourself
@ -98,6 +88,10 @@ Experience_Bars:
Enable: true
Color: YELLOW
BarStyle: SEGMENTED_6
Maces:
Enable: true
Color: BLUE
BarStyle: SEGMENTED_6
Repair:
Enable: true
Color: PURPLE
@ -170,6 +164,7 @@ Experience_Formula:
# Experience gained will get multiplied by these values. 1.0 by default, 0.5 means half XP gained. This happens right before multiplying the XP by the global multiplier.
Skill_Multiplier:
Maces: 1.0
Crossbows: 1.0
Tridents: 1.0
Swords: 1.0
@ -217,6 +212,9 @@ Diminished_Returns:
Repair: 20000
Fishing: 20000
Alchemy: 20000
Crossbows: 20000
Tridents: 20000
Maces: 20000
Time_Interval: 10

View File

@ -1,3 +1,4 @@
Placeholder= This value is for any WIP locale entries that will not be displayed to users
JSON.Rank=Rank
JSON.DescriptionHeader=Description:
JSON.JWrapper.Header=Details
@ -26,6 +27,7 @@ JSON.Salvage=Salvage
JSON.Swords=Swords
JSON.Taming=Taming
JSON.Tridents=Tridents
JSON.Maces=Maces
JSON.Unarmed=Unarmed
JSON.Woodcutting=Woodcutting
JSON.URL.Website=The official mcMMO Website!
@ -96,6 +98,7 @@ Overhaul.Name.Smelting=Smelting
Overhaul.Name.Swords=Swords
Overhaul.Name.Taming=Taming
Overhaul.Name.Tridents=Tridents
Overhaul.Name.Maces=Maces
Overhaul.Name.Unarmed=Unarmed
Overhaul.Name.Woodcutting=Woodcutting
# /mcMMO Command Style Stuff
@ -122,6 +125,7 @@ XPBar.Smelting=Smelting Lv.&6{0}
XPBar.Swords=Swords Lv.&6{0}
XPBar.Taming=Taming Lv.&6{0}
XPBar.Tridents=Tridents Lv.&6{0}
XPBar.Maces=Maces Lv.&6{0}
XPBar.Unarmed=Unarmed Lv.&6{0}
XPBar.Woodcutting=Woodcutting Lv.&6{0}
#This is just a preset template that gets used if the 'ExtraDetails' setting is turned on in experience.yml (off by default), you can ignore this template and just edit the strings above
@ -457,9 +461,6 @@ Tridents.Listener=Tridents:
Maces.SkillName=MACES
Maces.Ability.Lower=&7You lower your mace.
Maces.Ability.Ready=&3You &6ready&3 your Mace.
Maces.Skills.MaceSmash.Refresh=&aYour &eGiga Smash &aability is refreshed!
Maces.Skills.MaceSmash.Other.On=&a{0}&2 used &cGiga Smash!
Maces.SubSkill.GigaSmash.Name=Giga Smash
Maces.SubSkill.MacesLimitBreak.Name=Maces Limit Break
Maces.SubSkill.MacesLimitBreak.Description=Breaking your limits. Increased damage against tough opponents. Intended for PVP, up to server settings for whether it will boost damage in PVE.
Maces.SubSkill.MacesLimitBreak.Stat=Limit Break Max DMG

View File

@ -154,6 +154,9 @@ commands:
salvage:
description: Detailed mcMMO skill info
permission: mcmmo.commands.salvage
maces:
description: Detailed mcMMO skill info
permission: mcmmo.commands.maces
mmopower:
description: Shows skill mastery and power level info
permission: mcmmo.commands.mmopower

View File

@ -443,6 +443,30 @@ Salvage:
Rank_6: 750
Rank_7: 850
Rank_8: 1000
Maces:
TridentsLimitBreak:
Standard:
Rank_1: 10
Rank_2: 20
Rank_3: 30
Rank_4: 40
Rank_5: 50
Rank_6: 60
Rank_7: 70
Rank_8: 80
Rank_9: 90
Rank_10: 100
RetroMode:
Rank_1: 100
Rank_2: 200
Rank_3: 300
Rank_4: 400
Rank_5: 500
Rank_6: 600
Rank_7: 700
Rank_8: 800
Rank_9: 900
Rank_10: 1000
Mining:
MotherLode:
Standard:

View File

@ -16,13 +16,12 @@ import com.gmail.nossr50.util.blockmeta.ChunkManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillTools;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.PluginManager;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
@ -31,9 +30,10 @@ import java.util.UUID;
import java.util.logging.Logger;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
public abstract class MMOTestEnvironment {
protected MockedStatic<Bukkit> mockedBukkit;
protected MockedStatic<mcMMO> mockedMcMMO;
protected MockedStatic<ChatConfig> mockedChatConfig;
protected MockedStatic<ExperienceConfig> experienceConfig;
@ -63,26 +63,27 @@ public abstract class MMOTestEnvironment {
protected PlayerProfile playerProfile;
protected McMMOPlayer mmoPlayer;
protected String playerName = "testPlayer";
protected ItemFactory itemFactory;
protected ChunkManager chunkManager;
protected MaterialMapStore materialMapStore;
protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException {
mockedMcMMO = Mockito.mockStatic(mcMMO.class);
mcMMO.p = Mockito.mock(mcMMO.class);
mockedMcMMO = mockStatic(mcMMO.class);
mcMMO.p = mock(mcMMO.class);
when(mcMMO.p.getLogger()).thenReturn(logger);
// place store
chunkManager = Mockito.mock(ChunkManager.class);
chunkManager = mock(ChunkManager.class);
when(mcMMO.getPlaceStore()).thenReturn(chunkManager);
// shut off mod manager for woodcutting
when(mcMMO.getModManager()).thenReturn(Mockito.mock(ModManager.class));
when(mcMMO.getModManager()).thenReturn(mock(ModManager.class));
when(mcMMO.getModManager().isCustomLog(any())).thenReturn(false);
// chat config
mockedChatConfig = Mockito.mockStatic(ChatConfig.class);
when(ChatConfig.getInstance()).thenReturn(Mockito.mock(ChatConfig.class));
mockedChatConfig = mockStatic(ChatConfig.class);
when(ChatConfig.getInstance()).thenReturn(mock(ChatConfig.class));
// general config
mockGeneralConfig();
@ -108,29 +109,34 @@ public abstract class MMOTestEnvironment {
mockPermissions();
mockedRankUtils = Mockito.mockStatic(RankUtils.class);
mockedRankUtils = mockStatic(RankUtils.class);
// wire server
this.server = Mockito.mock(Server.class);
this.server = mock(Server.class);
when(mcMMO.p.getServer()).thenReturn(server);
mockedBukkit = mockStatic(Bukkit.class);
when(Bukkit.getItemFactory()).thenReturn(itemFactory);
itemFactory = mock(ItemFactory.class);
// when(itemFactory.getItemMeta(any())).thenReturn(mock(ItemMeta.class));
// wire plugin manager
this.pluginManager = Mockito.mock(PluginManager.class);
this.pluginManager = mock(PluginManager.class);
when(server.getPluginManager()).thenReturn(pluginManager);
// wire world
this.world = Mockito.mock(World.class);
this.world = mock(World.class);
// wire Misc
this.mockedMisc = Mockito.mockStatic(Misc.class);
this.mockedMisc = mockStatic(Misc.class);
when(Misc.getBlockCenter(any())).thenReturn(new Location(world, 0, 0, 0));
// setup player and player related mocks after everything else
this.player = Mockito.mock(Player.class);
this.player = mock(Player.class);
when(player.getUniqueId()).thenReturn(playerUUID);
// wire inventory
this.playerInventory = Mockito.mock(PlayerInventory.class);
this.playerInventory = mock(PlayerInventory.class);
when(player.getInventory()).thenReturn(playerInventory);
// PlayerProfile and McMMOPlayer are partially mocked
@ -138,7 +144,7 @@ public abstract class MMOTestEnvironment {
mmoPlayer = Mockito.spy(new McMMOPlayer(player, playerProfile));
// wire user manager
this.mockedUserManager = Mockito.mockStatic(UserManager.class);
this.mockedUserManager = mockStatic(UserManager.class);
when(UserManager.getPlayer(player)).thenReturn(mmoPlayer);
this.materialMapStore = new MaterialMapStore();
@ -146,7 +152,7 @@ public abstract class MMOTestEnvironment {
}
private void mockPermissions() {
mockedPermissions = Mockito.mockStatic(Permissions.class);
mockedPermissions = mockStatic(Permissions.class);
when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(true);
when(Permissions.canUseSubSkill(any(Player.class), any(SubSkillType.class))).thenReturn(true);
when(Permissions.isSubSkillEnabled(any(Player.class), any(SubSkillType.class))).thenReturn(true);
@ -155,16 +161,16 @@ public abstract class MMOTestEnvironment {
}
private void mockRankConfig() {
rankConfig = Mockito.mock(RankConfig.class);
rankConfig = mock(RankConfig.class);
}
private void mockAdvancedConfig() {
this.advancedConfig = Mockito.mock(AdvancedConfig.class);
this.advancedConfig = mock(AdvancedConfig.class);
when(mcMMO.p.getAdvancedConfig()).thenReturn(advancedConfig);
}
private void mockGeneralConfig() {
generalConfig = Mockito.mock(GeneralConfig.class);
generalConfig = mock(GeneralConfig.class);
when(generalConfig.getTreeFellerThreshold()).thenReturn(100);
when(generalConfig.getDoubleDropsEnabled(PrimarySkillType.WOODCUTTING, Material.OAK_LOG)).thenReturn(true);
when(generalConfig.getLocale()).thenReturn("en_US");
@ -172,15 +178,15 @@ public abstract class MMOTestEnvironment {
}
private void mockPartyConfig() {
partyConfig = Mockito.mock(PartyConfig.class);
partyConfig = mock(PartyConfig.class);
when(partyConfig.isPartyEnabled()).thenReturn(false);
when(mcMMO.p.getPartyConfig()).thenReturn(partyConfig);
}
private void mockExperienceConfig() {
experienceConfig = Mockito.mockStatic(ExperienceConfig.class);
experienceConfig = mockStatic(ExperienceConfig.class);
when(ExperienceConfig.getInstance()).thenReturn(Mockito.mock(ExperienceConfig.class));
when(ExperienceConfig.getInstance()).thenReturn(mock(ExperienceConfig.class));
// Combat
when(ExperienceConfig.getInstance().getCombatXP("Cow")).thenReturn(1D);
@ -212,5 +218,8 @@ public abstract class MMOTestEnvironment {
if (mockedEventUtils != null) {
mockedEventUtils.close();
}
if (mockedBukkit != null) {
mockedBukkit.close();
}
}
}

View File

@ -0,0 +1,69 @@
//package com.gmail.nossr50.config.skills.alchemy;
//
//import com.gmail.nossr50.MMOTestEnvironment;
//import org.bukkit.inventory.meta.ItemMeta;
//import org.bukkit.inventory.meta.PotionMeta;
//import org.junit.jupiter.api.AfterEach;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.Test;
//
//import java.io.File;
//import java.net.URL;
//import java.util.logging.Logger;
//
//import static org.junit.jupiter.api.Assertions.assertNotNull;
//import static org.mockito.ArgumentMatchers.any;
//import static org.mockito.Mockito.mock;
//import static org.mockito.Mockito.when;
//
//class PotionConfigTest extends MMOTestEnvironment {
//
// public static final String POTION_LEGACY_POTION_YML = "potion/legacy_potion.yml";
// public static final String POTION_MODERN_YML = "potion/modern_potion.yml";
// public static final Logger logger = Logger.getLogger(PotionConfigTest.class.getName());
//
// @BeforeEach
// void setUp() {
// mockBaseEnvironment(logger);
// final PotionMeta potionMeta = mock(PotionMeta.class);
// when(itemFactory.getItemMeta(any())).thenReturn(potionMeta);
// }
//
// @AfterEach
// void tearDown() {
// cleanupBaseEnvironment();
// }
//
// @Test
// void testLoadLegacyConfig() {
// final PotionConfig potionConfig = getPotionConfig(POTION_LEGACY_POTION_YML);
// assertNotNull(potionConfig);
//
// potionConfig.loadConcoctions();
// int loaded = potionConfig.loadPotionMap();
// System.out.println("Loaded " + loaded + " potions");
// }
//
// @Test
// void testModernConfig() {
// final PotionConfig potionConfig = getPotionConfig(POTION_MODERN_YML);
// assertNotNull(potionConfig);
//
// potionConfig.loadConcoctions();
// int loaded = potionConfig.loadPotionMap();
// System.out.println("Loaded " + loaded + " potions");
// }
//
// private PotionConfig getPotionConfig(String path) {
// // Get the file URL using the class loader
// final URL resource = getClass().getClassLoader().getResource(path);
// if (resource == null) {
// throw new IllegalArgumentException("file not found!");
// } else {
// // Convert URL to a File object
// final File potionFile = new File(resource.getFile());
// System.out.println("File path: " + potionFile.getAbsolutePath());
// return new PotionConfig(potionFile);
// }
// }
//}

View File

@ -10,7 +10,6 @@ import com.gmail.nossr50.util.skills.SkillTools;
import com.google.common.io.Files;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@ -38,32 +37,30 @@ class FlatFileDatabaseManagerTest {
public static final @NotNull String BAD_DATA_FILE_LINE_TWENTY_THREE = "nossr51:baddata:::baddata:baddata:640:baddata:1000:1000:1000:baddata:baddata:baddata:baddata:16:0:500:20273:0:0:0:0::1000:0:0:baddata:1593543012:0:0:0:0::1000:0:0:baddata:IGNORED:1000:0:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1:0:";
public static final @NotNull String DB_BADDATA = "baddatadb.users";
public static final @NotNull String DB_HEALTHY = "healthydb.users";
public static final @NotNull String HEALTHY_DB_LINE_1 = "nossr50:1:IGNORED:IGNORED:10:2:20:3:4:5:6:7:8:9:10:30:40:50:60:70:80:90:100:IGNORED:11:110:111:222:333:444:555:666:777:IGNORED:12:120:888:IGNORED:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:2020:140:14:150:15:1111:2222:3333";
public static final @NotNull String HEALTHY_DB_LINE_ONE_UUID_STR = "588fe472-1c82-4c4e-9aa1-7eefccb277e3";
public static final String DB_MISSING_LAST_LOGIN = "missinglastlogin.users";
public static final String LINE_TWO_FROM_MISSING_DB = "nossr50:1:IGNORED:IGNORED:10:2:20:3:4:5:6:7:8:9:10:30:40:50:60:70:80:90:100:IGNORED:11:110:111:222:333:444:555:666:777:IGNORED:12:120:888:0:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:";
private static File tempDir;
private final static @NotNull Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
private final long PURGE_TIME = 2630000000L;
private static @Nullable FlatFileDatabaseManager db;
//Making them all unique makes it easier on us to edit this stuff later
int expectedLvlMining = 1, expectedLvlWoodcutting = 2, expectedLvlRepair = 3,
expectedLvlUnarmed = 4, expectedLvlHerbalism = 5, expectedLvlExcavation = 6,
expectedLvlArchery = 7, expectedLvlSwords = 8, expectedLvlAxes = 9, expectedLvlAcrobatics = 10,
expectedLvlTaming = 11, expectedLvlFishing = 12, expectedLvlAlchemy = 13, expectedLvlCrossbows = 14,
expectedLvlTridents = 15;
expectedLvlTridents = 15, expectedLvlMaces = 16;
float expectedExpMining = 10, expectedExpWoodcutting = 20, expectedExpRepair = 30,
expectedExpUnarmed = 40, expectedExpHerbalism = 50, expectedExpExcavation = 60,
expectedExpArchery = 70, expectedExpSwords = 80, expectedExpAxes = 90, expectedExpAcrobatics = 100,
expectedExpTaming = 110, expectedExpFishing = 120, expectedExpAlchemy = 130, expectedExpCrossbows = 140,
expectedExpTridents = 150;
expectedExpTridents = 150, expectedExpMaces = 160;
long expectedBerserkCd = 111, expectedGigaDrillBreakerCd = 222, expectedTreeFellerCd = 333,
expectedGreenTerraCd = 444, expectedSerratedStrikesCd = 555, expectedSkullSplitterCd = 666,
expectedSuperBreakerCd = 777, expectedBlastMiningCd = 888, expectedChimaeraWingCd = 999,
expectedSuperShotgunCd = 1111, expectedTridentSuperCd = 2222, expectedExplosiveShotCd = 3333;
expectedSuperShotgunCd = 1111, expectedTridentSuperCd = 2222, expectedExplosiveShotCd = 3333,
expectedMacesSuperCd = 4444;
int expectedScoreboardTips = 1111;
Long expectedLastLogin = 2020L;
@ -75,10 +72,8 @@ class FlatFileDatabaseManagerTest {
@BeforeEach
void init() {
assertNull(db);
//noinspection UnstableApiUsage
tempDir = Files.createTempDir();
db = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
}
private @NotNull String getTemporaryUserFilePath() {
@ -88,7 +83,6 @@ class FlatFileDatabaseManagerTest {
@AfterEach
void tearDown() {
recursiveDelete(tempDir);
db = null;
}
//Nothing wrong with this database
@ -150,17 +144,19 @@ class FlatFileDatabaseManagerTest {
@Test
void testDefaultInit() {
db = new FlatFileDatabaseManager(getTemporaryUserFilePath(), logger, PURGE_TIME, 0);
new FlatFileDatabaseManager(getTemporaryUserFilePath(), logger, PURGE_TIME, 0);
}
@Test
void testUpdateLeaderboards() {
assertNotNull(db);
assertEquals(LeaderboardStatus.UPDATED, db.updateLeaderboards());
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
assertNotNull(flatFileDatabaseManager);
assertEquals(LeaderboardStatus.UPDATED, flatFileDatabaseManager.updateLeaderboards());
}
@Test
void testSaveUser() {
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
//Make a Profile to save and check to see if it worked
UUID uuid = UUID.fromString("588fe472-1c82-4c4e-9aa1-7eefccb277e3");
String playerName = "nossr50";
@ -168,15 +164,15 @@ class FlatFileDatabaseManagerTest {
//The above profile should be "zero" initialized
//Save the zero version and see if it looks correct
assertNotNull(db);
assertTrue(db.getUsersFile().exists()); //Users file should have been created from the above com.gmail.nossr50.database.FlatFileDatabaseManager.checkFileHealthAndStructure
assertNotNull(db.getUsersFile());
assertNotNull(flatFileDatabaseManager);
assertTrue(flatFileDatabaseManager.getUsersFile().exists()); //Users file should have been created from the above com.gmail.nossr50.database.FlatFileDatabaseManager.checkFileHealthAndStructure
assertNotNull(flatFileDatabaseManager.getUsersFile());
//The DB is empty at this point, add our user
assertTrue(db.saveUser(testProfile)); //True means we saved the user
//The flatFileDatabaseManager is empty at this point, add our user
assertTrue(flatFileDatabaseManager.saveUser(testProfile)); //True means we saved the user
//Check for the empty profile
PlayerProfile retrievedFromData = db.loadPlayerProfile(uuid);
PlayerProfile retrievedFromData = flatFileDatabaseManager.loadPlayerProfile(uuid);
assertTrue(retrievedFromData.isLoaded()); //PlayerProfile::isLoaded returns true if the data was created from the file, false if it wasn't found and a dummy profile was returned
assertEquals(uuid, retrievedFromData.getUniqueId());
assertEquals(playerName, retrievedFromData.getPlayerName());
@ -187,9 +183,9 @@ class FlatFileDatabaseManagerTest {
String alteredName = "changedmyname";
PlayerProfile changedNameProfile = new PlayerProfile(alteredName, uuid, 0);
assertTrue(db.saveUser(changedNameProfile)); //True means we saved the user
assertTrue(flatFileDatabaseManager.saveUser(changedNameProfile)); //True means we saved the user
retrievedFromData = db.loadPlayerProfile(uuid);
retrievedFromData = flatFileDatabaseManager.loadPlayerProfile(uuid);
assertTrue(retrievedFromData.isLoaded()); //PlayerProfile::isLoaded returns true if the data was created from the file, false if it wasn't found and a dummy profile was returned
assertEquals(uuid, retrievedFromData.getUniqueId());
assertEquals(alteredName, retrievedFromData.getPlayerName());
@ -198,49 +194,27 @@ class FlatFileDatabaseManagerTest {
@Test
void testAddedMissingLastLoginValues() {
File dbFile = prepareDatabaseTestResource(DB_MISSING_LAST_LOGIN);
//This makes sure our private method is working before the tests run afterwards
ArrayList<String[]> dataFromFile = getSplitDataFromFile(dbFile);
logger.info("File Path: "+ dbFile.getAbsolutePath());
assertArrayEquals(LINE_TWO_FROM_MISSING_DB.split(":"), dataFromFile.get(1));
assertEquals(dataFromFile.get(1)[FlatFileDatabaseManager.UUID_INDEX], HEALTHY_DB_LINE_ONE_UUID_STR);
db = new FlatFileDatabaseManager(dbFile, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = db.checkFileHealthAndStructure();
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(dbFile, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = flatFileDatabaseManager.checkFileHealthAndStructure();
assertNotNull(flagsFound);
assertTrue(flagsFound.contains(FlatFileDataFlag.LAST_LOGIN_SCHEMA_UPGRADE));
//Check for the fixed value
PlayerProfile profile = db.loadPlayerProfile("nossr50");
PlayerProfile profile = flatFileDatabaseManager.loadPlayerProfile("nossr50");
assertEquals(-1, (long) profile.getLastLogin());
}
@Test
void testLoadByName() {
File healthyDB = prepareDatabaseTestResource(DB_HEALTHY);
/*
* We have established the files are in good order, so now for the actual testing
*/
//This makes sure our private method is working before the tests run afterwards
ArrayList<String[]> dataFromFile = getSplitDataFromFile(healthyDB);
logger.info("File Path: "+healthyDB.getAbsolutePath());
assertArrayEquals(HEALTHY_DB_LINE_1.split(":"), dataFromFile.get(0));
assertEquals(dataFromFile.get(0)[FlatFileDatabaseManager.UUID_INDEX], HEALTHY_DB_LINE_ONE_UUID_STR);
db = new FlatFileDatabaseManager(healthyDB, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = db.checkFileHealthAndStructure();
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(healthyDB, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = flatFileDatabaseManager.checkFileHealthAndStructure();
assertNull(flagsFound); //No flags should be found
/*
* Once the DB looks fine load the profile
*/
String playerName = "nossr50";
UUID uuid = UUID.fromString("588fe472-1c82-4c4e-9aa1-7eefccb277e3");
PlayerProfile profile = db.loadPlayerProfile(playerName);
PlayerProfile profile = flatFileDatabaseManager.loadPlayerProfile(playerName);
testHealthyDataProfileValues(playerName, uuid, profile);
}
@ -251,16 +225,16 @@ class FlatFileDatabaseManagerTest {
String playerName = "nossr50";
int newUserTestStartingLvl = 1337;
db = new FlatFileDatabaseManager(new File(tempDir.getPath() + File.separator + TEST_FILE_NAME), logger, PURGE_TIME, newUserTestStartingLvl, true);
db.checkFileHealthAndStructure();
var flatFileDatabaseManager = new FlatFileDatabaseManager(new File(tempDir.getPath() + File.separator + TEST_FILE_NAME), logger, PURGE_TIME, newUserTestStartingLvl, true);
flatFileDatabaseManager.checkFileHealthAndStructure();
PlayerProfile playerProfile = db.newUser(playerName, uuid);
PlayerProfile playerProfile = flatFileDatabaseManager.newUser(playerName, uuid);
assertTrue(playerProfile.isLoaded());
assertEquals(playerName, playerProfile.getPlayerName());
assertEquals(uuid, playerProfile.getUniqueId());
PlayerProfile retrievedFromDisk = db.loadPlayerProfile(uuid);
PlayerProfile retrievedFromDisk = flatFileDatabaseManager.loadPlayerProfile(uuid);
assertTrue(retrievedFromDisk.isLoaded());
assertEquals(playerName, retrievedFromDisk.getPlayerName());
assertEquals(uuid, retrievedFromDisk.getUniqueId());
@ -270,11 +244,11 @@ class FlatFileDatabaseManagerTest {
checkNewUserValues(retrievedFromDisk, newUserTestStartingLvl);
//TODO: Should we do any dupe checking? Probably not needed as it would be caught on the next load
db.newUser("disco", new UUID(3, 3));
db.newUser("dingus", new UUID(3, 4));
db.newUser("duped_dingus", new UUID(3, 4));
flatFileDatabaseManager.newUser("disco", new UUID(3, 3));
flatFileDatabaseManager.newUser("dingus", new UUID(3, 4));
flatFileDatabaseManager.newUser("duped_dingus", new UUID(3, 4));
assertEquals(5, getSplitDataFromFile(db.getUsersFile()).size());
assertEquals(5, getSplitDataFromFile(flatFileDatabaseManager.getUsersFile()).size());
}
@Test
@ -286,16 +260,16 @@ class FlatFileDatabaseManagerTest {
File file = prepareDatabaseTestResource(DB_HEALTHY); //Existing DB
int newUserTestStartingLvl = 1337;
db = new FlatFileDatabaseManager(file, logger, PURGE_TIME, newUserTestStartingLvl, true);
db.checkFileHealthAndStructure();
var flatFileDatabaseManager = new FlatFileDatabaseManager(file, logger, PURGE_TIME, newUserTestStartingLvl, true);
flatFileDatabaseManager.checkFileHealthAndStructure();
PlayerProfile playerProfile = db.newUser(playerName, uuid);
PlayerProfile playerProfile = flatFileDatabaseManager.newUser(playerName, uuid);
assertTrue(playerProfile.isLoaded());
assertEquals(playerName, playerProfile.getPlayerName());
assertEquals(uuid, playerProfile.getUniqueId());
PlayerProfile retrievedFromDisk = db.loadPlayerProfile(uuid);
PlayerProfile retrievedFromDisk = flatFileDatabaseManager.loadPlayerProfile(uuid);
assertTrue(retrievedFromDisk.isLoaded());
assertEquals(playerName, retrievedFromDisk.getPlayerName());
assertEquals(uuid, retrievedFromDisk.getUniqueId());
@ -305,15 +279,15 @@ class FlatFileDatabaseManagerTest {
checkNewUserValues(retrievedFromDisk, newUserTestStartingLvl);
//TODO: Should we do any dupe checking? Probably not needed as it would be caught on the next load
db.newUser("bidoof", new UUID(3, 3));
db.newUser("derp", new UUID(3, 4));
db.newUser("pizza", new UUID(3, 4));
flatFileDatabaseManager.newUser("bidoof", new UUID(3, 3));
flatFileDatabaseManager.newUser("derp", new UUID(3, 4));
flatFileDatabaseManager.newUser("pizza", new UUID(3, 4));
assertEquals(7, getSplitDataFromFile(db.getUsersFile()).size());
assertEquals(7, getSplitDataFromFile(flatFileDatabaseManager.getUsersFile()).size());
//Now we *fix* the DB and there should be one less
db.checkFileHealthAndStructure();
assertEquals(6, getSplitDataFromFile(db.getUsersFile()).size());
//Now we *fix* the flatFileDatabaseManager and there should be one less
flatFileDatabaseManager.checkFileHealthAndStructure();
assertEquals(6, getSplitDataFromFile(flatFileDatabaseManager.getUsersFile()).size());
}
private void checkNewUserValues(@NotNull PlayerProfile playerProfile, int startingLevel) {
@ -338,71 +312,45 @@ class FlatFileDatabaseManagerTest {
@Test
void testLoadByUUID() {
File dbFile = prepareDatabaseTestResource(DB_HEALTHY);
/*
* We have established the files are in good order, so now for the actual testing
*/
//This makes sure our private method is working before the tests run afterwards
ArrayList<String[]> dataFromFile = getSplitDataFromFile(dbFile);
logger.info("File Path: " + dbFile.getAbsolutePath());
assertArrayEquals(HEALTHY_DB_LINE_1.split(":"), dataFromFile.get(0));
assertEquals(dataFromFile.get(0)[FlatFileDatabaseManager.UUID_INDEX], HEALTHY_DB_LINE_ONE_UUID_STR);
db = new FlatFileDatabaseManager(dbFile, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = db.checkFileHealthAndStructure();
var flatFileDatabaseManager = new FlatFileDatabaseManager(dbFile, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = flatFileDatabaseManager.checkFileHealthAndStructure();
assertNull(flagsFound); //No flags should be found
/*
* Once the DB looks fine load the profile
* Once the flatFileDatabaseManager looks fine load the profile
*/
String playerName = "nossr50";
UUID uuid = UUID.fromString("588fe472-1c82-4c4e-9aa1-7eefccb277e3");
PlayerProfile profile1 = db.loadPlayerProfile(uuid);
PlayerProfile profile1 = flatFileDatabaseManager.loadPlayerProfile(uuid);
testHealthyDataProfileValues(playerName, uuid, profile1);
assertFalse(db.loadPlayerProfile(new UUID(0, 1)).isLoaded()); //This profile should not exist and therefor will return unloaded
assertFalse(flatFileDatabaseManager.loadPlayerProfile(new UUID(0, 1)).isLoaded()); //This profile should not exist and therefor will return unloaded
}
@Test
void testLoadByUUIDAndName() {
File dbFile = prepareDatabaseTestResource(DB_HEALTHY);
/*
* We have established the files are in good order, so now for the actual testing
*/
//This makes sure our private method is working before the tests run afterwards
ArrayList<String[]> dataFromFile = getSplitDataFromFile(dbFile);
logger.info("File Path: " + dbFile.getAbsolutePath());
assertArrayEquals(HEALTHY_DB_LINE_1.split(":"), dataFromFile.get(0));
assertEquals(dataFromFile.get(0)[FlatFileDatabaseManager.UUID_INDEX], HEALTHY_DB_LINE_ONE_UUID_STR);
db = new FlatFileDatabaseManager(dbFile, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = db.checkFileHealthAndStructure();
var flatFileDatabaseManager = new FlatFileDatabaseManager(dbFile, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = flatFileDatabaseManager.checkFileHealthAndStructure();
assertNull(flagsFound); //No flags should be found
/*
* Once the DB looks fine load the profile
*/
String playerName = "nossr50";
UUID uuid = UUID.fromString("588fe472-1c82-4c4e-9aa1-7eefccb277e3");
Player player = initMockPlayer(playerName, uuid);
PlayerProfile profile1 = db.loadPlayerProfile(player);
PlayerProfile profile1 = flatFileDatabaseManager.loadPlayerProfile(player);
testHealthyDataProfileValues(playerName, uuid, profile1);
String updatedName = "updatedName";
Player updatedNamePlayer = initMockPlayer(updatedName, uuid);
PlayerProfile updatedNameProfile = db.loadPlayerProfile(updatedNamePlayer);
PlayerProfile updatedNameProfile = flatFileDatabaseManager.loadPlayerProfile(updatedNamePlayer);
testHealthyDataProfileValues(updatedName, uuid, updatedNameProfile);
Player shouldNotExist = initMockPlayer("doesntexist", new UUID(0, 1));
PlayerProfile profile3 = db.loadPlayerProfile(shouldNotExist);
PlayerProfile profile3 = flatFileDatabaseManager.loadPlayerProfile(shouldNotExist);
assertFalse(profile3.isLoaded());
}
@ -484,6 +432,7 @@ class FlatFileDatabaseManagerTest {
case BLAST_MINING -> expectedBlastMiningCd;
case TRIDENTS_SUPER_ABILITY -> expectedTridentSuperCd;
case EXPLOSIVE_SHOT -> expectedExplosiveShotCd;
case MACES_SUPER_ABILITY -> expectedMacesSuperCd;
default -> throw new RuntimeException("Values not defined for super ability please add " +
"values for " + superAbilityType.toString() + " to the test");
};
@ -491,165 +440,147 @@ class FlatFileDatabaseManagerTest {
}
private float getExpectedExperienceHealthyDBEntryOne(@NotNull PrimarySkillType primarySkillType) {
switch(primarySkillType) {
case ACROBATICS:
return expectedExpAcrobatics;
case ALCHEMY:
return expectedExpAlchemy;
case ARCHERY:
return expectedExpArchery;
case AXES:
return expectedExpAxes;
case CROSSBOWS:
return expectedExpCrossbows;
case EXCAVATION:
return expectedExpExcavation;
case FISHING:
return expectedExpFishing;
case HERBALISM:
return expectedExpHerbalism;
case MINING:
return expectedExpMining;
case REPAIR:
return expectedExpRepair;
case SALVAGE:
case SMELTING:
return 0;
case SWORDS:
return expectedExpSwords;
case TAMING:
return expectedExpTaming;
case TRIDENTS:
return expectedExpTridents;
case UNARMED:
return expectedExpUnarmed;
case WOODCUTTING:
return expectedExpWoodcutting;
}
return switch (primarySkillType) {
case ACROBATICS -> expectedExpAcrobatics;
case ALCHEMY -> expectedExpAlchemy;
case ARCHERY -> expectedExpArchery;
case AXES -> expectedExpAxes;
case CROSSBOWS -> expectedExpCrossbows;
case EXCAVATION -> expectedExpExcavation;
case FISHING -> expectedExpFishing;
case HERBALISM -> expectedExpHerbalism;
case MINING -> expectedExpMining;
case REPAIR -> expectedExpRepair;
case SALVAGE, SMELTING -> 0;
case SWORDS -> expectedExpSwords;
case TAMING -> expectedExpTaming;
case TRIDENTS -> expectedExpTridents;
case UNARMED -> expectedExpUnarmed;
case WOODCUTTING -> expectedExpWoodcutting;
case MACES -> expectedExpMaces;
default ->
throw new RuntimeException("Values for skill not defined, please add values for " + primarySkillType.toString() + " to the test");
};
}
private int getExpectedLevelHealthyDBEntryOne(@NotNull PrimarySkillType primarySkillType) {
switch(primarySkillType) {
case ACROBATICS:
return expectedLvlAcrobatics;
case ALCHEMY:
return expectedLvlAlchemy;
case ARCHERY:
return expectedLvlArchery;
case AXES:
return expectedLvlAxes;
case CROSSBOWS:
return expectedLvlCrossbows;
case EXCAVATION:
return expectedLvlExcavation;
case FISHING:
return expectedLvlFishing;
case HERBALISM:
return expectedLvlHerbalism;
case MINING:
return expectedLvlMining;
case REPAIR:
return expectedLvlRepair;
case SALVAGE:
case SMELTING:
return 0;
case SWORDS:
return expectedLvlSwords;
case TAMING:
return expectedLvlTaming;
case TRIDENTS:
return expectedLvlTridents;
case UNARMED:
return expectedLvlUnarmed;
case WOODCUTTING:
return expectedLvlWoodcutting;
}
return switch (primarySkillType) {
case ACROBATICS -> expectedLvlAcrobatics;
case ALCHEMY -> expectedLvlAlchemy;
case ARCHERY -> expectedLvlArchery;
case AXES -> expectedLvlAxes;
case CROSSBOWS -> expectedLvlCrossbows;
case EXCAVATION -> expectedLvlExcavation;
case FISHING -> expectedLvlFishing;
case HERBALISM -> expectedLvlHerbalism;
case MINING -> expectedLvlMining;
case REPAIR -> expectedLvlRepair;
case SALVAGE, SMELTING -> 0;
case SWORDS -> expectedLvlSwords;
case TAMING -> expectedLvlTaming;
case TRIDENTS -> expectedLvlTridents;
case UNARMED -> expectedLvlUnarmed;
case WOODCUTTING -> expectedLvlWoodcutting;
case MACES -> expectedLvlMaces;
default ->
throw new RuntimeException("Values for skill not defined, please add values for " + primarySkillType.toString() + " to the test");
};
}
@Test
void testOverwriteName() {
overwriteDataAndCheckForFlag(db, duplicateNameDatabaseData, FlatFileDataFlag.DUPLICATE_NAME);
ArrayList<String[]> splitDataLines = getSplitDataFromFile(db.getUsersFile());
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, duplicateNameDatabaseData, FlatFileDataFlag.DUPLICATE_NAME);
ArrayList<String[]> splitDataLines = getSplitDataFromFile(flatFileDatabaseManager.getUsersFile());
assertNotEquals(splitDataLines.get(1)[0], splitDataLines.get(0)[0]); //Name comparison
}
@Test
void testDataNotFound() {
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
//Save the zero version and see if it looks correct
assertNotNull(db);
assertTrue(db.getUsersFile().exists());
assertNotNull(db.getUsersFile());
assertNotNull(flatFileDatabaseManager);
assertTrue(flatFileDatabaseManager.getUsersFile().exists());
assertNotNull(flatFileDatabaseManager.getUsersFile());
//Check for the "unloaded" profile
PlayerProfile retrievedFromData = db.loadPlayerProfile("nossr50");
PlayerProfile retrievedFromData = flatFileDatabaseManager.loadPlayerProfile("nossr50");
assertFalse(retrievedFromData.isLoaded()); //PlayerProfile::isLoaded returns false if data doesn't exist for the user
}
@Test
void testPurgePowerlessUsers() {
replaceDataInFile(db, normalDatabaseData);
int purgeCount = db.purgePowerlessUsers();
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
replaceDataInFile(flatFileDatabaseManager, normalDatabaseData);
int purgeCount = flatFileDatabaseManager.purgePowerlessUsers();
assertEquals(purgeCount, 1); //1 User should have been purged
}
@Test
void testCheckFileHealthAndStructure() {
replaceDataInFile(db, badDatabaseData);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
replaceDataInFile(flatFileDatabaseManager, badDatabaseData);
List<FlatFileDataFlag> dataFlags = db.checkFileHealthAndStructure();
List<FlatFileDataFlag> dataFlags = flatFileDatabaseManager.checkFileHealthAndStructure();
assertNotNull(dataFlags);
assertNotEquals(dataFlags.size(), 0);
}
@Test
void testFindFixableDuplicateNames() {
overwriteDataAndCheckForFlag(db, duplicateNameDatabaseData, FlatFileDataFlag.DUPLICATE_NAME);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, duplicateNameDatabaseData, FlatFileDataFlag.DUPLICATE_NAME);
}
@Test
void testFindDuplicateUUIDs() {
overwriteDataAndCheckForFlag(db, duplicateUUIDDatabaseData, FlatFileDataFlag.DUPLICATE_UUID);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, duplicateUUIDDatabaseData, FlatFileDataFlag.DUPLICATE_UUID);
}
@Test()
void findBadUUIDData() {
overwriteDataAndCheckForFlag(db, badUUIDDatabaseData, FlatFileDataFlag.BAD_UUID_DATA);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, badUUIDDatabaseData, FlatFileDataFlag.BAD_UUID_DATA);
}
@Test
void testFindCorruptData() {
overwriteDataAndCheckForFlag(db, corruptDatabaseData, FlatFileDataFlag.CORRUPTED_OR_UNRECOGNIZABLE);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, corruptDatabaseData, FlatFileDataFlag.CORRUPTED_OR_UNRECOGNIZABLE);
}
@Test
void testFindEmptyNames() {
overwriteDataAndCheckForFlag(db, emptyNameDatabaseData, FlatFileDataFlag.MISSING_NAME);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, emptyNameDatabaseData, FlatFileDataFlag.MISSING_NAME);
}
@Test
void testFindBadValues() {
overwriteDataAndCheckForFlag(db, badDatabaseData, FlatFileDataFlag.BAD_VALUES);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, badDatabaseData, FlatFileDataFlag.BAD_VALUES);
}
@Test
void testFindOutdatedData() {
overwriteDataAndCheckForFlag(db, outdatedDatabaseData, FlatFileDataFlag.INCOMPLETE);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
overwriteDataAndCheckForFlag(flatFileDatabaseManager, outdatedDatabaseData, FlatFileDataFlag.INCOMPLETE);
}
@Test
void testGetDatabaseType() {
assertNotNull(db);
assertEquals(db.getDatabaseType(), DatabaseType.FLATFILE);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
assertNotNull(flatFileDatabaseManager);
assertEquals(flatFileDatabaseManager.getDatabaseType(), DatabaseType.FLATFILE);
}
@Test
void testReadRank() {
//This is an empty DB
assertNotNull(db);
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
String rankBoyName = "rankBoy";
UUID rankBoyUUID = new UUID(1337, 1337);
String rankGirlName = "rankGirl";
@ -658,9 +589,9 @@ class FlatFileDatabaseManagerTest {
PlayerProfile rankGirlProfile = addPlayerProfileWithLevelsAndSave(rankGirlName, rankGirlUUID, 100); //Rank 1
PlayerProfile rankBoyProfile = addPlayerProfileWithLevelsAndSave(rankBoyName, rankBoyUUID, 10); //Rank 2
assertEquals(LeaderboardStatus.UPDATED, db.updateLeaderboards());
Map<PrimarySkillType, Integer> rankGirlPositions = db.readRank(rankGirlName);
Map<PrimarySkillType, Integer> rankBoyPositions = db.readRank(rankBoyName);
assertEquals(LeaderboardStatus.UPDATED, flatFileDatabaseManager.updateLeaderboards());
Map<PrimarySkillType, Integer> rankGirlPositions = flatFileDatabaseManager.readRank(rankGirlName);
Map<PrimarySkillType, Integer> rankBoyPositions = flatFileDatabaseManager.readRank(rankBoyName);
for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if(primarySkillType.isChildSkill()) {
@ -672,8 +603,8 @@ class FlatFileDatabaseManagerTest {
}
}
assertEquals(1, db.readRank(rankGirlName).get(null)); //Girl should be position 1
assertEquals(2, db.readRank(rankBoyName).get(null)); //Boy should be position 2
assertEquals(1, flatFileDatabaseManager.readRank(rankGirlName).get(null)); //Girl should be position 1
assertEquals(2, flatFileDatabaseManager.readRank(rankBoyName).get(null)); //Boy should be position 2
}
@Test
@ -741,11 +672,11 @@ class FlatFileDatabaseManagerTest {
}
private @NotNull PlayerProfile addPlayerProfileWithLevelsAndSave(String playerName, UUID uuid, int levels) {
assertNotNull(db);
assertFalse(db.loadPlayerProfile(uuid).isLoaded());
FlatFileDatabaseManager flatFileDatabaseManager = new FlatFileDatabaseManager(new File(getTemporaryUserFilePath()), logger, PURGE_TIME, 0, true);
assertFalse(flatFileDatabaseManager.loadPlayerProfile(uuid).isLoaded());
db.newUser(playerName, uuid);
PlayerProfile leveledProfile = db.loadPlayerProfile(uuid);
flatFileDatabaseManager.newUser(playerName, uuid);
PlayerProfile leveledProfile = flatFileDatabaseManager.loadPlayerProfile(uuid);
assertTrue(leveledProfile.isLoaded());
assertEquals(playerName, leveledProfile.getPlayerName());
@ -758,8 +689,8 @@ class FlatFileDatabaseManagerTest {
leveledProfile.modifySkill(primarySkillType, levels); //TODO: This method also resets XP, not cool
}
db.saveUser(leveledProfile);
leveledProfile = db.loadPlayerProfile(uuid);
flatFileDatabaseManager.saveUser(leveledProfile);
leveledProfile = flatFileDatabaseManager.loadPlayerProfile(uuid);
for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if(SkillTools.isChildSkill(primarySkillType)) {

View File

@ -0,0 +1,51 @@
package com.gmail.nossr50.util;
import org.bukkit.potion.PotionType;
import org.junit.jupiter.api.Test;
import static com.gmail.nossr50.util.PotionUtil.convertLegacyNames;
import static com.gmail.nossr50.util.PotionUtil.matchPotionType;
import static org.junit.jupiter.api.Assertions.assertEquals;
class PotionUtilTest {
@Test
void testDisplay() {
// System.out.println("\n");
// System.out.println("\n");
// System.out.println("\n");
// System.out.println("\n");
// for(var s : PotionType.values()) {
// System.out.println("PotionType.getKey().getKey(): " + s.getKey().getKey());
// System.out.println("PotionType.name(): " + s.name());
// System.out.println("PotionType.toString():" + s.toString());
// System.out.println("\n");
// }
}
@Test
void testMatchPotionType() {
String potionTypeStr = "UNCRAFTABLE";
PotionType potionType = matchPotionType(potionTypeStr, false, false);
assertEquals(PotionType.WATER, potionType);
String potionTypeStr2 = "NIGHT_VISION";
PotionType potionType2 = matchPotionType(potionTypeStr2, false, false);
assertEquals(PotionType.NIGHT_VISION, potionType2);
String nightVisionLong = "NIGHT_VISION";
PotionType potionType3 = matchPotionType(nightVisionLong, false, true);
assertEquals(PotionType.LONG_NIGHT_VISION, potionType3);
nightVisionLong = "LONG_NIGHT_VISION";
potionType3 = matchPotionType(nightVisionLong, false, true);
assertEquals(PotionType.LONG_NIGHT_VISION, potionType3);
}
@Test
void testConvertLegacyNames() {
final String potionTypeStr = "UNCRAFTABLE";
final String converted = convertLegacyNames(potionTypeStr);
assertEquals("WATER", converted);
}
}

View File

@ -1,3 +1,3 @@
nossr50:1:IGNORED:IGNORED:10:2:20:3:4:5:6:7:8:9:10:30:40:50:60:70:80:90:100:IGNORED:11:110:111:222:333:444:555:666:777:IGNORED:12:120:888:IGNORED:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:2020:140:14:150:15:1111:2222:3333:
mrfloris:2420:::0:2452:0:1983:1937:1790:3042:1138:3102:2408:3411:0:0:0:0:0:0:0:0::642:0:1617583171:0:1617165043:0:1617583004:1617563189:1616785408::2184:0:0:1617852413:HEARTS:415:0:631e3896-da2a-4077-974b-d047859d76bc:5:1600906906:3030:0:0:0:0:0:0:0:
powerless:0:::0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0::0:0:0:0:0:0:0:0:0::0:0:0:1337:HEARTS:0:0:e0d07db8-f7e8-43c7-9ded-864dfc6f3b7c:5:1600906906:4040:0:0:0:0:0:0:0:
nossr50:1:IGNORED:IGNORED:10:2:20:3:4:5:6:7:8:9:10:30:40:50:60:70:80:90:100:IGNORED:11:110:111:222:333:444:555:666:777:IGNORED:12:120:888:IGNORED:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:2020:140:14:150:15:1111:2222:3333:160:16:4444:
mrfloris:2420:::0:2452:0:1983:1937:1790:3042:1138:3102:2408:3411:0:0:0:0:0:0:0:0::642:0:1617583171:0:1617165043:0:1617583004:1617563189:1616785408::2184:0:0:1617852413:HEARTS:415:0:631e3896-da2a-4077-974b-d047859d76bc:5:1600906906:3030:0:0:0:0:0:0:0:0:0:0:
powerless:0:::0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0::0:0:0:0:0:0:0:0:0::0:0:0:1337:HEARTS:0:0:e0d07db8-f7e8-43c7-9ded-864dfc6f3b7c:5:1600906906:4040:0:0:0:0:0:0:0:0:0:0: