@@ -33,6 +33,10 @@ public class SkullCache {
3333 * accessed.
3434 */
3535 private static final HashMap <UUID , ItemStack > skullMap = new HashMap <>();
36+ private static final HashMap <String , ItemStack > skullBase64Map = new HashMap <>();
37+ private static final HashMap <String , Long > timeBase64Map = new HashMap <>();
38+ private static final HashMap <String , ItemStack > skullURLMap = new HashMap <>();
39+ private static final HashMap <String , Long > timeURLMap = new HashMap <>();
3640 private static final HashMap <UUID , Long > timeMap = new HashMap <>();
3741
3842 /**
@@ -41,10 +45,20 @@ public class SkullCache {
4145 * @param uuid The player's uuid.
4246 */
4347 public static void cacheSkull (UUID uuid , String name ) {
44- skullMap .put (uuid , skullFromUuid (uuid , name ));
48+ skullMap .put (uuid , itemWithUuid (uuid , name ));
4549 timeMap .put (uuid , System .currentTimeMillis ());
4650 }
4751
52+ public static void cacheSkullBase64 (String base64 ) {
53+ skullBase64Map .put (base64 , itemWithBase64 (base64 ));
54+ timeBase64Map .put (base64 , System .currentTimeMillis ());
55+ }
56+
57+ public static void cacheSkullURL (String url ) {
58+ skullURLMap .put (url , itemWithURL (url ));
59+ timeURLMap .put (url , System .currentTimeMillis ());
60+ }
61+
4862 /**
4963 * Cache a skull from an offline player.
5064 *
@@ -73,7 +87,7 @@ public static void cacheSkulls(HashMap<UUID, String> uuids) {
7387 new Thread (() -> {
7488 long start = System .currentTimeMillis ();
7589 for (Entry <UUID , String > entry : uuids .entrySet ()) {
76- skullMap .put (entry .getKey (), skullFromUuid (entry .getKey (), entry .getValue ()));
90+ skullMap .put (entry .getKey (), itemWithUuid (entry .getKey (), entry .getValue ()));
7791 timeMap .put (entry .getKey (), System .currentTimeMillis ());
7892 }
7993 // Generate an inventory off the rip to try to fix the hashmap
@@ -128,7 +142,7 @@ public static ItemStack getSkull(UUID uuid, String name) {
128142 timeMap .put (uuid , System .currentTimeMillis ());
129143 ItemStack skull = skullMap .get (uuid );
130144 if (skull == null ) {
131- skull = skullFromUuid (uuid , name );
145+ skull = itemWithUuid (uuid , name );
132146 cacheSkull (uuid , name );
133147 }
134148 return skull ;
@@ -160,6 +174,26 @@ public static ItemStack getSkull(Player player) {
160174 return getSkull (player .getUniqueId (), player .getName ());
161175 }
162176
177+ public static ItemStack getSkullBase64 (String base64 ) {
178+ timeBase64Map .put (base64 , System .currentTimeMillis ());
179+ ItemStack skull = skullBase64Map .get (base64 );
180+ if (skull == null ) {
181+ skull = itemWithBase64 (base64 );
182+ cacheSkullBase64 (base64 );
183+ }
184+ return skull ;
185+ }
186+
187+ public static ItemStack getSkullURL (String url ) {
188+ timeURLMap .put (url , System .currentTimeMillis ());
189+ ItemStack skull = skullURLMap .get (url );
190+ if (skull == null ) {
191+ skull = itemWithURL (url );
192+ cacheSkullURL (url );
193+ }
194+ return skull ;
195+ }
196+
163197 /**
164198 * Get an array of player skulls from uuids.
165199 *
@@ -227,30 +261,6 @@ public static void flushWeek() {
227261 flush (604800000 );
228262 }
229263
230- /**
231- * Creates a new player head item stack.
232- *
233- * @return Player head.
234- */
235- public static ItemStack createSkull () {
236- return new ItemStack (Material .PLAYER_HEAD );
237- }
238-
239- /**
240- * Creates a player skull item with the skin based on a player's UUID.
241- *
242- * @param id The player's UUID.
243- * @return The head of the player.
244- */
245- public static ItemStack skullFromUuid (UUID id , String name ) {
246- try {
247- return itemWithUuid (createSkull (), id , name );
248- } catch (Exception exception ) {
249- exception .printStackTrace ();
250- }
251- return null ;
252- }
253-
254264 @ SuppressWarnings ("deprecation" )
255265 static private JsonParser parser = new JsonParser ();
256266 static private String API_PROFILE_LINK = "https://sessionserver.mojang.com/session/minecraft/profile/" ;
@@ -304,15 +314,47 @@ public static ItemStack getSkull(String url, UUID uuid) {
304314 return skull ;
305315 }
306316
317+ public static ItemStack getSkull (String url ) {
318+ ItemStack skull = new ItemStack (Material .PLAYER_HEAD );
319+ if (url == null || url .isEmpty ())
320+ return skull ;
321+ SkullMeta skullMeta = (SkullMeta ) skull .getItemMeta ();
322+ PlayerProfile profile = Bukkit .getServer ().createPlayerProfile (UUID .randomUUID ());
323+ try {
324+ profile .getTextures ().setSkin (new URL (url ));
325+ } catch (MalformedURLException e ) {
326+ e .printStackTrace ();
327+ }
328+ skullMeta .setOwnerProfile (profile );
329+ skull .setItemMeta (skullMeta );
330+ return skull ;
331+ }
332+
333+ public static String getUrlFromBase64 (String base64 ) {
334+ String decoded = new String (Base64 .getDecoder ().decode (base64 ));
335+ // We simply remove the "beginning" and "ending" part of the JSON, so we're left
336+ // with only the URL. You could use a proper
337+ // JSON parser for this, but that's not worth it. The String will always start
338+ // exactly with this stuff anyway
339+ return decoded .substring ("{\" textures\" :{\" SKIN\" :{\" url\" :\" " .length (), decoded .length () - "\" }}}" .length ());
340+ }
341+
342+ public static ItemStack itemWithBase64 (String base64 ) {
343+ return getSkull (getUrlFromBase64 (base64 ));
344+ }
345+
346+ public static ItemStack itemWithURL (String url ) {
347+ return getSkull (url );
348+ }
349+
307350 /**
308351 * Modifies a skull to use the skin of the player with a given uuid.
309352 *
310353 * @param item The item to apply the name to. Must be a player skull.
311354 * @param id The player's uuid.
312355 * @return The head of the player.
313356 */
314- public static ItemStack itemWithUuid (ItemStack item , UUID id , String playerName ) throws Exception {
315- notNull (item , "item" );
357+ public static ItemStack itemWithUuid (UUID id , String playerName ) {
316358 notNull (id , "id" );
317359
318360 return getSkull (getSkinUrl (id .toString ()), id );
0 commit comments