diff --git a/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java b/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java index 7280d322e..40292ba23 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java +++ b/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java @@ -23,6 +23,7 @@ import org.bukkit.inventory.meta.BannerMeta; import org.bukkit.inventory.meta.BlockStateMeta; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import org.bukkit.inventory.meta.FireworkEffectMeta; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; @@ -61,12 +62,14 @@ public class MetaItemStack { } } - private final transient Pattern splitPattern = Pattern.compile("[:+',;.]"); + private static final transient Pattern splitPattern = Pattern.compile("[:+',;.]"); + private static final transient Pattern hexPattern = Pattern.compile("#([0-9a-fA-F]{6})"); private ItemStack stack; private FireworkEffect.Builder builder = FireworkEffect.builder(); private PotionEffectType pEffectType; private PotionEffect pEffect; private boolean validFirework = false; + private boolean validFireworkCharge = false; private boolean validPotionEffect = false; private boolean validPotionDuration = false; private boolean validPotionPower = false; @@ -174,6 +177,15 @@ public class MetaItemStack { } stack.setItemMeta(fmeta); } + if (validFireworkCharge) { + if (!hasMetaPermission(sender, "firework", true, true, ess)) { + throw new Exception(tl("noMetaFirework")); + } + final FireworkEffect effect = builder.build(); + final FireworkEffectMeta meta = (FireworkEffectMeta) stack.getItemMeta(); + meta.setEffect(effect); + stack.setItemMeta(meta); + } } } @@ -236,6 +248,8 @@ public class MetaItemStack { } else if (MaterialUtil.isFirework(stack.getType())) { //WARNING - Meta for fireworks will be ignored after this point. addFireworkMeta(sender, false, string, ess); + } else if (MaterialUtil.isFireworkCharge(stack.getType())) { + addChargeMeta(sender, false, string, ess); } else if (MaterialUtil.isPotion(stack.getType())) { //WARNING - Meta for potions will be ignored after this point. addPotionMeta(sender, false, string, ess); @@ -300,6 +314,67 @@ public class MetaItemStack { stack.setItemMeta(meta); } + private void addChargeMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception { + final String[] split = splitPattern.split(string, 2); + if (split.length < 2) { + return; + } + + if (split[0].equalsIgnoreCase("color") || split[0].equalsIgnoreCase("colour") || (allowShortName && split[0].equalsIgnoreCase("c"))) { + final List primaryColors = new ArrayList<>(); + final String[] colors = split[1].split(","); + for (final String color : colors) { + if (colorMap.containsKey(color.toUpperCase())) { + validFireworkCharge = true; + primaryColors.add(colorMap.get(color.toUpperCase()).getFireworkColor()); + } else if (hexPattern.matcher(color).matches()) { + validFireworkCharge = true; + primaryColors.add(Color.fromRGB(Integer.decode(color))); + } else { + throw new Exception(tl("invalidFireworkFormat", split[1], split[0])); + } + } + builder.withColor(primaryColors); + } else if (split[0].equalsIgnoreCase("shape") || split[0].equalsIgnoreCase("type") || (allowShortName && (split[0].equalsIgnoreCase("s") || split[0].equalsIgnoreCase("t")))) { + FireworkEffect.Type finalEffect = null; + split[1] = split[1].equalsIgnoreCase("large") ? "BALL_LARGE" : split[1]; + if (fireworkShape.containsKey(split[1].toUpperCase())) { + finalEffect = fireworkShape.get(split[1].toUpperCase()); + } else { + throw new Exception(tl("invalidFireworkFormat", split[1], split[0])); + } + if (finalEffect != null) { + builder.with(finalEffect); + } + } else if (split[0].equalsIgnoreCase("fade") || (allowShortName && split[0].equalsIgnoreCase("f"))) { + final List fadeColors = new ArrayList<>(); + final String[] colors = split[1].split(","); + for (final String color : colors) { + if (colorMap.containsKey(color.toUpperCase())) { + fadeColors.add(colorMap.get(color.toUpperCase()).getFireworkColor()); + } else if (hexPattern.matcher(color).matches()) { + fadeColors.add(Color.fromRGB(Integer.decode(color))); + } else { + throw new Exception(tl("invalidFireworkFormat", split[1], split[0])); + } + } + if (!fadeColors.isEmpty()) { + builder.withFade(fadeColors); + } + } else if (split[0].equalsIgnoreCase("effect") || (allowShortName && split[0].equalsIgnoreCase("e"))) { + final String[] effects = split[1].split(","); + for (final String effect : effects) { + if (effect.equalsIgnoreCase("twinkle")) { + builder.flicker(true); + } else if (effect.equalsIgnoreCase("trail")) { + builder.trail(true); + } else { + throw new Exception(tl("invalidFireworkFormat", split[1], split[0])); + } + } + } + } + public void addFireworkMeta(final CommandSource sender, final boolean allowShortName, final String string, final IEssentials ess) throws Exception { if (MaterialUtil.isFirework(stack.getType())) { final String[] split = splitPattern.split(string, 2); @@ -328,6 +403,9 @@ public class MetaItemStack { if (colorMap.containsKey(color.toUpperCase())) { validFirework = true; primaryColors.add(colorMap.get(color.toUpperCase()).getFireworkColor()); + } else if (hexPattern.matcher(color).matches()) { + validFirework = true; + primaryColors.add(Color.fromRGB(Integer.decode(color))); } else { throw new Exception(tl("invalidFireworkFormat", split[1], split[0])); } @@ -350,6 +428,8 @@ public class MetaItemStack { for (final String color : colors) { if (colorMap.containsKey(color.toUpperCase())) { fadeColors.add(colorMap.get(color.toUpperCase()).getFireworkColor()); + } else if (hexPattern.matcher(color).matches()) { + fadeColors.add(Color.fromRGB(Integer.decode(color))); } else { throw new Exception(tl("invalidFireworkFormat", split[1], split[0])); } diff --git a/Essentials/src/main/java/com/earth2me/essentials/items/AbstractItemDb.java b/Essentials/src/main/java/com/earth2me/essentials/items/AbstractItemDb.java index e219bf3b1..c5e2339bd 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/items/AbstractItemDb.java +++ b/Essentials/src/main/java/com/earth2me/essentials/items/AbstractItemDb.java @@ -18,6 +18,7 @@ import org.bukkit.inventory.meta.BannerMeta; import org.bukkit.inventory.meta.BlockStateMeta; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import org.bukkit.inventory.meta.FireworkEffectMeta; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; @@ -268,35 +269,15 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb { final FireworkMeta fireworkMeta = (FireworkMeta) is.getItemMeta(); if (fireworkMeta.hasEffects()) { for (final FireworkEffect effect : fireworkMeta.getEffects()) { - if (effect.getColors() != null && !effect.getColors().isEmpty()) { - sb.append("color:"); - boolean first = true; - for (final Color c : effect.getColors()) { - if (!first) { - sb.append(","); // same thing as above. - } - sb.append(c.toString()); - first = false; - } - sb.append(" "); - } - - sb.append("shape:").append(effect.getType().name()).append(" "); - if (effect.getFadeColors() != null && !effect.getFadeColors().isEmpty()) { - sb.append("fade:"); - boolean first = true; - for (final Color c : effect.getFadeColors()) { - if (!first) { - sb.append(","); // same thing as above. - } - sb.append(c.toString()); - first = false; - } - sb.append(" "); - } + serializeEffectMeta(sb, effect); } sb.append("power:").append(fireworkMeta.getPower()).append(" "); } + } else if (MaterialUtil.isFireworkCharge(material)) { + final FireworkEffectMeta fireworkEffectMeta = (FireworkEffectMeta) is.getItemMeta(); + if (fireworkEffectMeta.hasEffect()) { + serializeEffectMeta(sb, fireworkEffectMeta.getEffect()); + } } else if (MaterialUtil.isPotion(material)) { final Potion potion = Potion.fromItemStack(is); for (final PotionEffect e : potion.getEffects()) { @@ -353,6 +334,35 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb { return sb.toString().trim().replaceAll("ยง", "&"); } + private void serializeEffectMeta(StringBuilder sb, FireworkEffect effect) { + if (effect.getColors() != null && !effect.getColors().isEmpty()) { + sb.append("color:"); + boolean first = true; + for (final Color c : effect.getColors()) { + if (!first) { + sb.append(","); // same thing as above. + } + sb.append("#").append(Integer.toHexString(c.asRGB())); + first = false; + } + sb.append(" "); + } + + sb.append("shape:").append(effect.getType().name()).append(" "); + if (effect.getFadeColors() != null && !effect.getFadeColors().isEmpty()) { + sb.append("fade:"); + boolean first = true; + for (final Color c : effect.getFadeColors()) { + if (!first) { + sb.append(","); // same thing as above. + } + sb.append("#").append(Integer.toHexString(c.asRGB())); + first = false; + } + sb.append(" "); + } + } + @Override public boolean isReady() { return ready; diff --git a/Essentials/src/main/java/com/earth2me/essentials/utils/MaterialUtil.java b/Essentials/src/main/java/com/earth2me/essentials/utils/MaterialUtil.java index a2e82af9c..2a4e4c3e2 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/utils/MaterialUtil.java +++ b/Essentials/src/main/java/com/earth2me/essentials/utils/MaterialUtil.java @@ -16,6 +16,7 @@ public final class MaterialUtil { private static final Set BEDS; private static final Set BANNERS; private static final Set FIREWORKS; + private static final Set FIREWORK_CHARGE; private static final Set LEGACY_SKULLS; private static final Set LEATHER_ARMOR; private static final Set MOB_HEADS; @@ -54,8 +55,9 @@ public final class MaterialUtil { "PINK_BANNER", "GRAY_BANNER", "LIGHT_GRAY_BANNER", "CYAN_BANNER", "PURPLE_BANNER", "BLUE_BANNER", "BROWN_BANNER", "GREEN_BANNER", "RED_BANNER", "BLACK_BANNER", "SHIELD"); - FIREWORKS = EnumUtil.getAllMatching(Material.class, "FIREWORK", "FIREWORK_ROCKET", - "FIREWORK_CHARGE", "FIREWORK_STAR"); + FIREWORKS = EnumUtil.getAllMatching(Material.class, "FIREWORK", "FIREWORK_ROCKET"); + + FIREWORK_CHARGE = EnumUtil.getAllMatching(Material.class, "FIREWORK_CHARGE", "FIREWORK_STAR"); LEATHER_ARMOR = EnumUtil.getAllMatching(Material.class, "LEATHER_HELMET", "LEATHER_CHESTPLATE", "LEATHER_LEGGINGS", "LEATHER_BOOTS"); @@ -116,6 +118,10 @@ public final class MaterialUtil { return FIREWORKS.contains(material); } + public static boolean isFireworkCharge(final Material material) { + return FIREWORK_CHARGE.contains(material); + } + public static boolean isLeatherArmor(final Material material) { return LEATHER_ARMOR.contains(material); }