Skip to content

Commit

Permalink
async
Browse files Browse the repository at this point in the history
  • Loading branch information
OliverSchlueter committed Aug 12, 2024
1 parent dcbb805 commit d284315
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 91 deletions.
142 changes: 81 additions & 61 deletions api/src/main/java/de/oliver/fancynpcs/api/utils/SkinFetcher.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package de.oliver.fancynpcs.api.utils;


import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import de.oliver.fancylib.UUIDFetcher;
Expand All @@ -20,6 +19,7 @@
import java.util.Map;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

public final class SkinFetcher {
Expand All @@ -29,81 +29,101 @@ private SkinFetcher() {
}

/**
* Fetches the skin data from the Mojang API.
* Fetches the skin data from the Mojang API asynchronously.
*
* @param identifier The identifier of the skin. This can be a UUID, username, URL or a placeholder by PAPI.
* @throws IOException If the skin data could not be fetched.
* @return A CompletableFuture that will contain the SkinData.
*/
public static SkinData fetchSkin(String identifier) throws IOException {
String parsedIdentifier = ChatColorHandler.translate(identifier, List.of(PlaceholderAPIParser.class));
public static CompletableFuture<SkinData> fetchSkin(String identifier) {
return CompletableFuture.supplyAsync(() -> {
String parsedIdentifier = ChatColorHandler.translate(identifier, List.of(PlaceholderAPIParser.class));

if (skinCache.containsKey(parsedIdentifier)) {
return skinCache.get(parsedIdentifier);
}
if (skinCache.containsKey(parsedIdentifier)) {
return skinCache.get(parsedIdentifier);
}

if (isURL(parsedIdentifier)) {
return fetchSkinByURL(parsedIdentifier);
}
if (isURL(parsedIdentifier)) {
return fetchSkinByURL(parsedIdentifier).join();
}

if (isUUID(parsedIdentifier)) {
return fetchSkinByUUID(parsedIdentifier);
}
if (isUUID(parsedIdentifier)) {
return fetchSkinByUUID(parsedIdentifier).join();
}

// assume it's a username
UUID uuid = UUIDFetcher.getUUID(parsedIdentifier);
if (uuid != null) {
return fetchSkinByUUID(uuid.toString());
}
// assume it's a username
UUID uuid = UUIDFetcher.getUUID(parsedIdentifier);
if (uuid != null) {
return fetchSkinByUUID(uuid.toString()).join();
}

return null;
return null;
});
}

/**
* Fetches the skin data from the Mojang API.
* Fetches the skin data from the Mojang API by UUID asynchronously.
*
* @param uuid The UUID of the player.
* @return A CompletableFuture that will contain the SkinData.
* @throws IOException If the skin data could not be fetched.
*/
public static SkinData fetchSkinByUUID(String uuid) throws IOException {
URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");

String json = new Scanner(conn.getInputStream(), StandardCharsets.UTF_8).useDelimiter("\\A").next();
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(json).getAsJsonObject();

String value = obj.getAsJsonArray("properties").get(0).getAsJsonObject().getAsJsonPrimitive("value").getAsString();
String signature = obj.getAsJsonArray("properties").get(0).getAsJsonObject().getAsJsonPrimitive("signature").getAsString();
SkinData skinData = new SkinData(uuid, value, signature);

skinCache.put(uuid, skinData);
return skinData;
public static CompletableFuture<SkinData> fetchSkinByUUID(String uuid) {
return CompletableFuture.supplyAsync(() -> {
try {
URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");

String json = new Scanner(conn.getInputStream(), StandardCharsets.UTF_8).useDelimiter("\\A").next();
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(json).getAsJsonObject();

String value = obj.getAsJsonArray("properties").get(0).getAsJsonObject().getAsJsonPrimitive("value").getAsString();
String signature = obj.getAsJsonArray("properties").get(0).getAsJsonObject().getAsJsonPrimitive("signature").getAsString();
SkinData skinData = new SkinData(uuid, value, signature);

skinCache.put(uuid, skinData);
return skinData;
} catch (IOException e) {
FancyNpcsPlugin.get().getPlugin().getLogger().warning("Failed to fetch skin data for UUID " + uuid);
return null;
}
});
}

/**
* Fetches the skin data from the Mojang API.
* Fetches the skin data from the Mojang API by URL asynchronously.
*
* @param skinURL The URL of the skin.
* @return A CompletableFuture that will contain the SkinData.
* @throws IOException If the skin data could not be fetched.
*/
public static SkinData fetchSkinByURL(String skinURL) throws IOException {
URL url = new URL("https://api.mineskin.org/generate/url");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream());
outputStream.writeBytes("url=" + URLEncoder.encode(skinURL, StandardCharsets.UTF_8));
outputStream.close();

String json = new Scanner(conn.getInputStream(), StandardCharsets.UTF_8).useDelimiter("\\A").next();
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(json).getAsJsonObject();

String value = obj.getAsJsonObject("data").getAsJsonObject("texture").getAsJsonPrimitive("value").getAsString();
String signature = obj.getAsJsonObject("data").getAsJsonObject("texture").getAsJsonPrimitive("signature").getAsString();
SkinData skinData = new SkinData(skinURL, value, signature);

skinCache.put(skinURL, skinData);
return skinData;
public static CompletableFuture<SkinData> fetchSkinByURL(String skinURL) {
return CompletableFuture.supplyAsync(() -> {
try {
URL url = new URL("https://api.mineskin.org/generate/url");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream());
outputStream.writeBytes("url=" + URLEncoder.encode(skinURL, StandardCharsets.UTF_8));
outputStream.close();

String json = new Scanner(conn.getInputStream(), StandardCharsets.UTF_8).useDelimiter("\\A").next();
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(json).getAsJsonObject();

String value = obj.getAsJsonObject("data").getAsJsonObject("texture").getAsJsonPrimitive("value").getAsString();
String signature = obj.getAsJsonObject("data").getAsJsonObject("texture").getAsJsonPrimitive("signature").getAsString();
SkinData skinData = new SkinData(skinURL, value, signature);

skinCache.put(skinURL, skinData);
return skinData;
} catch (IOException e) {
FancyNpcsPlugin.get().getPlugin().getLogger().warning("Failed to fetch skin data for URL " + skinURL);
return null;
}
});
}

private static boolean isURL(String identifier) {
Expand Down Expand Up @@ -136,9 +156,9 @@ public record SkinData(@NotNull String identifier, @Nullable String value, @Null
public String value() {
if (value == null || value.isEmpty()) {
try {
SkinData skinData = fetchSkin(identifier);
SkinData skinData = fetchSkin(identifier).join();
return skinData == null ? null : skinData.value();
} catch (IOException e) {
} catch (Exception e) {
FancyNpcsPlugin.get().getPlugin().getLogger().warning("Failed to fetch skin data for " + identifier);
}
}
Expand All @@ -155,14 +175,14 @@ public String value() {
public String signature() {
if (signature == null || signature.isEmpty()) {
try {
SkinData skinData = fetchSkin(identifier);
SkinData skinData = fetchSkin(identifier).join();
return skinData == null ? null : skinData.signature();
} catch (IOException e) {
} catch (Exception e) {
FancyNpcsPlugin.get().getPlugin().getLogger().warning("Failed to fetch skin data for " + identifier);
}
}

return signature;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ public void create() {
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""));
((ServerPlayer) npc).gameProfile = gameProfile;

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}
} else {
EntityType<?> nmsType = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, MappingKeys1_19_4.ENTITY_TYPE__FACTORY.getMapping()); // EntityType.factory
Expand All @@ -90,6 +85,11 @@ public void spawn(Player player) {
return;
}

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}

NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,6 @@ public void create() {
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""));
((ServerPlayer) npc).gameProfile = gameProfile;

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}
} else {
EntityType<?> nmsType = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, MappingKeys1_20_1.ENTITY_TYPE__FACTORY.getMapping()); // EntityType.factory
Expand All @@ -91,6 +86,11 @@ public void spawn(Player player) {
return;
}

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}

NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ public void create() {
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""), ClientInformation.createDefault());
((ServerPlayer) npc).gameProfile = gameProfile;

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}
} else {
EntityType<?> nmsType = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, MappingKeys1_20_2.ENTITY_TYPE__FACTORY.getMapping()); // EntityType.factory
Expand All @@ -93,6 +88,11 @@ public void spawn(Player player) {
return;
}

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}

NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@ public void create() {
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""), ClientInformation.createDefault());
((ServerPlayer) npc).gameProfile = gameProfile;

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}
} else {
EntityType<?> nmsType = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, MappingKeys1_20_4.ENTITY_TYPE__FACTORY.getMapping()); // EntityType.factory
Expand All @@ -92,6 +87,11 @@ public void spawn(Player player) {
return;
}

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}

NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,6 @@ public void create() {
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""), ClientInformation.createDefault());
((ServerPlayer) npc).gameProfile = gameProfile;

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}
} else {
EntityType<?> nmsType = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, MappingKeys1_20_6.ENTITY_TYPE__FACTORY.getMapping()); // EntityType.factory
Expand All @@ -95,6 +90,11 @@ public void spawn(Player player) {
return;
}

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}

NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ public void create() {
if (data.getType() == org.bukkit.entity.EntityType.PLAYER) {
npc = new ServerPlayer(minecraftServer, serverLevel, new GameProfile(uuid, ""), ClientInformation.createDefault());
((ServerPlayer) npc).gameProfile = gameProfile;

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}
} else {
EntityType<?> nmsType = BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(data.getType().getKey()));
EntityType.EntityFactory factory = (EntityType.EntityFactory) ReflectionUtils.getValue(nmsType, MappingKeys1_21.ENTITY_TYPE__FACTORY.getMapping()); // EntityType.factory
Expand All @@ -93,6 +88,11 @@ public void spawn(Player player) {
return;
}

if (data.getSkin() != null && data.getSkin().value() != null && data.getSkin().signature() != null) {
// sessionserver.mojang.com/session/minecraft/profile/<UUID>?unsigned=false
((ServerPlayer) npc).getGameProfile().getProperties().replaceValues("textures", ImmutableList.of(new Property("textures", data.getSkin().value(), data.getSkin().signature())));
}

NpcSpawnEvent spawnEvent = new NpcSpawnEvent(this, player);
spawnEvent.callEvent();
if (spawnEvent.isCancelled()) {
Expand Down

0 comments on commit d284315

Please sign in to comment.