From 48c7aa3e841c83a25b91d54ed117b1ccbaacee8e Mon Sep 17 00:00:00 2001 From: zreed Date: Tue, 22 Jul 2014 20:01:26 -0400 Subject: [PATCH] Add an UpgradeManager --- .../database/FlatfileDatabaseManager.java | 9 + .../nossr50/database/SQLDatabaseManager.java | 358 ++++++++++-------- .../database/DatabaseUpdateType.java | 13 - .../datatypes/database/UpgradeType.java | 11 + src/main/java/com/gmail/nossr50/mcMMO.java | 8 + .../nossr50/util/upgrade/UpgradeManager.java | 65 ++++ src/main/resources/upgrades.yml | 9 + 7 files changed, 299 insertions(+), 174 deletions(-) delete mode 100644 src/main/java/com/gmail/nossr50/datatypes/database/DatabaseUpdateType.java create mode 100644 src/main/java/com/gmail/nossr50/datatypes/database/UpgradeType.java create mode 100644 src/main/java/com/gmail/nossr50/util/upgrade/UpgradeManager.java create mode 100644 src/main/resources/upgrades.yml diff --git a/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java index bca300508..7cd35d99e 100644 --- a/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java @@ -22,6 +22,7 @@ import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.MobHealthbarType; import com.gmail.nossr50.datatypes.database.DatabaseType; import com.gmail.nossr50.datatypes.database.PlayerStat; +import com.gmail.nossr50.datatypes.database.UpgradeType; import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.datatypes.skills.AbilityType; import com.gmail.nossr50.datatypes.skills.SkillType; @@ -762,6 +763,14 @@ public final class FlatfileDatabaseManager implements DatabaseManager { tryClose(out); } } + + mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_FISHING); + mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_BLAST_MINING_COOLDOWN); + mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_SQL_INDEXES); + mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_MOB_HEALTHBARS); + mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.DROP_SQL_PARTY_NAMES); + mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.DROP_SPOUT); + mcMMO.getUpgradeManager().setUpgradeCompleted(UpgradeType.ADD_ALCHEMY); return; } diff --git a/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java index 663577583..84e3027f5 100644 --- a/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java +++ b/src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java @@ -4,6 +4,7 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; @@ -17,8 +18,8 @@ import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.datatypes.MobHealthbarType; import com.gmail.nossr50.datatypes.database.DatabaseType; -import com.gmail.nossr50.datatypes.database.DatabaseUpdateType; import com.gmail.nossr50.datatypes.database.PlayerStat; +import com.gmail.nossr50.datatypes.database.UpgradeType; import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.datatypes.skills.AbilityType; import com.gmail.nossr50.datatypes.skills.SkillType; @@ -135,9 +136,9 @@ public final class SQLDatabaseManager implements DatabaseManager { success &= saveHuds(userId, (mobHealthbarType == null ? Config.getInstance().getMobHealthbarDefault().toString() : mobHealthbarType.toString())); success &= saveLongs( "UPDATE " + tablePrefix + "cooldowns SET " - + " mining = ?, woodcutting = ?, unarmed = ?" - + ", herbalism = ?, excavation = ?, swords = ?" - + ", axes = ?, blast_mining = ? WHERE user_id = ?", + + " mining = ?, woodcutting = ?, unarmed = ?" + + ", herbalism = ?, excavation = ?, swords = ?" + + ", axes = ?, blast_mining = ? WHERE user_id = ?", userId, profile.getAbilityDATS(AbilityType.SUPER_BREAKER), profile.getAbilityDATS(AbilityType.TREE_FELLER), @@ -149,10 +150,10 @@ public final class SQLDatabaseManager implements DatabaseManager { profile.getAbilityDATS(AbilityType.BLAST_MINING)); success &= saveIntegers( "UPDATE " + tablePrefix + "skills SET " - + " taming = ?, mining = ?, repair = ?, woodcutting = ?" - + ", unarmed = ?, herbalism = ?, excavation = ?" - + ", archery = ?, swords = ?, axes = ?, acrobatics = ?" - + ", fishing = ?, alchemy = ? WHERE user_id = ?", + + " taming = ?, mining = ?, repair = ?, woodcutting = ?" + + ", unarmed = ?, herbalism = ?, excavation = ?" + + ", archery = ?, swords = ?, axes = ?, acrobatics = ?" + + ", fishing = ?, alchemy = ? WHERE user_id = ?", profile.getSkillLevel(SkillType.TAMING), profile.getSkillLevel(SkillType.MINING), profile.getSkillLevel(SkillType.REPAIR), @@ -169,10 +170,10 @@ public final class SQLDatabaseManager implements DatabaseManager { userId); success &= saveIntegers( "UPDATE " + tablePrefix + "experience SET " - + " taming = ?, mining = ?, repair = ?, woodcutting = ?" - + ", unarmed = ?, herbalism = ?, excavation = ?" - + ", archery = ?, swords = ?, axes = ?, acrobatics = ?" - + ", fishing = ?, alchemy = ? WHERE user_id = ?", + + " taming = ?, mining = ?, repair = ?, woodcutting = ?" + + ", unarmed = ?, herbalism = ?, excavation = ?" + + ", archery = ?, swords = ?, axes = ?, acrobatics = ?" + + ", fishing = ?, alchemy = ? WHERE user_id = ?", profile.getSkillXpLevel(SkillType.TAMING), profile.getSkillXpLevel(SkillType.MINING), profile.getSkillXpLevel(SkillType.REPAIR), @@ -242,8 +243,8 @@ public final class SQLDatabaseManager implements DatabaseManager { for (SkillType skillType : SkillType.NON_CHILD_SKILLS) { 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 = ?)"; + "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); @@ -254,8 +255,8 @@ public final class SQLDatabaseManager implements DatabaseManager { 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"; + "AND " + skillName + " = (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " + + "WHERE user = '" + playerName + "') ORDER BY user"; statement.close(); @@ -361,16 +362,16 @@ public final class SQLDatabaseManager implements DatabaseManager { try { statement = connection.prepareStatement( "SELECT " - + "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, " - + "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, " - + "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, " - + "h.mobhealthbar " - + "FROM " + tablePrefix + "users u " - + "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) " - + "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) " - + "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) " - + "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) " - + "WHERE u.user = ?"); + + "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, " + + "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, " + + "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, " + + "h.mobhealthbar " + + "FROM " + tablePrefix + "users u " + + "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) " + + "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) " + + "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) " + + "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) " + + "WHERE u.user = ?"); statement.setString(1, playerName); ResultSet result = statement.executeQuery(); @@ -437,16 +438,16 @@ public final class SQLDatabaseManager implements DatabaseManager { try { statement = connection.prepareStatement( "SELECT " - + "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, " - + "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, " - + "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, " - + "h.mobhealthbar " - + "FROM " + tablePrefix + "users u " - + "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) " - + "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) " - + "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) " - + "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) " - + "WHERE u.user = ?"); + + "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, " + + "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, " + + "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, " + + "h.mobhealthbar " + + "FROM " + tablePrefix + "users u " + + "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) " + + "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) " + + "JOIN " + tablePrefix + "cooldowns c ON (u.id = c.user_id) " + + "JOIN " + tablePrefix + "huds h ON (u.id = h.user_id) " + + "WHERE u.user = ?"); List usernames = getStoredUsers(); ResultSet resultSet; int convertedUsers = 0; @@ -483,20 +484,20 @@ public final class SQLDatabaseManager implements DatabaseManager { } /** - * 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 attempting a database connection each - * time McMMO needs the database. - * - * @return the boolean value for whether or not we are connected - */ + * 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 attempting a database connection each + * time McMMO needs the database. + * + * @return the boolean value for whether or not we are connected + */ public boolean checkConnected() { boolean isClosed = true; boolean isValid = false; @@ -709,144 +710,174 @@ public final class SQLDatabaseManager implements DatabaseManager { + "PRIMARY KEY (`user_id`)) " + "DEFAULT CHARSET=latin1;"); - for (DatabaseUpdateType updateType : DatabaseUpdateType.values()) { + for (UpgradeType updateType : UpgradeType.values()) { checkDatabaseStructure(updateType); } + + mcMMO.p.getLogger().info("Killing orphans"); + write("DELETE FROM `" + tablePrefix + "experience` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "experience`.`user_id` = `u`.`id`)"); + write("DELETE FROM `" + tablePrefix + "huds` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "huds`.`user_id` = `u`.`id`)"); + write("DELETE FROM `" + tablePrefix + "cooldowns` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "cooldowns`.`user_id` = `u`.`id`)"); + write("DELETE FROM `" + tablePrefix + "skills` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "skills`.`user_id` = `u`.`id`)"); } /** - * Check database structure for missing values. + * Check database structure for necessary upgrades. * - * @param update Type of data to check updates for + * @param upgrade Upgrade to attempt to apply */ - private void checkDatabaseStructure(DatabaseUpdateType update) { - String sql = ""; - - switch (update) { - case BLAST_MINING: - sql = "SELECT * FROM `" + tablePrefix + "cooldowns` ORDER BY `" + tablePrefix + "cooldowns`.`blast_mining` ASC LIMIT 0 , 30"; - break; - - case FISHING: - sql = "SELECT * FROM `" + tablePrefix + "experience` ORDER BY `" + tablePrefix + "experience`.`fishing` ASC LIMIT 0 , 30"; - break; - - case ALCHEMY: - sql = "SELECT * FROM `" + tablePrefix + "experience` ORDER BY `" + tablePrefix + "experience`.`alchemy` 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;"); - } - return; - - case MOB_HEALTHBARS: - sql = "SELECT * FROM `" + tablePrefix + "huds` ORDER BY `" + tablePrefix + "huds`.`mobhealthbar` ASC LIMIT 0 , 30"; - break; - - case PARTY_NAMES: - write("ALTER TABLE `" + tablePrefix + "users` DROP COLUMN `party` ;"); - return; - - case DROPPED_SPOUT: - write("ALTER TABLE `" + tablePrefix + "huds` DROP COLUMN `hudtype` ;"); - return; - - case KILL_ORPHANS: - mcMMO.p.getLogger().info("Killing orphans"); - write( - "DELETE FROM " + tablePrefix + "experience " + - "WHERE NOT EXISTS (SELECT * FROM " + - tablePrefix + "users u WHERE " + - tablePrefix + "experience.user_id = u.id);" - ); - write( - "DELETE FROM " + tablePrefix + "huds " + - "WHERE NOT EXISTS (SELECT * FROM " + - tablePrefix + "users u WHERE " + - tablePrefix + "huds.user_id = u.id);" - ); - write( - "DELETE FROM " + tablePrefix + "cooldowns " + - "WHERE NOT EXISTS (SELECT * FROM " + - tablePrefix + "users u WHERE " + - tablePrefix + "cooldowns.user_id = u.id);" - ); - write( - "DELETE FROM " + tablePrefix + "skills " + - "WHERE NOT EXISTS (SELECT * FROM " + - tablePrefix + "users u WHERE " + - tablePrefix + "skills.user_id = u.id);" - ); - return; - - default: - break; + private void checkDatabaseStructure(UpgradeType upgrade) { + if (!checkConnected()) { + return; } - ResultSet resultSet; - PreparedStatement statement = null; + if (!mcMMO.getUpgradeManager().shouldUpgrade(upgrade)) { + mcMMO.p.debug("Skipping " + upgrade.name() + " upgrade (unneeded)"); + return; + } + + Statement statement = null; + ResultSet resultSet = null; try { - if (!checkConnected()) { - return; - } + statement = connection.createStatement(); - statement = connection.prepareStatement(sql); - resultSet = statement.executeQuery(); - - while (resultSet.next()) { - // No reason to do anything here... we're just trying to catch exceptions - } - } - 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' ;"); + switch (upgrade) { + case ADD_FISHING: + try { + statement.executeQuery("SELECT `fishing` FROM `" + tablePrefix + "skills` LIMIT 1"); + } + catch (SQLException ex) { + mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Fishing..."); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "skills` ADD `fishing` int(10) NOT NULL DEFAULT '0'"); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "experience` ADD `fishing` int(10) 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' ;"); + case ADD_BLAST_MINING_COOLDOWN: + try { + statement.executeQuery("SELECT `blast_mining` FROM `" + tablePrefix + "cooldowns` LIMIT 1"); + } + catch (SQLException ex) { + mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Blast Mining..."); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "cooldowns` ADD `blast_mining` int(32) 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 '" + Config.getInstance().getMobHealthbarDefault() + "' ;"); + case ADD_SQL_INDEXES: + resultSet = statement.executeQuery("SHOW INDEX FROM `" + tablePrefix + "skills` WHERE `Key_name` LIKE 'idx\\_%'"); + resultSet.last(); + + if (resultSet.getRow() != SkillType.NON_CHILD_SKILLS.size()) { + mcMMO.p.getLogger().info("Indexing tables, this may take a while on larger databases"); + + for (SkillType skill : SkillType.NON_CHILD_SKILLS) { + String skill_name = skill.name().toLowerCase(); + + try { + statement.executeUpdate("ALTER TABLE `" + tablePrefix + "skills` ADD INDEX `idx_" + skill_name + "` (`" + skill_name + "`) USING BTREE"); + } + catch (SQLException ex) { + // Ignore + } + } + } break; - case ALCHEMY: - mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Alchemy..."); - write("ALTER TABLE `"+tablePrefix + "skills` ADD `alchemy` int(10) NOT NULL DEFAULT '0' ;"); - write("ALTER TABLE `"+tablePrefix + "experience` ADD `alchemy` int(10) NOT NULL DEFAULT '0' ;"); + case ADD_MOB_HEALTHBARS: + try { + statement.executeQuery("SELECT `mobhealthbar` FROM `" + tablePrefix + "huds` LIMIT 1"); + } + catch (SQLException ex) { + mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for mob healthbars..."); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "huds` ADD `mobhealthbar` varchar(50) NOT NULL DEFAULT '" + Config.getInstance().getMobHealthbarDefault() + "'"); + } break; - + + case DROP_SQL_PARTY_NAMES: + try { + resultSet = statement.executeQuery("SELECT * FROM `" + tablePrefix + "users` LIMIT 1"); + + ResultSetMetaData rsmeta = resultSet.getMetaData(); + boolean column_exists = false; + + for (int i = 1; i <= rsmeta.getColumnCount(); i++) { + if (rsmeta.getColumnName(i).equalsIgnoreCase("party")) { + column_exists = true; + break; + } + } + + if (column_exists) { + mcMMO.p.getLogger().info("Removing party name from users table..."); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "users` DROP COLUMN `party`"); + } + } + catch (SQLException ex) { + // Ignore + } + break; + + case DROP_SPOUT: + try { + resultSet = statement.executeQuery("SELECT * FROM `" + tablePrefix + "huds` LIMIT 1"); + + ResultSetMetaData rsmeta = resultSet.getMetaData(); + boolean column_exists = false; + + for (int i = 1; i <= rsmeta.getColumnCount(); i++) { + if (rsmeta.getColumnName(i).equalsIgnoreCase("hudtype")) { + column_exists = true; + break; + } + } + + if (column_exists) { + mcMMO.p.getLogger().info("Removing Spout HUD type from huds table..."); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "huds` DROP COLUMN `hudtype`"); + } + } + catch (SQLException ex) { + // Ignore + } + break; + + case ADD_ALCHEMY: + try { + statement.executeQuery("SELECT `alchemy` FROM `" + tablePrefix + "skills` LIMIT 1"); + } + catch (SQLException ex) { + mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for Alchemy..."); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "skills` ADD `alchemy` int(10) NOT NULL DEFAULT '0'"); + statement.executeQuery("ALTER TABLE `" + tablePrefix + "experience` ADD `alchemy` int(10) NOT NULL DEFAULT '0'"); + } + break; + default: break; + } + + mcMMO.getUpgradeManager().setUpgradeCompleted(upgrade); + } + catch (SQLException ex) { + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } + catch (SQLException e) { + // Ignore + } + } if (statement != null) { try { statement.close(); } catch (SQLException e) { - // Ignore the error, we're leaving + // Ignore } } } @@ -856,6 +887,7 @@ public final class SQLDatabaseManager implements DatabaseManager { * Attempt to write the SQL query. * * @param sql Query to write. + * * @return true if the query was successfully written, false otherwise. */ private boolean write(String sql) { @@ -891,6 +923,7 @@ public final class SQLDatabaseManager implements DatabaseManager { * 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 */ private int update(String sql) { @@ -925,6 +958,7 @@ public final class SQLDatabaseManager implements DatabaseManager { * Read SQL query. * * @param sql SQL query to read + * * @return the rows in this SQL query */ private HashMap> read(String sql) { @@ -970,6 +1004,7 @@ public final class SQLDatabaseManager implements DatabaseManager { * Get the Integer. Only return first row / first field. * * @param statement SQL query to execute + * * @return the value in the first row / first field */ private int readInt(PreparedStatement statement) { @@ -1113,6 +1148,7 @@ public final class SQLDatabaseManager implements DatabaseManager { * Retrieve the database id for a player * * @param playerName The name of the user to retrieve the id for + * * @return the requested id or -1 if not found */ private int readId(String playerName) { @@ -1183,8 +1219,8 @@ public final class SQLDatabaseManager implements DatabaseManager { } private PlayerProfile loadFromResult(String playerName, ResultSet result) throws SQLException { - Map skills = new HashMap(); // Skill & Level - Map skillsXp = new HashMap(); // Skill & XP + Map skills = new HashMap(); // Skill & Level + Map skillsXp = new HashMap(); // Skill & XP Map skillsDATS = new HashMap(); // Ability & Cooldown MobHealthbarType mobHealthbarType; diff --git a/src/main/java/com/gmail/nossr50/datatypes/database/DatabaseUpdateType.java b/src/main/java/com/gmail/nossr50/datatypes/database/DatabaseUpdateType.java deleted file mode 100644 index 2223c1969..000000000 --- a/src/main/java/com/gmail/nossr50/datatypes/database/DatabaseUpdateType.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.gmail.nossr50.datatypes.database; - -public enum DatabaseUpdateType { - FISHING, - BLAST_MINING, - INDEX, - MOB_HEALTHBARS, - PARTY_NAMES, - KILL_ORPHANS, - DROPPED_SPOUT, - ALCHEMY - ; -} diff --git a/src/main/java/com/gmail/nossr50/datatypes/database/UpgradeType.java b/src/main/java/com/gmail/nossr50/datatypes/database/UpgradeType.java new file mode 100644 index 000000000..1f901e68a --- /dev/null +++ b/src/main/java/com/gmail/nossr50/datatypes/database/UpgradeType.java @@ -0,0 +1,11 @@ +package com.gmail.nossr50.datatypes.database; + +public enum UpgradeType { + ADD_FISHING, + ADD_BLAST_MINING_COOLDOWN, + ADD_SQL_INDEXES, + ADD_MOB_HEALTHBARS, + DROP_SQL_PARTY_NAMES, + DROP_SPOUT, + ADD_ALCHEMY; +} diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index 5f0e7a071..d4ea83366 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -60,6 +60,7 @@ import com.gmail.nossr50.util.commands.CommandRegistrationManager; import com.gmail.nossr50.util.experience.FormulaManager; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.scoreboards.ScoreboardManager; +import com.gmail.nossr50.util.upgrade.UpgradeManager; import net.shatteredlands.shatt.backup.ZipLibrary; @@ -72,6 +73,7 @@ public class mcMMO extends JavaPlugin { private static DatabaseManager databaseManager; private static FormulaManager formulaManager; private static HolidayManager holidayManager; + private static UpgradeManager upgradeManager; /* File Paths */ private static String mainDirectory; @@ -129,6 +131,8 @@ public class mcMMO extends JavaPlugin { PluginManager pluginManager = getServer().getPluginManager(); healthBarPluginEnabled = pluginManager.getPlugin("HealthBar") != null; + upgradeManager = new UpgradeManager(); + setupFilePaths(); modManager = new ModManager(); @@ -309,6 +313,10 @@ public class mcMMO extends JavaPlugin { return modManager; } + public static UpgradeManager getUpgradeManager() { + return upgradeManager; + } + @Deprecated public static void setDatabaseManager(DatabaseManager databaseManager) { mcMMO.databaseManager = databaseManager; diff --git a/src/main/java/com/gmail/nossr50/util/upgrade/UpgradeManager.java b/src/main/java/com/gmail/nossr50/util/upgrade/UpgradeManager.java new file mode 100644 index 000000000..571f3b439 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/util/upgrade/UpgradeManager.java @@ -0,0 +1,65 @@ +package com.gmail.nossr50.util.upgrade; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Set; + +import com.gmail.nossr50.config.ConfigLoader; +import com.gmail.nossr50.datatypes.database.UpgradeType; + +public class UpgradeManager extends ConfigLoader { + private final Set setNeededUpgrades; + + public UpgradeManager() { + super("upgrades.yml"); + + setNeededUpgrades = EnumSet.allOf(UpgradeType.class); + + loadKeys(); + } + + /** + * Check if the given {@link UpgradeType} is necessary. + * + * @param type Upgrade type to check + * + * @return true if plugin data needs to have the given upgrade + */ + public boolean shouldUpgrade(final UpgradeType type) { + return setNeededUpgrades.contains(type); + } + + /** + * Set the given {@link UpgradeType} as completed. Does nothing if + * the upgrade was applied previously. + * + * @param type Upgrade type to set as complete + */ + public void setUpgradeCompleted(final UpgradeType type) { + if (!setNeededUpgrades.remove(type)) { + return; + } + + plugin.debug("Saving upgrade status for type " + type.toString() + "..."); + + config.set("Upgrades_Finished." + type.toString(), true); + + try { + config.save(getFile()); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void loadKeys() { + for (UpgradeType type : UpgradeType.values()) { + if (config.getBoolean("Upgrades_Finished." + type.toString())) { + setNeededUpgrades.remove(type); + } + } + + plugin.debug("Needed upgrades: " + Arrays.toString(setNeededUpgrades.toArray(new UpgradeType[setNeededUpgrades.size()]))); + } +} diff --git a/src/main/resources/upgrades.yml b/src/main/resources/upgrades.yml new file mode 100644 index 000000000..3858dfe0c --- /dev/null +++ b/src/main/resources/upgrades.yml @@ -0,0 +1,9 @@ +# WARNING: DO NOT MODIFY THIS CONFIG +Upgrades_Finished: + ADD_FISHING: false + ADD_BLAST_MINING_COOLDOWN: false + ADD_SQL_INDEXES: false + ADD_MOB_HEALTHBARS: false + DROP_SQL_PARTY_NAMES: false + DROP_SPOUT: false + ADD_ALCHEMY: false