Updated Skull class handling custom heads. No more relying on MHF_* accounts
This commit is contained in:
parent
e2b2ab466d
commit
3b4cf63c48
@ -4,6 +4,8 @@ import com.google.common.collect.Streams;
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
import io.papermc.paper.datacomponent.DataComponentType;
|
||||
import io.papermc.paper.datacomponent.DataComponentType.Valued;
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import io.papermc.paper.datacomponent.item.ResolvableProfile;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import org.bukkit.Material;
|
||||
@ -389,6 +391,15 @@ public class ItemStackBuilder {
|
||||
return data(DataComponentTypes.CAN_PLACE_ON, ItemAdventurePredicate.itemAdventurePredicate(canPlaceOn)); */
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code profile} data component to the provided profile.
|
||||
* @param profile the profile to use as the component value.
|
||||
* @return itself.
|
||||
*/
|
||||
public ItemStackBuilder profile(ResolvableProfile profile) {
|
||||
return data(DataComponentTypes.PROFILE, profile);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build the {@link ItemStack}.
|
||||
|
@ -0,0 +1,126 @@
|
||||
package fr.pandacube.lib.paper.inventory;
|
||||
|
||||
import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
import io.papermc.paper.datacomponent.item.ResolvableProfile;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Represents some special mob heads, also support creating player skulls and custom skulls.
|
||||
*/
|
||||
public enum Skull {
|
||||
|
||||
/** Jungle wood arrow left. */
|
||||
ARROW_LEFT("http://textures.minecraft.net/texture/3625902b389ed6c147574e422da8f8f361c8eb57e7631676a72777e7b1d"),
|
||||
/** Jungle wood arrow right. */
|
||||
ARROW_RIGHT("http://textures.minecraft.net/texture/d4be8aeec11849697adc6fd1f189b16642dff19f2955c05deaba68c9dff1be"),
|
||||
/** Jungle wood arrow up. */
|
||||
ARROW_UP("http://textures.minecraft.net/texture/88c0f37dec764d6e26b57aa8212572fbace5ee8f27f7b61c1fdaa47dd4c893"),
|
||||
/** Jungle wood arrow down. */
|
||||
ARROW_DOWN("http://textures.minecraft.net/texture/751ced2e647366f8f3ad2dfe415cca85651bfaf9739a95cd57b6f21cba053"),
|
||||
/** Jungle wood question mark. */
|
||||
QUESTION("http://textures.minecraft.net/texture/b4d7cc4dca986a53f1d6b52aaf376dc6acc73b8b287f42dc8fef5808bb5d76"),
|
||||
/** Jungle wood exclamation mark. */
|
||||
EXCLAMATION("http://textures.minecraft.net/texture/e869dc405a3155f281c16a3e8d9ff54afc1599153b4d9385c9b7bab88680f0");
|
||||
|
||||
private final String skinUrl;
|
||||
|
||||
Skull(String skinUrl) {
|
||||
this.skinUrl = skinUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the item based on this Skull enum.
|
||||
* @return the item stack.
|
||||
*/
|
||||
public ItemStack get() {
|
||||
return getFromSkinURL(skinUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an item stack builder already containing the skull.
|
||||
* @return an item stack builder already containing the skull.
|
||||
*/
|
||||
public ItemStackBuilder builder() {
|
||||
return ItemStackBuilder.wrap(get());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull of a player based on their name.
|
||||
*
|
||||
* @param name player's name
|
||||
* @return item stack
|
||||
*/
|
||||
public static ItemStack getFromPlayerName(String name) {
|
||||
return getFromProfile(ResolvableProfile.resolvableProfile().name(name).build());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by url.
|
||||
* @param url skin url.
|
||||
* @return item stack
|
||||
*/
|
||||
public static ItemStack getFromSkinURL(String url) {
|
||||
return getFromProfile(ResolvableProfile.resolvableProfile().addProperty(getTexturesProperty(url)).build());
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static ItemStack getFromProfile(ResolvableProfile profile) {
|
||||
return ItemStackBuilder.of(Material.PLAYER_HEAD).profile(profile).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The URL prefix for all the player related textures (skin, cape)
|
||||
*/
|
||||
public static final String TEXTURE_URL_PREFIX = "http://textures.minecraft.net/texture/";
|
||||
|
||||
private static final Pattern textureIdMatcher = Pattern.compile("^[0-9a-fA-F]+$");
|
||||
|
||||
/**
|
||||
* Generate the base64 value of the "textures" profile property, based on the provided skin url!
|
||||
* @param skinURL the URL of the skin. The "https" will be replaced by "http" because this is the protocol used in
|
||||
* the profile property url. If only the texture id part is provided, {@link #TEXTURE_URL_PREFIX} is
|
||||
* prepended.
|
||||
* @return the base64 encoded texture data.
|
||||
*/
|
||||
private static String encodeTextureBase64String(String skinURL) {
|
||||
if (skinURL.startsWith("https://")) // secure url is not the url found in texture data (even if it actually works in the browser)
|
||||
skinURL = "http://" + skinURL.substring("https://".length());
|
||||
if (!skinURL.startsWith(TEXTURE_URL_PREFIX)) { // accept taking only the texture id part ()
|
||||
if (textureIdMatcher.matcher(skinURL).matches())
|
||||
skinURL = TEXTURE_URL_PREFIX + skinURL;
|
||||
else
|
||||
throw new IllegalArgumentException("Invalid skin URL. Must be from " + TEXTURE_URL_PREFIX + ".");
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(String.format("{\"textures\":{\"SKIN\":{\"url\":\"%s\"}}}", skinURL).getBytes());
|
||||
}
|
||||
|
||||
|
||||
private static ProfileProperty getTexturesProperty(String skinURL) {
|
||||
return new ProfileProperty("textures", encodeTextureBase64String(skinURL));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,230 +0,0 @@
|
||||
package fr.pandacube.lib.paper.util;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import com.destroystokyo.paper.profile.ProfileProperty;
|
||||
|
||||
import fr.pandacube.lib.chat.Chat;
|
||||
|
||||
/**
|
||||
* Represents some special mob heads, also support creating player skulls and custom skulls.
|
||||
*
|
||||
* @author xigsag, SBPrime
|
||||
*
|
||||
* @see <a href="https://github.com/TigerHix/Hex-Utils/blob/9954159a323d12733b29c287a56980991cee2948/hex/util/Skull.java">github.com/TigerHix/Hex-Utils/hex/util/Skull.java</a>
|
||||
*/
|
||||
public enum Skull {
|
||||
|
||||
/** Standard skull of player MHF_ArrowLeft. */
|
||||
ARROW_LEFT("MHF_ArrowLeft"),
|
||||
/** Standard skull of player MHF_ArrowRight. */
|
||||
ARROW_RIGHT("MHF_ArrowRight"),
|
||||
/** Standard skull of player MHF_ArrowUp. */
|
||||
ARROW_UP("MHF_ArrowUp"),
|
||||
/** Standard skull of player MHF_ArrowDown. */
|
||||
ARROW_DOWN("MHF_ArrowDown"),
|
||||
/** Standard skull of player MHF_Question. */
|
||||
QUESTION("MHF_Question"),
|
||||
/** Standard skull of player MHF_Exclamation. */
|
||||
EXCLAMATION("MHF_Exclamation"),
|
||||
/** Standard skull of player FHG_Cam. */
|
||||
CAMERA("FHG_Cam"),
|
||||
|
||||
/** Standard skull of player MHF_PigZombie. */
|
||||
ZOMBIE_PIGMAN("MHF_PigZombie"),
|
||||
/** Standard skull of player MHF_Pig. */
|
||||
PIG("MHF_Pig"),
|
||||
/** Standard skull of player MHF_Sheep. */
|
||||
SHEEP("MHF_Sheep"),
|
||||
/** Standard skull of player MHF_Blaze. */
|
||||
BLAZE("MHF_Blaze"),
|
||||
/** Standard skull of player MHF_Chicken. */
|
||||
CHICKEN("MHF_Chicken"),
|
||||
/** Standard skull of player MHF_Cow. */
|
||||
COW("MHF_Cow"),
|
||||
/** Standard skull of player MHF_Slime. */
|
||||
SLIME("MHF_Slime"),
|
||||
/** Standard skull of player MHF_Spider. */
|
||||
SPIDER("MHF_Spider"),
|
||||
/** Standard skull of player MHF_Squid. */
|
||||
SQUID("MHF_Squid"),
|
||||
/** Standard skull of player MHF_Villager. */
|
||||
VILLAGER("MHF_Villager"),
|
||||
/** Standard skull of player MHF_Ocelot. */
|
||||
OCELOT("MHF_Ocelot"),
|
||||
/** Standard skull of player MHF_Herobrine. */
|
||||
HEROBRINE("MHF_Herobrine"),
|
||||
/** Standard skull of player MHF_LavaSlime. */
|
||||
LAVA_SLIME("MHF_LavaSlime"),
|
||||
/** Standard skull of player MHF_MushroomCow. */
|
||||
MOOSHROOM("MHF_MushroomCow"),
|
||||
/** Standard skull of player MHF_Golem. */
|
||||
GOLEM("MHF_Golem"),
|
||||
/** Standard skull of player MHF_Ghast. */
|
||||
GHAST("MHF_Ghast"),
|
||||
/** Standard skull of player MHF_Enderman. */
|
||||
ENDERMAN("MHF_Enderman"),
|
||||
/** Standard skull of player MHF_CaveSpider. */
|
||||
CAVE_SPIDER("MHF_CaveSpider"),
|
||||
|
||||
/** Standard skull of player MHF_Cactus. */
|
||||
CACTUS("MHF_Cactus"),
|
||||
/** Standard skull of player MHF_Cake. */
|
||||
CAKE("MHF_Cake"),
|
||||
/** Standard skull of player MHF_Chest. */
|
||||
CHEST("MHF_Chest"),
|
||||
/** Standard skull of player MHF_Melon. */
|
||||
MELON("MHF_Melon"),
|
||||
/** Standard skull of player MHF_OakLog. */
|
||||
LOG("MHF_OakLog"),
|
||||
/** Standard skull of player MHF_Pumpkin. */
|
||||
PUMPKIN("MHF_Pumpkin"),
|
||||
/** Standard skull of player MHF_TNT. */
|
||||
TNT("MHF_TNT"),
|
||||
/** Standard skull of player MHF_TNT2. */
|
||||
DYNAMITE("MHF_TNT2");
|
||||
|
||||
private final String name;
|
||||
|
||||
Skull(String mcName) {
|
||||
name = mcName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the item based on this Skull enum.
|
||||
*
|
||||
* @return item stack
|
||||
*/
|
||||
public ItemStack get() {
|
||||
return get(null, null);
|
||||
}
|
||||
/**
|
||||
* Return the item based on this Skull enum, with the provided display name and lore.
|
||||
* @param displayName the display name to add to the returned skull.
|
||||
* @param lore the lore to add to the returned skull.
|
||||
* @return item stack
|
||||
*/
|
||||
public ItemStack get(Chat displayName, List<Chat> lore) {
|
||||
return getFromPlayerName(name, displayName, lore);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull of a player based on their name.
|
||||
*
|
||||
* @param name player's name
|
||||
* @param displayName the display name to add to the returned skull.
|
||||
* @param lore the lore to add to the returned skull.
|
||||
* @return item stack
|
||||
*/
|
||||
public static ItemStack getFromPlayerName(String name, Chat displayName, List<Chat> lore) {
|
||||
ItemStack itemStack = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
SkullMeta meta = (SkullMeta) itemStack.getItemMeta();
|
||||
|
||||
@SuppressWarnings({ "deprecation", "unused" })
|
||||
boolean b = meta.setOwner(name);
|
||||
|
||||
if (displayName != null)
|
||||
meta.displayName(displayName.get());
|
||||
|
||||
if (lore != null)
|
||||
meta.lore(lore.stream().map(Chat::get).collect(Collectors.toList()));
|
||||
|
||||
itemStack.setItemMeta(meta);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by url.
|
||||
* @param url skin url.
|
||||
* @return item stack
|
||||
*/
|
||||
public static ItemStack getFromSkinURL(String url) {
|
||||
return getFromSkinURL(url, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by url.
|
||||
*
|
||||
* @param url the skin full url.
|
||||
* @param displayName the display name to add to the returned skull.
|
||||
* @param lore the lore to add to the returned skull.
|
||||
* @return item stack
|
||||
*/
|
||||
public static ItemStack getFromSkinURL(String url, Chat displayName, List<Chat> lore) {
|
||||
return getFromBase64String(Base64.getEncoder().encodeToString(String.format("{\"textures\":{\"SKIN\":{\"url\":\"%s\"}}}", url).getBytes()), displayName, lore);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by a base64 String.
|
||||
*
|
||||
* @param str the base64 string from game profile information.
|
||||
* @return item stack
|
||||
*/
|
||||
public static ItemStack getFromBase64String(String str) {
|
||||
return getFromBase64String(str, null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a skull that has a custom texture specified by a base64 String.
|
||||
*
|
||||
* @param str the base64 string from game profile information.
|
||||
* @param displayName the display name to add to the returned skull.
|
||||
* @param lore the lore to add to the returned skull.
|
||||
* @return item stack
|
||||
*/
|
||||
public static ItemStack getFromBase64String(String str, Chat displayName, List<Chat> lore) {
|
||||
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
|
||||
|
||||
SkullMeta headMeta = (SkullMeta) head.getItemMeta();
|
||||
|
||||
PlayerProfile profile = Bukkit.createProfile(UUID.nameUUIDFromBytes(str.getBytes()));
|
||||
profile.setProperty(new ProfileProperty("textures", str));
|
||||
headMeta.setPlayerProfile(profile);
|
||||
|
||||
if (displayName != null)
|
||||
headMeta.displayName(displayName.get());
|
||||
|
||||
if (lore != null)
|
||||
headMeta.lore(lore.stream().map(Chat::get).collect(Collectors.toList()));
|
||||
|
||||
head.setItemMeta(headMeta);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user