Skip to content

Commit

Permalink
feat: add SkullItemCreator#byUuid to create skulls for offline players
Browse files Browse the repository at this point in the history
  • Loading branch information
SpraxDev committed Sep 22, 2024
1 parent 8006159 commit 791b037
Showing 1 changed file with 43 additions and 0 deletions.
43 changes: 43 additions & 0 deletions Core/src/main/java/com/craftaro/core/utils/SkullItemCreator.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -12,11 +15,14 @@
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());
Expand Down Expand Up @@ -56,6 +62,43 @@ public static ItemStack createDefaultSkullForUuid(UUID uuid) {
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<ItemStack> 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;
Expand Down

0 comments on commit 791b037

Please sign in to comment.