mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-08-02 20:45:28 +02:00
Add more tests, fix null name bug
This commit is contained in:
@@ -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);
|
||||
|
||||
/**
|
||||
|
@@ -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) {
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user