mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2024-11-27 05:05:18 +01:00
Fixes some errors with HeadGetter (#1569)
* Add getKey and getValue for Pair calls for nicer access. * Fixes ConcurrentModificationException in HeadGetter. Fixes an issue when elements with the same name were overwritten by HeadGetter.
This commit is contained in:
parent
1d4fd435a9
commit
3581537537
@ -2,17 +2,13 @@ package world.bentobox.bentobox.api.panels;
|
||||
|
||||
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 class Panel implements HeadRequester, InventoryHolder {
|
||||
@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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,25 @@ public class Pair<X, 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()
|
||||
*/
|
||||
|
@ -9,11 +9,11 @@ import java.net.URL;
|
||||
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 org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
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<String, PanelItem> names = new HashMap<>();
|
||||
private static final Queue<Pair<String, PanelItem>> names = new LinkedBlockingQueue<>();
|
||||
|
||||
/**
|
||||
* Requesters of player heads.
|
||||
@ -89,7 +90,7 @@ public class HeadGetter {
|
||||
// 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 class HeadGetter {
|
||||
*/
|
||||
private void runPlayerHeadGetter() {
|
||||
Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, () -> {
|
||||
synchronized (names)
|
||||
synchronized (HeadGetter.names)
|
||||
{
|
||||
Iterator<Entry<String, PanelItem>> it = names.entrySet().iterator();
|
||||
|
||||
if (it.hasNext())
|
||||
if (!HeadGetter.names.isEmpty())
|
||||
{
|
||||
Entry<String, PanelItem> elementEntry = it.next();
|
||||
Pair<String, PanelItem> 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 @@ public class HeadGetter {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user