From 9034a36f075bc9c25c31f5caeac5109fa59dbe80 Mon Sep 17 00:00:00 2001 From: riking Date: Sat, 8 Jun 2013 21:51:42 -0700 Subject: [PATCH] Implement importing from any database in /mmoupdate --- Changelog.txt | 2 + .../commands/database/MmoshowdbCommand.java | 42 ++++++ .../commands/database/MmoupdateCommand.java | 125 ++++++++++++++++-- .../database/DatabaseManagerFactory.java | 4 + .../runnables/database/ConversionTask.java | 41 ++++++ .../database/FromFlatfileConversionTask.java | 46 ------- .../commands/CommandRegistrationManager.java | 15 ++- .../resources/locale/locale_en_US.properties | 11 +- src/main/resources/plugin.yml | 7 +- 9 files changed, 228 insertions(+), 65 deletions(-) create mode 100644 src/main/java/com/gmail/nossr50/commands/database/MmoshowdbCommand.java create mode 100644 src/main/java/com/gmail/nossr50/runnables/database/ConversionTask.java delete mode 100644 src/main/java/com/gmail/nossr50/runnables/database/FromFlatfileConversionTask.java diff --git a/Changelog.txt b/Changelog.txt index 9da24ce04..1c58a332c 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -29,6 +29,8 @@ Version 1.4.06-dev + Added information about /party itemshare and /party expshare to the party help page + Added option to use scoreboards for power level display instead of Spout. + Added permission node to prevent inspecting hidden players + + Added SQL to Flatfile database conversion + + Added ability to use custom database managers and convert to/from them = Fixed bug where spawned arrows could throw ArrayIndexOutOfBoundsException = Fixed bug where custom Spout titles were overwritten by mcMMO. = Fixed bug where Nether Quartz wasn't included in Smelting or item sharing diff --git a/src/main/java/com/gmail/nossr50/commands/database/MmoshowdbCommand.java b/src/main/java/com/gmail/nossr50/commands/database/MmoshowdbCommand.java new file mode 100644 index 000000000..4f5f6c6cb --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/database/MmoshowdbCommand.java @@ -0,0 +1,42 @@ +package com.gmail.nossr50.commands.database; + +import java.util.List; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabExecutor; + +import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.database.DatabaseManagerFactory; +import com.gmail.nossr50.locale.LocaleLoader; +import com.google.common.collect.ImmutableList; + +public class MmoshowdbCommand implements TabExecutor { + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length != 0) { + return false; + } + else { + Class clazz = DatabaseManagerFactory.getCustomDatabaseManagerClass(); + if (clazz != null) { + sender.sendMessage(LocaleLoader.getString("Commands.mmoshowdb", clazz.getName())); + return true; + } + else { + if (Config.getInstance().getUseMySQL()) { + sender.sendMessage(LocaleLoader.getString("Commands.mmoshowdb", "sql")); + } + else { + sender.sendMessage(LocaleLoader.getString("Commands.mmoshowdb", "flatfile")); + } + return true; + } + } + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { + return ImmutableList.of(); + } +} diff --git a/src/main/java/com/gmail/nossr50/commands/database/MmoupdateCommand.java b/src/main/java/com/gmail/nossr50/commands/database/MmoupdateCommand.java index 3e6ad42d8..739ae5ca2 100644 --- a/src/main/java/com/gmail/nossr50/commands/database/MmoupdateCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/database/MmoupdateCommand.java @@ -1,49 +1,148 @@ package com.gmail.nossr50.commands.database; import java.util.List; - import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.TabExecutor; import org.bukkit.entity.Player; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.database.DatabaseManager; +import com.gmail.nossr50.database.DatabaseManagerFactory; +import com.gmail.nossr50.datatypes.player.PlayerProfile; import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.runnables.database.FromFlatfileConversionTask; +import com.gmail.nossr50.runnables.database.ConversionTask; import com.gmail.nossr50.util.player.UserManager; import com.google.common.collect.ImmutableList; public class MmoupdateCommand implements TabExecutor { + @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!Config.getInstance().getUseMySQL()) { - sender.sendMessage("SQL Mode is not enabled."); // TODO: Localize - return true; - } - switch (args.length) { - case 0: - sender.sendMessage(LocaleLoader.getString("Commands.mmoupdate.Start")); + case 1: + String argType = args[0]; + String oldType = validateName(sender, args[0]); + if (oldType == null) { + return true; + } + + String newType = getCurrentDb(); + + if (newType.equals(oldType)) { + sender.sendMessage(LocaleLoader.getString("Commands.mmoupdate.Same", argType)); + return true; + } + + DatabaseManager oldDb; + if (oldType == "sql") { + oldDb = DatabaseManagerFactory.createSQLDatabaseManager(); + } + else if (oldType == "flatfile") { + oldDb = DatabaseManagerFactory.createFlatfileDatabaseManager(); + } + else try { + @SuppressWarnings("unchecked") + Class clazz = (Class) Class.forName(oldType); + oldDb = DatabaseManagerFactory.createCustomDatabaseManager((Class) clazz); + + oldType = clazz.getSimpleName(); // For pretty-printing; we have the database now + } + catch (Throwable e) { + return false; + } + + sender.sendMessage(LocaleLoader.getString("Commands.mmoupdate.Start", oldType, newType)); + + // Convert the online players right away, without waiting + // first, flush out the current data UserManager.saveAll(); UserManager.clearAll(); - new FromFlatfileConversionTask().runTaskAsynchronously(mcMMO.p); for (Player player : mcMMO.p.getServer().getOnlinePlayers()) { + // Get the profile from the old database and save it in the new + PlayerProfile profile = oldDb.loadPlayerProfile(player.getName(), false); + if (profile.isLoaded()) { + mcMMO.getDatabaseManager().saveUser(profile); + } + + // Reload from the current database via UserManager UserManager.addUser(player); } - sender.sendMessage(LocaleLoader.getString("Commands.mmoupdate.Finish")); + // Schedule the task for all users + new ConversionTask(oldDb, sender, oldType, newType).runTaskAsynchronously(mcMMO.p); + return true; default: - return false; + break; + } + // If you don't do your research, you get lied to + if (!(sender instanceof ConsoleCommandSender)) { + sender.sendMessage(LocaleLoader.getString("Commands.mmoupdate.OpOnly")); + return true; + } + return false; + } + + /** + * @return null - if type not recognized / class not found + * empty string - if type is same as current + * normalized string - if type is recognized + */ + private String validateName(CommandSender sender, String type) { + if (type.equalsIgnoreCase("sql") || type.equalsIgnoreCase("mysql")) { + return "sql"; + } + + if (type.equalsIgnoreCase("flatfile")) { + return "flatfile"; + } + + try { + Class clazz = Class.forName(type); + + if (!DatabaseManager.class.isAssignableFrom(clazz)) { + sender.sendMessage(LocaleLoader.getString("Commands.mmoupdate.InvalidType", type)); + return null; + } + + return type; + } + catch (Exception e) { + sender.sendMessage(LocaleLoader.getString("Commands.mmoupdate.InvalidType", type)); + return null; + } + } + + private String getCurrentDb() { + if (DatabaseManagerFactory.getCustomDatabaseManagerClass() != null) { + return DatabaseManagerFactory.getCustomDatabaseManagerClass().getSimpleName(); + } + + if (Config.getInstance().getUseMySQL()) { + return "sql"; + } + else { + return "flatfile"; } } @Override public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - return ImmutableList.of(); + if (sender instanceof Player) { + // What, you're trying to run this on a live server? No autocomplete for you! Do your research first! + return ImmutableList.of(); + } + + Class clazz = DatabaseManagerFactory.getCustomDatabaseManagerClass(); + if (clazz != null) { + return ImmutableList.of("confirm", "flatfile", "sql", clazz.getName()); + } + return ImmutableList.of("confirm", "flatfile", "sql"); } } diff --git a/src/main/java/com/gmail/nossr50/database/DatabaseManagerFactory.java b/src/main/java/com/gmail/nossr50/database/DatabaseManagerFactory.java index e8f0f6835..a798af736 100644 --- a/src/main/java/com/gmail/nossr50/database/DatabaseManagerFactory.java +++ b/src/main/java/com/gmail/nossr50/database/DatabaseManagerFactory.java @@ -46,6 +46,10 @@ public class DatabaseManagerFactory { customManager = clazz; } + public static Class getCustomDatabaseManagerClass() { + return customManager; + } + // For data conversion purposes public static FlatfileDatabaseManager createFlatfileDatabaseManager() { diff --git a/src/main/java/com/gmail/nossr50/runnables/database/ConversionTask.java b/src/main/java/com/gmail/nossr50/runnables/database/ConversionTask.java new file mode 100644 index 000000000..c20f291c0 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/runnables/database/ConversionTask.java @@ -0,0 +1,41 @@ +package com.gmail.nossr50.runnables.database; + +import java.util.logging.Level; + +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.locale.LocaleLoader; + +public class ConversionTask extends BukkitRunnable { + private final DatabaseManager sourceDb; + private final CommandSender sender; + private final String message; + + public ConversionTask(DatabaseManager from, CommandSender sendback, String oldType, String newType) { + sourceDb = from; + sender = sendback; + message = LocaleLoader.getString("Commands.mmoupdate.Finish", oldType, newType); + } + + @Override + public void run() { + sourceDb.convertUsers(mcMMO.getDatabaseManager()); + + // Announce completeness + mcMMO.p.getServer().getScheduler().runTask(mcMMO.p, new CompleteAnnouncement()); + } + + public class CompleteAnnouncement implements Runnable { + @Override + public void run() { + try { + sender.sendMessage(message); + } catch (Exception e) { + mcMMO.p.getLogger().log(Level.WARNING, "Exception sending database conversion completion message to " + sender.getName(), e); + } + } + } +} diff --git a/src/main/java/com/gmail/nossr50/runnables/database/FromFlatfileConversionTask.java b/src/main/java/com/gmail/nossr50/runnables/database/FromFlatfileConversionTask.java deleted file mode 100644 index bf48ec65d..000000000 --- a/src/main/java/com/gmail/nossr50/runnables/database/FromFlatfileConversionTask.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.gmail.nossr50.runnables.database; - -import java.io.BufferedReader; -import java.io.FileReader; - -import org.bukkit.scheduler.BukkitRunnable; - -import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.database.DatabaseManager; -import com.gmail.nossr50.database.DatabaseManagerFactory; -import com.gmail.nossr50.datatypes.player.PlayerProfile; - -public class FromFlatfileConversionTask extends BukkitRunnable { - - @Override - public void run() { - String location = mcMMO.getUsersFilePath(); - - try { - DatabaseManager from = DatabaseManagerFactory.createFlatfileDatabaseManager(); - DatabaseManager to = mcMMO.getDatabaseManager(); - - BufferedReader in = new BufferedReader(new FileReader(location)); - String line = ""; - int converted = 0; - - while ((line = in.readLine()) != null) { - - // Find if the line contains the player we want. - String[] playerData = line.split(":"); - String playerName = playerData[0]; - PlayerProfile profile = from.loadPlayerProfile(playerName, false); - if (profile.isLoaded()) { - to.saveUser(profile); - converted++; - } - } - - mcMMO.p.getLogger().info("Database updated from users file, " + converted + " items added/updated to DB"); - in.close(); - } - catch (Exception e) { - mcMMO.p.getLogger().severe("Exception while reading " + location + " (Are you sure you formatted it correctly?) " + e.toString()); - } - } -} diff --git a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java index cf4b18638..971fccbf3 100644 --- a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java +++ b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java @@ -19,6 +19,7 @@ import com.gmail.nossr50.commands.chat.AdminChatCommand; import com.gmail.nossr50.commands.chat.PartyChatCommand; import com.gmail.nossr50.commands.database.McpurgeCommand; import com.gmail.nossr50.commands.database.McremoveCommand; +import com.gmail.nossr50.commands.database.MmoshowdbCommand; import com.gmail.nossr50.commands.database.MmoupdateCommand; import com.gmail.nossr50.commands.experience.AddlevelsCommand; import com.gmail.nossr50.commands.experience.AddxpCommand; @@ -276,11 +277,20 @@ public final class CommandRegistrationManager { PluginCommand command = mcMMO.p.getCommand("mmoupdate"); command.setDescription(LocaleLoader.getString("Commands.Description.mmoupdate")); command.setPermission("mcmmo.commands.mmoupdate"); - command.setPermissionMessage(permissionsMessage); - command.setUsage(LocaleLoader.getString("Commands.Usage.0", "mmoupdate")); + command.setPermissionMessage(LocaleLoader.getString("Commands.mmoupdate.OpOnly")); + command.setUsage(LocaleLoader.getString("Commands.Usage.1", "mmoupdate", "")); command.setExecutor(new MmoupdateCommand()); } + private static void registerMmoshowdbCommand() { + PluginCommand command = mcMMO.p.getCommand("mmoshowdb"); + command.setDescription(LocaleLoader.getString("Commands.Description.mmoshowdb")); + command.setPermission("mcmmo.commands.mmoshowdb"); + command.setPermissionMessage(permissionsMessage); + command.setUsage(LocaleLoader.getString("Commands.Usage.0", "mmoshowdb")); + command.setExecutor(new MmoshowdbCommand()); + } + private static void registerAdminChatCommand() { PluginCommand command = mcMMO.p.getCommand("adminchat"); command.setDescription(LocaleLoader.getString("Commands.Description.adminchat")); @@ -421,6 +431,7 @@ public final class CommandRegistrationManager { registerMcpurgeCommand(); registerMcremoveCommand(); registerMmoupdateCommand(); + registerMmoshowdbCommand(); // Experience Commands registerAddlevelsCommand(); diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index bc652a60a..30805aa5d 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -442,8 +442,11 @@ Commands.mmoedit=[player] [[RED]] - Modify target Commands.mmoedit.AllSkills.1=[[GREEN]]Your level in all skills was set to {0}! Commands.mmoedit.Modified.1=[[GREEN]]Your level in {0} was set to {1}! Commands.mmoedit.Modified.2=[[RED]]{0} has been modified for {1}. -Commands.mmoupdate.Start=[[GRAY]]Starting conversion... -Commands.mmoupdate.Finish=[[GREEN]]Conversion finished! +Commands.mmoupdate.Same=[[RED]]You are already using the {0} database! +Commands.mmoupdate.InvalidType=[[RED]]{0} is not a valid database type. +Commands.mmoupdate.Start=[[GRAY]]Starting conversion from {0} to {1}... +Commands.mmoupdate.Finish=[[GRAY]]Database migration complete; the {1} database now has all data from the {0} database. +Commands.mmoshowdb=[[YELLOW]]The currently used database is [[GREEN]]{0} Commands.ModDescription=[[RED]]- Read brief mod description Commands.NoConsole=This command does not support console usage. Commands.Notifications.Off=Ability notifications toggled [[RED]]off @@ -505,6 +508,7 @@ Commands.Usage.0=[[RED]]Proper usage is /{0} Commands.Usage.1=[[RED]]Proper usage is /{0} {1} Commands.Usage.2=[[RED]]Proper usage is /{0} {1} {2} Commands.Usage.3=[[RED]]Proper usage is /{0} {1} {2} {3} +Commands.Usage.FullClassName=classname Commands.Usage.Level=level Commands.Usage.Message=message Commands.Usage.Page=page @@ -751,7 +755,8 @@ Commands.Description.mcremove=Remove a user from the mcMMO database Commands.Description.mcstats=Show your mcMMO levels and XP Commands.Description.mctop=Show mcMMO leader boards Commands.Description.mmoedit=Edit mcMMO levels for a user -Commands.Description.mmoupdate=Convert mcMMO database from Flatfile to MySQL +Commands.Description.mmoupdate=Migrate mcMMO database from an old database into the current one +Commands.Description.mmoshowdb=Show the name of the current database type (for later use with /mmoupdate) Commands.Description.party=Control various mcMMO party settings Commands.Description.partychat=Toggle mcMMO party chat on/off or send party chat messages Commands.Description.ptp=Teleport to an mcMMO party member diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 66d105419..210eeae8a 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -58,7 +58,9 @@ commands: inspect: description: View detailed mcMMO info on another player mmoupdate: - description: Convert from Flat File to MySQL + description: Migrate mcMMO database from an old database type to the current + mmoshowdb: + description: Show the name of the current database type (for later use with /mmoupdate) partychat: aliases: [pc, p] description: Toggle Party chat or send party chat messages @@ -717,6 +719,7 @@ permissions: mcmmo.commands.mmoedit: true mcmmo.commands.mmoedit.others: true mcmmo.commands.mmoupdate: true + mcmmo.commands.mmoshowdb: true mcmmo.commands.ptp.world.all: true mcmmo.commands.skillreset.all: true mcmmo.commands.vampirism.all: true @@ -908,6 +911,8 @@ permissions: description: Allows access to the mmoedit command for other players mcmmo.commands.mmoupdate: description: Allows access to the mmoupdate command + mcmmo.commands.mmoshowdb: + description: Allows access to the mmoshowdb command mcmmo.commands.mobhealth: default: true description: Allows access to the mobhealth command