Add more tests, fix null name bug

This commit is contained in:
nossr50 2021-04-13 12:41:23 -07:00
parent 5b4af3f9ce
commit f7339277f8
25 changed files with 491 additions and 128 deletions

View File

@ -1,5 +1,10 @@
Version 2.1.189
FlatFileDB now stores the last login of users again (was completely non functional for a while)
Newly created flat file databases (mcmmo.users file) will have a comment line at the top noting the date the database was created
Fixed a bug where FlatFileDatabase users could have their names saved as "null" (names will be fixed the next time the player logs in)
Rewrote how FlatFileDatabase verifies data integrity
(API) Added com.gmail.nossr50.database.DatabaseManager.loadPlayerProfile(org.bukkit.OfflinePlayer)
(API) Deprecated com.gmail.nossr50.database.DatabaseManager.loadPlayerProfile(java.util.UUID, java.lang.String)
Added unit tests for FlatFileDatabaseManager (see notes)
Fixed a bug where FlatFileDatabaseManager didn't properly upgrade older database entries to the newest schema
The setting to disable the mcMMO user block tracker has been moved from our "hidden config" to persistent_data.yml
@ -17,7 +22,7 @@ Version 2.1.189
(API) Some members of PrimarySkillType were removed and not deprecated (such as the field constants)
NOTES:
The tests added for FlatFileDatabase will help make sure bugs don't result in any loss of data
I spent over 20 hours refactoring FlatFileDB and writing unit tests for it, this will ensure that any changes in the code that could break the database are caught
Ultra Permissions is SAFE to use with mcMMO
After getting in contact with the UltraPermissions devs and exhaustive testing, I have concluded that using UltraPermissions is completely safe with mcMMO. The users who had an issue with performance currently have an unknown cause, potentially it is from a plugin using the UltraPermissions API I really can't say without more data. My apologies to the UltraPermissions team for reporting an issue between our two plugins directly, as that is not the case. I would have tested it myself sooner but UltraPermissions was closed source and premium so I wasn't particularly motivated to do so, however I have been given access to the binaries so now I can do all the testing I want if future issues ever arise which I have zero expectations that they will.

View File

@ -12,6 +12,7 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.skills.child.FamilyTree;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.SkillTools;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.BlockState;
@ -80,7 +81,7 @@ public final class ExperienceAPI {
public static boolean isNonChildSkill(String skillType) {
PrimarySkillType skill = mcMMO.p.getSkillTools().matchSkill(skillType);
return skill != null && !mcMMO.p.getSkillTools().isChildSkill(skill);
return skill != null && !SkillTools.isChildSkill(skill);
}
@Deprecated
@ -626,7 +627,7 @@ public final class ExperienceAPI {
PlayerProfile profile = getOfflineProfile(playerName);
PrimarySkillType skill = getSkillType(skillType);
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
Set<PrimarySkillType> parentSkills = FamilyTree.getParents(skill);
for (PrimarySkillType parentSkill : parentSkills) {
@ -657,7 +658,7 @@ public final class ExperienceAPI {
PlayerProfile profile = getOfflineProfile(uuid);
PrimarySkillType skill = getSkillType(skillType);
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
Set<PrimarySkillType> parentSkills = FamilyTree.getParents(skill);
for (PrimarySkillType parentSkill : parentSkills) {
@ -763,7 +764,7 @@ public final class ExperienceAPI {
int powerLevel = 0;
PlayerProfile profile = getOfflineProfile(playerName);
for (PrimarySkillType type : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType type : SkillTools.NON_CHILD_SKILLS) {
powerLevel += profile.getSkillLevel(type);
}
@ -784,7 +785,7 @@ public final class ExperienceAPI {
int powerLevel = 0;
PlayerProfile profile = getOfflineProfile(uuid);
for (PrimarySkillType type : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType type : SkillTools.NON_CHILD_SKILLS) {
powerLevel += profile.getSkillLevel(type);
}
@ -1181,7 +1182,7 @@ public final class ExperienceAPI {
private static PrimarySkillType getNonChildSkillType(String skillType) throws InvalidSkillException, UnsupportedOperationException {
PrimarySkillType skill = getSkillType(skillType);
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
throw new UnsupportedOperationException("Child skills do not have XP");
}

View File

@ -2,6 +2,7 @@ package com.gmail.nossr50.api;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.skills.SkillTools;
import java.util.ArrayList;
import java.util.Arrays;
@ -31,7 +32,7 @@ public final class SkillAPI {
* @return a list of strings with valid skill names
*/
public static List<String> getNonChildSkills() {
return getListFromEnum(mcMMO.p.getSkillTools().NON_CHILD_SKILLS);
return getListFromEnum(SkillTools.NON_CHILD_SKILLS);
}
/**

View File

@ -7,6 +7,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.commands.CommandUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillTools;
import com.google.common.collect.ImmutableList;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
@ -50,7 +51,7 @@ public abstract class ExperienceCommand implements TabExecutor {
skill = null;
}
if (skill != null && mcMMO.p.getSkillTools().isChildSkill(skill))
if (skill != null && SkillTools.isChildSkill(skill))
{
sender.sendMessage(LocaleLoader.getString("Commands.Skill.ChildSkill"));
return true;
@ -83,7 +84,7 @@ public abstract class ExperienceCommand implements TabExecutor {
skill = null;
}
if (skill != null && mcMMO.p.getSkillTools().isChildSkill(skill))
if (skill != null && SkillTools.isChildSkill(skill))
{
sender.sendMessage(LocaleLoader.getString("Commands.Skill.ChildSkill"));
return true;
@ -171,7 +172,7 @@ public abstract class ExperienceCommand implements TabExecutor {
protected void editValues(Player player, PlayerProfile profile, PrimarySkillType skill, int value, boolean isSilent) {
if (skill == null) {
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
handleCommand(player, profile, primarySkillType, value);
}

View File

@ -10,6 +10,7 @@ import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.commands.CommandUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillTools;
import com.google.common.collect.ImmutableList;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
@ -167,7 +168,7 @@ public class SkillresetCommand implements TabExecutor {
protected void editValues(Player player, PlayerProfile profile, PrimarySkillType skill) {
if (skill == null) {
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
handleCommand(player, profile, primarySkillType);
}

View File

@ -51,7 +51,7 @@
//
// private void toggle(boolean enable, PrimarySkillType skill) {
// if (skill == null) {
// for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
// for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
// primarySkillType.setHardcoreStatLossEnabled(enable);
// }
// }

View File

@ -51,7 +51,7 @@
//
// private void toggle(boolean enable, PrimarySkillType skill) {
// if (skill == null) {
// for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
// for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
// primarySkillType.setHardcoreVampirismEnabled(enable);
// }
// }

View File

@ -15,6 +15,7 @@ import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.PerksUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillActivationType;
import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.util.text.StringUtils;
import com.gmail.nossr50.util.text.TextComponentFactory;
import com.google.common.collect.ImmutableList;
@ -142,7 +143,7 @@ public abstract class SkillCommand implements TabExecutor {
player.sendMessage(LocaleLoader.getString("Skills.Overhaul.Header", skillName));
if(!mcMMO.p.getSkillTools().isChildSkill(skill))
if(!SkillTools.isChildSkill(skill))
{
/*
* NON-CHILD SKILLS
@ -188,7 +189,7 @@ public abstract class SkillCommand implements TabExecutor {
}
/*
if (!mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (!SkillTools.isChildSkill(skill)) {
player.sendMessage(LocaleLoader.getString("Skills.Header", skillName));
player.sendMessage(LocaleLoader.getString("Commands.XPGain", LocaleLoader.getString("Commands.XPGain." + StringUtils.getCapitalized(skill.toString()))));
player.sendMessage(LocaleLoader.getString("Effects.Level", skillValue, mcMMOPlayer.getSkillXpLevel(skill), mcMMOPlayer.getXpToLevel(skill)));

View File

@ -5,6 +5,7 @@ import com.gmail.nossr50.datatypes.database.DatabaseType;
import com.gmail.nossr50.datatypes.database.PlayerStat;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -92,12 +93,17 @@ public interface DatabaseManager {
*/
@NotNull PlayerProfile loadPlayerProfile(@NotNull String playerName);
default @NotNull PlayerProfile loadPlayerProfile(@NotNull OfflinePlayer offlinePlayer) {
return loadPlayerProfile(offlinePlayer.getUniqueId(), offlinePlayer.getName());
}
/**
* Load a player from the database.
*
* @param uuid The uuid of the player to load from the database
* @return The player's data, or an unloaded PlayerProfile if not found
* @deprecated Use {@link DatabaseManager#loadPlayerProfile(org.bukkit.OfflinePlayer)} if possible
*/
@Deprecated
@NotNull PlayerProfile loadPlayerProfile(@NotNull UUID uuid, @Nullable String playerName);
/**

View File

@ -9,12 +9,15 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.skills.SkillTools;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.logging.Logger;
@ -28,6 +31,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
private final @NotNull Logger logger;
private final long purgeTime;
private final int startingLevel;
private boolean testing;
private final long UPDATE_WAIT_TIME = 600000L; // 10 minutes
private final @NotNull File usersFile;
@ -82,6 +86,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
this.logger = logger;
this.purgeTime = purgeTime;
this.startingLevel = startingLevel;
this.testing = testing;
if(!testing) {
List<FlatFileDataFlag> flatFileDataFlags = checkFileHealthAndStructure();
@ -218,6 +223,10 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
// Write the new file
out = new FileWriter(usersFilePath);
out.write(writer.toString());
if(testing) {
System.out.println(writer.toString());
}
}
catch (IOException e) {
logger.severe("Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?)" + e);
@ -321,8 +330,19 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
String line;
boolean wroteUser = false;
if(testing) {
System.out.println("-- saveUser bufferedreader feed --");
}
// While not at the end of the file
while ((line = in.readLine()) != null) {
if(testing) {
System.out.println(line);
}
if(line.startsWith("#")) {
writer.append(line).append("\r\n");
continue;
}
//Check for incomplete or corrupted data
if(!line.contains(":")) {
@ -365,6 +385,11 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
writeUserToLine(profile, playerName, uuid, writer);
}
if(testing) {
System.out.println("-- saveUser (FileWriter contents before save) --");
System.out.println(writer.toString());
}
// Write the new file
out = new FileWriter(usersFilePath);
out.write(writer.toString());
@ -445,7 +470,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
public @NotNull List<PlayerStat> readLeaderboard(@Nullable PrimarySkillType primarySkillType, int pageNumber, int statsPerPage) throws InvalidSkillException {
//Fix for a plugin that people are using that is throwing SQL errors
if(primarySkillType != null && mcMMO.p.getSkillTools().isChildSkill(primarySkillType)) {
if(primarySkillType != null && SkillTools.isChildSkill(primarySkillType)) {
logger.severe("A plugin hooking into mcMMO is being naughty with our database commands, update all plugins that hook into mcMMO and contact their devs!");
throw new InvalidSkillException("A plugin hooking into mcMMO that you are using is attempting to read leaderboard skills for child skills, child skills do not have leaderboards! This is NOT an mcMMO error!");
}
@ -462,7 +487,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
Map<PrimarySkillType, Integer> skills = new EnumMap<PrimarySkillType, Integer>(PrimarySkillType.class);
for (PrimarySkillType skill : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) {
skills.put(skill, getPlayerRank(playerName, playerStatHash.get(skill)));
}
@ -549,15 +574,19 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
}
}
public @NotNull PlayerProfile loadPlayerProfile(@NotNull OfflinePlayer offlinePlayer) {
return loadPlayerByUUID(offlinePlayer.getUniqueId(), offlinePlayer.getName(), offlinePlayer.isOnline());
}
public @NotNull PlayerProfile loadPlayerProfile(@NotNull String playerName) {
return loadPlayerByName(playerName);
}
public @NotNull PlayerProfile loadPlayerProfile(@NotNull UUID uuid, @Nullable String playerName) {
return loadPlayerByUUID(uuid, playerName);
return loadPlayerByUUID(uuid, playerName, false);
}
private @NotNull PlayerProfile loadPlayerByUUID(@NotNull UUID uuid, @Nullable String playerName) {
private @NotNull PlayerProfile loadPlayerByUUID(@NotNull UUID uuid, @Nullable String playerName, boolean isOnline) {
BufferedReader in = null;
synchronized (fileWritingLock) {
@ -594,9 +623,13 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
/* Check for nickname changes and update since we are here anyways */
if (!rawSplitData[USERNAME_INDEX].equalsIgnoreCase(playerName)) {
//logger.info("Name updated for player: " + rawSplitData[USERNAME_INDEX] + " => " + playerName);
rawSplitData[USERNAME_INDEX] = playerName;
if(playerName != null) {
if(isOnline) {
if (!rawSplitData[USERNAME_INDEX].equalsIgnoreCase(playerName)) {
//logger.info("Name updated for player: " + rawSplitData[USERNAME_INDEX] + " => " + playerName);
rawSplitData[USERNAME_INDEX] = playerName;
}
}
}
return loadFromLine(rawSplitData);
@ -969,15 +1002,39 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
playerStatHash.put(PrimarySkillType.ALCHEMY, alchemy);
}
/**
* Makes sure that the users file has valid entries
* @return
*/
private void initEmptyDB() {
BufferedWriter bufferedWriter = null;
synchronized (fileWritingLock) {
try {
// Open the file to write the player
bufferedWriter = new BufferedWriter(new FileWriter(usersFilePath, true));
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.now();
bufferedWriter.append("# mcMMO Database created on ").append(localDateTime.format(dateTimeFormatter)).append("\r\n"); //Empty file
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bufferedWriter != null) {
try {
bufferedWriter.close();
}
catch (IOException e) {
// Ignore
}
}
}
}
}
public @Nullable List<FlatFileDataFlag> checkFileHealthAndStructure() {
ArrayList<FlatFileDataFlag> flagsFound = null;
logger.info("(" + usersFile.getPath() + ") Validating database file..");
FlatFileDataProcessor dataProcessor = null;
if(!usersFile.exists()) {
initEmptyDB();
}
if (usersFile.exists()) {
BufferedReader bufferedReader = null;
FileWriter fileWriter = null;
@ -988,10 +1045,18 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
try {
String currentLine;
String dbCommentDate = null;
bufferedReader = new BufferedReader(new FileReader(usersFilePath));
//Analyze the data
while ((currentLine = bufferedReader.readLine()) != null) {
//Commented lines
if(currentLine.startsWith("#") && dbCommentDate == null) { //The first commented line in the file is likely to be our note about when the file was created
dbCommentDate = currentLine;
continue;
}
if(currentLine.isEmpty())
continue;
@ -1005,6 +1070,9 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
logger.info("Saving the updated and or repaired FlatFile Database...");
fileWriter = new FileWriter(usersFilePath);
//Write data to file
if(dbCommentDate != null)
fileWriter.write(dbCommentDate);
fileWriter.write(dataProcessor.processDataForSave().toString());
}
} catch (IOException e) {
@ -1078,6 +1146,7 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
Map<SuperAbilityType, Integer> skillsDATS = new EnumMap<>(SuperAbilityType.class); // Ability & Cooldown
Map<UniqueDataType, Integer> uniquePlayerDataMap = new EnumMap<>(UniqueDataType.class);
int scoreboardTipsShown;
long lastLogin;
String username = character[USERNAME_INDEX];
@ -1108,13 +1177,6 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
// Acrobatics - Unused
tryLoadSkillCooldownFromRawData(skillsDATS, character, SuperAbilityType.BLAST_MINING, COOLDOWN_BLAST_MINING, username);
// try {
// mobHealthbarType = MobHealthbarType.valueOf(character[HEALTHBAR]);
// }
// catch (Exception e) {
// mobHealthbarType = Config.getInstance().getMobHealthbarDefault();
// }
UUID uuid;
try {
uuid = UUID.fromString(character[UUID_INDEX]);
@ -1137,7 +1199,13 @@ public final class FlatFileDatabaseManager implements DatabaseManager {
uniquePlayerDataMap.put(UniqueDataType.CHIMAERA_WING_DATS, 0);
}
return new PlayerProfile(character[USERNAME_INDEX], uuid, skills, skillsXp, skillsDATS, null, scoreboardTipsShown, uniquePlayerDataMap);
try {
lastLogin = Long.parseLong(character[LAST_LOGIN]);
} catch (Exception e) {
lastLogin = System.currentTimeMillis();
}
return new PlayerProfile(character[USERNAME_INDEX], uuid, skills, skillsXp, skillsDATS, scoreboardTipsShown, uniquePlayerDataMap, lastLogin);
}
private void tryLoadSkillCooldownFromRawData(@NotNull Map<SuperAbilityType, Integer> cooldownMap, @NotNull String[] character, @NotNull SuperAbilityType superAbilityType, int cooldownSuperBreaker, @NotNull String userName) {

View File

@ -12,6 +12,7 @@ import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.database.UUIDUpdateAsyncTask;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.skills.SkillTools;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.bukkit.entity.Player;
@ -174,8 +175,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
}
catch (SQLException ex) {
printErrors(ex);
}
finally {
} finally {
tryClose(statement);
tryClose(connection);
massUpdateLock.unlock();
@ -271,7 +271,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setInt(12, profile.getSkillLevel(PrimarySkillType.FISHING));
statement.setInt(13, profile.getSkillLevel(PrimarySkillType.ALCHEMY));
int total = 0;
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS)
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS)
total += profile.getSkillLevel(primarySkillType);
statement.setInt(14, total);
statement.setInt(15, id);
@ -330,7 +330,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
}
statement = connection.prepareStatement("UPDATE " + tablePrefix + "huds SET mobhealthbar = ?, scoreboardtips = ? WHERE user_id = ?");
statement.setString(1, profile.getMobHealthbarType() == null ? mcMMO.p.getGeneralConfig().getMobHealthbarDefault().name() : profile.getMobHealthbarType().name());
statement.setString(1, MobHealthbarType.HEARTS.name());
statement.setInt(2, profile.getScoreboardTipsShown());
statement.setInt(3, id);
success = (statement.executeUpdate() != 0);
@ -355,7 +355,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
List<PlayerStat> stats = new ArrayList<>();
//Fix for a plugin that people are using that is throwing SQL errors
if(skill != null && mcMMO.p.getSkillTools().isChildSkill(skill)) {
if(skill != null && SkillTools.isChildSkill(skill)) {
mcMMO.p.getLogger().severe("A plugin hooking into mcMMO is being naughty with our database commands, update all plugins that hook into mcMMO and contact their devs!");
throw new InvalidSkillException("A plugin hooking into mcMMO that you are using is attempting to read leaderboard skills for child skills, child skills do not have leaderboards! This is NOT an mcMMO error!");
}
@ -404,7 +404,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
try {
connection = getConnection(PoolIdentifier.MISC);
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
String skillName = primarySkillType.name().toLowerCase(Locale.ENGLISH);
// Get count of all users with higher skill level than player
String sql = "SELECT COUNT(*) AS 'rank' FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
@ -932,7 +932,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
}
if (mcMMO.p.getGeneralConfig().getTruncateSkills()) {
for (PrimarySkillType skill : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) {
int cap = mcMMO.p.getSkillTools().getLevelCap(skill);
if (cap != Integer.MAX_VALUE) {
statement = connection.prepareStatement("UPDATE `" + tablePrefix + "skills` SET `" + skill.name().toLowerCase(Locale.ENGLISH) + "` = " + cap + " WHERE `" + skill.name().toLowerCase(Locale.ENGLISH) + "` > " + cap);
@ -1152,14 +1152,6 @@ public final class SQLDatabaseManager implements DatabaseManager {
skillsDATS.put(SuperAbilityType.BLAST_MINING, result.getInt(OFFSET_DATS + 12));
uniqueData.put(UniqueDataType.CHIMAERA_WING_DATS, result.getInt(OFFSET_DATS + 13));
try {
mobHealthbarType = MobHealthbarType.valueOf(result.getString(OFFSET_OTHER + 1));
}
catch (Exception e) {
mobHealthbarType = mcMMO.p.getGeneralConfig().getMobHealthbarDefault();
}
try {
scoreboardTipsShown = result.getInt(OFFSET_OTHER + 2);
}
@ -1174,7 +1166,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
uuid = null;
}
return new PlayerProfile(playerName, uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown, uniqueData);
return new PlayerProfile(playerName, uuid, skills, skillsXp, skillsDATS, scoreboardTipsShown, uniqueData, null);
}
private void printErrors(SQLException ex) {
@ -1291,10 +1283,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
resultSet = statement.executeQuery("SHOW INDEX FROM `" + tablePrefix + "skills` WHERE `Key_name` LIKE 'idx\\_%'");
resultSet.last();
if (resultSet.getRow() != mcMMO.p.getSkillTools().NON_CHILD_SKILLS.size()) {
if (resultSet.getRow() != SkillTools.NON_CHILD_SKILLS.size()) {
mcMMO.p.getLogger().info("Indexing tables, this may take a while on larger databases");
for (PrimarySkillType skill : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) {
String skill_name = skill.name().toLowerCase(Locale.ENGLISH);
try {

View File

@ -51,6 +51,7 @@ import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.PerksUtils;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.sounds.SoundManager;
import com.gmail.nossr50.util.sounds.SoundType;
@ -280,7 +281,7 @@ public class McMMOPlayer implements Identified {
public double getProgressInCurrentSkillLevel(PrimarySkillType primarySkillType)
{
if(mcMMO.p.getSkillTools().isChildSkill(primarySkillType)) {
if(SkillTools.isChildSkill(primarySkillType)) {
return 1.0D;
}
@ -569,7 +570,7 @@ public class McMMOPlayer implements Identified {
public int getPowerLevel() {
int powerLevel = 0;
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
if (mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, primarySkillType)) {
powerLevel += getSkillLevel(primarySkillType);
}
@ -611,7 +612,7 @@ public class McMMOPlayer implements Identified {
return;
}
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
Set<PrimarySkillType> parentSkills = FamilyTree.getParents(skill);
float splitXp = xp / parentSkills.size();
@ -668,7 +669,7 @@ public class McMMOPlayer implements Identified {
Bukkit.getPluginManager().callEvent(mcMMOPlayerPreXpGainEvent);
xp = mcMMOPlayerPreXpGainEvent.getXpGained();
if (mcMMO.p.getSkillTools().isChildSkill(primarySkillType)) {
if (SkillTools.isChildSkill(primarySkillType)) {
Set<PrimarySkillType> parentSkills = FamilyTree.getParents(primarySkillType);
for (PrimarySkillType parentSkill : parentSkills) {

View File

@ -1,7 +1,6 @@
package com.gmail.nossr50.datatypes.player;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.MobHealthbarType;
import com.gmail.nossr50.datatypes.experience.FormulaType;
import com.gmail.nossr50.datatypes.experience.SkillXpGain;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
@ -10,6 +9,7 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.runnables.player.PlayerProfileSaveTask;
import com.gmail.nossr50.skills.child.FamilyTree;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillTools;
import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -27,10 +27,11 @@ public class PlayerProfile {
private volatile boolean changed;
/* HUDs */
private MobHealthbarType mobHealthbarType;
private int scoreboardTipsShown;
private int saveAttempts = 0;
private @Nullable Long lastLogin;
/* Skill Data */
private final Map<PrimarySkillType, Integer> skills = new EnumMap<>(PrimarySkillType.class); // Skill & Level
private final Map<PrimarySkillType, Float> skillsXp = new EnumMap<>(PrimarySkillType.class); // Skill & XP
@ -50,20 +51,22 @@ public class PlayerProfile {
this.uuid = uuid;
this.playerName = playerName;
mobHealthbarType = mcMMO.p.getGeneralConfig().getMobHealthbarDefault();
scoreboardTipsShown = 0;
for (SuperAbilityType superAbilityType : SuperAbilityType.values()) {
abilityDATS.put(superAbilityType, 0);
}
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
skills.put(primarySkillType, mcMMO.p.getAdvancedConfig().getStartingLevel());
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
int startingLvl = mcMMO.p != null ? mcMMO.p.getAdvancedConfig().getStartingLevel() : 0; //TODO: Setup the mock since this was to avoid setting up a mock in a test
skills.put(primarySkillType, startingLvl);
skillsXp.put(primarySkillType, 0F);
}
//Misc Cooldowns
uniquePlayerData.put(UniqueDataType.CHIMAERA_WING_DATS, 0); //Chimaera wing
lastLogin = System.currentTimeMillis();
}
@Deprecated
@ -77,10 +80,9 @@ public class PlayerProfile {
this.loaded = isLoaded;
}
public PlayerProfile(@NotNull String playerName, UUID uuid, Map<PrimarySkillType, Integer> levelData, Map<PrimarySkillType, Float> xpData, Map<SuperAbilityType, Integer> cooldownData, @Nullable MobHealthbarType mobHealthbarType, int scoreboardTipsShown, Map<UniqueDataType, Integer> uniqueProfileData) {
public PlayerProfile(@NotNull String playerName, UUID uuid, Map<PrimarySkillType, Integer> levelData, Map<PrimarySkillType, Float> xpData, Map<SuperAbilityType, Integer> cooldownData, int scoreboardTipsShown, Map<UniqueDataType, Integer> uniqueProfileData, @Nullable Long lastLogin) {
this.playerName = playerName;
this.uuid = uuid;
mobHealthbarType = mcMMO.p.getGeneralConfig().getMobHealthbarDefault();
this.scoreboardTipsShown = scoreboardTipsShown;
skills.putAll(levelData);
@ -89,6 +91,9 @@ public class PlayerProfile {
uniquePlayerData.putAll(uniqueProfileData);
loaded = true;
if(lastLogin != null)
this.lastLogin = lastLogin;
}
public void scheduleAsyncSave() {
@ -115,7 +120,7 @@ public class PlayerProfile {
}
// TODO should this part be synchronized?
PlayerProfile profileCopy = new PlayerProfile(playerName, uuid, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType, scoreboardTipsShown, ImmutableMap.copyOf(uniquePlayerData));
PlayerProfile profileCopy = new PlayerProfile(playerName, uuid, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), scoreboardTipsShown, ImmutableMap.copyOf(uniquePlayerData), lastLogin);
changed = !mcMMO.getDatabaseManager().saveUser(profileCopy);
if (changed) {
@ -149,6 +154,19 @@ public class PlayerProfile {
}
}
/**
* Get this users last login, will return current java.lang.System#currentTimeMillis() if it doesn't exist
* @return the last login
* @deprecated This is only function for FlatFileDB atm and its only here for unit testing right now
*/
@Deprecated
public @NotNull Long getLastLogin() {
if(lastLogin == null)
return System.currentTimeMillis();
else
return lastLogin;
}
public String getPlayerName() {
return playerName;
}
@ -167,20 +185,6 @@ public class PlayerProfile {
return loaded;
}
/*
* Mob Healthbars
*/
public MobHealthbarType getMobHealthbarType() {
return mobHealthbarType;
}
public void setMobHealthbarType(MobHealthbarType mobHealthbarType) {
markProfileDirty();
this.mobHealthbarType = mobHealthbarType;
}
/**
* Marks the profile as "dirty" which flags a profile to be saved in the next save operation
*/
@ -256,7 +260,7 @@ public class PlayerProfile {
*/
public int getSkillLevel(PrimarySkillType skill) {
return mcMMO.p.getSkillTools().isChildSkill(skill) ? getChildSkillLevel(skill) : skills.get(skill);
return SkillTools.isChildSkill(skill) ? getChildSkillLevel(skill) : skills.get(skill);
}
public float getSkillXpLevelRaw(PrimarySkillType skill) {
@ -264,7 +268,7 @@ public class PlayerProfile {
}
public int getSkillXpLevel(PrimarySkillType skill) {
if(mcMMO.p.getSkillTools().isChildSkill(skill)) {
if(SkillTools.isChildSkill(skill)) {
return 0;
}
@ -272,7 +276,7 @@ public class PlayerProfile {
}
public void setSkillXpLevel(PrimarySkillType skill, float xpLevel) {
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
return;
}
@ -299,7 +303,7 @@ public class PlayerProfile {
* @param xp Amount of xp to remove
*/
public void removeXp(PrimarySkillType skill, int xp) {
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
return;
}
@ -309,7 +313,7 @@ public class PlayerProfile {
}
public void removeXp(PrimarySkillType skill, float xp) {
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
return;
}
@ -325,7 +329,7 @@ public class PlayerProfile {
* @param level New level value for the skill
*/
public void modifySkill(PrimarySkillType skill, int level) {
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
return;
}
@ -358,7 +362,7 @@ public class PlayerProfile {
public void addXp(PrimarySkillType skill, float xp) {
markProfileDirty();
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
Set<PrimarySkillType> parentSkills = FamilyTree.getParents(skill);
float dividedXP = (xp / parentSkills.size());
@ -417,7 +421,7 @@ public class PlayerProfile {
* @return the total amount of Xp until next level
*/
public int getXpToLevel(PrimarySkillType primarySkillType) {
if(mcMMO.p.getSkillTools().isChildSkill(primarySkillType)) {
if(SkillTools.isChildSkill(primarySkillType)) {
return 0;
}

View File

@ -191,7 +191,7 @@ public enum PrimarySkillType {
*/
@Deprecated
public boolean isChildSkill() {
return mcMMO.p.getSkillTools().isChildSkill(this);
return SkillTools.isChildSkill(this);
}
/**

View File

@ -12,6 +12,7 @@ import com.gmail.nossr50.util.player.PlayerLevelUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils;
import org.bukkit.entity.Player;
@ -132,7 +133,7 @@ public class SelfListener implements Listener {
return;
}
if (mcMMO.p.getSkillTools().isChildSkill(primarySkillType)) {
if (SkillTools.isChildSkill(primarySkillType)) {
return;
}

View File

@ -4,6 +4,7 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
import com.gmail.nossr50.util.skills.SkillTools;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@ -46,7 +47,7 @@ public class McrankCommandDisplayTask extends BukkitRunnable {
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Heading"));
sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName));
for (PrimarySkillType skill : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) {
// if (!mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, skill)) {
// continue;
// }

View File

@ -10,6 +10,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillTools;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitRunnable;
@ -58,7 +59,7 @@ public class FormulaConversionTask extends BukkitRunnable {
private void editValues(PlayerProfile profile) {
mcMMO.p.debug("========================================================================");
mcMMO.p.debug("Conversion report for " + profile.getPlayerName() + ":");
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
int oldLevel = profile.getSkillLevel(primarySkillType);
int oldXPLevel = profile.getSkillXpLevel(primarySkillType);
int totalOldXP = mcMMO.getFormulaManager().calculateTotalExperience(oldLevel, oldXPLevel);

View File

@ -1,7 +1,7 @@
package com.gmail.nossr50.skills.child;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.skills.SkillTools;
import java.util.Collections;
import java.util.EnumSet;
@ -41,13 +41,13 @@ public class FamilyTree {
}
protected static void enforceChildSkill(PrimarySkillType skill) {
if (!mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (!SkillTools.isChildSkill(skill)) {
throw new IllegalArgumentException(skill.name() + " is not a child skill!");
}
}
protected static void enforceNotChildSkill(PrimarySkillType skill) {
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
throw new IllegalArgumentException(skill.name() + " is a child skill!");
}
}

View File

@ -35,6 +35,7 @@ import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.SkillTools;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
@ -405,7 +406,7 @@ public final class EventUtils {
experienceChanged = event.getExperienceChanged();
PlayerProfile playerProfile = UserManager.getPlayer(player).getProfile();
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
String skillName = primarySkillType.toString();
int playerSkillLevel = playerProfile.getSkillLevel(primarySkillType);
int threshold = mcMMO.p.getGeneralConfig().getHardcoreDeathStatPenaltyLevelThreshold();
@ -454,7 +455,7 @@ public final class EventUtils {
PlayerProfile victimProfile = UserManager.getPlayer(victim).getProfile();
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
String skillName = primarySkillType.toString();
int victimSkillLevel = victimProfile.getSkillLevel(primarySkillType);

View File

@ -6,6 +6,7 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.worldguard.WorldGuardManager;
import com.gmail.nossr50.worldguard.WorldGuardUtils;
import org.bukkit.entity.Player;
@ -34,7 +35,7 @@ public final class HardcoreManager {
HashMap<String, Integer> levelChanged = new HashMap<>();
HashMap<String, Float> experienceChanged = new HashMap<>();
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
if (!mcMMO.p.getGeneralConfig().getHardcoreStatLossEnabled(primarySkillType)) {
levelChanged.put(primarySkillType.toString(), 0);
experienceChanged.put(primarySkillType.toString(), 0F);
@ -86,7 +87,7 @@ public final class HardcoreManager {
HashMap<String, Integer> levelChanged = new HashMap<>();
HashMap<String, Float> experienceChanged = new HashMap<>();
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
if (!mcMMO.p.getGeneralConfig().getHardcoreVampirismEnabled(primarySkillType)) {
levelChanged.put(primarySkillType.toString(), 0);
experienceChanged.put(primarySkillType.toString(), 0F);
@ -135,7 +136,7 @@ public final class HardcoreManager {
public static boolean isStatLossEnabled() {
boolean enabled = false;
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
if (mcMMO.p.getGeneralConfig().getHardcoreStatLossEnabled(primarySkillType)) {
enabled = true;
break;
@ -153,7 +154,7 @@ public final class HardcoreManager {
public static boolean isVampirismEnabled() {
boolean enabled = false;
for (PrimarySkillType primarySkillType : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType primarySkillType : SkillTools.NON_CHILD_SKILLS) {
if (mcMMO.p.getGeneralConfig().getHardcoreVampirismEnabled(primarySkillType)) {
enabled = true;
break;

View File

@ -7,6 +7,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillTools;
import com.gmail.nossr50.util.skills.SkillUtils;
import com.gmail.nossr50.util.text.StringUtils;
import com.google.common.collect.ImmutableList;
@ -25,7 +26,7 @@ public final class CommandUtils {
private CommandUtils() {}
public static boolean isChildSkill(CommandSender sender, PrimarySkillType skill) {
if (skill == null || !mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (skill == null || !SkillTools.isChildSkill(skill)) {
return false;
}
@ -205,7 +206,7 @@ public final class CommandUtils {
}
public static String displaySkill(PlayerProfile profile, PrimarySkillType skill) {
if (mcMMO.p.getSkillTools().isChildSkill(skill)) {
if (SkillTools.isChildSkill(skill)) {
return LocaleLoader.getString("Skills.ChildStats", LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".Listener") + " ", profile.getSkillLevel(skill));
}
if (profile.getSkillLevel(skill) == mcMMO.p.getSkillTools().getLevelCap(skill)){

View File

@ -16,6 +16,7 @@ import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.scoreboards.ScoreboardManager.SidebarType;
import com.gmail.nossr50.util.skills.SkillTools;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -488,7 +489,7 @@ public class ScoreboardWrapper {
case SKILL_BOARD:
Validate.notNull(targetSkill);
if (!mcMMO.p.getSkillTools().isChildSkill(targetSkill)) {
if (!SkillTools.isChildSkill(targetSkill)) {
int currentXP = mcMMOPlayer.getSkillXpLevel(targetSkill);
sidebarObjective.getScore(ScoreboardManager.LABEL_CURRENT_XP).setScore(currentXP);
@ -573,7 +574,7 @@ public class ScoreboardWrapper {
// Calculate power level here
int powerLevel = 0;
for (PrimarySkillType skill : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) { // Don't include child skills, makes the list too long
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) { // Don't include child skills, makes the list too long
int level = newProfile.getSkillLevel(skill);
powerLevel += level;
@ -606,7 +607,7 @@ public class ScoreboardWrapper {
Integer rank;
Player player = mcMMO.p.getServer().getPlayerExact(playerName);
for (PrimarySkillType skill : mcMMO.p.getSkillTools().NON_CHILD_SKILLS) {
for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) {
if (!mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, skill)) {
continue;
}

View File

@ -29,7 +29,7 @@ public class SkillTools {
public final @NotNull ImmutableList<String> FORMATTED_SUBSKILL_NAMES;
public final @NotNull ImmutableSet<String> EXACT_SUBSKILL_NAMES;
public final @NotNull ImmutableList<PrimarySkillType> CHILD_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> NON_CHILD_SKILLS;
public final static @NotNull ImmutableList<PrimarySkillType> NON_CHILD_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> COMBAT_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> GATHERING_SKILLS;
public final @NotNull ImmutableList<PrimarySkillType> MISC_SKILLS;
@ -42,6 +42,16 @@ public class SkillTools {
private final ImmutableMap<PrimarySkillType, SuperAbilityType> mainActivatedAbilityChildMap;
private final ImmutableMap<PrimarySkillType, ToolType> primarySkillToolMap;
static {
ArrayList<PrimarySkillType> tempNonChildSkills = new ArrayList<>();
for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (primarySkillType != PrimarySkillType.SALVAGE && primarySkillType != PrimarySkillType.SMELTING)
tempNonChildSkills.add(primarySkillType);
}
NON_CHILD_SKILLS = ImmutableList.copyOf(tempNonChildSkills);
}
public SkillTools(@NotNull mcMMO pluginRef) {
this.pluginRef = pluginRef;
@ -130,18 +140,18 @@ public class SkillTools {
*/
List<PrimarySkillType> childSkills = new ArrayList<>();
List<PrimarySkillType> nonChildSkills = new ArrayList<>();
// List<PrimarySkillType> nonChildSkills = new ArrayList<>();
for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if (isChildSkill(primarySkillType)) {
if (isChildSkill(primarySkillType))
childSkills.add(primarySkillType);
} else {
nonChildSkills.add(primarySkillType);
}
// } {
// nonChildSkills.add(primarySkillType);
// }
}
CHILD_SKILLS = ImmutableList.copyOf(childSkills);
NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
// NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
/*
* Build categorized skill lists
@ -318,7 +328,7 @@ public class SkillTools {
}
// TODO: This is a little "hacky", we probably need to add something to distinguish child skills in the enum, or to use another enum for them
public boolean isChildSkill(PrimarySkillType primarySkillType) {
public static boolean isChildSkill(PrimarySkillType primarySkillType) {
switch (primarySkillType) {
case SALVAGE:
case SMELTING:

View File

@ -2,6 +2,11 @@ package com.gmail.nossr50.database;
import com.gmail.nossr50.TestUtil;
import com.gmail.nossr50.datatypes.database.DatabaseType;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.datatypes.player.UniqueDataType;
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
import com.gmail.nossr50.util.skills.SkillTools;
import com.google.common.io.Files;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -9,18 +14,14 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.logging.Logger;
import static org.junit.Assert.*;
@ -30,17 +31,39 @@ import static org.junit.Assert.*;
public class FlatFileDatabaseManagerTest {
public static final @NotNull String TEST_FILE_NAME = "test.mcmmo.users";
public static final int HEALTHY_RETURN_CODE = 0;
public static final String BAD_FILE_LINE_ONE = "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:";
public static final 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 BAD_FILE_LINE_ONE = "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:";
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:2020:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:";
public static final @NotNull String HEALTHY_DB_LINE_ONE_UUID_STR = "588fe472-1c82-4c4e-9aa1-7eefccb277e3";
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;
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;
long expectedBerserkCd = 111, expectedGigaDrillBreakerCd = 222, expectedTreeFellerCd = 333,
expectedGreenTerraCd = 444, expectedSerratedStrikesCd = 555, expectedSkullSplitterCd = 666,
expectedSuperBreakerCd = 777, expectedBlastMiningCd = 888, expectedChimaeraWingCd = 999;
int expectedScoreboardTips = 1111;
Long expectedLastLogin = 2020L;
@Before
public void init() {
assertNull(db);
//noinspection UnstableApiUsage
tempDir = Files.createTempDir();
db = new FlatFileDatabaseManager(new File(tempDir.getPath() + File.separator + TEST_FILE_NAME), logger, PURGE_TIME, 0, true);
}
@ -108,6 +131,249 @@ public class FlatFileDatabaseManagerTest {
"mrfloris:2420:::0:2452:0:1983:1937:1790:3042:badvalue: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:"
};
@Test
public void testSaveUser() {
//Make a Profile to save and check to see if it worked
UUID uuid = UUID.fromString("588fe472-1c82-4c4e-9aa1-7eefccb277e3");
String playerName = "nossr50";
PlayerProfile testProfile = new PlayerProfile(playerName, uuid);
//The above profile should be "zero" initialized
//Save the zero version and see if it looks correct
assertNotNull(db);
assertFalse(db.getUsersFile().exists());
db.checkFileHealthAndStructure();
assertTrue(db.getUsersFile().exists()); //Users file should have been created from the above com.gmail.nossr50.database.FlatFileDatabaseManager.checkFileHealthAndStructure
assertNotNull(db.getUsersFile());
//The DB is empty at this point, add our user
assertTrue(db.saveUser(testProfile)); //True means we saved the user
//Check for the empty profile
PlayerProfile retrievedFromData = db.loadPlayerProfile(playerName);
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());
}
@Test
public void testLoadByName() {
}
@Test
public void testLoadByUUID() {
/*
* This test uses a file provided in test resources
*/
ClassLoader classLoader = getClass().getClassLoader();
URI resourceFileURI = null;
try {
resourceFileURI = classLoader.getResource(DB_HEALTHY).toURI();
} catch (URISyntaxException e) {
e.printStackTrace();
}
assertNotNull(resourceFileURI);
File fromResourcesFile = new File(resourceFileURI);
assertNotNull(resourceFileURI);
File copyOfFile = new File(tempDir.getPath() + File.separator + DB_HEALTHY);
if(copyOfFile.exists()) {
//noinspection ResultOfMethodCallIgnored
copyOfFile.delete();
}
assertTrue(fromResourcesFile.exists());
try {
//noinspection UnstableApiUsage
Files.copy(fromResourcesFile, copyOfFile);
} catch (IOException e) {
e.printStackTrace();
}
assertNotNull(copyOfFile);
/*
* 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(copyOfFile);
System.out.println("File Path: "+copyOfFile.getAbsolutePath());
assertArrayEquals(HEALTHY_DB_LINE_1.split(":"), dataFromFile.get(0));
assertEquals(dataFromFile.get(0)[FlatFileDatabaseManager.UUID_INDEX], HEALTHY_DB_LINE_ONE_UUID_STR);
UUID healthDBEntryOneUUID = UUID.fromString(HEALTHY_DB_LINE_ONE_UUID_STR);
FlatFileDatabaseManager db_a = new FlatFileDatabaseManager(copyOfFile, logger, PURGE_TIME, 0, true);
List<FlatFileDataFlag> flagsFound = db_a.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_a.loadPlayerProfile(uuid, null);
testHealthyDataProfileValues(db_a, playerName, uuid, profile);
}
private void testHealthyDataProfileValues(FlatFileDatabaseManager flatFileDatabaseManager, String playerName, UUID uuid, PlayerProfile playerProfile) {
PlayerProfile profile = flatFileDatabaseManager.loadPlayerProfile(uuid, null);
assertTrue(profile.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, profile.getUniqueId());
assertEquals(playerName, profile.getPlayerName());
/*
* Player is a match and data is loaded, check values
*/
for(PrimarySkillType primarySkillType : PrimarySkillType.values()) {
if(SkillTools.isChildSkill(primarySkillType))
continue;
// System.out.println("Checking expected values for: "+primarySkillType);
// System.out.println("Profile Level Value: "+profile.getSkillLevel(primarySkillType));
// System.out.println("Expected Lvl Value: "+getExpectedLevelHealthyDBEntryOne(primarySkillType));
// System.out.println("Profile Exp Value: "+profile.getSkillXpLevelRaw(primarySkillType));
// System.out.println("Expected Exp Value: "+getExpectedExperienceHealthyDBEntryOne(primarySkillType));
assertEquals(getExpectedLevelHealthyDBEntryOne(primarySkillType), profile.getSkillLevel(primarySkillType));
assertEquals(getExpectedExperienceHealthyDBEntryOne(primarySkillType), profile.getSkillXpLevelRaw(primarySkillType), 0);
}
//Check the other things
for(SuperAbilityType superAbilityType : SuperAbilityType.values()) {
assertEquals(getExpectedSuperAbilityDATS(superAbilityType), profile.getAbilityDATS(superAbilityType));
}
assertEquals(expectedChimaeraWingCd, profile.getUniqueData(UniqueDataType.CHIMAERA_WING_DATS));
assertEquals(expectedScoreboardTips, profile.getScoreboardTipsShown());
assertEquals(expectedLastLogin, profile.getLastLogin());
}
private long getExpectedSuperAbilityDATS(@NotNull SuperAbilityType superAbilityType) {
switch(superAbilityType) {
case BERSERK:
return expectedBerserkCd;
case SUPER_BREAKER:
return expectedSuperBreakerCd;
case GIGA_DRILL_BREAKER:
return expectedGigaDrillBreakerCd;
case GREEN_TERRA:
return expectedGreenTerraCd;
case SKULL_SPLITTER:
return expectedSkullSplitterCd;
case TREE_FELLER:
return expectedTreeFellerCd;
case SERRATED_STRIKES:
return expectedSerratedStrikesCd;
case BLAST_MINING:
return expectedBlastMiningCd;
}
return -1;
}
//TODO: Why is this stuff a float?
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 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 UNARMED:
return expectedExpUnarmed;
case WOODCUTTING:
return expectedExpWoodcutting;
}
return -1;
}
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 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 UNARMED:
return expectedLvlUnarmed;
case WOODCUTTING:
return expectedLvlWoodcutting;
}
return -1;
}
@Test
public void testOverwriteName() {
}
@Test
public void testDataNotFound() {
//Save the zero version and see if it looks correct
assertNotNull(db);
assertFalse(db.getUsersFile().exists());
db.checkFileHealthAndStructure();
assertTrue(db.getUsersFile().exists()); //Users file should have been created from the above com.gmail.nossr50.database.FlatFileDatabaseManager.checkFileHealthAndStructure
assertNotNull(db.getUsersFile());
//Check for the "unloaded" profile
PlayerProfile retrievedFromData = db.loadPlayerProfile("nossr50");
assertFalse(retrievedFromData.isLoaded()); //PlayerProfile::isLoaded returns false if data doesn't exist for the user
}
@Test
public void testPurgePowerlessUsers() {
replaceDataInFile(db, normalDatabaseData);
@ -167,14 +433,11 @@ public class FlatFileDatabaseManagerTest {
@Test
public void testLoadFromFile() {
Path resourceDirectory = Paths.get("src","test","resources");
String absolutePath = resourceDirectory.toFile().getAbsolutePath();
ClassLoader classLoader = getClass().getClassLoader();
URI resourceFileURI = null;
try {
resourceFileURI = classLoader.getResource("baddatadb.users").toURI();
resourceFileURI = classLoader.getResource(DB_BADDATA).toURI();
} catch (URISyntaxException e) {
e.printStackTrace();
}
@ -182,7 +445,7 @@ public class FlatFileDatabaseManagerTest {
assertNotNull(resourceFileURI);
File fromResourcesFile = new File(resourceFileURI);
assertNotNull(resourceFileURI);
File copyOfFile = new File(tempDir.getPath() + File.separator + "baddatafile.users");
File copyOfFile = new File(tempDir.getPath() + File.separator + DB_BADDATA);
if(copyOfFile.exists()) {
copyOfFile.delete();
@ -282,7 +545,6 @@ public class FlatFileDatabaseManagerTest {
}
}
}
}
private void overwriteDataAndCheckForFlag(@NotNull FlatFileDatabaseManager targetDatabase, @NotNull String[] data, @NotNull FlatFileDataFlag flag) {

View File

@ -0,0 +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:2020:HEARTS:13:130:588fe472-1c82-4c4e-9aa1-7eefccb277e3:1111:999:
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:
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:0:HEARTS:0:0:e0d07db8-f7e8-43c7-9ded-864dfc6f3b7c:5:1600906906: