From eea5784527cc925763484f80ee2483fd118a85ca Mon Sep 17 00:00:00 2001 From: GJ Date: Thu, 18 Apr 2013 17:37:36 -0400 Subject: [PATCH] Abstract our database operations into a single class. This allows the logic between SQL and Flatfile to remain more hidden in most cases and makes the code easier to read. --- .../commands/database/McpurgeCommand.java | 18 +- .../commands/database/McremoveCommand.java | 20 +- .../commands/player/McrankCommand.java | 60 +- .../nossr50/commands/player/MctopCommand.java | 28 +- .../nossr50/database/DatabaseManager.java | 646 +------------ ...ager.java => FlatfileDatabaseManager.java} | 135 +-- .../nossr50/database/SQLDatabaseManager.java | 628 ++++++++++++ .../datatypes/player/PlayerProfile.java | 895 ++++++++---------- src/main/java/com/gmail/nossr50/mcMMO.java | 18 +- .../commands/McrankCommandAsyncTask.java | 6 +- .../commands/McrankCommandDisplayTask.java | 24 +- .../commands/MctopCommandAsyncTask.java | 6 +- .../runnables/database/SQLConversionTask.java | 24 +- .../runnables/database/SQLReconnectTask.java | 4 +- .../runnables/database/UserPurgeTask.java | 18 +- .../player/PlayerProfileSaveTask.java | 7 +- .../nossr50/util/player/UserManager.java | 16 - .../shatt/backup/ZipLibrary.java | 4 +- 18 files changed, 1181 insertions(+), 1376 deletions(-) rename src/main/java/com/gmail/nossr50/database/{LeaderboardManager.java => FlatfileDatabaseManager.java} (70%) create mode 100644 src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java diff --git a/src/main/java/com/gmail/nossr50/commands/database/McpurgeCommand.java b/src/main/java/com/gmail/nossr50/commands/database/McpurgeCommand.java index 3f9fe2029..06237fab9 100644 --- a/src/main/java/com/gmail/nossr50/commands/database/McpurgeCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/database/McpurgeCommand.java @@ -6,9 +6,8 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; +import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.database.DatabaseManager; -import com.gmail.nossr50.database.LeaderboardManager; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.util.Permissions; @@ -24,19 +23,10 @@ public class McpurgeCommand implements TabExecutor { switch (args.length) { case 0: - if (Config.getInstance().getUseMySQL()) { - DatabaseManager.purgePowerlessSQL(); + mcMMO.databaseManager.purgePowerlessUsers(); - if (Config.getInstance().getOldUsersCutoff() != -1) { - DatabaseManager.purgeOldSQL(); - } - } - else { - LeaderboardManager.purgePowerlessFlatfile(); - - if (Config.getInstance().getOldUsersCutoff() != -1) { - LeaderboardManager.purgeOldFlatfile(); - } + if (Config.getInstance().getOldUsersCutoff() != -1) { + mcMMO.databaseManager.purgeOldUsers(); } sender.sendMessage(LocaleLoader.getString("Commands.mcpurge.Success")); diff --git a/src/main/java/com/gmail/nossr50/commands/database/McremoveCommand.java b/src/main/java/com/gmail/nossr50/commands/database/McremoveCommand.java index 941beb4f7..c996e81bb 100644 --- a/src/main/java/com/gmail/nossr50/commands/database/McremoveCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/database/McremoveCommand.java @@ -9,12 +9,9 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; import org.bukkit.util.StringUtil; -import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.database.DatabaseManager; -import com.gmail.nossr50.database.LeaderboardManager; +import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.commands.CommandUtils; import com.gmail.nossr50.util.player.UserManager; @@ -35,20 +32,11 @@ public class McremoveCommand implements TabExecutor { return true; } - /* MySQL */ - if (Config.getInstance().getUseMySQL()) { - String tablePrefix = Config.getInstance().getMySQLTablePrefix(); - - if (DatabaseManager.update("DELETE FROM " + tablePrefix + "users WHERE " + tablePrefix + "users.user = '" + args[0] + "'") != 0) { - Misc.profileCleanup(args[0]); - sender.sendMessage(LocaleLoader.getString("Commands.mcremove.Success", args[0])); - } + if (mcMMO.databaseManager.removeUser(args[0])) { + sender.sendMessage(LocaleLoader.getString("Commands.mcremove.Success", args[0])); } else { - if (LeaderboardManager.removeFlatFileUser(args[0])) { - Misc.profileCleanup(args[0]); - sender.sendMessage(LocaleLoader.getString("Commands.mcremove.Success", args[0])); - } + sender.sendMessage(args[0] + " could not be removed from the database."); // Pretty sure this should NEVER happen. } return true; diff --git a/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java b/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java index f22b31a91..f007bda10 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java @@ -10,18 +10,12 @@ import org.bukkit.command.TabExecutor; import org.bukkit.util.StringUtil; import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.database.LeaderboardManager; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.player.PlayerProfile; -import com.gmail.nossr50.datatypes.skills.SkillType; -import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.runnables.commands.McrankCommandAsyncTask; 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.SkillUtils; - import com.google.common.collect.ImmutableList; public class McrankCommand implements TabExecutor { @@ -38,13 +32,7 @@ public class McrankCommand implements TabExecutor { return true; } - if (Config.getInstance().getUseMySQL()) { - sqlDisplay(sender, sender.getName()); - } - else { - flatfileDisplay(sender, sender.getName()); - } - + display(sender, sender.getName()); return true; case 1: @@ -62,18 +50,12 @@ public class McrankCommand implements TabExecutor { if (CommandUtils.tooFar(sender, mcMMOPlayer.getPlayer(), Permissions.mcrankFar(sender))) { return true; } - - } else if (CommandUtils.inspectOffline(sender, new PlayerProfile(playerName, false), Permissions.mcrankOffline(sender))) { + } + else if (CommandUtils.inspectOffline(sender, new PlayerProfile(playerName, false), Permissions.mcrankOffline(sender))) { return true; } - if (Config.getInstance().getUseMySQL()) { - sqlDisplay(sender, playerName); - } - else { - flatfileDisplay(sender, playerName); - } - + display(sender, playerName); return true; default: @@ -92,39 +74,7 @@ public class McrankCommand implements TabExecutor { } } - private void flatfileDisplay(CommandSender sender, String playerName) { - LeaderboardManager.updateLeaderboards(); // Make sure the information is up to date - - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Heading")); - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName)); - - for (SkillType skillType : SkillType.values()) { - int[] rankInts = LeaderboardManager.getPlayerRank(playerName, skillType); - - if (!Permissions.skillEnabled(sender, skillType) || skillType.isChildSkill()) { - continue; - } - - if (rankInts[1] == 0) { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", SkillUtils.getSkillName(skillType), LocaleLoader.getString("Commands.mcrank.Unranked"))); // Don't bother showing ranking for players without skills - } - else { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", SkillUtils.getSkillName(skillType), rankInts[0])); - } - } - - // Show the powerlevel ranking - int[] rankInts = LeaderboardManager.getPlayerRank(playerName); - - if (rankInts[1] == 0) { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Overall", LocaleLoader.getString("Commands.mcrank.Unranked"))); // Don't bother showing ranking for players without skills - } - else { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Overall", rankInts[0])); - } - } - - private void sqlDisplay(CommandSender sender, String playerName) { + private void display(CommandSender sender, String playerName) { new McrankCommandAsyncTask(playerName, sender).runTaskAsynchronously(mcMMO.p); } } diff --git a/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java b/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java index 1fb03e9a3..663912609 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java @@ -11,7 +11,7 @@ import org.bukkit.util.StringUtil; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.database.LeaderboardManager; +import com.gmail.nossr50.database.FlatfileDatabaseManager; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.runnables.commands.MctopCommandAsyncTask; @@ -26,17 +26,14 @@ public class MctopCommand implements TabExecutor { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - boolean useMySQL = Config.getInstance().getUseMySQL(); - - switch (args.length) { case 0: - display(1, "ALL", sender, useMySQL, command); + display(1, "ALL", sender, command); return true; case 1: if (StringUtils.isInt(args[0])) { - display(Math.abs(Integer.parseInt(args[0])), "ALL", sender, useMySQL, command); + display(Math.abs(Integer.parseInt(args[0])), "ALL", sender, command); return true; } @@ -44,7 +41,7 @@ public class MctopCommand implements TabExecutor { return true; } - display(1, skill.toString(), sender, useMySQL, command); + display(1, skill.toString(), sender, command); return true; case 2: @@ -56,7 +53,7 @@ public class MctopCommand implements TabExecutor { return true; } - display(Math.abs(Integer.parseInt(args[1])), skill.toString(), sender, useMySQL, command); + display(Math.abs(Integer.parseInt(args[1])), skill.toString(), sender, command); return true; default: @@ -74,19 +71,14 @@ public class MctopCommand implements TabExecutor { } } - private void display(int page, String skill, CommandSender sender, boolean sql, Command command) { + private void display(int page, String skill, CommandSender sender, Command command) { if (!skill.equalsIgnoreCase("all") && !Permissions.mctop(sender, this.skill)) { sender.sendMessage(command.getPermissionMessage()); return; } - if (sql) { - if (skill.equalsIgnoreCase("all")) { - sqlDisplay(page, "taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing", sender); - } - else { - sqlDisplay(page, skill, sender); - } + if (Config.getInstance().getUseMySQL()) { + sqlDisplay(page, skill, sender); } else { flatfileDisplay(page, skill, sender); @@ -94,7 +86,7 @@ public class MctopCommand implements TabExecutor { } private void flatfileDisplay(int page, String skill, CommandSender sender) { - LeaderboardManager.updateLeaderboards(); // Make sure we have the latest information + FlatfileDatabaseManager.updateLeaderboards(); // Make sure we have the latest information if (skill.equalsIgnoreCase("all")) { sender.sendMessage(LocaleLoader.getString("Commands.PowerLevel.Leaderboard")); @@ -105,7 +97,7 @@ public class MctopCommand implements TabExecutor { int position = (page * 10) - 9; - for (String playerStat : LeaderboardManager.retrieveInfo(skill, page)) { + for (String playerStat : FlatfileDatabaseManager.retrieveInfo(skill, page)) { if (playerStat == null) { continue; } diff --git a/src/main/java/com/gmail/nossr50/database/DatabaseManager.java b/src/main/java/com/gmail/nossr50/database/DatabaseManager.java index 32f426985..ecf62411c 100644 --- a/src/main/java/com/gmail/nossr50/database/DatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/DatabaseManager.java @@ -1,643 +1,63 @@ package com.gmail.nossr50.database; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; +import java.io.File; +import java.io.IOException; import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.datatypes.database.DatabaseUpdateType; -import com.gmail.nossr50.datatypes.skills.SkillType; -import com.gmail.nossr50.runnables.database.SQLReconnectTask; import com.gmail.nossr50.util.Misc; -public final class DatabaseManager { - private static String connectionString; +public class DatabaseManager { + private final mcMMO plugin; + private final boolean isUsingSQL; + private File usersFile; - private static String tablePrefix = Config.getInstance().getMySQLTablePrefix(); - private static Connection connection = null; + public DatabaseManager(final mcMMO plugin, final boolean isUsingSQL) { + this.plugin = plugin; + this.isUsingSQL = isUsingSQL; - // Scale waiting time by this much per failed attempt - private static final double SCALING_FACTOR = 40; - - // Minimum wait in nanoseconds (default 500ms) - private static final long MIN_WAIT = 500L * 1000000L; - - // Maximum time to wait between reconnects (default 5 minutes) - private static final long MAX_WAIT = 5L * 60L * 1000L * 1000000L; - - // How long to wait when checking if connection is valid (default 3 seconds) - private static final int VALID_TIMEOUT = 3; - - // When next to try connecting to Database in nanoseconds - private static long nextReconnectTimestamp = 0L; - - // How many connection attempts have failed - private static int reconnectAttempt = 0; - - private static final long ONE_MONTH = 2630000000L; - - private DatabaseManager() {} - - /** - * Attempt to connect to the mySQL database. - */ - public static void connect() { - Config configInstance = Config.getInstance(); - connectionString = "jdbc:mysql://" + configInstance.getMySQLServerName() + ":" + configInstance.getMySQLServerPort() + "/" + configInstance.getMySQLDatabaseName(); - - try { - mcMMO.p.getLogger().info("Attempting connection to MySQL..."); - - // Force driver to load if not yet loaded - Class.forName("com.mysql.jdbc.Driver"); - Properties connectionProperties = new Properties(); - connectionProperties.put("user", configInstance.getMySQLUserName()); - connectionProperties.put("password", configInstance.getMySQLUserPassword()); - connectionProperties.put("autoReconnect", "false"); - connectionProperties.put("maxReconnects", "0"); - connection = DriverManager.getConnection(connectionString, connectionProperties); - - mcMMO.p.getLogger().info("Connection to MySQL was a success!"); + if (isUsingSQL) { + SQLDatabaseManager.checkConnected(); + SQLDatabaseManager.createStructure(); } - catch (SQLException ex) { - connection = null; - - if (reconnectAttempt == 0 || reconnectAttempt >= 11) { - mcMMO.p.getLogger().info("Connection to MySQL failed!"); - } - } - catch (ClassNotFoundException ex) { - connection = null; - - if (reconnectAttempt == 0 || reconnectAttempt >= 11) { - mcMMO.p.getLogger().info("MySQL database driver not found!"); - } + else { + usersFile = new File(mcMMO.getUsersFilePath()); + createFlatfileDatabase(); + FlatfileDatabaseManager.updateLeaderboards(); } } - /** - * Attempt to create the database structure. - */ - public static void createStructure() { - write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "users` (" - + "`id` int(10) unsigned NOT NULL AUTO_INCREMENT," - + "`user` varchar(40) NOT NULL," - + "`lastlogin` int(32) unsigned NOT NULL," - + "PRIMARY KEY (`id`)," - + "UNIQUE KEY `user` (`user`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;"); - write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "huds` (" - + "`user_id` int(10) unsigned NOT NULL," - + "`hudtype` varchar(50) NOT NULL DEFAULT 'STANDARD'," - + "`mobhealthbar` varchar(50) NOT NULL DEFAULT 'HEARTS'," - + "PRIMARY KEY (`user_id`)," - + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " - + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); - write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "cooldowns` (" - + "`user_id` int(10) unsigned NOT NULL," - + "`taming` int(32) unsigned NOT NULL DEFAULT '0'," - + "`mining` int(32) unsigned NOT NULL DEFAULT '0'," - + "`woodcutting` int(32) unsigned NOT NULL DEFAULT '0'," - + "`repair` int(32) unsigned NOT NULL DEFAULT '0'," - + "`unarmed` int(32) unsigned NOT NULL DEFAULT '0'," - + "`herbalism` int(32) unsigned NOT NULL DEFAULT '0'," - + "`excavation` int(32) unsigned NOT NULL DEFAULT '0'," - + "`archery` int(32) unsigned NOT NULL DEFAULT '0'," - + "`swords` int(32) unsigned NOT NULL DEFAULT '0'," - + "`axes` int(32) unsigned NOT NULL DEFAULT '0'," - + "`acrobatics` int(32) unsigned NOT NULL DEFAULT '0'," - + "`blast_mining` int(32) unsigned NOT NULL DEFAULT '0'," - + "PRIMARY KEY (`user_id`)," - + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " - + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); - write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "skills` (" - + "`user_id` int(10) unsigned NOT NULL," - + "`taming` int(10) unsigned NOT NULL DEFAULT '0'," - + "`mining` int(10) unsigned NOT NULL DEFAULT '0'," - + "`woodcutting` int(10) unsigned NOT NULL DEFAULT '0'," - + "`repair` int(10) unsigned NOT NULL DEFAULT '0'," - + "`unarmed` int(10) unsigned NOT NULL DEFAULT '0'," - + "`herbalism` int(10) unsigned NOT NULL DEFAULT '0'," - + "`excavation` int(10) unsigned NOT NULL DEFAULT '0'," - + "`archery` int(10) unsigned NOT NULL DEFAULT '0'," - + "`swords` int(10) unsigned NOT NULL DEFAULT '0'," - + "`axes` int(10) unsigned NOT NULL DEFAULT '0'," - + "`acrobatics` int(10) unsigned NOT NULL DEFAULT '0'," - + "PRIMARY KEY (`user_id`)," - + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " - + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); - write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "experience` (" - + "`user_id` int(10) unsigned NOT NULL," - + "`taming` int(10) unsigned NOT NULL DEFAULT '0'," - + "`mining` int(10) unsigned NOT NULL DEFAULT '0'," - + "`woodcutting` int(10) unsigned NOT NULL DEFAULT '0'," - + "`repair` int(10) unsigned NOT NULL DEFAULT '0'," - + "`unarmed` int(10) unsigned NOT NULL DEFAULT '0'," - + "`herbalism` int(10) unsigned NOT NULL DEFAULT '0'," - + "`excavation` int(10) unsigned NOT NULL DEFAULT '0'," - + "`archery` int(10) unsigned NOT NULL DEFAULT '0'," - + "`swords` int(10) unsigned NOT NULL DEFAULT '0'," - + "`axes` int(10) unsigned NOT NULL DEFAULT '0'," - + "`acrobatics` int(10) unsigned NOT NULL DEFAULT '0'," - + "PRIMARY KEY (`user_id`)," - + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " - + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); - - checkDatabaseStructure(DatabaseUpdateType.FISHING); - checkDatabaseStructure(DatabaseUpdateType.BLAST_MINING); - checkDatabaseStructure(DatabaseUpdateType.CASCADE_DELETE); - checkDatabaseStructure(DatabaseUpdateType.INDEX); - checkDatabaseStructure(DatabaseUpdateType.MOB_HEALTHBARS); + public void purgePowerlessUsers() { + plugin.getLogger().info("Purging powerless users..."); + plugin.getLogger().info("Purged " + (isUsingSQL ? SQLDatabaseManager.purgePowerlessSQL() : FlatfileDatabaseManager.purgePowerlessFlatfile()) + " users from the database."); } - /** - * Attempt to write the SQL query. - * - * @param sql Query to write. - * @return true if the query was successfully written, false otherwise. - */ - public static boolean write(String sql) { - if (!checkConnected()) { - return false; - } - - PreparedStatement statement = null; - try { - statement = connection.prepareStatement(sql); - statement.executeUpdate(); - return true; - } - catch (SQLException ex) { - printErrors(ex); - return false; - } - finally { - if (statement != null) { - try { - statement.close(); - } - catch (SQLException e) { - printErrors(e); - } - } - } + public void purgeOldUsers() { + plugin.getLogger().info("Purging old users..."); + plugin.getLogger().info("Purged " + (isUsingSQL ? SQLDatabaseManager.purgeOldSQL() : FlatfileDatabaseManager.removeOldFlatfileUsers()) + " users from the database."); } - /** - * Returns the number of rows affected by either a DELETE or UPDATE query - * - * @param sql SQL query to execute - * @return the number of rows affected - */ - public static int update(String sql) { - if (!checkConnected()) { - return 0; - } - - int rows = 0; - - PreparedStatement statement = null; - try { - statement = connection.prepareStatement(sql); - rows = statement.executeUpdate(); - } - catch (SQLException ex) { - printErrors(ex); - } - finally { - if (statement != null) { - try { - statement.close(); - } - catch (SQLException e) { - printErrors(e); - } - } - } - - return rows; - } - - /** - * Get the Integer. Only return first row / first field. - * - * @param sql SQL query to execute - * @return the value in the first row / first field - */ - public static int getInt(String sql) { - if (!checkConnected()) { - return 0; - } - - int result = 0; - - PreparedStatement statement = null; - - try { - statement = connection.prepareStatement(sql); - ResultSet resultSet = statement.executeQuery(); - - if (resultSet.next()) { - result = resultSet.getInt(1); - } - } - catch (SQLException ex) { - printErrors(ex); - } - finally { - if (statement != null) { - try { - statement.close(); - } - catch (SQLException e) { - printErrors(e); - } - } - } - - return result; - } - - /** - * Check connection status and re-establish if dead or stale. - * - * If the very first immediate attempt fails, further attempts - * will be made in progressively larger intervals up to MAX_WAIT - * intervals. - * - * This allows for MySQL to time out idle connections as needed by - * server operator, without affecting McMMO, while still providing - * protection against a database outage taking down Bukkit's tick - * processing loop due to attemping a database connection each - * time McMMO needs the database. - * - * @return the boolean value for whether or not we are connected - */ - public static boolean checkConnected() { - boolean isClosed = true; - boolean isValid = false; - boolean exists = (connection != null); - - // If we're waiting for server to recover then leave early - if (nextReconnectTimestamp > 0 && nextReconnectTimestamp > System.nanoTime()) { - return false; - } - - if (exists) { - try { - isClosed = connection.isClosed(); - } - catch (SQLException e) { - isClosed = true; - e.printStackTrace(); - printErrors(e); - } - - if (!isClosed) { - try { - isValid = connection.isValid(VALID_TIMEOUT); - } - catch (SQLException e) { - // Don't print stack trace because it's valid to lose idle connections to the server and have to restart them. - isValid = false; - } - } - } - - // Leave if all ok - if (exists && !isClosed && isValid) { - // Housekeeping - nextReconnectTimestamp = 0; - reconnectAttempt = 0; + public boolean removeUser(String playerName) { + if (isUsingSQL ? SQLDatabaseManager.removeUserSQL(playerName) : FlatfileDatabaseManager.removeFlatFileUser(playerName)) { + Misc.profileCleanup(playerName); return true; } - // Cleanup after ourselves for GC and MySQL's sake - if (exists && !isClosed) { - try { - connection.close(); - } - catch (SQLException ex) { - // This is a housekeeping exercise, ignore errors - } - } - - // Try to connect again - connect(); - - // Leave if connection is good - try { - if (connection != null && !connection.isClosed()) { - // Schedule a database save if we really had an outage - if (reconnectAttempt > 1) { - new SQLReconnectTask().runTaskLater(mcMMO.p, 5); - } - nextReconnectTimestamp = 0; - reconnectAttempt = 0; - return true; - } - } - catch (SQLException e) { - // Failed to check isClosed, so presume connection is bad and attempt later - e.printStackTrace(); - printErrors(e); - } - - reconnectAttempt++; - nextReconnectTimestamp = (long)(System.nanoTime() + Math.min(MAX_WAIT, (reconnectAttempt * SCALING_FACTOR * MIN_WAIT))); return false; } - /** - * Read SQL query. - * - * @param sql SQL query to read - * @return the rows in this SQL query - */ - public static HashMap> read(String sql) { - ResultSet resultSet; - HashMap> rows = new HashMap>(); - - if (checkConnected()) { - PreparedStatement statement = null; - - try { - statement = connection.prepareStatement(sql); - resultSet = statement.executeQuery(); - - while (resultSet.next()) { - ArrayList column = new ArrayList(); - - for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) { - column.add(resultSet.getString(i)); - } - - rows.put(resultSet.getRow(), column); - } - } - catch (SQLException ex) { - printErrors(ex); - } - finally { - if (statement != null) { - try { - statement.close(); - } - catch (SQLException e) { - printErrors(e); - } - } - } + private void createFlatfileDatabase() { + if (usersFile.exists()) { + return; } - return rows; - } + usersFile.getParentFile().mkdir(); - public static Map readSQLRank(String playerName) { - ResultSet resultSet; - Map skills = new HashMap(); - - if (checkConnected()) { - try { - for (SkillType skillType : SkillType.values()) { - if (skillType.isChildSkill()) { - continue; - } - - String skillName = skillType.name().toLowerCase(); - String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " + - "AND " + skillName + " > (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + - "WHERE user = ?)"; - - PreparedStatement statement = connection.prepareStatement(sql); - statement.setString(1, playerName); - resultSet = statement.executeQuery(); - - resultSet.next(); - - int rank = resultSet.getInt("rank"); - - sql = "SELECT user, " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " + - "AND " + skillName + " = (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + - "WHERE user = '" + playerName + "') ORDER BY user"; - - statement = connection.prepareStatement(sql); - resultSet = statement.executeQuery(); - - while (resultSet.next()) { - if (resultSet.getString("user").equalsIgnoreCase(playerName)) { - skills.put(skillType.name(), rank + resultSet.getRow()); - break; - } - } - - statement.close(); - } - - String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + - "WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > 0 " + - "AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > " + - "(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " + - "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?)"; - - PreparedStatement statement = connection.prepareStatement(sql); - statement.setString(1, playerName); - resultSet = statement.executeQuery(); - - resultSet.next(); - - int rank = resultSet.getInt("rank"); - - sql = "SELECT user, taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " + - "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + - "WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > 0 " + - "AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing = " + - "(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " + - "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?) ORDER BY user"; - - statement = connection.prepareStatement(sql); - statement.setString(1, playerName); - resultSet = statement.executeQuery(); - - while (resultSet.next()) { - if (resultSet.getString("user").equalsIgnoreCase(playerName)) { - skills.put("ALL", rank + resultSet.getRow()); - break; - } - } - - statement.close(); - } - catch (SQLException ex) { - printErrors(ex); - } - } - - return skills; - } - - public static void purgePowerlessSQL() { - mcMMO.p.getLogger().info("Purging powerless users..."); - HashMap> usernames; - - usernames = read("SELECT u.user FROM " + tablePrefix + "skills AS s, " + tablePrefix + "users AS u " + "WHERE s.user_id = u.id AND " + - "(s.taming+s.mining+s.woodcutting+s.repair+s.unarmed+s.herbalism+s.excavation+s.archery+s.swords+s.axes+s.acrobatics+s.fishing) = 0"); - - write("DELETE FROM " + tablePrefix + "users WHERE " + tablePrefix + "users.id IN (SELECT * FROM " + - "(SELECT u.id FROM " + tablePrefix + "skills AS s, " + tablePrefix + "users AS u " + "WHERE s.user_id = u.id " + - "AND (s.taming+s.mining+s.woodcutting+s.repair+s.unarmed+s.herbalism+s.excavation+s.archery+s.swords+s.axes+s.acrobatics+s.fishing) = 0) AS p)"); - - int purgedUsers = 0; - for (int i = 1; i <= usernames.size(); i++) { - String playerName = usernames.get(i).get(0); - - if (playerName == null || mcMMO.p.getServer().getOfflinePlayer(playerName).isOnline()) { - continue; - } - - Misc.profileCleanup(playerName); - purgedUsers++; - } - - mcMMO.p.getLogger().info("Purged " + purgedUsers + " users from the database."); - } - - public static void purgeOldSQL() { - mcMMO.p.getLogger().info("Purging old users..."); - long currentTime = System.currentTimeMillis(); - long purgeTime = ONE_MONTH * Config.getInstance().getOldUsersCutoff(); - HashMap> usernames = read("SELECT user FROM " + tablePrefix + "users WHERE ((" + currentTime + " - lastlogin*1000) > " + purgeTime + ")"); - write("DELETE FROM " + tablePrefix + "users WHERE " + tablePrefix + "users.id IN (SELECT * FROM (SELECT id FROM " + tablePrefix + "users WHERE ((" + currentTime + " - lastlogin*1000) > " + purgeTime + ")) AS p)"); - - int purgedUsers = 0; - for (int i = 1; i <= usernames.size(); i++) { - String playerName = usernames.get(i).get(0); - - if (playerName == null) { - continue; - } - - Misc.profileCleanup(playerName); - purgedUsers++; - } - - mcMMO.p.getLogger().info("Purged " + purgedUsers + " users from the database."); - } - - /** - * Check database structure for missing values. - * - * @param update Type of data to check updates for - */ - private static void checkDatabaseStructure(DatabaseUpdateType update) { - String sql = null; - ResultSet resultSet = null; - HashMap> rows = new HashMap>(); - - switch (update) { - case BLAST_MINING: - sql = "SELECT * FROM `" + tablePrefix + "cooldowns` ORDER BY `" + tablePrefix + "cooldowns`.`blast_mining` ASC LIMIT 0 , 30"; - break; - - case CASCADE_DELETE: - write("ALTER TABLE `" + tablePrefix + "huds` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); - write("ALTER TABLE `" + tablePrefix + "experience` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); - write("ALTER TABLE `" + tablePrefix + "cooldowns` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); - write("ALTER TABLE `" + tablePrefix + "skills` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); - break; - - case FISHING: - sql = "SELECT * FROM `" + tablePrefix + "experience` ORDER BY `" + tablePrefix + "experience`.`fishing` ASC LIMIT 0 , 30"; - break; - - case INDEX: - if (read("SHOW INDEX FROM " + tablePrefix + "skills").size() != 13 && checkConnected()) { - mcMMO.p.getLogger().info("Indexing tables, this may take a while on larger databases"); - write("ALTER TABLE `" + tablePrefix + "skills` ADD INDEX `idx_taming` (`taming`) USING BTREE, " - + "ADD INDEX `idx_mining` (`mining`) USING BTREE, " - + "ADD INDEX `idx_woodcutting` (`woodcutting`) USING BTREE, " - + "ADD INDEX `idx_repair` (`repair`) USING BTREE, " - + "ADD INDEX `idx_unarmed` (`unarmed`) USING BTREE, " - + "ADD INDEX `idx_herbalism` (`herbalism`) USING BTREE, " - + "ADD INDEX `idx_excavation` (`excavation`) USING BTREE, " - + "ADD INDEX `idx_archery` (`archery`) USING BTREE, " - + "ADD INDEX `idx_swords` (`swords`) USING BTREE, " - + "ADD INDEX `idx_axes` (`axes`) USING BTREE, " - + "ADD INDEX `idx_acrobatics` (`acrobatics`) USING BTREE, " - + "ADD INDEX `idx_fishing` (`fishing`) USING BTREE;"); - } - break; - - case MOB_HEALTHBARS: - sql = "SELECT * FROM `" + tablePrefix + "huds` ORDER BY `" + tablePrefix + "huds`.`mobhealthbar` ASC LIMIT 0 , 30"; - break; - - default: - break; - } - - PreparedStatement statement = null; try { - if (!checkConnected()) { - return; - } - - statement = connection.prepareStatement(sql); - resultSet = statement.executeQuery(); - - while (resultSet.next()) { - ArrayList column = new ArrayList(); - - for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) { - column.add(resultSet.getString(i)); - } - - rows.put(resultSet.getRow(), column); - } + plugin.debug("Creating mcmmo.users file..."); + new File(mcMMO.getUsersFilePath()).createNewFile(); } - catch (SQLException ex) { - switch (update) { - case BLAST_MINING: - mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Blast Mining..."); - write("ALTER TABLE `"+tablePrefix + "cooldowns` ADD `blast_mining` int(32) NOT NULL DEFAULT '0' ;"); - break; - - case FISHING: - mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Fishing..."); - write("ALTER TABLE `"+tablePrefix + "skills` ADD `fishing` int(10) NOT NULL DEFAULT '0' ;"); - write("ALTER TABLE `"+tablePrefix + "experience` ADD `fishing` int(10) NOT NULL DEFAULT '0' ;"); - break; - - case MOB_HEALTHBARS: - mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for mob healthbars..."); - write("ALTER TABLE `" + tablePrefix + "huds` ADD `mobhealthbar` varchar(50) NOT NULL DEFAULT 'HEARTS' ;"); - break; - - default: - break; - } + catch (IOException e) { + e.printStackTrace(); } - finally { - if (statement != null) { - try { - statement.close(); - } - catch (SQLException e) { - // Ignore the error, we're leaving - } - } - } - } - - private static void printErrors(SQLException ex) { - mcMMO.p.getLogger().severe("SQLException: " + ex.getMessage()); - mcMMO.p.getLogger().severe("SQLState: " + ex.getSQLState()); - mcMMO.p.getLogger().severe("VendorError: " + ex.getErrorCode()); } } diff --git a/src/main/java/com/gmail/nossr50/database/LeaderboardManager.java b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java similarity index 70% rename from src/main/java/com/gmail/nossr50/database/LeaderboardManager.java rename to src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java index cd21c9456..d3447b411 100644 --- a/src/main/java/com/gmail/nossr50/database/LeaderboardManager.java +++ b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; +import java.util.Map; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; @@ -16,7 +17,7 @@ import com.gmail.nossr50.datatypes.database.PlayerStat; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.util.StringUtils; -public final class LeaderboardManager { +public final class FlatfileDatabaseManager { private static HashMap> playerStatHash = new HashMap>(); private static List powerLevels = new ArrayList(); private static long lastUpdate = 0; @@ -24,7 +25,7 @@ public final class LeaderboardManager { private static final long UPDATE_WAIT_TIME = 600000L; // 10 minutes private static final long ONE_MONTH = 2630000000L; - private LeaderboardManager() {} + private FlatfileDatabaseManager() {} /** * Update the leader boards. @@ -35,6 +36,7 @@ public final class LeaderboardManager { return; } + String usersFilePath = mcMMO.getUsersFilePath(); lastUpdate = System.currentTimeMillis(); // Log when the last update was run powerLevels.clear(); // Clear old values from the power levels @@ -54,8 +56,7 @@ public final class LeaderboardManager { // Read from the FlatFile database and fill our arrays with information try { - FileReader file = new FileReader(mcMMO.getUsersFilePath()); - BufferedReader in = new BufferedReader(file); + BufferedReader in = new BufferedReader(new FileReader(usersFilePath)); String line = ""; ArrayList players = new ArrayList(); @@ -72,72 +73,25 @@ public final class LeaderboardManager { players.add(playerName); - if (data.length > 1 && StringUtils.isInt(data[1])) { - mining.add(new PlayerStat(playerName, Integer.parseInt(data[1]))); - powerLevel += Integer.parseInt(data[1]); - } - - if (data.length > 5 && StringUtils.isInt(data[5])) { - woodcutting.add(new PlayerStat(playerName, Integer.parseInt(data[5]))); - powerLevel += Integer.parseInt(data[5]); - } - - if (data.length > 7 && StringUtils.isInt(data[7])) { - repair.add(new PlayerStat(playerName, Integer.parseInt(data[7]))); - powerLevel += Integer.parseInt(data[7]); - } - - if (data.length > 8 && StringUtils.isInt(data[8])) { - unarmed.add(new PlayerStat(playerName, Integer.parseInt(data[8]))); - powerLevel += Integer.parseInt(data[8]); - } - - if (data.length > 9 && StringUtils.isInt(data[9])) { - herbalism.add(new PlayerStat(playerName, Integer.parseInt(data[9]))); - powerLevel += Integer.parseInt(data[9]); - } - - if (data.length > 10 && StringUtils.isInt(data[10])) { - excavation.add(new PlayerStat(playerName, Integer.parseInt(data[10]))); - powerLevel += Integer.parseInt(data[10]); - } - - if (data.length > 11 && StringUtils.isInt(data[11])) { - archery.add(new PlayerStat(playerName, Integer.parseInt(data[11]))); - powerLevel += Integer.parseInt(data[11]); - } - - if (data.length > 12 && StringUtils.isInt(data[12])) { - swords.add(new PlayerStat(playerName, Integer.parseInt(data[12]))); - powerLevel += Integer.parseInt(data[12]); - } - - if (data.length > 13 && StringUtils.isInt(data[13])) { - axes.add(new PlayerStat(playerName, Integer.parseInt(data[13]))); - powerLevel += Integer.parseInt(data[13]); - } - - if (data.length > 14 && StringUtils.isInt(data[14])) { - acrobatics.add(new PlayerStat(playerName, Integer.parseInt(data[14]))); - powerLevel += Integer.parseInt(data[14]); - } - - if (data.length > 24 && StringUtils.isInt(data[24])) { - taming.add(new PlayerStat(playerName, Integer.parseInt(data[24]))); - powerLevel += Integer.parseInt(data[24]); - } - - if (data.length > 34 && StringUtils.isInt(data[34])) { - fishing.add(new PlayerStat(playerName, Integer.parseInt(data[34]))); - powerLevel += Integer.parseInt(data[34]); - } + powerLevel += loadStat(mining, playerName, data, 1); + powerLevel += loadStat(woodcutting, playerName, data, 5); + powerLevel += loadStat(repair, playerName, data, 7); + powerLevel += loadStat(unarmed, playerName, data, 8); + powerLevel += loadStat(herbalism, playerName, data, 9); + powerLevel += loadStat(excavation, playerName, data, 10); + powerLevel += loadStat(archery, playerName, data, 11); + powerLevel += loadStat(swords, playerName, data, 12); + powerLevel += loadStat(axes, playerName, data, 13); + powerLevel += loadStat(acrobatics, playerName, data, 14); + powerLevel += loadStat(taming, playerName, data, 24); + powerLevel += loadStat(fishing, playerName, data, 34); powerLevels.add(new PlayerStat(playerName, powerLevel)); } in.close(); } catch (Exception e) { - mcMMO.p.getLogger().severe("Exception while reading " + mcMMO.getUsersFilePath() + " (Are you sure you formatted it correctly?)" + e.toString()); + mcMMO.p.getLogger().severe("Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?)" + e.toString()); } SkillComparator c = new SkillComparator(); @@ -203,14 +157,6 @@ public final class LeaderboardManager { return info; } - public static int[] getPlayerRank(String playerName) { - return getPlayerRank(playerName, powerLevels); - } - - public static int[] getPlayerRank(String playerName, SkillType skillType) { - return getPlayerRank(playerName, playerStatHash.get(skillType)); - } - public static boolean removeFlatFileUser(String playerName) { boolean worked = false; @@ -266,7 +212,7 @@ public final class LeaderboardManager { return worked; } - public static void purgePowerlessFlatfile() { + public static int purgePowerlessFlatfile() { mcMMO.p.getLogger().info("Purging powerless users..."); int purgedUsers = 0; @@ -277,16 +223,10 @@ public final class LeaderboardManager { } } - mcMMO.p.getLogger().info("Purged " + purgedUsers + " users from the database."); + return purgedUsers; } - public static void purgeOldFlatfile() { - mcMMO.p.getLogger().info("Purging old users..."); - int purgedUsers = removeOldFlatfileUsers(); - mcMMO.p.getLogger().info("Purged " + purgedUsers + " users from the database."); - } - - private static int removeOldFlatfileUsers() { + public static int removeOldFlatfileUsers() { int removedPlayers = 0; long currentTime = System.currentTimeMillis(); long purgeTime = ONE_MONTH * Config.getInstance().getOldUsersCutoff(); @@ -350,22 +290,47 @@ public final class LeaderboardManager { return removedPlayers; } - private static int[] getPlayerRank(String playerName, List statsList) { + private static Integer getPlayerRank(String playerName, List statsList) { int currentPos = 1; if (statsList == null) { - return new int[] {0, 0}; + return null; } for (PlayerStat stat : statsList) { if (stat.name.equalsIgnoreCase(playerName)) { - return new int[] {currentPos, stat.statVal}; + return currentPos; } currentPos++; } - return new int[] {0, 0}; + return null; + } + + public static Map getPlayerRanks(String playerName) { + updateLeaderboards(); + + Map skills = new HashMap(); + + for (SkillType skill : SkillType.values()) { + skills.put(playerName, getPlayerRank(playerName, playerStatHash.get(skill))); + } + + skills.put("ALL", getPlayerRank(playerName, powerLevels)); + + return skills; + } + + private static int loadStat(List statList, String playerName, String[] data, int dataIndex) { + if (data.length > dataIndex) { + int statValue = Integer.parseInt(data[dataIndex]); + + statList.add(new PlayerStat(playerName, statValue)); + return statValue; + } + + return 0; } private static class SkillComparator implements Comparator { diff --git a/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java new file mode 100644 index 000000000..c286e3f09 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java @@ -0,0 +1,628 @@ +package com.gmail.nossr50.database; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.datatypes.database.DatabaseUpdateType; +import com.gmail.nossr50.datatypes.skills.SkillType; +import com.gmail.nossr50.runnables.database.SQLReconnectTask; +import com.gmail.nossr50.util.Misc; + +public final class SQLDatabaseManager { + private static String connectionString; + + private static String tablePrefix = Config.getInstance().getMySQLTablePrefix(); + private static Connection connection = null; + + // Scale waiting time by this much per failed attempt + private static final double SCALING_FACTOR = 40; + + // Minimum wait in nanoseconds (default 500ms) + private static final long MIN_WAIT = 500L * 1000000L; + + // Maximum time to wait between reconnects (default 5 minutes) + private static final long MAX_WAIT = 5L * 60L * 1000L * 1000000L; + + // How long to wait when checking if connection is valid (default 3 seconds) + private static final int VALID_TIMEOUT = 3; + + // When next to try connecting to Database in nanoseconds + private static long nextReconnectTimestamp = 0L; + + // How many connection attempts have failed + private static int reconnectAttempt = 0; + + private static final long ONE_MONTH = 2630000000L; + + private SQLDatabaseManager() {} + + /** + * Attempt to connect to the mySQL database. + */ + public static void connect() { + Config configInstance = Config.getInstance(); + connectionString = "jdbc:mysql://" + configInstance.getMySQLServerName() + ":" + configInstance.getMySQLServerPort() + "/" + configInstance.getMySQLDatabaseName(); + + try { + mcMMO.p.getLogger().info("Attempting connection to MySQL..."); + + // Force driver to load if not yet loaded + Class.forName("com.mysql.jdbc.Driver"); + Properties connectionProperties = new Properties(); + connectionProperties.put("user", configInstance.getMySQLUserName()); + connectionProperties.put("password", configInstance.getMySQLUserPassword()); + connectionProperties.put("autoReconnect", "false"); + connectionProperties.put("maxReconnects", "0"); + connection = DriverManager.getConnection(connectionString, connectionProperties); + + mcMMO.p.getLogger().info("Connection to MySQL was a success!"); + } + catch (SQLException ex) { + connection = null; + + if (reconnectAttempt == 0 || reconnectAttempt >= 11) { + mcMMO.p.getLogger().info("Connection to MySQL failed!"); + } + } + catch (ClassNotFoundException ex) { + connection = null; + + if (reconnectAttempt == 0 || reconnectAttempt >= 11) { + mcMMO.p.getLogger().info("MySQL database driver not found!"); + } + } + } + + /** + * Attempt to create the database structure. + */ + public static void createStructure() { + write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "users` (" + + "`id` int(10) unsigned NOT NULL AUTO_INCREMENT," + + "`user` varchar(40) NOT NULL," + + "`lastlogin` int(32) unsigned NOT NULL," + + "PRIMARY KEY (`id`)," + + "UNIQUE KEY `user` (`user`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;"); + write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "huds` (" + + "`user_id` int(10) unsigned NOT NULL," + + "`hudtype` varchar(50) NOT NULL DEFAULT 'STANDARD'," + + "`mobhealthbar` varchar(50) NOT NULL DEFAULT 'HEARTS'," + + "PRIMARY KEY (`user_id`)," + + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " + + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); + write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "cooldowns` (" + + "`user_id` int(10) unsigned NOT NULL," + + "`taming` int(32) unsigned NOT NULL DEFAULT '0'," + + "`mining` int(32) unsigned NOT NULL DEFAULT '0'," + + "`woodcutting` int(32) unsigned NOT NULL DEFAULT '0'," + + "`repair` int(32) unsigned NOT NULL DEFAULT '0'," + + "`unarmed` int(32) unsigned NOT NULL DEFAULT '0'," + + "`herbalism` int(32) unsigned NOT NULL DEFAULT '0'," + + "`excavation` int(32) unsigned NOT NULL DEFAULT '0'," + + "`archery` int(32) unsigned NOT NULL DEFAULT '0'," + + "`swords` int(32) unsigned NOT NULL DEFAULT '0'," + + "`axes` int(32) unsigned NOT NULL DEFAULT '0'," + + "`acrobatics` int(32) unsigned NOT NULL DEFAULT '0'," + + "`blast_mining` int(32) unsigned NOT NULL DEFAULT '0'," + + "PRIMARY KEY (`user_id`)," + + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " + + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); + write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "skills` (" + + "`user_id` int(10) unsigned NOT NULL," + + "`taming` int(10) unsigned NOT NULL DEFAULT '0'," + + "`mining` int(10) unsigned NOT NULL DEFAULT '0'," + + "`woodcutting` int(10) unsigned NOT NULL DEFAULT '0'," + + "`repair` int(10) unsigned NOT NULL DEFAULT '0'," + + "`unarmed` int(10) unsigned NOT NULL DEFAULT '0'," + + "`herbalism` int(10) unsigned NOT NULL DEFAULT '0'," + + "`excavation` int(10) unsigned NOT NULL DEFAULT '0'," + + "`archery` int(10) unsigned NOT NULL DEFAULT '0'," + + "`swords` int(10) unsigned NOT NULL DEFAULT '0'," + + "`axes` int(10) unsigned NOT NULL DEFAULT '0'," + + "`acrobatics` int(10) unsigned NOT NULL DEFAULT '0'," + + "PRIMARY KEY (`user_id`)," + + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " + + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); + write("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "experience` (" + + "`user_id` int(10) unsigned NOT NULL," + + "`taming` int(10) unsigned NOT NULL DEFAULT '0'," + + "`mining` int(10) unsigned NOT NULL DEFAULT '0'," + + "`woodcutting` int(10) unsigned NOT NULL DEFAULT '0'," + + "`repair` int(10) unsigned NOT NULL DEFAULT '0'," + + "`unarmed` int(10) unsigned NOT NULL DEFAULT '0'," + + "`herbalism` int(10) unsigned NOT NULL DEFAULT '0'," + + "`excavation` int(10) unsigned NOT NULL DEFAULT '0'," + + "`archery` int(10) unsigned NOT NULL DEFAULT '0'," + + "`swords` int(10) unsigned NOT NULL DEFAULT '0'," + + "`axes` int(10) unsigned NOT NULL DEFAULT '0'," + + "`acrobatics` int(10) unsigned NOT NULL DEFAULT '0'," + + "PRIMARY KEY (`user_id`)," + + "FOREIGN KEY (`user_id`) REFERENCES `" + tablePrefix + "users` (`id`) " + + "ON DELETE CASCADE) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); + + checkDatabaseStructure(DatabaseUpdateType.FISHING); + checkDatabaseStructure(DatabaseUpdateType.BLAST_MINING); + checkDatabaseStructure(DatabaseUpdateType.CASCADE_DELETE); + checkDatabaseStructure(DatabaseUpdateType.INDEX); + checkDatabaseStructure(DatabaseUpdateType.MOB_HEALTHBARS); + } + + /** + * Attempt to write the SQL query. + * + * @param sql Query to write. + * @return true if the query was successfully written, false otherwise. + */ + public static boolean write(String sql) { + if (!checkConnected()) { + return false; + } + + PreparedStatement statement = null; + try { + statement = connection.prepareStatement(sql); + statement.executeUpdate(); + return true; + } + catch (SQLException ex) { + printErrors(ex); + return false; + } + finally { + if (statement != null) { + try { + statement.close(); + } + catch (SQLException e) { + printErrors(e); + } + } + } + } + + public static boolean removeUserSQL(String playerName) { + return SQLDatabaseManager.update("DELETE FROM " + tablePrefix + "users WHERE " + tablePrefix + "users.user = '" + playerName + "'") != 0; + } + + /** + * Returns the number of rows affected by either a DELETE or UPDATE query + * + * @param sql SQL query to execute + * @return the number of rows affected + */ + public static int update(String sql) { + if (!checkConnected()) { + return 0; + } + + int rows = 0; + + PreparedStatement statement = null; + try { + statement = connection.prepareStatement(sql); + rows = statement.executeUpdate(); + } + catch (SQLException ex) { + printErrors(ex); + } + finally { + if (statement != null) { + try { + statement.close(); + } + catch (SQLException e) { + printErrors(e); + } + } + } + + return rows; + } + + /** + * Get the Integer. Only return first row / first field. + * + * @param sql SQL query to execute + * @return the value in the first row / first field + */ + public static int getInt(String sql) { + if (!checkConnected()) { + return 0; + } + + int result = 0; + + PreparedStatement statement = null; + + try { + statement = connection.prepareStatement(sql); + ResultSet resultSet = statement.executeQuery(); + + if (resultSet.next()) { + result = resultSet.getInt(1); + } + } + catch (SQLException ex) { + printErrors(ex); + } + finally { + if (statement != null) { + try { + statement.close(); + } + catch (SQLException e) { + printErrors(e); + } + } + } + + return result; + } + + /** + * Check connection status and re-establish if dead or stale. + * + * If the very first immediate attempt fails, further attempts + * will be made in progressively larger intervals up to MAX_WAIT + * intervals. + * + * This allows for MySQL to time out idle connections as needed by + * server operator, without affecting McMMO, while still providing + * protection against a database outage taking down Bukkit's tick + * processing loop due to attemping a database connection each + * time McMMO needs the database. + * + * @return the boolean value for whether or not we are connected + */ + public static boolean checkConnected() { + boolean isClosed = true; + boolean isValid = false; + boolean exists = (connection != null); + + // If we're waiting for server to recover then leave early + if (nextReconnectTimestamp > 0 && nextReconnectTimestamp > System.nanoTime()) { + return false; + } + + if (exists) { + try { + isClosed = connection.isClosed(); + } + catch (SQLException e) { + isClosed = true; + e.printStackTrace(); + printErrors(e); + } + + if (!isClosed) { + try { + isValid = connection.isValid(VALID_TIMEOUT); + } + catch (SQLException e) { + // Don't print stack trace because it's valid to lose idle connections to the server and have to restart them. + isValid = false; + } + } + } + + // Leave if all ok + if (exists && !isClosed && isValid) { + // Housekeeping + nextReconnectTimestamp = 0; + reconnectAttempt = 0; + return true; + } + + // Cleanup after ourselves for GC and MySQL's sake + if (exists && !isClosed) { + try { + connection.close(); + } + catch (SQLException ex) { + // This is a housekeeping exercise, ignore errors + } + } + + // Try to connect again + connect(); + + // Leave if connection is good + try { + if (connection != null && !connection.isClosed()) { + // Schedule a database save if we really had an outage + if (reconnectAttempt > 1) { + new SQLReconnectTask().runTaskLater(mcMMO.p, 5); + } + nextReconnectTimestamp = 0; + reconnectAttempt = 0; + return true; + } + } + catch (SQLException e) { + // Failed to check isClosed, so presume connection is bad and attempt later + e.printStackTrace(); + printErrors(e); + } + + reconnectAttempt++; + nextReconnectTimestamp = (long)(System.nanoTime() + Math.min(MAX_WAIT, (reconnectAttempt * SCALING_FACTOR * MIN_WAIT))); + return false; + } + + /** + * Read SQL query. + * + * @param sql SQL query to read + * @return the rows in this SQL query + */ + public static HashMap> read(String sql) { + ResultSet resultSet; + HashMap> rows = new HashMap>(); + + if (checkConnected()) { + PreparedStatement statement = null; + + try { + statement = connection.prepareStatement(sql); + resultSet = statement.executeQuery(); + + while (resultSet.next()) { + ArrayList column = new ArrayList(); + + for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) { + column.add(resultSet.getString(i)); + } + + rows.put(resultSet.getRow(), column); + } + } + catch (SQLException ex) { + printErrors(ex); + } + finally { + if (statement != null) { + try { + statement.close(); + } + catch (SQLException e) { + printErrors(e); + } + } + } + } + + return rows; + } + + public static Map readSQLRank(String playerName) { + ResultSet resultSet; + Map skills = new HashMap(); + + if (checkConnected()) { + try { + for (SkillType skillType : SkillType.values()) { + if (skillType.isChildSkill()) { + continue; + } + + String skillName = skillType.name().toLowerCase(); + String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " + + "AND " + skillName + " > (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + + "WHERE user = ?)"; + + PreparedStatement statement = connection.prepareStatement(sql); + statement.setString(1, playerName); + resultSet = statement.executeQuery(); + + resultSet.next(); + + int rank = resultSet.getInt("rank"); + + sql = "SELECT user, " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " + + "AND " + skillName + " = (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + + "WHERE user = '" + playerName + "') ORDER BY user"; + + statement = connection.prepareStatement(sql); + resultSet = statement.executeQuery(); + + while (resultSet.next()) { + if (resultSet.getString("user").equalsIgnoreCase(playerName)) { + skills.put(skillType.name(), rank + resultSet.getRow()); + break; + } + } + + statement.close(); + } + + String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + + "WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > 0 " + + "AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > " + + "(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " + + "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?)"; + + PreparedStatement statement = connection.prepareStatement(sql); + statement.setString(1, playerName); + resultSet = statement.executeQuery(); + + resultSet.next(); + + int rank = resultSet.getInt("rank"); + + sql = "SELECT user, taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " + + "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + + "WHERE taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing > 0 " + + "AND taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing = " + + "(SELECT taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing " + + "FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE user = ?) ORDER BY user"; + + statement = connection.prepareStatement(sql); + statement.setString(1, playerName); + resultSet = statement.executeQuery(); + + while (resultSet.next()) { + if (resultSet.getString("user").equalsIgnoreCase(playerName)) { + skills.put("ALL", rank + resultSet.getRow()); + break; + } + } + + statement.close(); + } + catch (SQLException ex) { + printErrors(ex); + } + } + + return skills; + } + + public static int purgePowerlessSQL() { + HashMap> usernames = read("SELECT u.user FROM " + tablePrefix + "skills AS s, " + tablePrefix + "users AS u WHERE s.user_id = u.id AND (s.taming+s.mining+s.woodcutting+s.repair+s.unarmed+s.herbalism+s.excavation+s.archery+s.swords+s.axes+s.acrobatics+s.fishing) = 0"); + write("DELETE FROM " + tablePrefix + "users WHERE " + tablePrefix + "users.id IN (SELECT * FROM (SELECT u.id FROM " + tablePrefix + "skills AS s, " + tablePrefix + "users AS u WHERE s.user_id = u.id AND (s.taming+s.mining+s.woodcutting+s.repair+s.unarmed+s.herbalism+s.excavation+s.archery+s.swords+s.axes+s.acrobatics+s.fishing) = 0) AS p)"); + + return processPurge(usernames.values()); + } + + public static int purgeOldSQL() { + long currentTime = System.currentTimeMillis(); + long purgeTime = ONE_MONTH * Config.getInstance().getOldUsersCutoff(); + + HashMap> usernames = read("SELECT user FROM " + tablePrefix + "users WHERE ((" + currentTime + " - lastlogin*1000) > " + purgeTime + ")"); + write("DELETE FROM " + tablePrefix + "users WHERE " + tablePrefix + "users.id IN (SELECT * FROM (SELECT id FROM " + tablePrefix + "users WHERE ((" + currentTime + " - lastlogin*1000) > " + purgeTime + ")) AS p)"); + + return processPurge(usernames.values()); + } + + private static int processPurge(Collection> usernames) { + int purgedUsers = 0; + + for (ArrayList user : usernames) { + Misc.profileCleanup(user.get(0)); + purgedUsers++; + } + + return purgedUsers; + } + + /** + * Check database structure for missing values. + * + * @param update Type of data to check updates for + */ + private static void checkDatabaseStructure(DatabaseUpdateType update) { + String sql = null; + ResultSet resultSet = null; + HashMap> rows = new HashMap>(); + + switch (update) { + case BLAST_MINING: + sql = "SELECT * FROM `" + tablePrefix + "cooldowns` ORDER BY `" + tablePrefix + "cooldowns`.`blast_mining` ASC LIMIT 0 , 30"; + break; + + case CASCADE_DELETE: + write("ALTER TABLE `" + tablePrefix + "huds` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); + write("ALTER TABLE `" + tablePrefix + "experience` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); + write("ALTER TABLE `" + tablePrefix + "cooldowns` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); + write("ALTER TABLE `" + tablePrefix + "skills` ADD FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE;"); + break; + + case FISHING: + sql = "SELECT * FROM `" + tablePrefix + "experience` ORDER BY `" + tablePrefix + "experience`.`fishing` ASC LIMIT 0 , 30"; + break; + + case INDEX: + if (read("SHOW INDEX FROM " + tablePrefix + "skills").size() != 13 && checkConnected()) { + mcMMO.p.getLogger().info("Indexing tables, this may take a while on larger databases"); + write("ALTER TABLE `" + tablePrefix + "skills` ADD INDEX `idx_taming` (`taming`) USING BTREE, " + + "ADD INDEX `idx_mining` (`mining`) USING BTREE, " + + "ADD INDEX `idx_woodcutting` (`woodcutting`) USING BTREE, " + + "ADD INDEX `idx_repair` (`repair`) USING BTREE, " + + "ADD INDEX `idx_unarmed` (`unarmed`) USING BTREE, " + + "ADD INDEX `idx_herbalism` (`herbalism`) USING BTREE, " + + "ADD INDEX `idx_excavation` (`excavation`) USING BTREE, " + + "ADD INDEX `idx_archery` (`archery`) USING BTREE, " + + "ADD INDEX `idx_swords` (`swords`) USING BTREE, " + + "ADD INDEX `idx_axes` (`axes`) USING BTREE, " + + "ADD INDEX `idx_acrobatics` (`acrobatics`) USING BTREE, " + + "ADD INDEX `idx_fishing` (`fishing`) USING BTREE;"); + } + break; + + case MOB_HEALTHBARS: + sql = "SELECT * FROM `" + tablePrefix + "huds` ORDER BY `" + tablePrefix + "huds`.`mobhealthbar` ASC LIMIT 0 , 30"; + break; + + default: + break; + } + + PreparedStatement statement = null; + try { + if (!checkConnected()) { + return; + } + + statement = connection.prepareStatement(sql); + resultSet = statement.executeQuery(); + + while (resultSet.next()) { + ArrayList column = new ArrayList(); + + for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) { + column.add(resultSet.getString(i)); + } + + rows.put(resultSet.getRow(), column); + } + } + catch (SQLException ex) { + switch (update) { + case BLAST_MINING: + mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Blast Mining..."); + write("ALTER TABLE `"+tablePrefix + "cooldowns` ADD `blast_mining` int(32) NOT NULL DEFAULT '0' ;"); + break; + + case FISHING: + mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Fishing..."); + write("ALTER TABLE `"+tablePrefix + "skills` ADD `fishing` int(10) NOT NULL DEFAULT '0' ;"); + write("ALTER TABLE `"+tablePrefix + "experience` ADD `fishing` int(10) NOT NULL DEFAULT '0' ;"); + break; + + case MOB_HEALTHBARS: + mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for mob healthbars..."); + write("ALTER TABLE `" + tablePrefix + "huds` ADD `mobhealthbar` varchar(50) NOT NULL DEFAULT 'HEARTS' ;"); + break; + + default: + break; + } + } + finally { + if (statement != null) { + try { + statement.close(); + } + catch (SQLException e) { + // Ignore the error, we're leaving + } + } + } + } + + private static void printErrors(SQLException ex) { + mcMMO.p.getLogger().severe("SQLException: " + ex.getMessage()); + mcMMO.p.getLogger().severe("SQLState: " + ex.getSQLState()); + mcMMO.p.getLogger().severe("VendorError: " + ex.getErrorCode()); + } +} diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java index f36bf39d3..d2b2a9c0c 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java @@ -12,7 +12,7 @@ import java.util.Set; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.config.spout.SpoutConfig; -import com.gmail.nossr50.database.DatabaseManager; +import com.gmail.nossr50.database.SQLDatabaseManager; import com.gmail.nossr50.datatypes.MobHealthbarType; import com.gmail.nossr50.datatypes.skills.AbilityType; import com.gmail.nossr50.datatypes.skills.SkillType; @@ -20,514 +20,56 @@ import com.gmail.nossr50.datatypes.spout.huds.HudType; import com.gmail.nossr50.datatypes.spout.huds.McMMOHud; import com.gmail.nossr50.skills.child.FamilyTree; import com.gmail.nossr50.util.Misc; -import com.gmail.nossr50.util.StringUtils; public class PlayerProfile { - private String playerName; - - // HUD - private McMMOHud spoutHud; - private HudType hudType; - private MobHealthbarType mobHealthbarType; - - // mySQL Stuff + private final String playerName; private int userId; - private boolean loaded; - private Map skills = new HashMap(); // Skills and Levels - private Map skillsXp = new HashMap(); // Skills and Xp - private Map skillsDATS = new HashMap(); + /* HUDs */ + private HudType hudType; + private MobHealthbarType mobHealthbarType; + private McMMOHud spoutHud; - private final static String location = mcMMO.getUsersFilePath(); + /* Skill Data */ + private final Map skills = new HashMap(); // Skill & Level + private final Map skillsXp = new HashMap(); // Skill & XP + private final Map skillsDATS = new HashMap(); // Ability & Cooldown public PlayerProfile(String playerName, boolean addNew) { this.playerName = playerName; + + hudType = mcMMO.spoutEnabled ? SpoutConfig.getInstance().getDefaultHudType() : HudType.DISABLED; mobHealthbarType = Config.getInstance().getMobHealthbarDefault(); - if (mcMMO.spoutEnabled) { - hudType = SpoutConfig.getInstance().getDefaultHudType(); - } - else { - hudType = HudType.DISABLED; - } - for (AbilityType abilityType : AbilityType.values()) { - skillsDATS.put(abilityType, 0); + skillsDATS.put(abilityType, 0); } for (SkillType skillType : SkillType.values()) { - if (!skillType.isChildSkill()) { - skills.put(skillType, 0); - skillsXp.put(skillType, 0); + if (skillType.isChildSkill()) { + continue; } + + skills.put(skillType, 0); + skillsXp.put(skillType, 0); } - if (Config.getInstance().getUseMySQL()) { - if (!loadMySQL() && addNew) { - addMySQLPlayer(); - loaded = true; - } - } - else if (!load() && addNew) { + if (!loadPlayer() && addNew) { addPlayer(); loaded = true; } } - public String getPlayerName() { - return playerName; - } - - public boolean loadMySQL() { - String tablePrefix = Config.getInstance().getMySQLTablePrefix(); - - userId = DatabaseManager.getInt("SELECT id FROM " + tablePrefix + "users WHERE user = '" + playerName + "'"); - - if (userId == 0) { - return false; - } - - HashMap> huds = DatabaseManager.read("SELECT hudtype FROM " + tablePrefix + "huds WHERE user_id = " + userId); - - if (huds.get(1) == null) { - DatabaseManager.write("INSERT INTO " + tablePrefix + "huds (user_id) VALUES (" + userId + ")"); - } - else { - hudType = HudType.valueOf(huds.get(1).get(0)); - mobHealthbarType = MobHealthbarType.valueOf(DatabaseManager.read("SELECT mobhealthbar FROM " + tablePrefix + "huds WHERE user_id = " + userId).get(1).get(0)); - } - - HashMap> cooldowns = DatabaseManager.read("SELECT mining, woodcutting, unarmed, herbalism, excavation, swords, axes, blast_mining FROM " + tablePrefix + "cooldowns WHERE user_id = " + userId); - ArrayList cooldownValues = cooldowns.get(1); - - if (cooldownValues == null) { - DatabaseManager.write("INSERT INTO " + tablePrefix + "cooldowns (user_id) VALUES (" + userId + ")"); - mcMMO.p.getLogger().warning(playerName + "does not exist in the cooldown table. Their cooldowns will be reset."); - } - else { - skillsDATS.put(AbilityType.SUPER_BREAKER, Integer.valueOf(cooldownValues.get(0))); - skillsDATS.put(AbilityType.TREE_FELLER, Integer.valueOf(cooldownValues.get(1))); - skillsDATS.put(AbilityType.BERSERK, Integer.valueOf(cooldownValues.get(2))); - skillsDATS.put(AbilityType.GREEN_TERRA, Integer.valueOf(cooldownValues.get(3))); - skillsDATS.put(AbilityType.GIGA_DRILL_BREAKER, Integer.valueOf(cooldownValues.get(4))); - skillsDATS.put(AbilityType.SERRATED_STRIKES, Integer.valueOf(cooldownValues.get(5))); - skillsDATS.put(AbilityType.SKULL_SPLITTER, Integer.valueOf(cooldownValues.get(6))); - skillsDATS.put(AbilityType.BLAST_MINING, Integer.valueOf(cooldownValues.get(7))); - } - - HashMap> stats = DatabaseManager.read("SELECT taming, mining, repair, woodcutting, unarmed, herbalism, excavation, archery, swords, axes, acrobatics, fishing FROM " + tablePrefix + "skills WHERE user_id = " + userId); - ArrayList statValues = stats.get(1); - - if (statValues == null) { - DatabaseManager.write("INSERT INTO " + tablePrefix + "skills (user_id) VALUES (" + userId + ")"); - mcMMO.p.getLogger().warning(playerName + "does not exist in the skills table. Their stats will be reset."); - } - else { - skills.put(SkillType.TAMING, Integer.valueOf(statValues.get(0))); - skills.put(SkillType.MINING, Integer.valueOf(statValues.get(1))); - skills.put(SkillType.REPAIR, Integer.valueOf(statValues.get(2))); - skills.put(SkillType.WOODCUTTING, Integer.valueOf(statValues.get(3))); - skills.put(SkillType.UNARMED, Integer.valueOf(statValues.get(4))); - skills.put(SkillType.HERBALISM, Integer.valueOf(statValues.get(5))); - skills.put(SkillType.EXCAVATION, Integer.valueOf(statValues.get(6))); - skills.put(SkillType.ARCHERY, Integer.valueOf(statValues.get(7))); - skills.put(SkillType.SWORDS, Integer.valueOf(statValues.get(8))); - skills.put(SkillType.AXES, Integer.valueOf(statValues.get(9))); - skills.put(SkillType.ACROBATICS, Integer.valueOf(statValues.get(10))); - skills.put(SkillType.FISHING, Integer.valueOf(statValues.get(11))); - } - - HashMap> experience = DatabaseManager.read("SELECT taming, mining, repair, woodcutting, unarmed, herbalism, excavation, archery, swords, axes, acrobatics, fishing FROM " + tablePrefix + "experience WHERE user_id = " + userId); - ArrayList experienceValues = experience.get(1); - - if (experienceValues == null) { - DatabaseManager.write("INSERT INTO " + tablePrefix + "experience (user_id) VALUES (" + userId + ")"); - mcMMO.p.getLogger().warning(playerName + "does not exist in the experience table. Their experience will be reset."); - } - else { - skillsXp.put(SkillType.TAMING, Integer.valueOf(experienceValues.get(0))); - skillsXp.put(SkillType.MINING, Integer.valueOf(experienceValues.get(1))); - skillsXp.put(SkillType.REPAIR, Integer.valueOf(experienceValues.get(2))); - skillsXp.put(SkillType.WOODCUTTING, Integer.valueOf(experienceValues.get(3))); - skillsXp.put(SkillType.UNARMED, Integer.valueOf(experienceValues.get(4))); - skillsXp.put(SkillType.HERBALISM, Integer.valueOf(experienceValues.get(5))); - skillsXp.put(SkillType.EXCAVATION, Integer.valueOf(experienceValues.get(6))); - skillsXp.put(SkillType.ARCHERY, Integer.valueOf(experienceValues.get(7))); - skillsXp.put(SkillType.SWORDS, Integer.valueOf(experienceValues.get(8))); - skillsXp.put(SkillType.AXES, Integer.valueOf(experienceValues.get(9))); - skillsXp.put(SkillType.ACROBATICS, Integer.valueOf(experienceValues.get(10))); - skillsXp.put(SkillType.FISHING, Integer.valueOf(experienceValues.get(11))); - } - - loaded = true; - return true; - } - - public void addMySQLPlayer() { - String tablePrefix = Config.getInstance().getMySQLTablePrefix(); - - DatabaseManager.write("INSERT INTO " + tablePrefix + "users (user, lastlogin) VALUES ('" + playerName + "'," + System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR + ")"); - userId = DatabaseManager.getInt("SELECT id FROM " + tablePrefix + "users WHERE user = '" + playerName + "'"); - - DatabaseManager.write("INSERT INTO " + tablePrefix + "cooldowns (user_id) VALUES (" + userId + ")"); - DatabaseManager.write("INSERT INTO " + tablePrefix + "skills (user_id) VALUES (" + userId + ")"); - DatabaseManager.write("INSERT INTO " + tablePrefix + "experience (user_id) VALUES (" + userId + ")"); - } - - public boolean load() { - try { - // Open the user file - FileReader file = new FileReader(location); - BufferedReader in = new BufferedReader(file); - String line; - - while ((line = in.readLine()) != null) { - // Find if the line contains the player we want. - String[] character = line.split(":"); - - if (!character[0].equalsIgnoreCase(playerName)) { - continue; - } - - if (character.length > 1 && StringUtils.isInt(character[1])) { - skills.put(SkillType.MINING, Integer.valueOf(character[1])); - } - - if (character.length > 4 && StringUtils.isInt(character[4])) { - skillsXp.put(SkillType.MINING, Integer.valueOf(character[4])); - } - - if (character.length > 5 && StringUtils.isInt(character[5])) { - skills.put(SkillType.WOODCUTTING, Integer.valueOf(character[5])); - } - - if (character.length > 6 && StringUtils.isInt(character[6])) { - skillsXp.put(SkillType.WOODCUTTING, Integer.valueOf(character[6])); - } - - if (character.length > 7 && StringUtils.isInt(character[7])) { - skills.put(SkillType.REPAIR, Integer.valueOf(character[7])); - } - - if (character.length > 8 && StringUtils.isInt(character[8])) { - skills.put(SkillType.UNARMED, Integer.valueOf(character[8])); - } - - if (character.length > 9 && StringUtils.isInt(character[9])) { - skills.put(SkillType.HERBALISM, Integer.valueOf(character[9])); - } - - if (character.length > 10 && StringUtils.isInt(character[10])) { - skills.put(SkillType.EXCAVATION, Integer.valueOf(character[10])); - } - - if (character.length > 11 && StringUtils.isInt(character[11])) { - skills.put(SkillType.ARCHERY, Integer.valueOf(character[11])); - } - - if (character.length > 12 && StringUtils.isInt(character[12])) { - skills.put(SkillType.SWORDS, Integer.valueOf(character[12])); - } - - if (character.length > 13 && StringUtils.isInt(character[13])) { - skills.put(SkillType.AXES, Integer.valueOf(character[13])); - } - - if (character.length > 14 && StringUtils.isInt(character[14])) { - skills.put(SkillType.ACROBATICS, Integer.valueOf(character[14])); - } - - if (character.length > 15 && StringUtils.isInt(character[15])) { - skillsXp.put(SkillType.REPAIR, Integer.valueOf(character[15])); - } - - if (character.length > 16 && StringUtils.isInt(character[16])) { - skillsXp.put(SkillType.UNARMED, Integer.valueOf(character[16])); - } - - if (character.length > 17 && StringUtils.isInt(character[17])) { - skillsXp.put(SkillType.HERBALISM, Integer.valueOf(character[17])); - } - - if (character.length > 18 && StringUtils.isInt(character[18])) { - skillsXp.put(SkillType.EXCAVATION, Integer.valueOf(character[18])); - } - - if (character.length > 19 && StringUtils.isInt(character[19])) { - skillsXp.put(SkillType.ARCHERY, Integer.valueOf(character[19])); - } - - if (character.length > 20 && StringUtils.isInt(character[20])) { - skillsXp.put(SkillType.SWORDS, Integer.valueOf(character[20])); - } - - if (character.length > 21 && StringUtils.isInt(character[21])) { - skillsXp.put(SkillType.AXES, Integer.valueOf(character[21])); - } - - if (character.length > 22 && StringUtils.isInt(character[22])) { - skillsXp.put(SkillType.ACROBATICS, Integer.valueOf(character[22])); - } - - if (character.length > 24 && StringUtils.isInt(character[24])) { - skills.put(SkillType.TAMING, Integer.valueOf(character[24])); - } - - if (character.length > 25 && StringUtils.isInt(character[25])) { - skillsXp.put(SkillType.TAMING, Integer.valueOf(character[25])); - } - - if (character.length > 26) { - skillsDATS.put(AbilityType.BERSERK, Integer.valueOf(character[26])); - } - - if (character.length > 27) { - skillsDATS.put(AbilityType.GIGA_DRILL_BREAKER, Integer.valueOf(character[27])); - } - - if (character.length > 28) { - skillsDATS.put(AbilityType.TREE_FELLER, Integer.valueOf(character[28])); - } - - if (character.length > 29) { - skillsDATS.put(AbilityType.GREEN_TERRA, Integer.valueOf(character[29])); - } - - if (character.length > 30) { - skillsDATS.put(AbilityType.SERRATED_STRIKES, Integer.valueOf(character[30])); - } - - if (character.length > 31) { - skillsDATS.put(AbilityType.SKULL_SPLITTER, Integer.valueOf(character[31])); - } - - if (character.length > 32) { - skillsDATS.put(AbilityType.SUPER_BREAKER, Integer.valueOf(character[32])); - } - - if (character.length > 33) { - hudType = HudType.valueOf(character[33]); - } - - if (character.length > 34) { - skills.put(SkillType.FISHING, Integer.valueOf(character[34])); - } - - if (character.length > 35) { - skillsXp.put(SkillType.FISHING, Integer.valueOf(character[35])); - } - - if (character.length > 36) { - skillsDATS.put(AbilityType.BLAST_MINING, Integer.valueOf(character[36])); - } - - if (character.length > 38) { - mobHealthbarType = MobHealthbarType.valueOf(character[38]); - } - - loaded = true; - - in.close(); - return true; - } - - in.close(); - } - catch (Exception e) { - e.printStackTrace(); - } - return false; - } - public void save() { - Long timestamp = System.currentTimeMillis(); - - // If we are using mysql save to database if (Config.getInstance().getUseMySQL()) { - String tablePrefix = Config.getInstance().getMySQLTablePrefix(); - - DatabaseManager.write("UPDATE " + tablePrefix + "huds SET hudtype = '" + hudType.toString() + "' WHERE user_id = " + userId); - DatabaseManager.write("UPDATE " + tablePrefix + "huds SET mobhealthbar = '" + mobHealthbarType.toString() + "' WHERE user_id = " + userId); - DatabaseManager.write("UPDATE " + tablePrefix + "users SET lastlogin = " + ((int) (timestamp / Misc.TIME_CONVERSION_FACTOR)) + " WHERE id = " + userId); - DatabaseManager.write("UPDATE " + tablePrefix + "cooldowns SET " - + " mining = " + skillsDATS.get(AbilityType.SUPER_BREAKER) - + ", woodcutting = " + skillsDATS.get(AbilityType.TREE_FELLER) - + ", unarmed = " + skillsDATS.get(AbilityType.BERSERK) - + ", herbalism = " + skillsDATS.get(AbilityType.GREEN_TERRA) - + ", excavation = " + skillsDATS.get(AbilityType.GIGA_DRILL_BREAKER) - + ", swords = " + skillsDATS.get(AbilityType.SERRATED_STRIKES) - + ", axes = " + skillsDATS.get(AbilityType.SKULL_SPLITTER) - + ", blast_mining = " + skillsDATS.get(AbilityType.BLAST_MINING) - + " WHERE user_id = " + userId); - DatabaseManager.write("UPDATE " + tablePrefix + "skills SET " - + " taming = " + skills.get(SkillType.TAMING) - + ", mining = " + skills.get(SkillType.MINING) - + ", repair = " + skills.get(SkillType.REPAIR) - + ", woodcutting = " + skills.get(SkillType.WOODCUTTING) - + ", unarmed = " + skills.get(SkillType.UNARMED) - + ", herbalism = " + skills.get(SkillType.HERBALISM) - + ", excavation = " + skills.get(SkillType.EXCAVATION) - + ", archery = " + skills.get(SkillType.ARCHERY) - + ", swords = " + skills.get(SkillType.SWORDS) - + ", axes = " + skills.get(SkillType.AXES) - + ", acrobatics = " + skills.get(SkillType.ACROBATICS) - + ", fishing = " + skills.get(SkillType.FISHING) - + " WHERE user_id = " + userId); - DatabaseManager.write("UPDATE " + tablePrefix + "experience SET " - + " taming = " + skillsXp.get(SkillType.TAMING) - + ", mining = " + skillsXp.get(SkillType.MINING) - + ", repair = " + skillsXp.get(SkillType.REPAIR) - + ", woodcutting = " + skillsXp.get(SkillType.WOODCUTTING) - + ", unarmed = " + skillsXp.get(SkillType.UNARMED) - + ", herbalism = " + skillsXp.get(SkillType.HERBALISM) - + ", excavation = " + skillsXp.get(SkillType.EXCAVATION) - + ", archery = " + skillsXp.get(SkillType.ARCHERY) - + ", swords = " + skillsXp.get(SkillType.SWORDS) - + ", axes = " + skillsXp.get(SkillType.AXES) - + ", acrobatics = " + skillsXp.get(SkillType.ACROBATICS) - + ", fishing = " + skillsXp.get(SkillType.FISHING) - + " WHERE user_id = " + userId); + saveMySQL(); } else { - // Otherwise save to flatfile - try { - // Open the file - FileReader file = new FileReader(location); - BufferedReader in = new BufferedReader(file); - StringBuilder writer = new StringBuilder(); - String line; - - // While not at the end of the file - while ((line = in.readLine()) != null) { - // Read the line in and copy it to the output it's not the player we want to edit - if (!line.split(":")[0].equalsIgnoreCase(playerName)) { - writer.append(line).append("\r\n"); - } - else { - // Otherwise write the new player information - writer.append(playerName).append(":"); - writer.append(skills.get(SkillType.MINING)).append(":"); - writer.append(":"); - writer.append(":"); - writer.append(skillsXp.get(SkillType.MINING)).append(":"); - writer.append(skills.get(SkillType.WOODCUTTING)).append(":"); - writer.append(skillsXp.get(SkillType.WOODCUTTING)).append(":"); - writer.append(skills.get(SkillType.REPAIR)).append(":"); - writer.append(skills.get(SkillType.UNARMED)).append(":"); - writer.append(skills.get(SkillType.HERBALISM)).append(":"); - writer.append(skills.get(SkillType.EXCAVATION)).append(":"); - writer.append(skills.get(SkillType.ARCHERY)).append(":"); - writer.append(skills.get(SkillType.SWORDS)).append(":"); - writer.append(skills.get(SkillType.AXES)).append(":"); - writer.append(skills.get(SkillType.ACROBATICS)).append(":"); - writer.append(skillsXp.get(SkillType.REPAIR)).append(":"); - writer.append(skillsXp.get(SkillType.UNARMED)).append(":"); - writer.append(skillsXp.get(SkillType.HERBALISM)).append(":"); - writer.append(skillsXp.get(SkillType.EXCAVATION)).append(":"); - writer.append(skillsXp.get(SkillType.ARCHERY)).append(":"); - writer.append(skillsXp.get(SkillType.SWORDS)).append(":"); - writer.append(skillsXp.get(SkillType.AXES)).append(":"); - writer.append(skillsXp.get(SkillType.ACROBATICS)).append(":"); - writer.append(":"); - writer.append(skills.get(SkillType.TAMING)).append(":"); - writer.append(skillsXp.get(SkillType.TAMING)).append(":"); - writer.append(skillsDATS.get(AbilityType.BERSERK)).append(":"); - writer.append(skillsDATS.get(AbilityType.GIGA_DRILL_BREAKER)).append(":"); - writer.append(skillsDATS.get(AbilityType.TREE_FELLER)).append(":"); - writer.append(skillsDATS.get(AbilityType.GREEN_TERRA)).append(":"); - writer.append(skillsDATS.get(AbilityType.SERRATED_STRIKES)).append(":"); - writer.append(skillsDATS.get(AbilityType.SKULL_SPLITTER)).append(":"); - writer.append(skillsDATS.get(AbilityType.SUPER_BREAKER)).append(":"); - writer.append(hudType.toString()).append(":"); - writer.append(skills.get(SkillType.FISHING)).append(":"); - writer.append(skillsXp.get(SkillType.FISHING)).append(":"); - writer.append(skillsDATS.get(AbilityType.BLAST_MINING)).append(":"); - writer.append(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR).append(":"); - writer.append(mobHealthbarType.toString()).append(":"); - writer.append("\r\n"); - } - } - - in.close(); - - // Write the new file - FileWriter out = new FileWriter(location); - out.write(writer.toString()); - out.flush(); - out.close(); - } - catch (Exception e) { - e.printStackTrace(); - } + saveFlatfile(); } } - public void addPlayer() { - try { - // Open the file to write the player - FileWriter file = new FileWriter(location, true); - BufferedWriter out = new BufferedWriter(file); - - // Add the player to the end - out.append(playerName).append(":"); - out.append("0:"); // Mining - out.append(":"); - out.append(":"); - out.append("0:"); // Xp - out.append("0:"); // Woodcutting - out.append("0:"); // WoodCuttingXp - out.append("0:"); // Repair - out.append("0:"); // Unarmed - out.append("0:"); // Herbalism - out.append("0:"); // Excavation - out.append("0:"); // Archery - out.append("0:"); // Swords - out.append("0:"); // Axes - out.append("0:"); // Acrobatics - out.append("0:"); // RepairXp - out.append("0:"); // UnarmedXp - out.append("0:"); // HerbalismXp - out.append("0:"); // ExcavationXp - out.append("0:"); // ArcheryXp - out.append("0:"); // SwordsXp - out.append("0:"); // AxesXp - out.append("0:"); // AcrobaticsXp - out.append(":"); - out.append("0:"); // Taming - out.append("0:"); // TamingXp - out.append("0:"); // DATS - out.append("0:"); // DATS - out.append("0:"); // DATS - out.append("0:"); // DATS - out.append("0:"); // DATS - out.append("0:"); // DATS - out.append("0:"); // DATS - out.append(hudType.toString()).append(":"); // HUD - out.append("0:"); // Fishing - out.append("0:"); // FishingXp - out.append("0:"); // Blast Mining - out.append(String.valueOf(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR)).append(":"); // LastLogin - out.append(mobHealthbarType.toString()).append(":"); // Mob Healthbar HUD - - // Add more in the same format as the line above - - out.newLine(); - out.close(); - } - catch (Exception e) { - e.printStackTrace(); - } - } - - /* - * mySQL Stuff - */ - - public int getMySQLuserId() { - return userId; - } - public boolean isLoaded() { return loaded; } @@ -594,8 +136,8 @@ public class PlayerProfile { * Reset all skill cooldowns. */ public void resetCooldowns() { - for (AbilityType x : skillsDATS.keySet()) { - skillsDATS.put(x, 0); + for (AbilityType ability : skillsDATS.keySet()) { + skillsDATS.put(ability, 0); } } @@ -611,17 +153,6 @@ public class PlayerProfile { return skills.get(skillType); } - public int getChildSkillLevel(SkillType skillType) { - Set parents = FamilyTree.getParents(skillType); - int sum = 0; - - for (SkillType parent : parents) { - sum += Math.min(getSkillLevel(parent), 1000); - } - - return sum / parents.size(); - } - public int getSkillXpLevel(SkillType skillType) { return skillsXp.get(skillType); } @@ -705,4 +236,384 @@ public class PlayerProfile { public int getXpToLevel(SkillType skillType) { return 1020 + (skills.get(skillType) * Config.getInstance().getFormulaMultiplierCurve()); } + + private int getChildSkillLevel(SkillType skillType) { + Set parents = FamilyTree.getParents(skillType); + int sum = 0; + + for (SkillType parent : parents) { + sum += Math.min(getSkillLevel(parent), 1000); + } + + return sum / parents.size(); + } + + private boolean loadPlayer() { + return Config.getInstance().getUseMySQL() ? loadMySQL() : loadFlatfile(); + } + + private void addPlayer() { + if (Config.getInstance().getUseMySQL()) { + addMySQLPlayer(); + } + else { + addFlatfilePlayer(); + } + } + + private boolean loadMySQL() { + String tablePrefix = Config.getInstance().getMySQLTablePrefix(); + + userId = SQLDatabaseManager.getInt("SELECT id FROM " + tablePrefix + "users WHERE user = '" + playerName + "'"); + + if (userId == 0) { + return false; + } + + ArrayList hudValues = SQLDatabaseManager.read("SELECT hudtype, mobhealthbar FROM " + tablePrefix + "huds WHERE user_id = " + userId).get(1); + + if (hudValues == null) { + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "huds (user_id, mobhealthbar) VALUES (" + userId + "," + mobHealthbarType.name() + ")"); + mcMMO.p.getLogger().warning(playerName + "does not exist in the HUD table. Their HUDs will be reset."); + } + else { + hudType = HudType.valueOf(hudValues.get(0)); + mobHealthbarType = MobHealthbarType.valueOf(hudValues.get(1)); + } + + ArrayList cooldownValues = SQLDatabaseManager.read("SELECT mining, woodcutting, unarmed, herbalism, excavation, swords, axes, blast_mining FROM " + tablePrefix + "cooldowns WHERE user_id = " + userId).get(1); + + if (cooldownValues == null) { + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "cooldowns (user_id) VALUES (" + userId + ")"); + mcMMO.p.getLogger().warning(playerName + "does not exist in the cooldown table. Their cooldowns will be reset."); + } + else { + skillsDATS.put(AbilityType.SUPER_BREAKER, Integer.valueOf(cooldownValues.get(0))); + skillsDATS.put(AbilityType.TREE_FELLER, Integer.valueOf(cooldownValues.get(1))); + skillsDATS.put(AbilityType.BERSERK, Integer.valueOf(cooldownValues.get(2))); + skillsDATS.put(AbilityType.GREEN_TERRA, Integer.valueOf(cooldownValues.get(3))); + skillsDATS.put(AbilityType.GIGA_DRILL_BREAKER, Integer.valueOf(cooldownValues.get(4))); + skillsDATS.put(AbilityType.SERRATED_STRIKES, Integer.valueOf(cooldownValues.get(5))); + skillsDATS.put(AbilityType.SKULL_SPLITTER, Integer.valueOf(cooldownValues.get(6))); + skillsDATS.put(AbilityType.BLAST_MINING, Integer.valueOf(cooldownValues.get(7))); + } + + ArrayList statValues = SQLDatabaseManager.read("SELECT taming, mining, repair, woodcutting, unarmed, herbalism, excavation, archery, swords, axes, acrobatics, fishing FROM " + tablePrefix + "skills WHERE user_id = " + userId).get(1); + + if (statValues == null) { + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "skills (user_id) VALUES (" + userId + ")"); + mcMMO.p.getLogger().warning(playerName + "does not exist in the skills table. Their stats will be reset."); + } + else { + skills.put(SkillType.TAMING, Integer.valueOf(statValues.get(0))); + skills.put(SkillType.MINING, Integer.valueOf(statValues.get(1))); + skills.put(SkillType.REPAIR, Integer.valueOf(statValues.get(2))); + skills.put(SkillType.WOODCUTTING, Integer.valueOf(statValues.get(3))); + skills.put(SkillType.UNARMED, Integer.valueOf(statValues.get(4))); + skills.put(SkillType.HERBALISM, Integer.valueOf(statValues.get(5))); + skills.put(SkillType.EXCAVATION, Integer.valueOf(statValues.get(6))); + skills.put(SkillType.ARCHERY, Integer.valueOf(statValues.get(7))); + skills.put(SkillType.SWORDS, Integer.valueOf(statValues.get(8))); + skills.put(SkillType.AXES, Integer.valueOf(statValues.get(9))); + skills.put(SkillType.ACROBATICS, Integer.valueOf(statValues.get(10))); + skills.put(SkillType.FISHING, Integer.valueOf(statValues.get(11))); + } + + ArrayList experienceValues = SQLDatabaseManager.read("SELECT taming, mining, repair, woodcutting, unarmed, herbalism, excavation, archery, swords, axes, acrobatics, fishing FROM " + tablePrefix + "experience WHERE user_id = " + userId).get(1); + + if (experienceValues == null) { + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "experience (user_id) VALUES (" + userId + ")"); + mcMMO.p.getLogger().warning(playerName + "does not exist in the experience table. Their experience will be reset."); + } + else { + skillsXp.put(SkillType.TAMING, Integer.valueOf(experienceValues.get(0))); + skillsXp.put(SkillType.MINING, Integer.valueOf(experienceValues.get(1))); + skillsXp.put(SkillType.REPAIR, Integer.valueOf(experienceValues.get(2))); + skillsXp.put(SkillType.WOODCUTTING, Integer.valueOf(experienceValues.get(3))); + skillsXp.put(SkillType.UNARMED, Integer.valueOf(experienceValues.get(4))); + skillsXp.put(SkillType.HERBALISM, Integer.valueOf(experienceValues.get(5))); + skillsXp.put(SkillType.EXCAVATION, Integer.valueOf(experienceValues.get(6))); + skillsXp.put(SkillType.ARCHERY, Integer.valueOf(experienceValues.get(7))); + skillsXp.put(SkillType.SWORDS, Integer.valueOf(experienceValues.get(8))); + skillsXp.put(SkillType.AXES, Integer.valueOf(experienceValues.get(9))); + skillsXp.put(SkillType.ACROBATICS, Integer.valueOf(experienceValues.get(10))); + skillsXp.put(SkillType.FISHING, Integer.valueOf(experienceValues.get(11))); + } + + loaded = true; + return true; + } + + private void addMySQLPlayer() { + String tablePrefix = Config.getInstance().getMySQLTablePrefix(); + + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "users (user, lastlogin) VALUES ('" + playerName + "'," + System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR + ")"); + userId = SQLDatabaseManager.getInt("SELECT id FROM " + tablePrefix + "users WHERE user = '" + playerName + "'"); + + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "huds (user_id, mobhealthbar) VALUES (" + userId + "," + mobHealthbarType.name() + ")"); + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "cooldowns (user_id) VALUES (" + userId + ")"); + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "skills (user_id) VALUES (" + userId + ")"); + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "experience (user_id) VALUES (" + userId + ")"); + } + + + private void addFlatfilePlayer() { + try { + // Open the file to write the player + BufferedWriter out = new BufferedWriter(new FileWriter(mcMMO.getUsersFilePath(), true)); + + // Add the player to the end + out.append(playerName).append(":"); + out.append("0:"); // Mining + out.append(":"); + out.append(":"); + out.append("0:"); // Xp + out.append("0:"); // Woodcutting + out.append("0:"); // WoodCuttingXp + out.append("0:"); // Repair + out.append("0:"); // Unarmed + out.append("0:"); // Herbalism + out.append("0:"); // Excavation + out.append("0:"); // Archery + out.append("0:"); // Swords + out.append("0:"); // Axes + out.append("0:"); // Acrobatics + out.append("0:"); // RepairXp + out.append("0:"); // UnarmedXp + out.append("0:"); // HerbalismXp + out.append("0:"); // ExcavationXp + out.append("0:"); // ArcheryXp + out.append("0:"); // SwordsXp + out.append("0:"); // AxesXp + out.append("0:"); // AcrobaticsXp + out.append(":"); + out.append("0:"); // Taming + out.append("0:"); // TamingXp + out.append("0:"); // DATS + out.append("0:"); // DATS + out.append("0:"); // DATS + out.append("0:"); // DATS + out.append("0:"); // DATS + out.append("0:"); // DATS + out.append("0:"); // DATS + out.append(hudType.toString()).append(":"); // HUD + out.append("0:"); // Fishing + out.append("0:"); // FishingXp + out.append("0:"); // Blast Mining + out.append(String.valueOf(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR)).append(":"); // LastLogin + out.append(mobHealthbarType.toString()).append(":"); // Mob Healthbar HUD + + // Add more in the same format as the line above + + out.newLine(); + out.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private boolean loadFlatfile() { + try { + // Open the user file + FileReader file = new FileReader(mcMMO.getUsersFilePath()); + BufferedReader in = new BufferedReader(file); + String line; + + while ((line = in.readLine()) != null) { + // Find if the line contains the player we want. + String[] character = line.split(":"); + + if (!character[0].equalsIgnoreCase(playerName)) { + continue; + } + + loadSkillData(SkillType.MINING, character, 1); + loadSkillData(SkillType.WOODCUTTING, character, 5); + loadSkillData(SkillType.REPAIR, character, 7); + loadSkillData(SkillType.UNARMED, character, 8); + loadSkillData(SkillType.HERBALISM, character, 9); + loadSkillData(SkillType.EXCAVATION, character, 10); + loadSkillData(SkillType.ARCHERY, character, 11); + loadSkillData(SkillType.SWORDS, character, 12); + loadSkillData(SkillType.AXES, character, 13); + loadSkillData(SkillType.ACROBATICS, character, 14); + loadSkillData(SkillType.TAMING, character, 24); + loadSkillData(SkillType.FISHING, character, 34); + + loadSkillXpData(SkillType.MINING, character, 4); + loadSkillXpData(SkillType.WOODCUTTING, character, 6); + loadSkillXpData(SkillType.REPAIR, character, 15); + loadSkillXpData(SkillType.UNARMED, character, 16); + loadSkillXpData(SkillType.HERBALISM, character, 17); + loadSkillXpData(SkillType.EXCAVATION, character, 18); + loadSkillXpData(SkillType.ARCHERY, character, 19); + loadSkillXpData(SkillType.SWORDS, character, 20); + loadSkillXpData(SkillType.AXES, character, 21); + loadSkillXpData(SkillType.ACROBATICS, character, 22); + loadSkillXpData(SkillType.TAMING, character, 25); + loadSkillXpData(SkillType.FISHING, character, 35); + + loadDATSData(AbilityType.BERSERK, character, 26); + loadDATSData(AbilityType.GIGA_DRILL_BREAKER, character, 27); + loadDATSData(AbilityType.TREE_FELLER, character, 28); + loadDATSData(AbilityType.GREEN_TERRA, character, 29); + loadDATSData(AbilityType.SERRATED_STRIKES, character, 30); + loadDATSData(AbilityType.SKULL_SPLITTER, character, 31); + loadDATSData(AbilityType.SUPER_BREAKER, character, 32); + loadDATSData(AbilityType.BLAST_MINING, character, 36); + + hudType = character.length > 33 ? HudType.valueOf(character[33]) : null; + mobHealthbarType = character.length > 38 ? MobHealthbarType.valueOf(character[38]) : null; + + loaded = true; + } + + in.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + + return loaded; + } + + private void saveMySQL() { + if (Config.getInstance().getUseMySQL()) { + String tablePrefix = Config.getInstance().getMySQLTablePrefix(); + + SQLDatabaseManager.write("UPDATE " + tablePrefix + "users SET lastlogin = " + ((int) (System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR)) + " WHERE id = " + userId); + SQLDatabaseManager.write("UPDATE " + tablePrefix + "huds SET " + + " hudtype = " + hudType.toString() + + ", mobhealthbar = " + mobHealthbarType.toString() + + " WHERE user_id = " + userId); + SQLDatabaseManager.write("UPDATE " + tablePrefix + "cooldowns SET " + + " mining = " + skillsDATS.get(AbilityType.SUPER_BREAKER) + + ", woodcutting = " + skillsDATS.get(AbilityType.TREE_FELLER) + + ", unarmed = " + skillsDATS.get(AbilityType.BERSERK) + + ", herbalism = " + skillsDATS.get(AbilityType.GREEN_TERRA) + + ", excavation = " + skillsDATS.get(AbilityType.GIGA_DRILL_BREAKER) + + ", swords = " + skillsDATS.get(AbilityType.SERRATED_STRIKES) + + ", axes = " + skillsDATS.get(AbilityType.SKULL_SPLITTER) + + ", blast_mining = " + skillsDATS.get(AbilityType.BLAST_MINING) + + " WHERE user_id = " + userId); + SQLDatabaseManager.write("UPDATE " + tablePrefix + "skills SET " + + " taming = " + skills.get(SkillType.TAMING) + + ", mining = " + skills.get(SkillType.MINING) + + ", repair = " + skills.get(SkillType.REPAIR) + + ", woodcutting = " + skills.get(SkillType.WOODCUTTING) + + ", unarmed = " + skills.get(SkillType.UNARMED) + + ", herbalism = " + skills.get(SkillType.HERBALISM) + + ", excavation = " + skills.get(SkillType.EXCAVATION) + + ", archery = " + skills.get(SkillType.ARCHERY) + + ", swords = " + skills.get(SkillType.SWORDS) + + ", axes = " + skills.get(SkillType.AXES) + + ", acrobatics = " + skills.get(SkillType.ACROBATICS) + + ", fishing = " + skills.get(SkillType.FISHING) + + " WHERE user_id = " + userId); + SQLDatabaseManager.write("UPDATE " + tablePrefix + "experience SET " + + " taming = " + skillsXp.get(SkillType.TAMING) + + ", mining = " + skillsXp.get(SkillType.MINING) + + ", repair = " + skillsXp.get(SkillType.REPAIR) + + ", woodcutting = " + skillsXp.get(SkillType.WOODCUTTING) + + ", unarmed = " + skillsXp.get(SkillType.UNARMED) + + ", herbalism = " + skillsXp.get(SkillType.HERBALISM) + + ", excavation = " + skillsXp.get(SkillType.EXCAVATION) + + ", archery = " + skillsXp.get(SkillType.ARCHERY) + + ", swords = " + skillsXp.get(SkillType.SWORDS) + + ", axes = " + skillsXp.get(SkillType.AXES) + + ", acrobatics = " + skillsXp.get(SkillType.ACROBATICS) + + ", fishing = " + skillsXp.get(SkillType.FISHING) + + " WHERE user_id = " + userId); + } + } + + private void saveFlatfile() { + try { + // Open the file + BufferedReader in = new BufferedReader(new FileReader(mcMMO.getUsersFilePath())); + StringBuilder writer = new StringBuilder(); + String line; + + // While not at the end of the file + while ((line = in.readLine()) != null) { + // Read the line in and copy it to the output it's not the player we want to edit + if (!line.split(":")[0].equalsIgnoreCase(playerName)) { + writer.append(line).append("\r\n"); + } + else { + // Otherwise write the new player information + writer.append(playerName).append(":"); + writer.append(skills.get(SkillType.MINING)).append(":"); + writer.append(":"); + writer.append(":"); + writer.append(skillsXp.get(SkillType.MINING)).append(":"); + writer.append(skills.get(SkillType.WOODCUTTING)).append(":"); + writer.append(skillsXp.get(SkillType.WOODCUTTING)).append(":"); + writer.append(skills.get(SkillType.REPAIR)).append(":"); + writer.append(skills.get(SkillType.UNARMED)).append(":"); + writer.append(skills.get(SkillType.HERBALISM)).append(":"); + writer.append(skills.get(SkillType.EXCAVATION)).append(":"); + writer.append(skills.get(SkillType.ARCHERY)).append(":"); + writer.append(skills.get(SkillType.SWORDS)).append(":"); + writer.append(skills.get(SkillType.AXES)).append(":"); + writer.append(skills.get(SkillType.ACROBATICS)).append(":"); + writer.append(skillsXp.get(SkillType.REPAIR)).append(":"); + writer.append(skillsXp.get(SkillType.UNARMED)).append(":"); + writer.append(skillsXp.get(SkillType.HERBALISM)).append(":"); + writer.append(skillsXp.get(SkillType.EXCAVATION)).append(":"); + writer.append(skillsXp.get(SkillType.ARCHERY)).append(":"); + writer.append(skillsXp.get(SkillType.SWORDS)).append(":"); + writer.append(skillsXp.get(SkillType.AXES)).append(":"); + writer.append(skillsXp.get(SkillType.ACROBATICS)).append(":"); + writer.append(":"); + writer.append(skills.get(SkillType.TAMING)).append(":"); + writer.append(skillsXp.get(SkillType.TAMING)).append(":"); + writer.append(skillsDATS.get(AbilityType.BERSERK)).append(":"); + writer.append(skillsDATS.get(AbilityType.GIGA_DRILL_BREAKER)).append(":"); + writer.append(skillsDATS.get(AbilityType.TREE_FELLER)).append(":"); + writer.append(skillsDATS.get(AbilityType.GREEN_TERRA)).append(":"); + writer.append(skillsDATS.get(AbilityType.SERRATED_STRIKES)).append(":"); + writer.append(skillsDATS.get(AbilityType.SKULL_SPLITTER)).append(":"); + writer.append(skillsDATS.get(AbilityType.SUPER_BREAKER)).append(":"); + writer.append(hudType.toString()).append(":"); + writer.append(skills.get(SkillType.FISHING)).append(":"); + writer.append(skillsXp.get(SkillType.FISHING)).append(":"); + writer.append(skillsDATS.get(AbilityType.BLAST_MINING)).append(":"); + writer.append(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR).append(":"); + writer.append(mobHealthbarType.toString()).append(":"); + writer.append("\r\n"); + } + } + + in.close(); + + // Write the new file + FileWriter out = new FileWriter(mcMMO.getUsersFilePath()); + out.write(writer.toString()); + out.flush(); + out.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private void loadSkillXpData(SkillType skill, String[] data, int dataIndex) { + if (data.length > dataIndex) { + skillsXp.put(skill, Integer.valueOf(data[dataIndex])); + } + } + + private void loadSkillData(SkillType skill, String[] data, int dataIndex) { + if (data.length > dataIndex) { + skills.put(skill, Integer.valueOf(data[dataIndex])); + } + } + + private void loadDATSData(AbilityType ability, String[] data, int dataIndex) { + if (data.length > dataIndex) { + skillsDATS.put(ability, Integer.valueOf(data[dataIndex])); + } + } } diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index 9cd536ee5..69cc774b6 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -23,7 +23,6 @@ import com.gmail.nossr50.config.mods.CustomToolConfig; import com.gmail.nossr50.config.spout.SpoutConfig; import com.gmail.nossr50.config.treasure.TreasureConfig; import com.gmail.nossr50.database.DatabaseManager; -import com.gmail.nossr50.database.LeaderboardManager; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.skills.AbilityType; import com.gmail.nossr50.listeners.BlockListener; @@ -65,8 +64,9 @@ public class mcMMO extends JavaPlugin { public static mcMMO p; - public static ChunkManager placeStore; + public static ChunkManager placeStore; public static RepairableManager repairableManager; + public static DatabaseManager databaseManager; // Jar Stuff public static File mcmmo; @@ -111,25 +111,13 @@ public class mcMMO extends JavaPlugin { setupSpout(); loadConfigFiles(); - if (!Config.getInstance().getUseMySQL()) { - UserManager.loadUsers(); - } + databaseManager = new DatabaseManager(this, Config.getInstance().getUseMySQL()); registerEvents(); registerCustomRecipes(); PartyManager.loadParties(); - // Setup the leader boards - if (Config.getInstance().getUseMySQL()) { - // TODO: Why do we have to check for a connection that hasn't be made yet? - DatabaseManager.checkConnected(); - DatabaseManager.createStructure(); - } - else { - LeaderboardManager.updateLeaderboards(); - } - for (Player player : getServer().getOnlinePlayers()) { UserManager.addUser(player); // In case of reload add all users back into UserManager } diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandAsyncTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandAsyncTask.java index 6010e5a4e..153cf153a 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandAsyncTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandAsyncTask.java @@ -6,7 +6,9 @@ import org.bukkit.command.CommandSender; import org.bukkit.scheduler.BukkitRunnable; import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.database.DatabaseManager; +import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.database.SQLDatabaseManager; +import com.gmail.nossr50.database.FlatfileDatabaseManager; public class McrankCommandAsyncTask extends BukkitRunnable { private final String playerName; @@ -19,7 +21,7 @@ public class McrankCommandAsyncTask extends BukkitRunnable { @Override public void run() { - Map skills = DatabaseManager.readSQLRank(playerName); + Map skills = Config.getInstance().getUseMySQL() ? SQLDatabaseManager.readSQLRank(playerName) : FlatfileDatabaseManager.getPlayerRanks(playerName); new McrankCommandDisplayTask(skills, sender, playerName).runTaskLater(mcMMO.p, 1); } diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java index d322ae28b..08cf68db3 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java @@ -6,6 +6,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.util.Permissions; @@ -24,27 +25,22 @@ public class McrankCommandDisplayTask extends BukkitRunnable { @Override public void run() { + Player player = mcMMO.p.getServer().getPlayer(playerName); + Integer rank; + sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Heading")); sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName)); - for (SkillType skillType : SkillType.values()) { - if ((sender instanceof Player && !Permissions.skillEnabled(sender, skillType)) || skillType.isChildSkill()) { + for (SkillType skill : SkillType.values()) { + if (skill.isChildSkill() || !Permissions.skillEnabled(player, skill)) { continue; } - if (skills.get(skillType.name()) == null) { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", SkillUtils.getSkillName(skillType), LocaleLoader.getString("Commands.mcrank.Unranked"))); - } - else { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", SkillUtils.getSkillName(skillType), skills.get(skillType.name()))); - } + rank = skills.get(skill.name()); + sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", SkillUtils.getSkillName(skill), (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank))); } - if (skills.get("ALL") == null) { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Overall", LocaleLoader.getString("Commands.mcrank.Unranked"))); - } - else { - sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Overall", skills.get("ALL"))); - } + rank = skills.get("ALL"); + sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Overall", (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank))); } } diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java index 3a79b05a8..ad29b1abb 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/MctopCommandAsyncTask.java @@ -8,7 +8,7 @@ import org.bukkit.scheduler.BukkitRunnable; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.database.DatabaseManager; +import com.gmail.nossr50.database.SQLDatabaseManager; public class MctopCommandAsyncTask extends BukkitRunnable { @@ -18,14 +18,14 @@ public class MctopCommandAsyncTask extends BukkitRunnable { public MctopCommandAsyncTask(int page, String query, CommandSender sender) { this.page = page; - this.query = query; + this.query = query.equalsIgnoreCase("ALL") ? "taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing" : query; this.sender = sender; } @Override public void run() { String tablePrefix = Config.getInstance().getMySQLTablePrefix(); - final HashMap> userslist = DatabaseManager.read("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 ORDER BY " + query + " DESC, user LIMIT " + ((page * 10) - 10) + ",10"); + final HashMap> userslist = SQLDatabaseManager.read("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 ORDER BY " + query + " DESC, user LIMIT " + ((page * 10) - 10) + ",10"); new MctopCommandDisplayTask(userslist, page, tablePrefix, sender).runTaskLater(mcMMO.p, 1); } diff --git a/src/main/java/com/gmail/nossr50/runnables/database/SQLConversionTask.java b/src/main/java/com/gmail/nossr50/runnables/database/SQLConversionTask.java index c1f34aac6..57fed6328 100644 --- a/src/main/java/com/gmail/nossr50/runnables/database/SQLConversionTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/database/SQLConversionTask.java @@ -7,7 +7,7 @@ import org.bukkit.scheduler.BukkitRunnable; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.database.DatabaseManager; +import com.gmail.nossr50.database.SQLDatabaseManager; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.StringUtils; @@ -158,7 +158,7 @@ public class SQLConversionTask extends BukkitRunnable { } // Check to see if the user is in the DB - id = DatabaseManager.getInt("SELECT id FROM " + id = SQLDatabaseManager.getInt("SELECT id FROM " + tablePrefix + "users WHERE user = '" + playerName + "'"); @@ -166,11 +166,11 @@ public class SQLConversionTask extends BukkitRunnable { theCount++; // Update the skill values - DatabaseManager.write("UPDATE " + SQLDatabaseManager.write("UPDATE " + tablePrefix + "users SET lastlogin = " + 0 + " WHERE id = " + id); - DatabaseManager.write("UPDATE " + SQLDatabaseManager.write("UPDATE " + tablePrefix + "skills SET " + " taming = taming+" + StringUtils.getInt(taming) @@ -186,7 +186,7 @@ public class SQLConversionTask extends BukkitRunnable { + ", acrobatics = acrobatics+" + StringUtils.getInt(acrobatics) + ", fishing = fishing+" + StringUtils.getInt(fishing) + " WHERE user_id = " + id); - DatabaseManager.write("UPDATE " + SQLDatabaseManager.write("UPDATE " + tablePrefix + "experience SET " + " taming = " + StringUtils.getInt(tamingXP) @@ -207,24 +207,24 @@ public class SQLConversionTask extends BukkitRunnable { theCount++; // Create the user in the DB - DatabaseManager.write("INSERT INTO " + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "users (user, lastlogin) VALUES ('" + playerName + "'," + System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR + ")"); - id = DatabaseManager.getInt("SELECT id FROM " + id = SQLDatabaseManager.getInt("SELECT id FROM " + tablePrefix + "users WHERE user = '" + playerName + "'"); - DatabaseManager.write("INSERT INTO " + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "skills (user_id) VALUES (" + id + ")"); - DatabaseManager.write("INSERT INTO " + SQLDatabaseManager.write("INSERT INTO " + tablePrefix + "experience (user_id) VALUES (" + id + ")"); // Update the skill values - DatabaseManager.write("UPDATE " + SQLDatabaseManager.write("UPDATE " + tablePrefix + "users SET lastlogin = " + 0 + " WHERE id = " + id); @@ -234,7 +234,7 @@ public class SQLConversionTask extends BukkitRunnable { + "users SET party = '" + party + "' WHERE id = " + id); */ - DatabaseManager.write("UPDATE " + SQLDatabaseManager.write("UPDATE " + tablePrefix + "skills SET " + " taming = taming+" + StringUtils.getInt(taming) @@ -250,7 +250,7 @@ public class SQLConversionTask extends BukkitRunnable { + ", acrobatics = acrobatics+" + StringUtils.getInt(acrobatics) + ", fishing = fishing+" + StringUtils.getInt(fishing) + " WHERE user_id = " + id); - DatabaseManager.write("UPDATE " + SQLDatabaseManager.write("UPDATE " + tablePrefix + "experience SET " + " taming = " + StringUtils.getInt(tamingXP) diff --git a/src/main/java/com/gmail/nossr50/runnables/database/SQLReconnectTask.java b/src/main/java/com/gmail/nossr50/runnables/database/SQLReconnectTask.java index 56904c1b4..830cc3ea4 100644 --- a/src/main/java/com/gmail/nossr50/runnables/database/SQLReconnectTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/database/SQLReconnectTask.java @@ -4,13 +4,13 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.database.DatabaseManager; +import com.gmail.nossr50.database.SQLDatabaseManager; import com.gmail.nossr50.util.player.UserManager; public class SQLReconnectTask extends BukkitRunnable { @Override public void run() { - if (DatabaseManager.checkConnected()) { + if (SQLDatabaseManager.checkConnected()) { UserManager.saveAll(); // Save all profiles UserManager.clearAll(); // Clear the profiles diff --git a/src/main/java/com/gmail/nossr50/runnables/database/UserPurgeTask.java b/src/main/java/com/gmail/nossr50/runnables/database/UserPurgeTask.java index 0206c054f..6c2c88196 100644 --- a/src/main/java/com/gmail/nossr50/runnables/database/UserPurgeTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/database/UserPurgeTask.java @@ -2,26 +2,16 @@ package com.gmail.nossr50.runnables.database; import org.bukkit.scheduler.BukkitRunnable; +import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.database.DatabaseManager; -import com.gmail.nossr50.database.LeaderboardManager; public class UserPurgeTask extends BukkitRunnable { @Override public void run() { - if (Config.getInstance().getUseMySQL()) { - DatabaseManager.purgePowerlessSQL(); + mcMMO.databaseManager.purgePowerlessUsers(); - if (Config.getInstance().getOldUsersCutoff() != -1) { - DatabaseManager.purgeOldSQL(); - } - } - else { - LeaderboardManager.purgePowerlessFlatfile(); - - if (Config.getInstance().getOldUsersCutoff() != -1) { - LeaderboardManager.purgeOldFlatfile(); - } + if (Config.getInstance().getOldUsersCutoff() != -1) { + mcMMO.databaseManager.purgeOldUsers(); } } } diff --git a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java index 76b0ea4a2..8b8933cfc 100644 --- a/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/player/PlayerProfileSaveTask.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.runnables.player; +import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import com.gmail.nossr50.datatypes.player.McMMOPlayer; @@ -19,8 +20,10 @@ public class PlayerProfileSaveTask extends BukkitRunnable { public void run() { playerProfile.save(); - if (!mcMMOPlayer.getPlayer().isOnline()) { - UserManager.remove(playerProfile.getPlayerName()); + Player player = mcMMOPlayer.getPlayer(); + + if (!player.isOnline()) { + UserManager.remove(player.getName()); } } } diff --git a/src/main/java/com/gmail/nossr50/util/player/UserManager.java b/src/main/java/com/gmail/nossr50/util/player/UserManager.java index 882998b6b..b1db369cc 100644 --- a/src/main/java/com/gmail/nossr50/util/player/UserManager.java +++ b/src/main/java/com/gmail/nossr50/util/player/UserManager.java @@ -1,7 +1,5 @@ package com.gmail.nossr50.util.player; -import java.io.File; -import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,20 +15,6 @@ public final class UserManager { private UserManager() {}; - /** - * Load users. - */ - public static void loadUsers() { - new File(mcMMO.getFlatFileDirectory()).mkdir(); - - try { - new File(mcMMO.getUsersFilePath()).createNewFile(); - } - catch (IOException e) { - e.printStackTrace(); - } - } - /** * Add a new user. * diff --git a/src/main/java/net/shatteredlands/shatt/backup/ZipLibrary.java b/src/main/java/net/shatteredlands/shatt/backup/ZipLibrary.java index e99bd4b12..0e55aadf6 100644 --- a/src/main/java/net/shatteredlands/shatt/backup/ZipLibrary.java +++ b/src/main/java/net/shatteredlands/shatt/backup/ZipLibrary.java @@ -48,10 +48,8 @@ public class ZipLibrary { // Create the Source List, and add directories/etc to the file. List sources = new ArrayList(); - if (!Config.getInstance().getUseMySQL()) { - sources.add(FlatFileDirectory); - } + sources.add(FlatFileDirectory); sources.add(ConfigFile); sources.add(TreasuresFile); sources.add(AdvancedConfigFile);