diff --git a/Core/src/main/java/com/craftaro/core/utils/SkullItemCreator.java b/Core/src/main/java/com/craftaro/core/utils/SkullItemCreator.java index b674b194..6c4deda6 100644 --- a/Core/src/main/java/com/craftaro/core/utils/SkullItemCreator.java +++ b/Core/src/main/java/com/craftaro/core/utils/SkullItemCreator.java @@ -1,8 +1,11 @@ package com.craftaro.core.utils; +import com.craftaro.core.http.SimpleHttpClient; +import com.craftaro.core.http.minecraft.MinecraftApiClient; import com.craftaro.core.nms.Nms; import com.craftaro.core.nms.entity.player.GameProfile; import com.cryptomorin.xseries.XMaterial; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SkullMeta; @@ -12,11 +15,14 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Objects; import java.util.UUID; +import java.util.concurrent.CompletableFuture; public final class SkullItemCreator { private static final String STEVE_TEXTURE = "ewogICJ0aW1lc3RhbXAiIDogMTYyMTcxNTMxMjI5MCwKICAicHJvZmlsZUlkIiA6ICJiNTM5NTkyMjMwY2I0MmE0OWY5YTRlYmYxNmRlOTYwYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJtYXJpYW5hZmFnIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzFhNGFmNzE4NDU1ZDRhYWI1MjhlN2E2MWY4NmZhMjVlNmEzNjlkMTc2OGRjYjEzZjdkZjMxOWE3MTNlYjgxMGIiCiAgICB9CiAgfQp9"; private static final String ALEX_TEXTURE = "rZvLQoZsgLYaoKqEuASopYAs7IAlZlsGkwagoM8ZX38cP9kalseZrWY5OHZVfoiftdQJ+lGOzkiFfyx6kNJDTZniLrnRa8sd3X6D65ZihT1sOm/RInCwxpS1K0zGCM2h9ErkWswfwaviIf7hJtrwk8/zL0bfzDk2IgX/IBvIZpVoYTfmQsVY9jgSwORrS9ObePGIfFgmThMoZnCYWQMVpS2+yTFA2wnw9hmisQK9UWBU+iBZv55bMmkMcyEuXw1w14DaEu+/M0UGD91LU4GmJLPA9T4GCuIV8GxOcraSVIajki1cMlOBQwIaibB2NE6KAwq1Zh6NnsNYucy6qFM+136lXfBchQ1Nx4FDRZQgt8VRqTMy/OQFpr2nTbWWbRU4gRFpKC3R0518DqUH0Qm612kPWniKku/QzUUBSe1PSVljBaZCyyRx0OB1a1/8MexboKRnPXuTDnmPa9UPfuH4VO0q+qYkjV2KUzP6e5vIP5aQ6USPrMie7MmAHFJzwAMIbLjgkTVx91GWtYqg/t7qBlvrdBRLIPPsy/DSOqa+2+4hABouVCPZrBMCMLzstPPQoqZAyiCqcKb2HqWSU0h9Bhx19yoIcbHCeI3zsQs8PqIBjUL4mO6VQT4lzHy0e3M61Xsdd8S1GtsakSetTvEtMdUwCEDfBA5PRRTLOVYTY+g="; + private static MinecraftApiClient minecraftApiClient = new MinecraftApiClient(new SimpleHttpClient()); + public static ItemStack byProfile(GameProfile profile) { ItemStack item = Objects.requireNonNull(XMaterial.PLAYER_HEAD.parseItem()); SkullMeta meta = (SkullMeta) Objects.requireNonNull(item.getItemMeta()); @@ -56,6 +62,43 @@ public final class SkullItemCreator { return byTextureValue(STEVE_TEXTURE); } + /** + * This method tries its best in determining the correct skin for a given UUID. + * It tries to request the corresponding profile (with skin data) from Mojang's API. + */ + public static CompletableFuture byUuid(UUID uuid) { + Player player = Bukkit.getPlayer(uuid); + if (player != null) { + return CompletableFuture.completedFuture(byPlayer(player)); + } + + try { + return Bukkit.getOfflinePlayer(uuid) + .getPlayerProfile() + .update() + .thenApply(profile -> { + if (profile.getTextures().getSkin() == null) { + return createDefaultSkullForUuid(uuid); + } + return byTextureUrl(profile.getTextures().getSkin().toString()); + }); + } catch (NoSuchMethodError ignored) { + // old spigot api version that doesn't have OfflinePlayer#getPlayerProfile() + } + + if (uuid.version() != 4) { + return CompletableFuture.completedFuture(createDefaultSkullForUuid(uuid)); + } + + return minecraftApiClient.fetchProfile(uuid) + .thenApply((profile) -> { + if (profile == null) { + return createDefaultSkullForUuid(uuid); + } + return byProfile(profile.createGameProfile()); + }); + } + private static Method skullMetaSetProfile = null; private static Field skullMetaProfileField = null; private static boolean setProfileUsesResolvable = false;