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.*: