Reworked ItemBuilder

This commit is contained in:
NichtStudioCode 2021-12-22 17:15:05 +01:00
parent dbad076ce1
commit 1560a5d688
6 changed files with 392 additions and 153 deletions

@ -1,21 +1,12 @@
package de.studiocode.invui.item; package de.studiocode.invui.item.builder;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import de.studiocode.inventoryaccess.util.ReflectionRegistry;
import de.studiocode.inventoryaccess.util.ReflectionUtils;
import de.studiocode.inventoryaccess.version.InventoryAccess; import de.studiocode.inventoryaccess.version.InventoryAccess;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.util.ComponentUtils; import de.studiocode.invui.util.ComponentUtils;
import de.studiocode.invui.util.MojangApiUtils;
import de.studiocode.invui.util.Pair; import de.studiocode.invui.util.Pair;
import de.studiocode.invui.window.impl.BaseWindow; import de.studiocode.invui.window.impl.BaseWindow;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemFlag;
@ -24,14 +15,11 @@ import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
import java.util.*; import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ItemBuilder implements ItemProvider { abstract class BaseItemBuilder<T> implements ItemProvider {
protected ItemStack base; protected ItemStack base;
protected Material material; protected Material material;
@ -42,52 +30,39 @@ public class ItemBuilder implements ItemProvider {
protected List<BaseComponent[]> lore; protected List<BaseComponent[]> lore;
protected List<ItemFlag> itemFlags; protected List<ItemFlag> itemFlags;
protected HashMap<Enchantment, Pair<Integer, Boolean>> enchantments; protected HashMap<Enchantment, Pair<Integer, Boolean>> enchantments;
protected GameProfile gameProfile;
protected List<Function<ItemStack, ItemStack>> modifiers; protected List<Function<ItemStack, ItemStack>> modifiers;
/** /**
* Constructs a new {@link ItemBuilder} based on the given {@link Material}. * Constructs a new {@link BaseItemBuilder} based on the given {@link Material}.
* *
* @param material The {@link Material} * @param material The {@link Material}
*/ */
public ItemBuilder(@NotNull Material material) { public BaseItemBuilder(@NotNull Material material) {
this.material = material; this.material = material;
} }
/** /**
* Constructs a new {@link ItemBuilder} based on the given {@link Material} and amount. * Constructs a new {@link BaseItemBuilder} based on the given {@link Material} and amount.
* *
* @param material The {@link Material} * @param material The {@link Material}
* @param amount The amount * @param amount The amount
*/ */
public ItemBuilder(@NotNull Material material, int amount) { public BaseItemBuilder(@NotNull Material material, int amount) {
this.material = material; this.material = material;
this.amount = amount; this.amount = amount;
} }
/** /**
* Constructs a new {@link ItemBuilder} based on the give {@link ItemStack}. * Constructs a new {@link BaseItemBuilder} based on the give {@link ItemStack}.
* This will keep the {@link ItemStack} and uses it's {@link ItemMeta} * This will keep the {@link ItemStack} and uses it's {@link ItemMeta}
* *
* @param base The {@link ItemStack to use as a base} * @param base The {@link ItemStack to use as a base}
*/ */
public ItemBuilder(@NotNull ItemStack base) { public BaseItemBuilder(@NotNull ItemStack base) {
this.base = base.clone(); this.base = base.clone();
this.amount = base.getAmount(); this.amount = base.getAmount();
} }
/**
* Constructs a new {@link ItemBuilder} of skull with the specified {@link HeadTexture}.
*
* @param headTexture The {@link HeadTexture}
*/
public ItemBuilder(@NotNull HeadTexture headTexture) {
material = Material.PLAYER_HEAD;
gameProfile = new GameProfile(UUID.randomUUID(), null);
PropertyMap propertyMap = gameProfile.getProperties();
propertyMap.put("textures", new Property("textures", headTexture.getTextureValue()));
}
/** /**
* Builds the {@link ItemStack} * Builds the {@link ItemStack}
* *
@ -137,10 +112,6 @@ public class ItemBuilder implements ItemProvider {
itemMeta.addItemFlags(itemFlags.toArray(new ItemFlag[0])); itemMeta.addItemFlags(itemFlags.toArray(new ItemFlag[0]));
} }
// game profile
if (gameProfile != null)
ReflectionUtils.setFieldValue(ReflectionRegistry.CB_CRAFT_META_SKULL_PROFILE_FIELD, itemMeta, gameProfile);
// apply to the item stack // apply to the item stack
itemStack.setItemMeta(itemMeta); itemStack.setItemMeta(itemMeta);
} }
@ -157,7 +128,7 @@ public class ItemBuilder implements ItemProvider {
/** /**
* Builds the {@link ItemStack} for a specific player. * Builds the {@link ItemStack} for a specific player.
* This is the method called by {@link BaseWindow} which gives you * This is the method called by {@link BaseWindow} which gives you
* the option to (for example) create a subclass of {@link ItemBuilder} that automatically * the option to (for example) create a subclass of {@link BaseItemBuilder} that automatically
* translates the item's name into the player's language. * translates the item's name into the player's language.
* *
* @param playerUUID The {@link UUID} of the {@link Player} * @param playerUUID The {@link UUID} of the {@link Player}
@ -169,81 +140,81 @@ public class ItemBuilder implements ItemProvider {
return get(); return get();
} }
public ItemBuilder setLegacyLore(@NotNull List<String> lore) { public T setLegacyLore(@NotNull List<String> lore) {
this.lore = lore.stream() this.lore = lore.stream()
.map(ComponentUtils::withoutPreFormatting) .map(ComponentUtils::withoutPreFormatting)
.collect(Collectors.toList()); .collect(Collectors.toList());
return this; return getThis();
} }
public ItemBuilder addLoreLines(@NotNull String... lines) { public T addLoreLines(@NotNull String... lines) {
if (lore == null) lore = new ArrayList<>(); if (lore == null) lore = new ArrayList<>();
for (String line : lines) for (String line : lines)
lore.add(ComponentUtils.withoutPreFormatting(line)); lore.add(ComponentUtils.withoutPreFormatting(line));
return this; return getThis();
} }
public ItemBuilder addLoreLines(@NotNull BaseComponent[]... lines) { public T addLoreLines(@NotNull BaseComponent[]... lines) {
if (lore == null) lore = new ArrayList<>(); if (lore == null) lore = new ArrayList<>();
lore.addAll(Arrays.stream(lines).map(ComponentUtils::withoutPreFormatting).collect(Collectors.toList())); lore.addAll(Arrays.stream(lines).map(ComponentUtils::withoutPreFormatting).collect(Collectors.toList()));
return this; return getThis();
} }
public ItemBuilder removeLoreLine(int index) { public T removeLoreLine(int index) {
if (lore != null) lore.remove(index); if (lore != null) lore.remove(index);
return this; return getThis();
} }
public ItemBuilder clearLore() { public T clearLore() {
if (lore != null) lore.clear(); if (lore != null) lore.clear();
return this; return getThis();
} }
public ItemBuilder addItemFlags(@NotNull ItemFlag... itemFlags) { public T addItemFlags(@NotNull ItemFlag... itemFlags) {
if (this.itemFlags == null) this.itemFlags = new ArrayList<>(); if (this.itemFlags == null) this.itemFlags = new ArrayList<>();
this.itemFlags.addAll(Arrays.asList(itemFlags)); this.itemFlags.addAll(Arrays.asList(itemFlags));
return this; return getThis();
} }
public ItemBuilder removeItemFlags(@NotNull ItemFlag... itemFlags) { public T removeItemFlags(@NotNull ItemFlag... itemFlags) {
if (this.itemFlags != null) if (this.itemFlags != null)
this.itemFlags.removeAll(Arrays.asList(itemFlags)); this.itemFlags.removeAll(Arrays.asList(itemFlags));
return this; return getThis();
} }
public ItemBuilder clearItemFlags() { public T clearItemFlags() {
if (itemFlags != null) itemFlags.clear(); if (itemFlags != null) itemFlags.clear();
return this; return getThis();
} }
public ItemBuilder addEnchantment(Enchantment enchantment, int level, boolean ignoreLevelRestriction) { public T addEnchantment(Enchantment enchantment, int level, boolean ignoreLevelRestriction) {
if (enchantments == null) enchantments = new HashMap<>(); if (enchantments == null) enchantments = new HashMap<>();
enchantments.put(enchantment, new Pair<>(level, ignoreLevelRestriction)); enchantments.put(enchantment, new Pair<>(level, ignoreLevelRestriction));
return this; return getThis();
} }
public ItemBuilder removeEnchantment(Enchantment enchantment) { public T removeEnchantment(Enchantment enchantment) {
if (enchantments == null) enchantments = new HashMap<>(); if (enchantments == null) enchantments = new HashMap<>();
enchantments.remove(enchantment); enchantments.remove(enchantment);
return this; return getThis();
} }
public ItemBuilder clearEnchantments() { public T clearEnchantments() {
if (enchantments != null) enchantments.clear(); if (enchantments != null) enchantments.clear();
return this; return getThis();
} }
public ItemBuilder addModifier(Function<ItemStack, ItemStack> modifier) { public T addModifier(Function<ItemStack, ItemStack> modifier) {
if (modifiers == null) modifiers = new ArrayList<>(); if (modifiers == null) modifiers = new ArrayList<>();
modifiers.add(modifier); modifiers.add(modifier);
return this; return getThis();
} }
public ItemBuilder clearModifiers() { public T clearModifiers() {
if (modifiers != null) modifiers.clear(); if (modifiers != null) modifiers.clear();
return this; return getThis();
} }
public ItemStack getBase() { public ItemStack getBase() {
@ -254,162 +225,100 @@ public class ItemBuilder implements ItemProvider {
return material; return material;
} }
public ItemBuilder setMaterial(@NotNull Material material) { public T setMaterial(@NotNull Material material) {
this.material = material; this.material = material;
return this; return getThis();
} }
public int getAmount() { public int getAmount() {
return amount; return amount;
} }
public ItemBuilder setAmount(int amount) { public T setAmount(int amount) {
this.amount = amount; this.amount = amount;
return this; return getThis();
} }
public int getDamage() { public int getDamage() {
return damage; return damage;
} }
public ItemBuilder setDamage(int damage) { public T setDamage(int damage) {
this.damage = damage; this.damage = damage;
return this; return getThis();
} }
public int getCustomModelData() { public int getCustomModelData() {
return customModelData; return customModelData;
} }
public ItemBuilder setCustomModelData(int customModelData) { public T setCustomModelData(int customModelData) {
this.customModelData = customModelData; this.customModelData = customModelData;
return this; return getThis();
} }
public BaseComponent[] getDisplayName() { public BaseComponent[] getDisplayName() {
return displayName; return displayName;
} }
public ItemBuilder setDisplayName(String displayName) { public T setDisplayName(String displayName) {
this.displayName = ComponentUtils.withoutPreFormatting(displayName); this.displayName = ComponentUtils.withoutPreFormatting(displayName);
return this; return getThis();
} }
public ItemBuilder setDisplayName(BaseComponent... displayName) { public T setDisplayName(BaseComponent... displayName) {
this.displayName = ComponentUtils.withoutPreFormatting(displayName); this.displayName = ComponentUtils.withoutPreFormatting(displayName);
return this; return getThis();
} }
public List<BaseComponent[]> getLore() { public List<BaseComponent[]> getLore() {
return lore; return lore;
} }
public ItemBuilder setLore(List<BaseComponent[]> lore) { public T setLore(List<BaseComponent[]> lore) {
this.lore = lore; this.lore = lore;
return this; return getThis();
} }
public List<ItemFlag> getItemFlags() { public List<ItemFlag> getItemFlags() {
return itemFlags; return itemFlags;
} }
public ItemBuilder setItemFlags(@NotNull List<ItemFlag> itemFlags) { public T setItemFlags(@NotNull List<ItemFlag> itemFlags) {
this.itemFlags = itemFlags; this.itemFlags = itemFlags;
return this; return getThis();
} }
public HashMap<Enchantment, Pair<Integer, Boolean>> getEnchantments() { public HashMap<Enchantment, Pair<Integer, Boolean>> getEnchantments() {
return enchantments; return enchantments;
} }
public ItemBuilder setEnchantments(@NotNull HashMap<Enchantment, Pair<Integer, Boolean>> enchantments) { public T setEnchantments(@NotNull HashMap<Enchantment, Pair<Integer, Boolean>> enchantments) {
this.enchantments = enchantments; this.enchantments = enchantments;
return this; return getThis();
}
public GameProfile getGameProfile() {
return gameProfile;
} }
public List<Function<ItemStack, ItemStack>> getModifiers() { public List<Function<ItemStack, ItemStack>> getModifiers() {
return modifiers; return modifiers;
} }
@SuppressWarnings("unchecked")
@Override @Override
public ItemBuilder clone() { public T clone() {
try { try {
ItemBuilder clone = ((ItemBuilder) super.clone()); BaseItemBuilder<T> clone = ((BaseItemBuilder<T>) super.clone());
if (base != null) clone.base = base.clone(); if (base != null) clone.base = base.clone();
if (lore != null) clone.lore = new ArrayList<>(lore); if (lore != null) clone.lore = new ArrayList<>(lore);
if (itemFlags != null) clone.itemFlags = new ArrayList<>(itemFlags); if (itemFlags != null) clone.itemFlags = new ArrayList<>(itemFlags);
if (enchantments != null) clone.enchantments = new HashMap<>(enchantments); if (enchantments != null) clone.enchantments = new HashMap<>(enchantments);
if (modifiers != null) clone.modifiers = new ArrayList<>(modifiers); if (modifiers != null) clone.modifiers = new ArrayList<>(modifiers);
return clone; return (T) clone;
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }
/** protected abstract T getThis();
* Contains the texture value for a player head.
*
* @see ItemBuilder
*/
public static class HeadTexture implements Serializable {
private static final Cache<UUID, String> textureCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.DAYS)
.build();
private static final Cache<String, UUID> uuidCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.DAYS)
.build();
private final String textureValue;
public HeadTexture(@NotNull String textureValue) {
this.textureValue = textureValue;
}
public static HeadTexture of(@NotNull OfflinePlayer offlinePlayer) {
return of(offlinePlayer.getUniqueId());
}
@SuppressWarnings("deprecation")
public static HeadTexture of(@NotNull String playerName) {
if (Bukkit.getServer().getOnlineMode()) {
// if the server is in online mode, the Minecraft UUID cache (usercache.json) can be used
return of(Bukkit.getOfflinePlayer(playerName).getUniqueId());
} else {
// the server isn't in online mode - the UUID has to be retrieved from the Mojang API
try {
return of(uuidCache.get(playerName, () -> MojangApiUtils.getCurrentUUID(playerName)));
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
}
public static HeadTexture of(@NotNull UUID uuid) {
try {
return new HeadTexture(textureCache.get(uuid, () -> MojangApiUtils.getSkinData(uuid, false)[0]));
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
public static void invalidateCache() {
uuidCache.invalidateAll();
textureCache.invalidateAll();
}
public String getTextureValue() {
return textureValue;
}
}
} }

@ -0,0 +1,44 @@
package de.studiocode.invui.item.builder;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
public final class ItemBuilder extends BaseItemBuilder<ItemBuilder> {
/**
* Constructs a new {@link BaseItemBuilder} based on the given {@link Material}.
*
* @param material The {@link Material}
*/
public ItemBuilder(@NotNull Material material) {
super(material);
}
/**
* Constructs a new {@link BaseItemBuilder} based on the given {@link Material} and amount.
*
* @param material The {@link Material}
* @param amount The amount
*/
public ItemBuilder(@NotNull Material material, int amount) {
super(material, amount);
}
/**
* Constructs a new {@link BaseItemBuilder} based on the give {@link ItemStack}.
* This will keep the {@link ItemStack} and uses it's {@link ItemMeta}
*
* @param base The {@link ItemStack to use as a base}
*/
public ItemBuilder(@NotNull ItemStack base) {
super(base);
}
@Override
protected ItemBuilder getThis() {
return this;
}
}

@ -0,0 +1,91 @@
package de.studiocode.invui.item.builder;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionData;
import org.bukkit.potion.PotionEffect;
import java.util.ArrayList;
import java.util.List;
public class PotionBuilder extends BaseItemBuilder<PotionBuilder> {
private List<PotionEffect> effects = new ArrayList<>();
private Color color;
private PotionData basePotionData;
public PotionBuilder(PotionType type) {
super(type.getMaterial());
}
public PotionBuilder(ItemStack base) {
super(base);
}
public PotionBuilder setColor(Color color) {
this.color = color;
return this;
}
public PotionBuilder setColor(java.awt.Color color) {
this.color = Color.fromRGB(color.getRed(), color.getGreen(), color.getBlue());
return this;
}
public PotionBuilder setBasePotionData(PotionData basePotionData) {
this.basePotionData = basePotionData;
return this;
}
public PotionBuilder addEffect(PotionEffect effect) {
effects.add(effect);
return this;
}
@Override
public ItemStack get() {
ItemStack item = super.get();
PotionMeta meta = (PotionMeta) item.getItemMeta();
meta.clearCustomEffects();
if (color != null) meta.setColor(color);
if (basePotionData != null) meta.setBasePotionData(basePotionData);
effects.forEach(effect -> meta.addCustomEffect(effect, true));
item.setItemMeta(meta);
return item;
}
@Override
public PotionBuilder clone() {
PotionBuilder builder = super.clone();
builder.effects = new ArrayList<>(effects);
return builder;
}
@Override
protected PotionBuilder getThis() {
return null;
}
public enum PotionType {
NORMAL(Material.POTION),
SPLASH(Material.SPLASH_POTION),
LINGERING(Material.LINGERING_POTION);
private final Material material;
PotionType(Material material) {
this.material = material;
}
public Material getMaterial() {
return material;
}
}
}

@ -0,0 +1,194 @@
package de.studiocode.invui.item.builder;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.properties.PropertyMap;
import de.studiocode.inventoryaccess.util.ReflectionRegistry;
import de.studiocode.inventoryaccess.util.ReflectionUtils;
import de.studiocode.invui.util.MojangApiUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.io.Serializable;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public final class SkullBuilder extends BaseItemBuilder<SkullBuilder> {
private GameProfile gameProfile;
/**
* Create a {@link SkullBuilder} of a {@link Player Player's} {@link UUID}.
*
* @param uuid The {@link UUID} of the skull owner.
*/
public SkullBuilder(UUID uuid) {
this(HeadTexture.of(uuid));
}
/**
* Create a {@link SkullBuilder} with the {@link Player Player's} username.
*
* @param username The username of the skull owner.
*/
public SkullBuilder(String username) {
this(HeadTexture.of(username));
}
/**
* Create a {@link SkullBuilder} with a {@link HeadTexture}.
*
* @param headTexture The {@link HeadTexture} to be applied to the skull.
*/
public SkullBuilder(HeadTexture headTexture) {
super(Material.PLAYER_HEAD);
setGameProfile(headTexture);
}
private void setGameProfile(HeadTexture texture) {
gameProfile = new GameProfile(UUID.randomUUID(), null);
PropertyMap propertyMap = gameProfile.getProperties();
propertyMap.put("textures", new Property("textures", texture.getTextureValue()));
}
@Override
public ItemStack get() {
ItemStack item = super.get();
ItemMeta meta = item.getItemMeta();
if (gameProfile != null)
ReflectionUtils.setFieldValue(ReflectionRegistry.CB_CRAFT_META_SKULL_PROFILE_FIELD, meta, gameProfile);
item.setItemMeta(meta);
return item;
}
@Override
public SkullBuilder setMaterial(@NotNull Material material) {
return this;
}
@Override
protected SkullBuilder getThis() {
return null;
}
/**
* Contains the texture value for a player head.
*
* @see SkullBuilder
*/
public static class HeadTexture implements Serializable {
private static final Cache<UUID, String> textureCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.DAYS)
.build();
private static final Cache<String, UUID> uuidCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.DAYS)
.build();
private final String textureValue;
/**
* Creates a new {@link HeadTexture} from the raw texture value.
*
* @param textureValue The texture value of this {@link HeadTexture}
* @see HeadTexture#of(OfflinePlayer)
* @see HeadTexture#of(UUID)
* @see HeadTexture#of(String)
*/
public HeadTexture(@NotNull String textureValue) {
this.textureValue = textureValue;
}
/**
* Retrieves the {@link HeadTexture} from this {@link OfflinePlayer}
* Please note that this data might not be pulled from the Mojang API as it might already be cached.
* Use {@link HeadTexture#invalidateCache()} to invalidate the cache.
*
* @param offlinePlayer The skull owner.
* @return The {@link HeadTexture} of that player.
* @see HeadTexture#of(UUID)
*/
public static HeadTexture of(@NotNull OfflinePlayer offlinePlayer) {
return of(offlinePlayer.getUniqueId());
}
/**
* Retrieves the {@link HeadTexture} from the username of the skull owner.
* This will first retrieve the {@link UUID} of the player from either Bukkit's usercache.json file
* (if the server is in only mode) or from the Mojang API (if the server is in offline mode).
* <p>
* Please note that this data might not be pulled from the Mojang API as it might already be cached.
* Use {@link HeadTexture#invalidateCache()} to invalidate the cache.
*
* @param playerName The username of the player.
* @return The {@link HeadTexture} of that player.
* @see HeadTexture#of(UUID)
*/
@SuppressWarnings("deprecation")
public static HeadTexture of(@NotNull String playerName) {
if (Bukkit.getServer().getOnlineMode()) {
// if the server is in online mode, the Minecraft UUID cache (usercache.json) can be used
return of(Bukkit.getOfflinePlayer(playerName).getUniqueId());
} else {
// the server isn't in online mode - the UUID has to be retrieved from the Mojang API
try {
return of(uuidCache.get(playerName, () -> MojangApiUtils.getCurrentUUID(playerName)));
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
}
/**
* Retrieves the {@link HeadTexture} from the {@link UUID} of the skull owner.
* Please note that this data might not be pulled from the Mojang API as it might already be cached.
* Use {@link HeadTexture#invalidateCache()} to invalidate the cache.
*
* @param uuid The {@link UUID} of the skull owner.
* @return The {@link HeadTexture} of that player.
*/
public static HeadTexture of(@NotNull UUID uuid) {
try {
return new HeadTexture(textureCache.get(uuid, () -> MojangApiUtils.getSkinData(uuid, false)[0]));
} catch (ExecutionException e) {
e.printStackTrace();
return null;
}
}
/**
* Invalidates the uuid and texture value cache.
* This means that when {@link HeadTexture#of(OfflinePlayer)}, {@link HeadTexture#of(UUID)}
* and {@link HeadTexture#of(String)} are called, these values will be pulled from the
* Mojang API again.
*/
public static void invalidateCache() {
uuidCache.invalidateAll();
textureCache.invalidateAll();
}
/**
* Gets the stored texture value.
*
* @return The stored texture value.
*/
public String getTextureValue() {
return textureValue;
}
}
}

@ -2,13 +2,14 @@ package de.studiocode.invui.item.impl;
import de.studiocode.invui.InvUI; import de.studiocode.invui.InvUI;
import de.studiocode.invui.item.Item; import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder;
import de.studiocode.invui.item.ItemProvider; import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.item.ItemWrapper;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -23,7 +24,7 @@ public class AsyncItem extends BaseItem {
private volatile ItemProvider itemProvider; private volatile ItemProvider itemProvider;
public AsyncItem(@Nullable ItemProvider itemProvider, @NotNull Supplier<? extends ItemProvider> providerSupplier) { public AsyncItem(@Nullable ItemProvider itemProvider, @NotNull Supplier<? extends ItemProvider> providerSupplier) {
this.itemProvider = itemProvider == null ? new ItemBuilder(Material.AIR) : itemProvider; this.itemProvider = itemProvider == null ? new ItemWrapper(new ItemStack(Material.AIR)) : itemProvider;
Bukkit.getScheduler().runTaskAsynchronously(InvUI.getInstance().getPlugin(), () -> { Bukkit.getScheduler().runTaskAsynchronously(InvUI.getInstance().getPlugin(), () -> {
this.itemProvider = providerSupplier.get(); this.itemProvider = providerSupplier.get();

@ -1,7 +1,7 @@
package de.studiocode.invui.resourcepack; package de.studiocode.invui.resourcepack;
import de.studiocode.invui.item.Item; import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemBuilder; import de.studiocode.invui.item.builder.ItemBuilder;
import de.studiocode.invui.item.impl.SimpleItem; import de.studiocode.invui.item.impl.SimpleItem;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Material; import org.bukkit.Material;