From 60f06415a290a659b5c8a56b1d9f879bbea91d10 Mon Sep 17 00:00:00 2001 From: syeyoung Date: Sat, 24 Apr 2021 17:51:21 +0900 Subject: commit #2 - YAY PARTY KCIKER!!@!@! --- .../impl/party/FeatureViewPlayerOnJoin.java | 164 +++++++++++++++++++-- .../features/impl/party/api/ApiFetchur.java | 136 ++++++++++++++--- .../features/impl/party/api/CachedData.java | 11 ++ .../features/impl/party/api/SkinFetchur.java | 71 +++++++++ 4 files changed, 344 insertions(+), 38 deletions(-) create mode 100644 src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/CachedData.java create mode 100644 src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/SkinFetchur.java (limited to 'src/main/java/kr') diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureViewPlayerOnJoin.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureViewPlayerOnJoin.java index f7e2f020..ceaaec84 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureViewPlayerOnJoin.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/FeatureViewPlayerOnJoin.java @@ -1,25 +1,37 @@ package kr.syeyoung.dungeonsguide.features.impl.party; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; import io.github.moulberry.hychat.HyChat; import io.github.moulberry.hychat.chat.ChatManager; import io.github.moulberry.hychat.gui.GuiChatBox; +import kr.syeyoung.dungeonsguide.config.guiconfig.FeatureEditPane; import kr.syeyoung.dungeonsguide.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.features.SimpleFeature; import kr.syeyoung.dungeonsguide.features.impl.party.api.ApiFetchur; import kr.syeyoung.dungeonsguide.features.impl.party.api.PlayerProfile; +import kr.syeyoung.dungeonsguide.features.impl.party.api.SkinFetchur; import kr.syeyoung.dungeonsguide.features.listener.ChatListener; import kr.syeyoung.dungeonsguide.features.listener.GuiPostRenderListener; import kr.syeyoung.dungeonsguide.gui.MPanel; import lombok.Getter; +import lombok.Setter; import lombok.SneakyThrows; import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.entity.EntityOtherPlayerMP; import net.minecraft.client.gui.*; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.client.resources.SkinManager; import net.minecraft.event.HoverEvent; -import net.minecraft.util.ChatComponentStyle; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.ChatStyle; -import net.minecraft.util.IChatComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.util.*; +import net.minecraft.world.World; import net.minecraftforge.client.event.ClientChatReceivedEvent; import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.fml.common.Loader; @@ -27,6 +39,7 @@ import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import java.awt.*; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.ExecutionException; @@ -41,12 +54,18 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen private Rectangle popupRect; private String lastuid; // actually current uid private Future> profileFuture; + private Future> gfFuture; + private Future skinFuture; + private FakePlayer fakePlayer; @SneakyThrows @Override public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) { if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChat)) { popupRect = null; profileFuture = null; + gfFuture = null; + skinFuture= null; + fakePlayer= null; return; } ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); @@ -65,18 +84,24 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen popupRect = null; profileFuture = null; lastuid = null; + gfFuture = null; + skinFuture= null; + fakePlayer= null; } if (uid != null && !uid.equals(lastuid) && (popupRect==null || !popupRect.contains(mouseX, mouseY))) { popupRect = null; profileFuture = null; + gfFuture = null; + skinFuture= null; + fakePlayer= null; lastuid = uid; } if (lastuid == null) return; if (popupRect == null) { - popupRect = new Rectangle(mouseX, mouseY, 100, 200); + popupRect = new Rectangle(mouseX, mouseY, 150, 200); if (popupRect.y + popupRect.height > scaledResolution.getScaledHeight()) { popupRect.y -= popupRect.y + popupRect.height - scaledResolution.getScaledHeight(); } @@ -86,25 +111,96 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen profileFuture = ApiFetchur.fetchMostRecentProfileAsync(lastuid, FeatureRegistry.PARTYKICKER_APIKEY.getAPIKey()); } - MPanel.clip(scaledResolution, popupRect.x, popupRect.y, popupRect.width, popupRect.height); + if (gfFuture == null) { + gfFuture = ApiFetchur.getSkinGameProfileByUUIDAsync(lastuid); + } + if (skinFuture == null && gfFuture.isDone()) { + skinFuture = SkinFetchur.getSkinSet(gfFuture.get().orElse(null)); + } + + if (fakePlayer == null && skinFuture != null && profileFuture != null && skinFuture.isDone() && profileFuture.isDone()) { + fakePlayer = new FakePlayer(gfFuture.get().orElse(null), skinFuture.get(), profileFuture.get().orElse(null)); + } + + + render(popupRect, scaledResolution, mouseX, mouseY, profileFuture.isDone() ? profileFuture.get() : null); + } + + public void render(Rectangle popupRect, ScaledResolution scaledResolution, int mouseX, int mouseY, Optional playerProfile) { - GL11.glEnable(GL11.GL_SCISSOR_TEST); GlStateManager.pushMatrix(); GlStateManager.translate(popupRect.x, popupRect.y, 0); Gui.drawRect(0,0, popupRect.width, popupRect.height, 0xFF000000); - System.out.println(lastuid + " - "+uid); - if (!profileFuture.isDone()) { + Gui.drawRect(1,1, popupRect.width-1, popupRect.height-1, 0xFFAAAAAA); + if (playerProfile == null) { Minecraft.getMinecraft().fontRendererObj.drawString("Fetching data...", 5,5, 0xFFFFFFFF); - } else { - Optional playerProfile = profileFuture.get(); - if (playerProfile.isPresent()) { - Minecraft.getMinecraft().fontRendererObj.drawString(playerProfile.get().getMemberUID(), 5,5, 0xFFFFFFFF); - } else { - Minecraft.getMinecraft().fontRendererObj.drawString("User could not be found", 5,5, 0xFFFFFFFF); + GlStateManager.popMatrix(); + return; + } + if (!playerProfile.isPresent()) { + Minecraft.getMinecraft().fontRendererObj.drawString("User could not be found", 5,5, 0xFFFFFFFF); + GlStateManager.popMatrix(); + return; + } + + + GL11.glEnable(GL11.GL_SCISSOR_TEST); + MPanel.clip(scaledResolution, popupRect.x, popupRect.y, popupRect.width, popupRect.height); + Gui.drawRect(0,0, 80, popupRect.height-40, 0xFF000000); + Gui.drawRect(1,1, 79, popupRect.height-41, 0xFF444444); + GlStateManager.color(1, 1, 1, 1.0F); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (fakePlayer != null) { + GuiInventory.drawEntityOnScreen(40, 150, 60, -(mouseX - popupRect.x - 75), 0, fakePlayer); + fr.drawString(fakePlayer.getName(), (80 - fr.getStringWidth(fakePlayer.getName())) / 2, 15, 0xFFEFFF00); + + int relX = mouseX - popupRect.x; + int relY = mouseY - popupRect.y; + ItemStack toHover = null; + System.out.println(relX + " , "+relY); + if (relX > 5 && relX < 75) { + if (33<=relY && relY <= 66) { + toHover = fakePlayer.getInventory()[3]; + } else if (66 <= relY && relY <= 108) { + toHover = fakePlayer.getInventory()[2]; + } else if (108 <= relY && relY <= 130) { + toHover = fakePlayer.getInventory()[1]; + } else if (130 <= relY && relY <= 154) { + toHover = fakePlayer.getInventory()[0]; + } } + + if (toHover != null) { + List list = toHover.getTooltip(Minecraft.getMinecraft().thePlayer, Minecraft.getMinecraft().gameSettings.advancedItemTooltips); + + for (int i = 0; i < list.size(); ++i) + { + if (i == 0) + { + list.set(i, toHover.getRarity().rarityColor + (String)list.get(i)); + } + else + { + list.set(i, EnumChatFormatting.GRAY + (String)list.get(i)); + } + } + + FontRenderer font = toHover.getItem().getFontRenderer(toHover); + System.out.println(list); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + FontRenderer theRenderer = (font == null ? fr : font); + int minY = scaledResolution.getScaledHeight() - (list.size()+4) * theRenderer.FONT_HEIGHT - popupRect.y; + + FeatureEditPane.drawHoveringText(list,relX, Math.min(minY, relY), theRenderer); + GL11.glEnable(GL11.GL_SCISSOR_TEST); + } + } else { + fr.drawString("Loading", 5,35, 0xFFEFFF00); } - GlStateManager.popMatrix(); + GL11.glDisable(GL11.GL_SCISSOR_TEST); + GlStateManager.popMatrix(); // 33 66 108 130 154 // 5 75 } public IChatComponent getHoveredComponent(ScaledResolution scaledResolution) { @@ -160,4 +256,40 @@ public class FeatureViewPlayerOnJoin extends SimpleFeature implements GuiPostRen return cached; } } + + public static class FakePlayer extends EntityOtherPlayerMP { + @Setter + @Getter + private PlayerProfile skyblockProfile; + private SkinFetchur.SkinSet skinSet; + private PlayerProfile.Armor armor; + private FakePlayer(World w) { + super(w, null); + throw new UnsupportedOperationException("what"); + } + public FakePlayer(GameProfile playerProfile, SkinFetchur.SkinSet skinSet, PlayerProfile skyblockProfile) { + super(Minecraft.getMinecraft().theWorld, playerProfile); + this.skyblockProfile = skyblockProfile; + this.skinSet = skinSet; + armor= skyblockProfile.getCurrentArmor(); + this.inventory.armorInventory = skyblockProfile.getCurrentArmor().getArmorSlots(); + } + + public String getSkinType() { + return this.skinSet == null ? DefaultPlayerSkin.getSkinType(getGameProfile().getId()) : this.skinSet.getSkinType(); + } + + public ResourceLocation getLocationSkin() { + return com.google.common.base.Objects.firstNonNull(skinSet.getSkinLoc(), DefaultPlayerSkin.getDefaultSkin(getGameProfile().getId())); + } + + public ResourceLocation getLocationCape() { + return skinSet.getCapeLoc(); + } + + @Override + public ItemStack[] getInventory() { + return this.inventory.armorInventory; + } + } } diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java index 00ede47d..adc15d43 100644 --- a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/ApiFetchur.java @@ -1,32 +1,32 @@ package kr.syeyoung.dungeonsguide.features.impl.party.api; import com.google.gson.*; +import com.mojang.authlib.GameProfile; import kr.syeyoung.dungeonsguide.utils.TextUtils; -import lombok.AllArgsConstructor; -import lombok.Data; +import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; -import org.apache.commons.io.IOUtils; +import scala.tools.cmd.Opt; import java.io.ByteArrayInputStream; -import java.io.DataInputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; -import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.*; public class ApiFetchur { private static final Gson gson = new Gson(); - private static final Map> playerProfileCache = new HashMap<>(); - private static final Map> nicknameToUID = new HashMap<>(); + private static final Map> playerProfileCache = new ConcurrentHashMap<>(); + private static final Map> nicknameToUID = new ConcurrentHashMap<>(); + private static final Map> UIDtoNickname = new ConcurrentHashMap<>(); + private static final Map> UIDtoGameProfile = new ConcurrentHashMap<>(); + private static final ExecutorService ex = Executors.newFixedThreadPool(4); public static void purgeCache() { @@ -34,28 +34,71 @@ public class ApiFetchur { nicknameToUID.clear(); } - @Data - @AllArgsConstructor - public static class CachedData { - private final long expire; - private final T data; - } - public static JsonObject getJson(String url) throws IOException { URLConnection connection = new URL(url).openConnection(); connection.setConnectTimeout(10000); connection.setReadTimeout(10000); return gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonObject.class); } + public static JsonArray getJsonArr(String url) throws IOException { + URLConnection connection = new URL(url).openConnection(); + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + return gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonArray.class); + } + private static final Map>> completableFutureMap4 = new ConcurrentHashMap<>(); + public static CompletableFuture> getSkinGameProfileByUUIDAsync(String uid) { + if (UIDtoGameProfile.containsKey(uid)) { + CachedData cachedData = UIDtoGameProfile.get(uid); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); + } + UIDtoGameProfile.remove(uid); + } + if (completableFutureMap4.containsKey(uid)) return completableFutureMap4.get(uid); + + CompletableFuture> completableFuture = new CompletableFuture<>(); + fetchNicknameAsync(uid).thenAccept(nick -> { + if (!nick.isPresent()) { + completableFuture.complete(Optional.empty()); + return; + } + ex.submit(() -> { + try { + Optional playerProfile = getSkinGameProfileByUUID(uid,nick.get()); + UIDtoGameProfile.put(uid, new CachedData(System.currentTimeMillis()+1000*60*30, playerProfile.orElse(null))); + completableFuture.complete(playerProfile); + completableFutureMap4.remove(uid); + return; + } catch (IOException e) { + e.printStackTrace(); + } + completableFuture.complete(Optional.empty()); + completableFutureMap4.remove(uid); + }); + }); + completableFutureMap4.put(uid, completableFuture); + return completableFuture; + } + + public static Optional getSkinGameProfileByUUID(String uid, String nickname) throws IOException { + GameProfile gameProfile = new GameProfile(UUID.fromString(uid), nickname); + GameProfile newProf = Minecraft.getMinecraft().getSessionService().fillProfileProperties(gameProfile, true); + return newProf == gameProfile ? Optional.empty() : Optional.of(newProf); + } + + + private static final Map>> completableFutureMap = new ConcurrentHashMap<>(); public static CompletableFuture> fetchMostRecentProfileAsync(String uid, String apiKey) { if (playerProfileCache.containsKey(uid)) { CachedData cachedData = playerProfileCache.get(uid); - if (cachedData.expire > System.currentTimeMillis()) { - return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.data)); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); } playerProfileCache.remove(uid); } + if (completableFutureMap.containsKey(uid)) return completableFutureMap.get(uid); CompletableFuture> completableFuture = new CompletableFuture<>(); ex.submit(() -> { @@ -63,24 +106,62 @@ public class ApiFetchur { Optional playerProfile = fetchMostRecentProfile(uid, apiKey); playerProfileCache.put(uid, new CachedData(System.currentTimeMillis()+1000*60*30, playerProfile.orElse(null))); completableFuture.complete(playerProfile); + completableFutureMap.remove(uid); return; } catch (IOException e) { e.printStackTrace(); } - playerProfileCache.put(uid, new CachedData(System.currentTimeMillis()+1000*60*30, null)); completableFuture.complete(Optional.empty()); + completableFutureMap.remove(uid); }); + completableFutureMap.put(uid, completableFuture); return completableFuture; } + private static final Map>> completableFutureMap3 = new ConcurrentHashMap<>(); + public static CompletableFuture> fetchNicknameAsync(String uid) { + if (UIDtoNickname.containsKey(uid)) { + CachedData cachedData = UIDtoNickname.get(uid); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); + } + UIDtoNickname.remove(uid); + } + if (completableFutureMap3.containsKey(uid)) return completableFutureMap3.get(uid); + + + CompletableFuture> completableFuture = new CompletableFuture<>(); + + ex.submit(() -> { + try { + Optional playerProfile = fetchNickname(uid); + UIDtoNickname.put(uid, new CachedData(System.currentTimeMillis()+1000*60*60*12,playerProfile.orElse(null))); + if (playerProfile.isPresent()) + nicknameToUID.put(playerProfile.orElse(null), new CachedData<>(System.currentTimeMillis()+1000*60*60*12, uid)); + completableFuture.complete(playerProfile); + completableFutureMap3.remove(uid); + return; + } catch (IOException e) { + e.printStackTrace(); + } + completableFuture.complete(Optional.empty()); + completableFutureMap3.remove(uid); + }); + completableFutureMap3.put(uid, completableFuture); + + return completableFuture; + } + + private static final Map>> completableFutureMap2 = new ConcurrentHashMap<>(); public static CompletableFuture> fetchUUIDAsync(String nickname) { if (nicknameToUID.containsKey(nickname)) { CachedData cachedData = nicknameToUID.get(nickname); - if (cachedData.expire > System.currentTimeMillis()) { - return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.data)); + if (cachedData.getExpire() > System.currentTimeMillis()) { + return CompletableFuture.completedFuture(Optional.ofNullable(cachedData.getData())); } nicknameToUID.remove(nickname); } + if (completableFutureMap2.containsKey(nickname)) return completableFutureMap2.get(nickname); CompletableFuture> completableFuture = new CompletableFuture<>(); @@ -88,15 +169,20 @@ public class ApiFetchur { ex.submit(() -> { try { Optional playerProfile = fetchUUID(nickname); - nicknameToUID.put(nickname, new CachedData(System.currentTimeMillis()+1000*60*60,playerProfile.orElse(null))); + nicknameToUID.put(nickname, new CachedData(System.currentTimeMillis()+1000*60*60*12,playerProfile.orElse(null))); + if (playerProfile.isPresent()) + UIDtoNickname.put(playerProfile.orElse(null), new CachedData<>(System.currentTimeMillis()+1000*60*60*12, nickname)); + completableFuture.complete(playerProfile); + completableFutureMap2.remove(nickname); return; } catch (IOException e) { e.printStackTrace(); } - nicknameToUID.put(nickname, new CachedData(System.currentTimeMillis()+1000*60*30, null)); completableFuture.complete(Optional.empty()); + completableFutureMap2.remove(nickname); }); + completableFutureMap2.put(nickname, completableFuture); return completableFuture; } @@ -106,6 +192,12 @@ public class ApiFetchur { if (json.has("error")) return Optional.empty(); return Optional.of(TextUtils.insertDashUUID(json.get("id").getAsString())); } + public static Optional fetchNickname(String uuid) throws IOException { + try { + JsonArray json = getJsonArr("https://api.mojang.com/user/profiles/" + uuid.replace("-", "") + "/names"); + return Optional.of(json.get(json.size()-1).getAsJsonObject().get("name").getAsString()); + } catch (Exception e) {return Optional.empty();} + } public static List fetchPlayerProfiles(String uid, String apiKey) throws IOException { JsonObject json = getJson("https://api.hypixel.net/skyblock/profiles?uuid="+uid+"&key="+apiKey); diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/CachedData.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/CachedData.java new file mode 100644 index 00000000..2d5e2bc7 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/CachedData.java @@ -0,0 +1,11 @@ +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class CachedData { + private final long expire; + private final T data; +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/SkinFetchur.java b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/SkinFetchur.java new file mode 100644 index 00000000..977aec47 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/features/impl/party/api/SkinFetchur.java @@ -0,0 +1,71 @@ +package kr.syeyoung.dungeonsguide.features.impl.party.api; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.client.resources.SkinManager; +import net.minecraft.util.ResourceLocation; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +public class SkinFetchur { + + private static Map> skinSetMap = new ConcurrentHashMap<>(); + + private static Map> currentReq = new HashMap<>(); + + public static CompletableFuture getSkinSet(GameProfile gameProfile) { + if (gameProfile == null) { + return CompletableFuture.completedFuture(new SkinSet(DefaultPlayerSkin.getDefaultSkinLegacy(), null, "default")); + } + if (skinSetMap.containsKey(gameProfile.getId().toString())) { + CachedData ss = skinSetMap.get(gameProfile.getId().toString()); + if (ss.getExpire() > System.currentTimeMillis()) + CompletableFuture.completedFuture(skinSetMap.get(gameProfile.getId().toString()).getData()); + skinSetMap.remove(gameProfile.getId().toString()); + } + if (currentReq.containsKey(gameProfile.getId().toString())) + return currentReq.get(gameProfile.getId().toString()); + + SkinSet skinSet = new SkinSet(); + CompletableFuture skinSet2 = new CompletableFuture<>(); + currentReq.put(gameProfile.getId().toString(), skinSet2); + Minecraft.getMinecraft().getSkinManager().loadProfileTextures(gameProfile, new SkinManager.SkinAvailableCallback() { + public void skinAvailable(MinecraftProfileTexture.Type p_180521_1_, ResourceLocation location, MinecraftProfileTexture profileTexture) { + switch (p_180521_1_) { + case SKIN: + skinSet.setSkinLoc(location); + skinSet.setSkinType(profileTexture.getMetadata("model")); + if (skinSet.getSkinType() == null) { + skinSet.setSkinType("default"); + } + skinSet2.complete(skinSet); + skinSetMap.put(gameProfile.getId().toString(), new CachedData<>(System.currentTimeMillis() + 1000*60*60*3, skinSet)); + currentReq.get(gameProfile.getId().toString()); + break; + case CAPE: + skinSet.setCapeLoc(location); + } + } + }, true); + + return skinSet2; + } + + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class SkinSet { + private ResourceLocation skinLoc; + private ResourceLocation capeLoc; + private String skinType; + } +} -- cgit