package in.twizmwaz.cardinal.util; import com.google.common.collect.Lists; import in.twizmwaz.cardinal.GameHandler; import in.twizmwaz.cardinal.module.modules.itemMods.ItemMods; import in.twizmwaz.cardinal.module.modules.kit.kitTypes.KitItem; import net.minecraft.server.CommandReplaceItem; import net.minecraft.server.MobEffectList; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.attribute.AttributeModifier; import org.bukkit.attribute.ItemAttributeModifier; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.potion.CraftPotionEffectType; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.material.MaterialData; import org.bukkit.potion.Potion; import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionType; import org.bukkit.util.Vector; import org.jdom2.Element; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; public class Parser { public static KitItem getKitItem(Element element) { ItemStack itemStack = getItem(element); int slot = -1; String slotString = element.getAttributeValue("slot", "-1"); if (NumberUtils.isNumber(slotString)) { slot = Integer.parseInt(slotString); } else { if (!slotString.startsWith("slot.")) slotString = "slot." + slotString; try { CommandReplaceItem replaceItem = new CommandReplaceItem(); Method m = CommandReplaceItem.class.getDeclaredMethod("e", String.class); // Returns inventory slot (int) m.setAccessible(true); // from a mojang string inventory slot = (int)m.invoke(replaceItem, slotString); // like "slot.weapon.offhand" } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) { e.printStackTrace(); } } return new KitItem(itemStack, slot); } public static ItemStack getItem(Element element) { int amount = Numbers.parseInt(element.getAttributeValue("amount", "1")); short damage = element.getAttributeValue("damage") != null ? Short.parseShort(element.getAttributeValue("damage")) : element.getText() != null && element.getText().contains(":") ? Short.parseShort(element.getText().split(":")[1]) : 0 ; ItemStack itemStack = new ItemStack(Material.AIR); if (element.getAttribute("material") != null) { itemStack = new ItemStack(Material.matchMaterial(element.getAttributeValue("material")), amount, damage); } else if (!element.getTextTrim().equals("")) { itemStack = new ItemStack(Material.matchMaterial(element.getText().split(":")[0]), amount, damage); } if (itemStack.getType() == Material.POTION) { itemStack = Potion.fromDamage(damage).toItemStack(amount); } if (element.getName().equalsIgnoreCase("book")) { itemStack = new ItemStack(Material.BOOK, amount, damage); } itemStack = CraftItemStack.asCraftCopy(itemStack); if (element.getAttributeValue("enchantment") != null) { for (String raw : element.getAttributeValue("enchantment").split(";")) { String[] enchant = raw.split(":"); int lvl = enchant.length > 1 ? Numbers.parseInt(enchant[1]) : 1; Enchantment enchantment = Enchantment.getByName(Strings.getTechnicalName(enchant[0])); if (enchantment == null) { net.minecraft.server.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); nmsStack.addEnchantment(net.minecraft.server.Enchantment.b(enchant[0].toLowerCase().replace(" ","_")), lvl); // Enchantment.b(String) gets Enchantment by name itemStack = CraftItemStack.asBukkitCopy(nmsStack); } else { itemStack.addUnsafeEnchantment(Enchantment.getByName(Strings.getTechnicalName(enchant[0])), lvl); } } } ItemMeta meta = itemStack.getItemMeta(); if (meta instanceof PotionMeta && element.getAttributeValue("potions") != null) { for (PotionEffect effect : parseEffects(element.getAttributeValue("potions"))) { ((PotionMeta) meta).addCustomEffect(effect, true); } } if (element.getAttributeValue("attributes") != null) { for (ItemAttributeModifier attribute : parseAttributes((element.getAttributeValue("attributes")))) { meta.addAttributeModifier(attribute.getModifier().getName(), attribute); } } for (Element attribute : element.getChildren("attribute")) { meta.addAttributeModifier(attribute.getText(), getAttribute(attribute)); } if (meta instanceof BookMeta && element.getName().equalsIgnoreCase("book")) { BookMeta bookMeta = (BookMeta) meta; bookMeta.setTitle(ChatColor.translateAlternateColorCodes('`',element.getChildText("author"))); bookMeta.setAuthor(ChatColor.translateAlternateColorCodes('`',element.getChildText("author"))); List<String> pages = new ArrayList<>(); for (Element page : element.getChild("pages").getChildren("page")) { pages.add(ChatColor.translateAlternateColorCodes('`', page.getText()).replace("\u0009", "")); } bookMeta.setPages(pages); } itemStack.setItemMeta(meta); return GameHandler.getGameHandler().getMatch().getModules().getModule(ItemMods.class).applyRules(applyMeta(itemStack, element)); } public static ItemStack applyMeta(ItemStack itemStack, Element element) { ItemMeta meta = itemStack.getItemMeta(); if (element.getAttributeValue("name") != null) { meta.setDisplayName(ChatColor.translateAlternateColorCodes('`', element.getAttributeValue("name"))); } if (element.getAttributeValue("lore") != null) { ArrayList<String> lore = new ArrayList<>(); for (String raw : element.getAttributeValue("lore").split("\\|")) { String colored = ChatColor.translateAlternateColorCodes('`', raw); lore.add(colored); } meta.setLore(lore); } meta.setUnbreakable(Numbers.parseBoolean(element.getAttributeValue("unbreakable"), false)); if (meta instanceof LeatherArmorMeta && element.getAttributeValue("color") != null) { LeatherArmorMeta leatherMeta = (LeatherArmorMeta) meta; leatherMeta.setColor(MiscUtil.convertHexToRGB(element.getAttributeValue("color"))); itemStack.setItemMeta(leatherMeta); } if (meta instanceof PotionMeta && element.getAttributeValue("potion") != null) { PotionMeta potionMeta = (PotionMeta) meta; PotionType type = PotionType.valueOf(Strings.getTechnicalName(element.getAttributeValue("potion"))); potionMeta.setBasePotionData(new PotionData(type)); } setItemFlag(meta, ItemFlag.HIDE_ENCHANTS, element, "show-enchantments"); setItemFlag(meta, ItemFlag.HIDE_ATTRIBUTES, element, "show-attributes"); setItemFlag(meta, ItemFlag.HIDE_UNBREAKABLE, element, "show-unbreakable"); setItemFlag(meta, ItemFlag.HIDE_DESTROYS, element, "show-can-destroy"); setItemFlag(meta, ItemFlag.HIDE_PLACED_ON, element, "show-can-place-on"); setItemFlag(meta, ItemFlag.HIDE_POTION_EFFECTS, element, "show-other"); for (Element enchant : element.getChildren("enchantment")) { String ench = enchant.getText(); Enchantment enchantment = Enchantment.getByName(Strings.getTechnicalName(ench)); int lvl = Numbers.parseInt(enchant.getAttributeValue("level"), 1); if (enchantment == null) { net.minecraft.server.ItemStack nmsStack = CraftItemStack.asNMSCopy(itemStack); nmsStack.addEnchantment(net.minecraft.server.Enchantment.b(ench.toLowerCase().replace(" ","_")), lvl); // Enchantment.b(String) gets Enchantment by name itemStack = CraftItemStack.asBukkitCopy(nmsStack); } else { itemStack.addUnsafeEnchantment(enchantment, lvl); } } if (meta instanceof PotionMeta) { for (Element effect : element.getChildren("effect")) { PotionEffect potionEffect = getPotion(effect); ((PotionMeta) meta).addCustomEffect(potionEffect, true); } } for (Element attribute : element.getChildren("attribute")) { ItemAttributeModifier itemAttribute = getAttribute(attribute); meta.addAttributeModifier(attribute.getText(), itemAttribute); } for (Element canDestroy : element.getChildren("can-destroy")) { if (canDestroy.getChildren("all-blocks").size() > 0) { meta.setCanDestroy(Material.values()); } else { Set<Material> materials = new HashSet<>(); for (Element material : canDestroy.getChildren("material")) { materials.add(parseMaterial(material.getText()).getKey()); } meta.setCanDestroy(materials); } } for (Element canPlace : element.getChildren("can-place-on")) { if (canPlace.getChildren("all-blocks").size() > 0) { meta.setCanPlaceOn(Material.values()); } else { Set<Material> materials = new HashSet<>(); for (Element material : canPlace.getChildren("material")) { materials.add(parseMaterial(material.getText()).getKey()); } meta.setCanPlaceOn(materials); } } itemStack.setItemMeta(meta); return itemStack; } private static void setItemFlag(ItemMeta meta, ItemFlag flag, Element element, String attribute) { if (element.getAttributeValue(attribute) == null) return; if (Numbers.parseBoolean(element.getAttributeValue(attribute), true)) meta.removeItemFlags(flag); else meta.addItemFlags(flag); } private static List<PotionEffect> parseEffects(String effects) { List<PotionEffect> effectList = new ArrayList<>(); for (String effect : effects.split(";")) { String[] split = effect.split(":"); PotionEffectType type = PotionEffectType.getByName(Strings.getTechnicalName(split[0])); if (type == null) type = new CraftPotionEffectType(MobEffectList.getByName(split[0].toLowerCase().replace(" ","_"))); effectList.add(new PotionEffect(type, Numbers.parseInt(split[1]), Numbers.parseInt(split[2]))); } return effectList; } private static List<ItemAttributeModifier> parseAttributes(String attributes) { List<ItemAttributeModifier> list = new ArrayList<>(); for (String attribute : attributes.split(";")) { String[] attr = attribute.split(":"); list.add(new ItemAttributeModifier(null, new AttributeModifier(UUID.randomUUID(), attr[0], Double.parseDouble(attr[2]), getOperation(attr[1])))); } return list; } public static PotionEffect getPotion(Element potion) { PotionEffectType type = PotionEffectType.getByName(Strings.getTechnicalName(potion.getText())); if (type == null) type = new CraftPotionEffectType(MobEffectList.getByName(potion.getText().toLowerCase().replace(" ","_"))); int duration = (int) (Strings.timeStringToExactSeconds(potion.getAttributeValue("duration")) * 20); int amplifier = 0; boolean ambient = false; if (potion.getAttributeValue("amplifier") != null) amplifier = Numbers.parseInt(potion.getAttributeValue("amplifier")) - 1; if (potion.getAttributeValue("ambient") != null) ambient = Boolean.parseBoolean(potion.getAttributeValue("ambient").toUpperCase()); return new PotionEffect(type, duration, amplifier, ambient); } public static ItemAttributeModifier getAttribute(Element attribute) { return new ItemAttributeModifier(getEquipmentSlot(attribute.getAttributeValue("slot", "")), new AttributeModifier(UUID.randomUUID(), attribute.getText(), Double.parseDouble(attribute.getAttributeValue("amount", "0.0")), getOperation(attribute.getAttributeValue("operation", "add")))); } public static AttributeModifier.Operation getOperation(String operation) { if (NumberUtils.isNumber(operation)) { return AttributeModifier.Operation.fromOpcode(Integer.parseInt(operation)); } else { switch (operation.toLowerCase()) { case("add"): return AttributeModifier.Operation.ADD_NUMBER; case("base"): return AttributeModifier.Operation.ADD_SCALAR; case("multiply"): return AttributeModifier.Operation.MULTIPLY_SCALAR_1; } } return AttributeModifier.Operation.ADD_NUMBER; } public static EquipmentSlot getEquipmentSlot(String slotName) { if (!slotName.startsWith("slot.")) slotName = "slot." + slotName; EquipmentSlot equipmentSlot = null; String[] path = slotName.split("\\."); if (path.length != 3) return null; if (path[1].equalsIgnoreCase("armor")) { equipmentSlot = EquipmentSlot.valueOf(Strings.getTechnicalName(path[2])); } else if (path[1].equalsIgnoreCase("weapon")) { if (path[2].equalsIgnoreCase("mainhand")) equipmentSlot = EquipmentSlot.HAND; if (path[2].equalsIgnoreCase("offhand")) equipmentSlot = EquipmentSlot.OFF_HAND; } return equipmentSlot; } public static ChatColor parseChatColor(String string) { for (ChatColor color : ChatColor.values()) { if (color.name().equals(Strings.getTechnicalName(string))) return color; } return ChatColor.WHITE; } public static DyeColor parseDyeColor(String string) { for (DyeColor color : DyeColor.values()) { if (color.name().equals(Strings.getTechnicalName(string))) return color; } return DyeColor.WHITE; } public static Pair<Material, Integer> parseMaterial(String material) { String type = material.split(":")[0].trim(); Integer damageValue = material.contains(":") ? Numbers.parseInt(material.split(":")[1].trim()) : -1; return new ImmutablePair<>(NumberUtils.isNumber(type) ? Material.getMaterial(Integer.parseInt(type)) : Material.matchMaterial(type), damageValue); } public static MaterialData parseMaterialData(String material) { String type = material.split(":")[0].trim(); byte damageValue = (byte) (material.contains(":") ? Numbers.parseInt(material.split(":")[1].trim()) : -1); return NumberUtils.isNumber(type) ? new MaterialData(Material.getMaterial(Integer.parseInt(type)), damageValue): new MaterialData(Material.matchMaterial(type), damageValue); } public static String getOrderedAttribute(String attribute, Element... elements) { for (Element element : elements) { if (element.getAttributeValue(attribute) != null && !element.getAttributeValue(attribute).equals("")) { return element.getAttributeValue(attribute); } } return null; } public static String getOrderedAttributeOrChild(String attribute, Element... elements) { if (getOrderedAttribute(attribute, elements) != null) return getOrderedAttribute(attribute, elements); if (elements[0].getChild(attribute) != null) return elements[0].getChildText(attribute); return null; } public static String getOrderedText(Element... elements) { for (Element element : elements) { if (element.getText() != null && !element.getText().equals("")) { return element.getText(); } } return null; } public static Vector parseVector(String string) { String[] split = string.split(","); return new Vector(toDouble(split[0]), toDouble(split[1]), toDouble(split[2])); } private static double toDouble (String s) { return Numbers.parseDouble(s.replace(" ", "")); } @SafeVarargs public static List<Element> getJoinedElements(List<Element>... elementLists) { List<Element> result = Lists.newArrayList(); for (List<Element> elementList : elementLists) { result.addAll(elementList); } return result; } public static Element[] addElement(Element element, Element... elements) { Element[] newElements = new Element[elements.length + 1]; newElements[0] = element; System.arraycopy(elements, 0, newElements, 1, elements.length); return newElements; } }