From a48ada306c3ecdf4fbf3cb7c442a8013fbcb632d Mon Sep 17 00:00:00 2001 From: TfT_02 Date: Sun, 20 Jul 2014 22:40:59 +0200 Subject: [PATCH] Add magical mod importer Usage: Create a folder called 'import' inside /mcMMO/mods/. Place your latest Cauldron 1.7+ startup log in this folder and rename it to 'import.log'. It is worth noting that it's advisable to create a short log by starting and stopping the server once, or by manually editing the log file to only include material mapping in order to speed up the import process. When the server is running, use the command /mcimport. You will see the import progress in the console, once it is done the files are created in /mcMMO/mods/output/. Any item that wasn't recognised gets placed in a .unknown.yml config file. Durability detection only works if the mod is installed when importing (it should be). --- Changelog.txt | 1 + .../nossr50/commands/McImportCommand.java | 352 ++++++++++++++++++ .../datatypes/skills/ModConfigType.java | 22 ++ .../commands/CommandRegistrationManager.java | 11 + src/main/resources/plugin.yml | 5 + 5 files changed, 391 insertions(+) create mode 100644 src/main/java/com/gmail/nossr50/commands/McImportCommand.java create mode 100644 src/main/java/com/gmail/nossr50/datatypes/skills/ModConfigType.java diff --git a/Changelog.txt b/Changelog.txt index b88908df6..6dedfeca8 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -18,6 +18,7 @@ Version 1.5.01-dev + Added options to tools.yml and armor.yml config files to set a pretty repair material name + Added full support for repairables in tools.yml and armor.yml config files + Added new API class SkillAPI used to get a list of valid skill names + + Added magical mod config file import command, for Cauldron 1.7+. Check wiki for usage = Fixed bug where pistons would mess with the block tracking = Fixed bug where the Updater was running on the main thread. = Fixed bug when players would use /ptp without being in a party diff --git a/src/main/java/com/gmail/nossr50/commands/McImportCommand.java b/src/main/java/com/gmail/nossr50/commands/McImportCommand.java new file mode 100644 index 000000000..7cd13b87a --- /dev/null +++ b/src/main/java/com/gmail/nossr50/commands/McImportCommand.java @@ -0,0 +1,352 @@ +package com.gmail.nossr50.commands; + +import java.io.BufferedReader; +import java.io.Closeable; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; + +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.datatypes.skills.ModConfigType; + +public class McImportCommand implements CommandExecutor { + int fileAmount; + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + switch (args.length) { + case 0: + importModConfig(); + return true; + + default: + return false; + } + } + + public boolean importModConfig() { + String importFilePath = mcMMO.getModDirectory() + File.separator + "import"; + File importFile = new File(importFilePath, "import.log"); + mcMMO.p.getLogger().info("Starting import of mod materials..."); + fileAmount = 0; + + HashMap> materialNames = new HashMap>(); + + BufferedReader in = null; + + try { + // Open the file + in = new BufferedReader(new FileReader(importFile)); + + String line; + String materialName; + + // While not at the end of the file + while ((line = in.readLine()) != null) { + String[] split1 = line.split("material "); + + if (split1.length != 2) { + continue; + } + + String[] split2 = split1[1].split(" with"); + + if (split2.length != 2) { + continue; + } + + materialName = split2[0]; + String[] materialSplit = materialName.split("_"); + + if (materialSplit.length > 1) { + // Categorise each material under a mod config type + ModConfigType type = ModConfigType.getModConfigType(materialName); + + if (!materialNames.containsKey(type)) { + materialNames.put(type, new ArrayList()); + } + + materialNames.get(type).add(materialName); + continue; + } + } + } + catch (FileNotFoundException e) { + mcMMO.p.getLogger().warning("Could not find " + importFile.getAbsolutePath() + " ! (No such file or directory)"); + mcMMO.p.getLogger().warning("Copy and paste latest.log to " + importFile.getParentFile().getAbsolutePath() + " and rename it to import.log"); + return false; + } + catch (Exception e) { + e.printStackTrace(); + return false; + } + finally { + tryClose(in); + } + + createOutput(materialNames); + + mcMMO.p.getLogger().info("Import finished! Created " + fileAmount + " files!"); + return true; + } + + private void createOutput(HashMap> materialNames) { + for (ModConfigType modConfigType : materialNames.keySet()) { + HashMap> materialNamesType = new HashMap>(); + + for (String materialName : materialNames.get(modConfigType)) { + String modName = materialName.split("_")[0].toLowerCase(); + + if (!materialNamesType.containsKey(modName)) { + materialNamesType.put(modName, new ArrayList()); + } + + materialNamesType.get(modName).add(materialName); + } + + createOutput(modConfigType, materialNamesType); + } + + } + + private void tryClose(Closeable c) { + if (c == null) { + return; + } + try { + c.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + + private void createOutput(ModConfigType modConfigType, HashMap> materialNames) { + File outputFilePath = new File(mcMMO.getModDirectory() + File.separator + "output"); + if (!outputFilePath.exists() && !outputFilePath.mkdirs()) { + mcMMO.p.getLogger().severe("Could not create output directory! " + outputFilePath.getAbsolutePath()); + } + + FileWriter out = null; + String type = modConfigType.name().toLowerCase(); + + for (String modName : materialNames.keySet()) { + File outputFile = new File(outputFilePath, modName + "." + type + ".yml"); + mcMMO.p.getLogger().info("Creating " + outputFile.getName()); + try { + if (outputFile.exists() && !outputFile.delete()) { + mcMMO.p.getLogger().severe("Not able to delete old output file! " + outputFile.getAbsolutePath()); + } + + if (!outputFile.createNewFile()) { + mcMMO.p.getLogger().severe("Could not create output file! " + outputFile.getAbsolutePath()); + continue; + } + + StringBuilder writer = new StringBuilder(); + HashMap> configSections = getConfigSections(modConfigType, modName, materialNames); + + if (configSections == null) { + mcMMO.p.getLogger().severe("Something went wrong!! type is " + type); + return; + } + + // Write the file, go through each skill and write all the materials + for (String configSection : configSections.keySet()) { + if (configSection.equals("UNIDENTIFIED")) { + writer.append("# This isn't a valid config section and all materials in this category need to be").append("\r\n"); + writer.append("# copy and pasted to a valid section of this config file.").append("\r\n"); + } + writer.append(configSection).append(":").append("\r\n"); + + for (String line : configSections.get(configSection)) { + writer.append(line).append("\r\n"); + } + + writer.append("\r\n"); + } + + out = new FileWriter(outputFile); + out.write(writer.toString()); + } + catch (IOException e) { + e.printStackTrace(); + return; + } + catch (Exception e) { + e.printStackTrace(); + return; + } + finally { + tryClose(out); + fileAmount++; + } + } + } + + private HashMap> getConfigSections(ModConfigType type, String modName, HashMap> materialNames) { + switch (type) { + case BLOCKS: + return getConfigSectionsBlocks(modName, materialNames); + case TOOLS: + return getConfigSectionsTools(modName, materialNames); + case ARMOR: + return getConfigSectionsArmor(modName, materialNames); + case UNKNOWN: + return getConfigSectionsUnknown(modName, materialNames); + } + + return null; + } + + private HashMap> getConfigSectionsBlocks(String modName, HashMap> materialNames) { + HashMap> configSections = new HashMap>(); + + // Go through all the materials and categorise them under a skill + for (String materialName : materialNames.get(modName)) { + String skillName = "UNIDENTIFIED"; + if (materialName.contains("ORE")) { + skillName = "Mining"; + } + else if (materialName.contains("LOG") || materialName.contains("LEAVES")) { + skillName = "Woodcutting"; + } + else if (materialName.contains("GRASS") || materialName.contains("FLOWER") || materialName.contains("CROP")) { + skillName = "Herbalism"; + } + else if (materialName.contains("DIRT") || materialName.contains("SAND")) { + skillName = "Excavation"; + } + + if (!configSections.containsKey(skillName)) { + configSections.put(skillName, new ArrayList()); + } + + ArrayList skillContents = configSections.get(skillName); + skillContents.add(" " + materialName + "|0:"); + skillContents.add(" " + " " + "XP_Gain: 99"); + skillContents.add(" " + " " + "Double_Drops_Enabled: true"); + + if (skillName.equals("Mining")) { + skillContents.add(" " + " " + "Smelting_XP_Gain: 9"); + } + else if (skillName.equals("Woodcutting")) { + skillContents.add(" " + " " + "Is_Log: " + materialName.contains("LOG")); + } + } + + return configSections; + } + + private HashMap> getConfigSectionsTools(String modName, HashMap> materialNames) { + HashMap> configSections = new HashMap>(); + + // Go through all the materials and categorise them under a tool type + for (String materialName : materialNames.get(modName)) { + String toolType = "UNIDENTIFIED"; + if (materialName.contains("PICKAXE")) { + toolType = "Pickaxes"; + } + else if (materialName.contains("AXE")) { + toolType = "Axes"; + } + else if (materialName.contains("BOW")) { + toolType = "Bows"; + } + else if (materialName.contains("HOE")) { + toolType = "Hoes"; + } + else if (materialName.contains("SHOVEL") || materialName.contains("SPADE")) { + toolType = "Shovels"; + } + else if (materialName.contains("SWORD")) { + toolType = "Swords"; + } + + if (!configSections.containsKey(toolType)) { + configSections.put(toolType, new ArrayList()); + } + + ArrayList skillContents = configSections.get(toolType); + skillContents.add(" " + materialName + ":"); + skillContents.add(" " + " " + "XP_Modifier: 1.0"); + skillContents.add(" " + " " + "Tier: 1"); + skillContents.add(" " + " " + "Ability_Enabled: true"); + addRepairableLines(materialName, skillContents); + } + + return configSections; + } + + private HashMap> getConfigSectionsArmor(String modName, HashMap> materialNames) { + HashMap> configSections = new HashMap>(); + + // Go through all the materials and categorise them under an armor type + for (String materialName : materialNames.get(modName)) { + String toolType = "UNIDENTIFIED"; + if (materialName.contains("BOOT") || materialName.contains("SHOE")) { + toolType = "Boots"; + } + else if (materialName.contains("CHESTPLATE") || materialName.contains("CHEST")) { + toolType = "Chestplates"; + } + else if (materialName.contains("HELM") || materialName.contains("HAT")) { + toolType = "Helmets"; + } + else if (materialName.contains("LEGGINGS") || materialName.contains("LEGS") || materialName.contains("PANTS")) { + toolType = "Leggings"; + } + + if (!configSections.containsKey(toolType)) { + configSections.put(toolType, new ArrayList()); + } + + ArrayList skillContents = configSections.get(toolType); + skillContents.add(" " + materialName + ":"); + addRepairableLines(materialName, skillContents); + } + + return configSections; + } + + private void addRepairableLines(String materialName, ArrayList skillContents) { + skillContents.add(" " + " " + "Repairable: true"); + skillContents.add(" " + " " + "Repair_Material: REPAIR_MATERIAL_NAME"); + skillContents.add(" " + " " + "Repair_Material_Data_Value: 0"); + skillContents.add(" " + " " + "Repair_Material_Quantity: 9"); + skillContents.add(" " + " " + "Repair_Material_Pretty_Name: Repair Item Name"); + skillContents.add(" " + " " + "Repair_MinimumLevel: 0"); + skillContents.add(" " + " " + "Repair_XpMultiplier: 1.0"); + + Material material = Material.matchMaterial(materialName); + short durability = (material == null) ? (short) 9999 : material.getMaxDurability(); + skillContents.add(" " + " " + "Durability: " + durability); + } + + private HashMap> getConfigSectionsUnknown(String modName, HashMap> materialNames) { + HashMap> configSections = new HashMap>(); + + // Go through all the materials and print them + for (String materialName : materialNames.get(modName)) { + String configKey = "UNIDENTIFIED"; + + if (!configSections.containsKey(configKey)) { + configSections.put(configKey, new ArrayList()); + } + + ArrayList skillContents = configSections.get(configKey); + skillContents.add(" " + materialName); + } + + return configSections; + } +} diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/ModConfigType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/ModConfigType.java new file mode 100644 index 000000000..df951d783 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/ModConfigType.java @@ -0,0 +1,22 @@ +package com.gmail.nossr50.datatypes.skills; + +public enum ModConfigType { + BLOCKS, + TOOLS, + ARMOR, + UNKNOWN; + + public static ModConfigType getModConfigType(String materialName) { + if (materialName.contains("HELM") || (materialName.contains("CHEST") && !materialName.contains("CHESTNUT")) || materialName.contains("LEGS") || materialName.contains("LEGGINGS") || materialName.contains("BOOT")) { + return ARMOR; + } + else if (materialName.contains("PICKAXE") || materialName.contains("AXE") || (materialName.contains("BOW") && !materialName.contains("BOWL")) || materialName.contains("HOE") || materialName.contains("SHOVEL") || materialName.contains("SWORD")) { + return TOOLS; + } + else if (materialName.contains("LOG") || materialName.contains("LEAVES") || materialName.contains("FLOWER") || materialName.contains("PLANT") || materialName.contains("CROP") || materialName.contains("ORE") || materialName.contains("DIRT") || materialName.contains("SAND") || materialName.contains("GRASS")) { + return BLOCKS; + } + + return UNKNOWN; + } +} 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 bb9b9a432..808135ae3 100644 --- a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java +++ b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java @@ -7,6 +7,7 @@ import org.bukkit.command.PluginCommand; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.commands.KrakenCommand; +import com.gmail.nossr50.commands.McImportCommand; import com.gmail.nossr50.commands.McabilityCommand; import com.gmail.nossr50.commands.McconvertCommand; import com.gmail.nossr50.commands.McgodCommand; @@ -409,8 +410,18 @@ public final class CommandRegistrationManager { command.setExecutor(new KrakenCommand()); } + private static void registerMcImportCommand() { + PluginCommand command = mcMMO.p.getCommand("mcimport"); + command.setDescription("Import mod config files"); //TODO: Localize + command.setPermission("mcmmo.commands.mcimport"); + command.setPermissionMessage(permissionsMessage); + command.setUsage(LocaleLoader.getString("Commands.Usage.0", "mcimport")); + command.setExecutor(new McImportCommand()); + } + public static void registerCommands() { // Generic Commands + registerMcImportCommand(); registerKrakenCommand(); registerMcabilityCommand(); registerMcgodCommand(); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f288f4b69..ed3797cf5 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -41,6 +41,8 @@ commands: aliases: [mccooldowns] mcgod: description: Toggle mcMMO god-mode on/off + mcimport: + description: Import mod config files mcstats: aliases: [stats] description: Shows your mcMMO stats and xp @@ -727,6 +729,7 @@ permissions: mcmmo.commands.mcconvert.all: true mcmmo.commands.mcgod: true mcmmo.commands.mcgod.others: true + mcmmo.commands.mcimport: true mcmmo.commands.mcpurge: true mcmmo.commands.mcrank.others.all: true mcmmo.commands.mcrefresh: true @@ -845,6 +848,8 @@ permissions: description: Allows access to the mcnotify command mcmmo.commands.mcpurge: description: Allows access to the mcpurge command + mcmmo.commands.mcimport: + description: Allows access to the mcimport command mcmmo.commands.mcrank: description: Allows access to the mcrank command mcmmo.commands.mcrank.others.*: