package com.gmail.nossr50.config.treasure; import com.gmail.nossr50.config.BukkitConfig; import com.gmail.nossr50.datatypes.treasure.*; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.EnchantmentUtils; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionType; import org.jetbrains.annotations.NotNull; import java.util.*; public class FishingTreasureConfig extends BukkitConfig { public static final String FILENAME = "fishing_treasures.yml"; private static FishingTreasureConfig instance; public @NotNull HashMap> fishingRewards = new HashMap<>(); public @NotNull HashMap> fishingEnchantments = new HashMap<>(); public @NotNull HashMap> shakeMap = new HashMap<>(); private FishingTreasureConfig() { super(FILENAME); loadKeys(); } public static FishingTreasureConfig getInstance() { if (instance == null) { instance = new FishingTreasureConfig(); } return instance; } @Override protected void validateConfigKeys() { //TODO: Rewrite legacy validation code List reason = new ArrayList<>(); ConfigurationSection enchantment_drop_rates = config.getConfigurationSection("Enchantment_Drop_Rates"); if(enchantment_drop_rates != null) { for (String tier : enchantment_drop_rates.getKeys(false)) { double totalEnchantDropRate = 0; double totalItemDropRate = 0; for (Rarity rarity : Rarity.values()) { double enchantDropRate = config.getDouble("Enchantment_Drop_Rates." + tier + "." + rarity.toString()); double itemDropRate = config.getDouble("Item_Drop_Rates." + tier + "." + rarity); if ((enchantDropRate < 0.0 || enchantDropRate > 100.0)) { mcMMO.p.getLogger().warning("The enchant drop rate for " + tier + " items that are " + rarity + "should be between 0.0 and 100.0!"); } if (itemDropRate < 0.0 || itemDropRate > 100.0) { mcMMO.p.getLogger().warning("The item drop rate for " + tier + " items that are " + rarity + "should be between 0.0 and 100.0!"); } totalEnchantDropRate += enchantDropRate; totalItemDropRate += itemDropRate; } if (totalEnchantDropRate < 0 || totalEnchantDropRate > 100.0) { mcMMO.p.getLogger().warning("The total enchant drop rate for " + tier + " should be between 0.0 and 100.0!"); } if (totalItemDropRate < 0 || totalItemDropRate > 100.0) { mcMMO.p.getLogger().warning("The total item drop rate for " + tier + " should be between 0.0 and 100.0!"); } } } else { mcMMO.p.getLogger().warning("Your fishing treasures config is empty, is this intentional? Delete it to regenerate."); } } @Override protected void loadKeys() { if (config.getConfigurationSection("Treasures") != null) { backup(); return; } loadTreasures("Fishing"); loadEnchantments(); for (EntityType entity : EntityType.values()) { if (entity.isAlive()) { loadTreasures("Shake." + entity); } } } private void loadTreasures(@NotNull String type) { boolean isFishing = type.equals("Fishing"); boolean isShake = type.contains("Shake"); ConfigurationSection treasureSection = config.getConfigurationSection(type); if (treasureSection == null) { return; } // Initialize fishing HashMap for (Rarity rarity : Rarity.values()) { if (!fishingRewards.containsKey(rarity)) { fishingRewards.put(rarity, (new ArrayList<>())); } } for (String treasureName : treasureSection.getKeys(false)) { // Validate all the things! List reason = new ArrayList<>(); String[] treasureInfo = treasureName.split("[|]"); String materialName = treasureInfo[0]; /* * Material, Amount, and Data */ Material material; if (materialName.contains("INVENTORY")) { // Use magic material BEDROCK to know that we're grabbing something from the inventory and not a normal treasure addShakeTreasure(new ShakeTreasure(new ItemStack(Material.BEDROCK, 1, (byte) 0), 1, getInventoryStealDropChance(), getInventoryStealDropLevel()), EntityType.PLAYER); continue; } else { material = Material.matchMaterial(materialName); } int amount = config.getInt(type + "." + treasureName + ".Amount"); short data = (treasureInfo.length == 2) ? Short.parseShort(treasureInfo[1]) : (short) config.getInt(type + "." + treasureName + ".Data"); if (material == null) { mcMMO.p.getLogger().warning("Cannot find matching item type in this version of MC, skipping - " + materialName); continue; } if (amount <= 0) { amount = 1; } if (material.isBlock() && (data > 127 || data < -128)) { mcMMO.p.getLogger().warning("Data of " + treasureName + " is invalid! " + data); } /* * XP, Drop Chance, and Drop Level */ int xp = config.getInt(type + "." + treasureName + ".XP"); double dropChance = config.getDouble(type + "." + treasureName + ".Drop_Chance"); int dropLevel = config.getInt(type + "." + treasureName + ".Drop_Level"); if (xp < 0) { mcMMO.p.getLogger().warning(treasureName + " has an invalid XP value: " + xp); } if (dropChance < 0.0D) { mcMMO.p.getLogger().warning(treasureName + " has an invalid Drop_Chance: " + dropChance); } if (dropLevel < 0) { mcMMO.p.getLogger().warning("Fishing Config: " + treasureName + " has an invalid Drop_Level: " + dropLevel); } /* * Specific Types */ Rarity rarity = null; if (isFishing) { String rarityStr = config.getString(type + "." + treasureName + ".Rarity"); if (rarityStr != null) { rarity = Rarity.getRarity(rarityStr); } else { mcMMO.p.getLogger().severe("Please edit your config and add a Rarity definition for - " + treasureName); mcMMO.p.getLogger().severe("Skipping this treasure until rarity is defined - " + treasureName); continue; } } /* * Itemstack */ ItemStack item = null; String customName = null; if (hasCustomName(type, treasureName)) { customName = config.getString(type + "." + treasureName + ".Custom_Name"); } if (materialName.contains("POTION")) { Material mat = Material.matchMaterial(materialName); if (mat == null) { mcMMO.p.getLogger().warning("Potion format for " + FILENAME + " has changed"); } else { item = new ItemStack(mat, amount, data); PotionMeta itemMeta = (PotionMeta) item.getItemMeta(); if (itemMeta == null) { mcMMO.p.getLogger().severe("Item meta when adding potion to fishing treasure was null, contact the mcMMO devs!"); continue; } PotionType potionType = null; try { potionType = PotionType.valueOf(config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER")); } catch (IllegalArgumentException ex) { mcMMO.p.getLogger().warning("Invalid Potion_Type: " + config.getString(type + "." + treasureName + ".PotionData.PotionType", "WATER")); } boolean extended = config.getBoolean(type + "." + treasureName + ".PotionData.Extended", false); boolean upgraded = config.getBoolean(type + "." + treasureName + ".PotionData.Upgraded", false); itemMeta.setBasePotionData(new PotionData(potionType, extended, upgraded)); if (customName != null) { itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', customName)); } if (config.contains(type + "." + treasureName + ".Lore")) { List lore = new ArrayList<>(); for (String s : config.getStringList(type + "." + treasureName + ".Lore")) { lore.add(ChatColor.translateAlternateColorCodes('&', s)); } itemMeta.setLore(lore); } item.setItemMeta(itemMeta); } } else if (material == Material.ENCHANTED_BOOK) { //If any whitelisted enchants exist we use whitelist-based matching item = new ItemStack(material, 1); ItemMeta itemMeta = item.getItemMeta(); List allowedEnchantsList = config.getStringList(type + "." + treasureName + ".Enchantments_Whitelist"); List disallowedEnchantsList = config.getStringList(type + "." + treasureName + ".Enchantments_Blacklist"); Set blackListedEnchants = new HashSet<>(); Set whiteListedEnchants = new HashSet<>(); matchAndFillSet(disallowedEnchantsList, blackListedEnchants); matchAndFillSet(allowedEnchantsList, whiteListedEnchants); if (customName != null && itemMeta != null) { itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', customName)); item.setItemMeta(itemMeta); } FishingTreasureBook fishingTreasureBook = new FishingTreasureBook(item, xp, blackListedEnchants, whiteListedEnchants); addFishingTreasure(rarity, fishingTreasureBook); //TODO: Add book support for shake continue; //The code in this whole file is a disaster, ignore this hacky solution :P } else { item = new ItemStack(material, amount, data); if (customName != null) { ItemMeta itemMeta = item.getItemMeta(); itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', customName)); item.setItemMeta(itemMeta); } if (config.contains(type + "." + treasureName + ".Lore")) { ItemMeta itemMeta = item.getItemMeta(); List lore = new ArrayList<>(); for (String s : config.getStringList(type + "." + treasureName + ".Lore")) { lore.add(ChatColor.translateAlternateColorCodes('&', s)); } itemMeta.setLore(lore); item.setItemMeta(itemMeta); } } //TODO: Rewrite legacy validation code // Look into what needs to change for this if (isFishing) { addFishingTreasure(rarity, new FishingTreasure(item, xp)); } else if (isShake) { ShakeTreasure shakeTreasure = new ShakeTreasure(item, xp, dropChance, dropLevel); EntityType entityType = EntityType.valueOf(type.substring(6)); addShakeTreasure(shakeTreasure, entityType); } } } private void addShakeTreasure(@NotNull ShakeTreasure shakeTreasure, @NotNull EntityType entityType) { if (!shakeMap.containsKey(entityType)) shakeMap.put(entityType, new ArrayList<>()); shakeMap.get(entityType).add(shakeTreasure); } private void addFishingTreasure(@NotNull Rarity rarity, @NotNull FishingTreasure fishingTreasure) { fishingRewards.get(rarity).add(fishingTreasure); } private boolean hasCustomName(@NotNull String type, @NotNull String treasureName) { return config.contains(type + "." + treasureName + ".Custom_Name"); } /** * Matches enchantments on a list (user provided string) to known enchantments in the Spigot API * Any matches are added to the passed set * * @param enchantListStr the users string list of enchantments * @param permissiveList the permissive list of enchantments */ private void matchAndFillSet(@NotNull List enchantListStr, @NotNull Set permissiveList) { if (enchantListStr.isEmpty()) { return; } for (String str : enchantListStr) { boolean foundMatch = false; for (Enchantment enchantment : Enchantment.values()) { if (enchantment.getKey().getKey().equalsIgnoreCase(str)) { permissiveList.add(enchantment); foundMatch = true; break; } } if (!foundMatch) { mcMMO.p.getLogger().info("[Fishing Treasure Init] Could not find any enchantments which matched the user defined enchantment named: " + str); } } } private void loadEnchantments() { for (Rarity rarity : Rarity.values()) { if (!fishingEnchantments.containsKey(rarity)) { fishingEnchantments.put(rarity, (new ArrayList<>())); } ConfigurationSection enchantmentSection = config.getConfigurationSection("Enchantments_Rarity." + rarity.toString()); if (enchantmentSection == null) { return; } for (String enchantmentName : enchantmentSection.getKeys(false)) { int level = config.getInt("Enchantments_Rarity." + rarity + "." + enchantmentName); Enchantment enchantment = EnchantmentUtils.getByName(enchantmentName); if (enchantment == null) { mcMMO.p.getLogger().warning("Skipping invalid enchantment in " + FILENAME + ": " + enchantmentName); continue; } fishingEnchantments.get(rarity).add(new EnchantmentTreasure(enchantment, level)); } } } public boolean getInventoryStealEnabled() { return config.contains("Shake.PLAYER.INVENTORY"); } public boolean getInventoryStealStacks() { return config.getBoolean("Shake.PLAYER.INVENTORY.Whole_Stacks"); } public double getInventoryStealDropChance() { return config.getDouble("Shake.PLAYER.INVENTORY.Drop_Chance"); } public int getInventoryStealDropLevel() { return config.getInt("Shake.PLAYER.INVENTORY.Drop_Level"); } public double getItemDropRate(int tier, @NotNull Rarity rarity) { return config.getDouble("Item_Drop_Rates.Tier_" + tier + "." + rarity); } public double getEnchantmentDropRate(int tier, @NotNull Rarity rarity) { return config.getDouble("Enchantment_Drop_Rates.Tier_" + tier + "." + rarity); } }