minions-plus/src/main/java/pw/hamzantal/minionsplus/util/SkullCreator.java

277 lines
6.8 KiB
Java

package pw.hamzantal.minionsplus.util;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Skull;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Base64;
import java.util.UUID;
/**
* A library for the Bukkit API to create player skulls
* from names, base64 strings, and texture URLs.
*
* Does not use any NMS code, and should work across all versions.
*
* @author Dean B on 12/28/2016.
*/
public class SkullCreator {
/**
* Creates a player skull based on a player's name.
*
* @param name The Player's name
* @return The head of the Player
*
* @deprecated names don't make for good identifiers
*/
@Deprecated
public static ItemStack itemFromName(String name) {
ItemStack item = getPlayerSkullItem();
return itemWithName(item, name);
}
/**
* Creates a player skull based on a player's name.
*
* @param item The item to apply the name to
* @param name The Player's name
* @return The head of the Player
*
* @deprecated names don't make for good identifiers
*/
@Deprecated
public static ItemStack itemWithName(ItemStack item, String name) {
notNull(item, "item");
notNull(name, "name");
return Bukkit.getUnsafe().modifyItemStack(item,
"{SkullOwner:\"" + name + "\"}"
);
}
/**
* Creates a player skull with a UUID. 1.13 only.
*
* @param id The Player's UUID
* @return The head of the Player
*/
public static ItemStack itemFromUuid(UUID id) {
ItemStack item = getPlayerSkullItem();
return itemWithUuid(item, id);
}
/**
* Creates a player skull based on a UUID. 1.13 only.
*
* @param item The item to apply the name to
* @param id The Player's UUID
* @return The head of the Player
*/
public static ItemStack itemWithUuid(ItemStack item, UUID id) {
notNull(item, "item");
notNull(id, "id");
SkullMeta meta = (SkullMeta) item.getItemMeta();
meta.setOwner(Bukkit.getOfflinePlayer(id).getName());
item.setItemMeta(meta);
return item;
}
/**
* Creates a player skull based on a Mojang server URL.
*
* @param url The URL of the Mojang skin
* @return The head associated with the URL
*/
public static ItemStack itemFromUrl(String url) {
ItemStack item = getPlayerSkullItem();
return itemWithUrl(item, url);
}
/**
* Creates a player skull based on a Mojang server URL.
*
* @param item The item to apply the skin to
* @param url The URL of the Mojang skin
* @return The head associated with the URL
*/
public static ItemStack itemWithUrl(ItemStack item, String url) {
notNull(item, "item");
notNull(url, "url");
return itemWithBase64(item, urlToBase64(url));
}
/**
* Creates a player skull based on a base64 string containing the link to the skin.
*
* @param base64 The base64 string containing the texture
* @return The head with a custom texture
*/
public static ItemStack itemFromBase64(String base64) {
ItemStack item = getPlayerSkullItem();
return itemWithBase64(item, base64);
}
/**
* Applies the base64 string to the ItemStack.
*
* @param item The ItemStack to put the base64 onto
* @param base64 The base64 string containing the texture
* @return The head with a custom texture
*/
public static ItemStack itemWithBase64(ItemStack item, String base64) {
notNull(item, "item");
notNull(base64, "base64");
UUID hashAsId = new UUID(base64.hashCode(), base64.hashCode());
return Bukkit.getUnsafe().modifyItemStack(item,
"{SkullOwner:{Id:\"" + hashAsId + "\",Properties:{textures:[{Value:\"" + base64 + "\"}]}}}"
);
}
/**
* Sets the block to a skull with the given name.
*
* @param block The block to set
* @param name The player to set it to
*
* @deprecated names don't make for good identifiers
*/
@Deprecated
public static void blockWithName(Block block, String name) {
notNull(block, "block");
notNull(name, "name");
setBlockType(block);
((Skull) block.getState()).setOwner(name);
}
/**
* Sets the block to a skull with the given UUID.
*
* @param block The block to set
* @param id The player to set it to
*/
public static void blockWithUuid(Block block, UUID id) {
notNull(block, "block");
notNull(id, "id");
setBlockType(block);
((Skull) block.getState()).setOwner(Bukkit.getOfflinePlayer(id).getName());
}
/**
* Sets the block to a skull with the given UUID.
*
* @param block The block to set
* @param url The mojang URL to set it to use
*/
public static void blockWithUrl(Block block, String url) {
notNull(block, "block");
notNull(url, "url");
blockWithBase64(block, urlToBase64(url));
}
/**
* Sets the block to a skull with the given UUID.
*
* @param block The block to set
* @param base64 The base64 to set it to use
*/
public static void blockWithBase64(Block block, String base64) {
notNull(block, "block");
notNull(base64, "base64");
UUID hashAsId = new UUID(base64.hashCode(), base64.hashCode());
String args = String.format(
"%d %d %d %s",
block.getX(),
block.getY(),
block.getZ(),
"{Owner:{Id:\"" + hashAsId + "\",Properties:{textures:[{Value:\"" + base64 + "\"}]}}}"
);
if (newerApi()) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "data merge block " + args);
} else {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),"blockdata " + args);
}
}
private static boolean newerApi() {
try {
Material.valueOf("PLAYER_HEAD");
return true;
} catch (IllegalArgumentException e) { // If PLAYER_HEAD doesn't exist
return false;
}
}
private static ItemStack getPlayerSkullItem() {
if (newerApi()) {
return new ItemStack(Material.valueOf("PLAYER_HEAD"));
} else {
return new ItemStack(Material.valueOf("SKULL_ITEM"), 1, (byte) 3);
}
}
private static void setBlockType(Block block) {
try {
block.setType(Material.valueOf("PLAYER_HEAD"), false);
} catch (IllegalArgumentException e) {
block.setType(Material.valueOf("SKULL"), false);
}
}
private static void notNull(Object o, String name) {
if (o == null) {
throw new NullPointerException(name + " should not be null!");
}
}
private static String urlToBase64(String url) {
URI actualUrl;
try {
actualUrl = new URI(url);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
String toEncode = "{\"textures\":{\"SKIN\":{\"url\":\"" + actualUrl.toString() + "\"}}}";
return Base64.getEncoder().encodeToString(toEncode.getBytes());
}
}
/* Format for skull
{
display:{
Name:"Cheese"
},
SkullOwner:{
Id:"9c919b83-f3fe-456f-a824-7d1d08cc8bd2",
Properties:{
textures:[
{
Value:"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTU1ZDYxMWE4NzhlODIxMjMxNzQ5YjI5NjU3MDhjYWQ5NDI2NTA2NzJkYjA5ZTI2ODQ3YTg4ZTJmYWMyOTQ2In19fQ=="
}
]
}
}
}
*/