diff --git a/src/main/java/com/Acrobot/Breeze/Utils/MaterialUtil.java b/src/main/java/com/Acrobot/Breeze/Utils/MaterialUtil.java index bc3bfbc..ddb77ef 100644 --- a/src/main/java/com/Acrobot/Breeze/Utils/MaterialUtil.java +++ b/src/main/java/com/Acrobot/Breeze/Utils/MaterialUtil.java @@ -1,6 +1,8 @@ package com.Acrobot.Breeze.Utils; +import com.Acrobot.Breeze.Collection.SimpleCache; import com.Acrobot.ChestShop.ChestShop; +import com.Acrobot.ChestShop.Configuration.Properties; import com.google.common.collect.ImmutableMap; import de.themoep.ShowItem.api.ShowItem; import info.somethingodd.OddItem.OddItem; @@ -20,9 +22,7 @@ import org.json.simple.JSONObject; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -37,8 +37,9 @@ public class MaterialUtil { public static final boolean LONG_NAME = true; public static final boolean SHORT_NAME = false; - - private static final Map MATERIAL_CACHE = new HashMap(); + public static final short MAXIMUM_SIGN_LETTERS = 15; + + private static final SimpleCache MATERIAL_CACHE = new SimpleCache<>(Properties.CACHE_SIZE); /** * Checks if the itemStack is empty or null @@ -81,27 +82,45 @@ public class MaterialUtil { * @return Material found */ public static Material getMaterial(String name) { - String formatted = name.replaceAll(" |_", "").toUpperCase(); + String formatted = name.toUpperCase(); - if (MATERIAL_CACHE.containsKey(formatted)) { - return MATERIAL_CACHE.get(formatted); + Material material = MATERIAL_CACHE.get(formatted); + if (material != null) { + return material; } - Material material = Material.matchMaterial(name); + material = Material.matchMaterial(name); if (material != null) { MATERIAL_CACHE.put(formatted, material); return material; } + + String[] nameParts = name.toUpperCase().split(" "); short length = Short.MAX_VALUE; for (Material currentMaterial : Material.values()) { - String matName = currentMaterial.name(); + String matName = currentMaterial.toString(); - if (matName.length() < length && matName.replace("_", "").startsWith(formatted)) { + if (matName.length() < length && matName.startsWith(formatted)) { length = (short) matName.length(); material = currentMaterial; + } else if (nameParts.length > 1) { + String[] matParts = matName.split("_"); + if (nameParts.length == matParts.length) { + boolean matched = true; + for (int i = 0; i < matParts.length; i++) { + if (!matParts[i].startsWith(nameParts[i])) { + matched = false; + break; + } + } + if (matched) { + material = currentMaterial; + break; + } + } } } @@ -117,7 +136,7 @@ public class MaterialUtil { * @return ItemStack's name */ public static String getName(ItemStack itemStack) { - return getName(itemStack, LONG_NAME); + return getName(itemStack, 0); } /** @@ -126,7 +145,9 @@ public class MaterialUtil { * @param itemStack ItemStack to name * @param showDataValue Should we also show the data value? * @return ItemStack's name + * @deprecated Use {@link #getName(ItemStack, int)} */ + @Deprecated public static String getName(ItemStack itemStack, boolean showDataValue) { String dataName = DataValue.name(itemStack); @@ -144,23 +165,80 @@ public class MaterialUtil { * @return ItemStack's name */ public static String getSignName(ItemStack itemStack) { - StringBuilder name = new StringBuilder(15); - + return getName(itemStack, MAXIMUM_SIGN_LETTERS); + } + + /** + * Returns item's name, with a maximum length + * + * @param itemStack ItemStack to name + * @param maxLength The max length that the name should have; 0 or below if it should be unlimited + * @return ItemStack's name + */ + public static String getName(ItemStack itemStack, int maxLength) { String alias = Odd.getAlias(itemStack); - String itemName = alias != null ? alias : itemStack.getType().name(); - itemName = StringUtil.capitalizeFirstLetter(itemName, '_'); - - name.append(itemName); - - if (itemStack.getDurability() != 0) { - name.append(':').append(itemStack.getDurability()); + String itemName = alias != null ? alias : itemStack.getType().toString(); + + String data = DataValue.name(itemStack); + String durability = ""; + if (data == null) { + if (itemStack.getDurability() != 0) { + durability = ":" + itemStack.getDurability(); + } } + data = data != null ? data + "_" : ""; + String metaData = ""; if (itemStack.hasItemMeta()) { - name.append('#').append(Metadata.getItemCode(itemStack)); + metaData = "#" + Metadata.getItemCode(itemStack); + } + + String code = data + itemName + durability + metaData; + if (maxLength > 0 && code.length() > maxLength) { + String[] itemParts = itemName.split("_"); + int exceeding = code.length() - maxLength; + int shortestIndex = 0; + int longestIndex = 0; + for (int i = 0; i < itemParts.length; i++) { + if (itemParts[longestIndex].length() < itemParts[i].length()) { + longestIndex = i; + } + if (itemParts[shortestIndex].length() > itemParts[i].length()) { + shortestIndex = i; + } + } + if (itemParts[longestIndex].length() - itemParts[shortestIndex].length() > exceeding) { + itemParts[longestIndex] = itemParts[longestIndex].substring(0, itemParts[longestIndex].length() - exceeding); + } else { + for (int i = itemParts.length - 1; i >= 0 && exceeding > 0; i--) { + int remove = 0; + if (itemParts[i].length() > itemParts[shortestIndex].length()) { + remove = itemParts[i].length() - itemParts[shortestIndex].length(); + } + if (remove > exceeding) { + remove = exceeding; + } + itemParts[i] = itemParts[i].substring(0, itemParts[i].length() - remove); + exceeding -= remove; + } + while (exceeding > 0) { + for (int i = itemParts.length - 1; i >= 0 && exceeding > 0; i--) { + itemParts[i] = itemParts[i].substring(0, itemParts[i].length() - 1); + exceeding--; + } + } + } + code = data + String.join("_", itemParts) + durability + metaData; } - return name.toString(); + code = StringUtil.capitalizeFirstLetter(code, '_'); + + ItemStack codeItem = getItem(code); + if (!equals(itemStack, codeItem)) { + throw new IllegalArgumentException("Cannot generate code for item " + itemStack + " with maximum length of " + maxLength); + } + + return code; } /** @@ -361,10 +439,10 @@ public class MaterialUtil { public static class Metadata { /** - * Returns the ItemStack represented by this code + * Returns the ItemMeta represented by this code * - * @param code Code representing the item - * @return Item represented by code + * @param code Code representing the ItemMeta + * @return ItemMeta represented by code */ public static ItemMeta getFromCode(String code) { ItemStack item = ChestShop.getItemDatabase().getFromCode(code); diff --git a/src/main/java/com/Acrobot/ChestShop/Commands/ItemInfo.java b/src/main/java/com/Acrobot/ChestShop/Commands/ItemInfo.java index 8090104..b21a1eb 100644 --- a/src/main/java/com/Acrobot/ChestShop/Commands/ItemInfo.java +++ b/src/main/java/com/Acrobot/ChestShop/Commands/ItemInfo.java @@ -35,11 +35,9 @@ public class ItemInfo implements CommandExecutor { return false; } - String durability = getDurability(item); - String metadata = getMetadata(item); - sender.sendMessage(Messages.prefix(iteminfo)); - sender.sendMessage(getNameAndID(item) + durability + metadata + ChatColor.WHITE); + sender.sendMessage(ChatColor.WHITE + "Full Name: " + ChatColor.GRAY + MaterialUtil.getName(item)); + sender.sendMessage(ChatColor.WHITE + "Shop Sign: " + ChatColor.GRAY + MaterialUtil.getSignName(item)); ItemInfoEvent event = new ItemInfoEvent(sender, item); ChestShop.callEvent(event); @@ -48,9 +46,7 @@ public class ItemInfo implements CommandExecutor { } private static String getNameAndID(ItemStack item) { - String itemName = MaterialUtil.getName(item); - - return ChatColor.GRAY + itemName; + return MaterialUtil.getName(item); } private static String getDurability(ItemStack item) { diff --git a/src/main/java/com/Acrobot/ChestShop/Configuration/Properties.java b/src/main/java/com/Acrobot/ChestShop/Configuration/Properties.java index 97a1625..e8e102b 100644 --- a/src/main/java/com/Acrobot/ChestShop/Configuration/Properties.java +++ b/src/main/java/com/Acrobot/ChestShop/Configuration/Properties.java @@ -11,7 +11,7 @@ public class Properties { public static boolean TURN_OFF_UPDATES = false; @PrecededBySpace - @ConfigurationComment("How large should the internal uuid and name caches be?") + @ConfigurationComment("How large should the internal caches be?") public static int CACHE_SIZE = 1000; @PrecededBySpace diff --git a/src/main/java/com/Acrobot/ChestShop/Listeners/PostTransaction/TransactionLogger.java b/src/main/java/com/Acrobot/ChestShop/Listeners/PostTransaction/TransactionLogger.java index bac4028..99a49e3 100644 --- a/src/main/java/com/Acrobot/ChestShop/Listeners/PostTransaction/TransactionLogger.java +++ b/src/main/java/com/Acrobot/ChestShop/Listeners/PostTransaction/TransactionLogger.java @@ -9,7 +9,7 @@ import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import static com.Acrobot.Breeze.Utils.InventoryUtil.mergeSimilarStacks; -import static com.Acrobot.Breeze.Utils.MaterialUtil.getSignName; +import static com.Acrobot.Breeze.Utils.MaterialUtil.getName; import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.BUY; /** @@ -26,7 +26,7 @@ public class TransactionLogger implements Listener { StringBuilder items = new StringBuilder(50); for (ItemStack item : mergeSimilarStacks(event.getStock())) { - items.append(item.getAmount()).append(' ').append(getSignName(item)); + items.append(item.getAmount()).append(' ').append(getName(item)); } String message = String.format(template, diff --git a/src/main/java/com/Acrobot/ChestShop/Listeners/PreShopCreation/ItemChecker.java b/src/main/java/com/Acrobot/ChestShop/Listeners/PreShopCreation/ItemChecker.java index f089e94..29e0ad3 100644 --- a/src/main/java/com/Acrobot/ChestShop/Listeners/PreShopCreation/ItemChecker.java +++ b/src/main/java/com/Acrobot/ChestShop/Listeners/PreShopCreation/ItemChecker.java @@ -1,7 +1,6 @@ package com.Acrobot.ChestShop.Listeners.PreShopCreation; import com.Acrobot.Breeze.Utils.MaterialUtil; -import com.Acrobot.Breeze.Utils.StringUtil; import com.Acrobot.ChestShop.Configuration.Messages; import com.Acrobot.ChestShop.Configuration.Properties; import com.Acrobot.ChestShop.Events.PreShopCreationEvent; @@ -26,17 +25,12 @@ import static com.Acrobot.ChestShop.Signs.ChestShopSign.AUTOFILL_CODE; * @author Acrobot */ public class ItemChecker implements Listener { - private static final short MAXIMUM_SIGN_LETTERS = 15; @EventHandler(priority = EventPriority.LOWEST) public static void onPreShopCreation(PreShopCreationEvent event) { String itemCode = event.getSignLine(ITEM_LINE); ItemStack item = MaterialUtil.getItem(itemCode); - if (Odd.getFromString(itemCode) != null) { - return; // The OddItem name is OK - } - if (item == null) { if (Properties.ALLOW_AUTO_ITEM_FILL && itemCode.equals(AUTOFILL_CODE)) { boolean foundItem = false; @@ -44,7 +38,6 @@ public class ItemChecker implements Listener { if (chest != null) { for (ItemStack stack : chest.getInventory().getContents()) { if (!MaterialUtil.isEmpty(stack)) { - item = stack; itemCode = MaterialUtil.getSignName(stack); event.setSignLine(ITEM_LINE, itemCode); @@ -66,36 +59,11 @@ public class ItemChecker implements Listener { return; } } - - String metadata = getMetadata(itemCode); - String longName = MaterialUtil.getName(item); - - if (longName.length() <= (MAXIMUM_SIGN_LETTERS - metadata.length())) { - if (isSameItem(longName + metadata, item)) { - String itemName = StringUtil.capitalizeFirstLetter(longName); - - event.setSignLine(ITEM_LINE, itemName + metadata); - return; - } - } - - String code = MaterialUtil.getName(item, SHORT_NAME); - - String[] parts = itemCode.split("(?=:|-|#)", 2); - String data = (parts.length > 1 ? parts[1] : ""); - - if (code.length() > (MAXIMUM_SIGN_LETTERS - data.length())) { - code = code.substring(0, MAXIMUM_SIGN_LETTERS - data.length()); - } - - if (!isSameItem(code + data, item)) { + + if (itemCode.length() > MAXIMUM_SIGN_LETTERS) { event.setOutcome(INVALID_ITEM); return; } - - code = StringUtil.capitalizeFirstLetter(code); - - event.setSignLine(ITEM_LINE, code + data); } private static boolean isSameItem(String newCode, ItemStack item) {