diff --git a/src/main/java/world/bentobox/bentobox/api/panels/Panel.java b/src/main/java/world/bentobox/bentobox/api/panels/Panel.java index c3ae9bfc7..98a88f733 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/Panel.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/Panel.java @@ -2,17 +2,13 @@ import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; +import java.util.OptionalInt; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.eclipse.jdt.annotation.NonNull; import world.bentobox.bentobox.api.user.User; @@ -190,18 +186,15 @@ public void setUser(User user) { @Override public void setHead(PanelItem item) { // Update the panel item - // Replace the item in the item list if the name is the same - items = items.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> (item.getName().equals(e.getValue().getName()) ? item : e.getValue()))); - // Replace the inventory slot item - for (int i = 0; i < inventory.getSize(); i++) { - ItemStack it = inventory.getItem(i); - if (it != null && it.getType().equals(Material.PLAYER_HEAD)) { - ItemMeta meta = it.getItemMeta(); - if (meta != null && ChatColor.stripColor(item.getName()).equals(ChatColor.stripColor(meta.getLocalizedName()))) { - inventory.setItem(i, item.getItem()); - } - } + // Find panel item index in items and replace it once more in inventory to update it. + + OptionalInt index = this.items.entrySet().stream(). + filter(entry -> entry.getValue() == item). + mapToInt(Map.Entry::getKey).findFirst(); + + if (index.isPresent()) { + // Update item inside inventory to change icon only if item is inside panel. + this.inventory.setItem(index.getAsInt(), item.getItem()); } } diff --git a/src/main/java/world/bentobox/bentobox/util/Pair.java b/src/main/java/world/bentobox/bentobox/util/Pair.java index 09b8cac74..775c5f111 100644 --- a/src/main/java/world/bentobox/bentobox/util/Pair.java +++ b/src/main/java/world/bentobox/bentobox/util/Pair.java @@ -17,6 +17,25 @@ public Pair(X x, Z z) { this.z = z; } + + /** + * Returns X element as key. + * @return X element + */ + public X getKey() { + return x; + } + + + /** + * Returns Z element as value. + * @return Z element + */ + public Z getValue() { + return z; + } + + /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/src/main/java/world/bentobox/bentobox/util/heads/HeadGetter.java b/src/main/java/world/bentobox/bentobox/util/heads/HeadGetter.java index de404b644..c75ce2354 100644 --- a/src/main/java/world/bentobox/bentobox/util/heads/HeadGetter.java +++ b/src/main/java/world/bentobox/bentobox/util/heads/HeadGetter.java @@ -9,11 +9,11 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; +import java.util.Queue; import java.util.Set; import java.util.UUID; +import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Collectors; import org.bukkit.Bukkit; @@ -21,6 +21,7 @@ import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.util.Pair; /** @@ -36,7 +37,7 @@ public class HeadGetter { /** * Local cache for storing requested names and items which must be updated. */ - private static final Map names = new HashMap<>(); + private static final Queue> names = new LinkedBlockingQueue<>(); /** * Requesters of player heads. @@ -89,7 +90,7 @@ public static void getHead(PanelItem panelItem, HeadRequester requester) { // Get the name headRequesters.computeIfAbsent(panelItem.getPlayerHeadName(), k -> new HashSet<>()). add(requester); - names.put(panelItem.getPlayerHeadName(), panelItem); + names.add(new Pair<>(panelItem.getPlayerHeadName(), panelItem)); } } @@ -117,21 +118,19 @@ public static void addToCache(HeadCache cache) */ private void runPlayerHeadGetter() { Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, () -> { - synchronized (names) + synchronized (HeadGetter.names) { - Iterator> it = names.entrySet().iterator(); - - if (it.hasNext()) + if (!HeadGetter.names.isEmpty()) { - Entry elementEntry = it.next(); + Pair elementEntry = HeadGetter.names.poll(); // TODO: In theory BentoBox could use User instance to find existing user UUID's. // It would avoid one API call. final String userName = elementEntry.getKey(); // Use cached userId as userId will not change :) - UUID userId = cachedHeads.containsKey(userName) ? - cachedHeads.get(userName).getUserId() : + UUID userId = HeadGetter.cachedHeads.containsKey(userName) ? + HeadGetter.cachedHeads.get(userName).getUserId() : HeadGetter.getUserIdFromName(userName); // Create new cache object. @@ -140,24 +139,22 @@ private void runPlayerHeadGetter() { HeadGetter.getTextureFromUUID(userId)); // Save in cache - cachedHeads.put(userName, cache); + HeadGetter.cachedHeads.put(userName, cache); // Tell requesters the head came in - if (headRequesters.containsKey(userName)) + if (HeadGetter.headRequesters.containsKey(userName)) { - for (HeadRequester req : headRequesters.get(userName)) + for (HeadRequester req : HeadGetter.headRequesters.get(userName)) { elementEntry.getValue().setHead(cache.getPlayerHead()); - Bukkit.getServer().getScheduler().runTaskAsynchronously(plugin, + Bukkit.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> req.setHead(elementEntry.getValue())); } } - - it.remove(); } } - }, 0L, 20L); + }, 0L, 10L); }