diff --git a/Essentials/src/main/java/com/earth2me/essentials/ISettings.java b/Essentials/src/main/java/com/earth2me/essentials/ISettings.java index 67be6b14d89..84fff0eb431 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/ISettings.java +++ b/Essentials/src/main/java/com/earth2me/essentials/ISettings.java @@ -422,6 +422,10 @@ public interface ISettings extends IConf { boolean isUpdateCheckEnabled(); + String getDateFormat(); + + String getTimeFormat(); + boolean showZeroBaltop(); String getNickRegex(); diff --git a/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java b/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java index 8347c19a391..effc277d430 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java +++ b/Essentials/src/main/java/com/earth2me/essentials/MetaItemStack.java @@ -20,6 +20,8 @@ import org.bukkit.block.Banner; import org.bukkit.block.banner.PatternType; import org.bukkit.enchantments.Enchantment; +import org.bukkit.Registry; +import org.bukkit.NamespacedKey; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BannerMeta; @@ -32,6 +34,10 @@ import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.inventory.meta.ArmorMeta; +import org.bukkit.inventory.meta.trim.ArmorTrim; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.bukkit.inventory.meta.trim.TrimPattern; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -343,6 +349,15 @@ public void addStringMeta(final CommandSource sender, final boolean allowUnsafe, } else { throw new TranslatableException("leatherSyntax"); } + } else if (MaterialUtil.isArmor(stack.getType()) && split.length > 1 && split[0].equalsIgnoreCase("trim")) { + final ArmorMeta armorMeta = (ArmorMeta) stack.getItemMeta(); + final String[] trimData = split[1].split("\\|"); + final TrimPattern pattern = Registry.TRIM_PATTERN.getOrThrow(NamespacedKey.minecraft(trimData[0].toLowerCase())); + final TrimMaterial material = Registry.TRIM_MATERIAL.getOrThrow(NamespacedKey.minecraft(trimData[1].toLowerCase())); + + armorMeta.setTrim(new ArmorTrim(material, pattern)); + + stack.setItemMeta(armorMeta); } else { parseEnchantmentStrings(sender, allowUnsafe, split, ess); } diff --git a/Essentials/src/main/java/com/earth2me/essentials/Settings.java b/Essentials/src/main/java/com/earth2me/essentials/Settings.java index 8980aa97b3f..5cc8954ff93 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/Settings.java +++ b/Essentials/src/main/java/com/earth2me/essentials/Settings.java @@ -2115,6 +2115,16 @@ public boolean isUpdateCheckEnabled() { return config.getBoolean("update-check", true); } + @Override + public String getDateFormat() { + return config.getString("date-format", "locale"); + } + + @Override + public String getTimeFormat() { + return config.getString("time-format", "locale"); + } + @Override public boolean showZeroBaltop() { return config.getBoolean("show-zero-baltop", true); 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 a3bcd932fdc..dcca8a2b959 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/items/AbstractItemDb.java +++ b/Essentials/src/main/java/com/earth2me/essentials/items/AbstractItemDb.java @@ -28,6 +28,8 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.inventory.meta.ArmorMeta; +import org.bukkit.inventory.meta.trim.ArmorTrim; import org.bukkit.plugin.Plugin; import org.bukkit.potion.PotionEffect; @@ -337,10 +339,21 @@ public String serialize(final ItemStack is, final boolean useResolvers) { } } } - } else if (MaterialUtil.isLeatherArmor(material)) { - final LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) is.getItemMeta(); - final int rgb = leatherArmorMeta.getColor().asRGB(); - sb.append("color:").append(rgb).append(" "); + } else if (MaterialUtil.isArmor(material)) { + final ArmorTrim armorTrim = ((ArmorMeta) is.getItemMeta()).getTrim(); + + if (armorTrim != null) { + final String trimPattern = armorTrim.getPattern().getKey().getKey(); + final String trimMaterial = armorTrim.getMaterial().getKey().getKey(); + + sb.append("trim:").append(trimPattern).append("|").append(trimMaterial).append(" "); + } + + if (MaterialUtil.isLeatherArmor(material)) { + final LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) is.getItemMeta(); + final int rgb = leatherArmorMeta.getColor().asRGB(); + sb.append("color:").append(rgb).append(" "); + } } return sb.toString().trim().replaceAll("ยง", "&"); diff --git a/Essentials/src/main/java/com/earth2me/essentials/textreader/KeywordReplacer.java b/Essentials/src/main/java/com/earth2me/essentials/textreader/KeywordReplacer.java index e61c5ced543..4fe3b491fe7 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/textreader/KeywordReplacer.java +++ b/Essentials/src/main/java/com/earth2me/essentials/textreader/KeywordReplacer.java @@ -4,6 +4,7 @@ import com.earth2me.essentials.ExecuteTimer; import com.earth2me.essentials.PlayerList; import com.earth2me.essentials.User; +import com.earth2me.essentials.ISettings; import com.earth2me.essentials.utils.AdventureUtil; import com.earth2me.essentials.utils.DateUtil; import com.earth2me.essentials.utils.DescParseTickFormat; @@ -20,6 +21,7 @@ import java.lang.management.ManagementFactory; import java.text.DateFormat; import java.text.NumberFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.EnumMap; @@ -27,6 +29,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -96,6 +99,8 @@ public class KeywordReplacer implements IText { private final transient IText input; private final transient List replaced; private final transient IEssentials ess; + + private final transient ISettings settings; private final transient boolean includePrivate; private final transient boolean replaceSpacesWithUnderscores; private final EnumMap keywordCache = new EnumMap<>(KeywordType.class); @@ -104,6 +109,7 @@ public KeywordReplacer(final IText input, final CommandSource sender, final IEss this.input = input; this.replaced = new ArrayList<>(this.input.getLines().size()); this.ess = ess; + this.settings = ess.getSettings(); this.includePrivate = true; this.replaceSpacesWithUnderscores = false; replaceKeywords(sender); @@ -113,6 +119,7 @@ public KeywordReplacer(final IText input, final CommandSource sender, final IEss this.input = input; this.replaced = new ArrayList<>(this.input.getLines().size()); this.ess = ess; + this.settings = ess.getSettings(); this.includePrivate = showPrivate; this.replaceSpacesWithUnderscores = false; replaceKeywords(sender); @@ -123,6 +130,7 @@ public KeywordReplacer(final IText input, final CommandSource sender, final IEss this.input = input; this.replaced = new ArrayList<>(this.input.getLines().size()); this.ess = ess; + this.settings = ess.getSettings(); this.includePrivate = showPrivate; this.replaceSpacesWithUnderscores = replaceSpacesWithUnderscores; replaceKeywords(sender); @@ -320,10 +328,20 @@ private String replaceLine(String line, final String fullMatch, final String[] m keywordCache.put(validKeyword, outputList); break; case TIME: - replacer = DateFormat.getTimeInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); + final String timeFormat = settings.getTimeFormat(); + + if (!Objects.equals(timeFormat, "locale")) + replacer = new SimpleDateFormat(timeFormat).format(new Date()); + else + replacer = DateFormat.getTimeInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); break; case DATE: - replacer = DateFormat.getDateInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); + final String dateFormat = settings.getDateFormat(); + + if (!Objects.equals(dateFormat, "locale")) + replacer = new SimpleDateFormat(dateFormat).format(new Date()); + else + replacer = DateFormat.getDateInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); break; case WORLDTIME12: if (user != null) { 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 125eed8fc9b..3db822004db 100644 --- a/Essentials/src/main/java/com/earth2me/essentials/utils/MaterialUtil.java +++ b/Essentials/src/main/java/com/earth2me/essentials/utils/MaterialUtil.java @@ -130,6 +130,10 @@ public static boolean isBoots(final Material material) { return BOOTS.contains(material); } + public static boolean isArmor(final Material material) { + return isHelmet(material) || isChestplate(material) || isLeggings(material) || isBoots(material); + } + public static boolean isBed(final Material material) { return BEDS.contains(material); } diff --git a/Essentials/src/main/resources/config.yml b/Essentials/src/main/resources/config.yml index 771d9372b64..45a4cb1364c 100644 --- a/Essentials/src/main/resources/config.yml +++ b/Essentials/src/main/resources/config.yml @@ -755,6 +755,24 @@ max-itemlore-lines: 10 # This uses the public GitHub API and no identifying information is sent or stored. update-check: true +############################################################ +# +------------------------------------------------------+ # +# | Keywords | # +# +------------------------------------------------------+ # +############################################################ + +# Format for the {DATE} keyword. +# Set `locale` to display dates according to the regional standards of the host location. +# For custom patterns, follow the Java SimpleDateFormat syntax conventions. https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html +# Custom pattern example: dd/MM/yyyy +date-format: locale + +# Format for the {TIME} keyword. +# Set `locale` to display time according to the regional standards of the host location. +# For custom patterns, follow the Java SimpleDateFormat syntax conventions. https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html +# Custom pattern example: HH:mm:ss +time-format: locale + ############################################################ # +------------------------------------------------------+ # # | Homes | #