From a34cfed3bf7a80fe8aa71f2e9f3d84d294a0f0d8 Mon Sep 17 00:00:00 2001 From: Matthew Messinger Date: Mon, 9 Jul 2018 11:53:22 -0400 Subject: [PATCH] Prevent preview textures from calling the skin server multiple times for each skin time. --- .../voxelmodpack/hdskins/HDSkinManager.java | 27 +--------- .../voxelmodpack/hdskins/PreviewTexture.java | 4 +- .../hdskins/PreviewTextureManager.java | 54 +++++++++++++++++++ .../hdskins/gui/EntityPlayerModel.java | 7 ++- .../hdskins/skins/LegacySkinServer.java | 18 +++++-- .../hdskins/skins/SkinServer.java | 6 +-- .../hdskins/skins/ValhallaSkinServer.java | 3 +- 7 files changed, 80 insertions(+), 39 deletions(-) create mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java index b65871b8..d0f92a93 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java @@ -223,31 +223,8 @@ public final class HDSkinManager implements IResourceManagerReloadListener { this.enabled = enabled; } - public static PreviewTexture getPreviewTexture(ResourceLocation skinResource, GameProfile profile, Type type, ResourceLocation def, @Nullable final SkinAvailableCallback callback) { - TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); - MinecraftProfileTexture url = INSTANCE.getGatewayServer().getPreviewTexture(type, profile).orElse(null); - if (url == null) - return null; - - IImageBuffer buffer = new ImageBufferDownloadHD(); - PreviewTexture skinTexture = new PreviewTexture(url.getMetadata("model"), url.getUrl(), def, type == Type.SKIN ? new IImageBuffer() { - @Override - @Nullable - public BufferedImage parseUserSkin(BufferedImage image) { - return buffer.parseUserSkin(image); - } - - @Override - public void skinAvailable() { - if (callback != null) { - callback.skinAvailable(type, skinResource, new MinecraftProfileTexture(url.getUrl(), Maps.newHashMap())); - } - } - } : null); - textureManager.loadTexture(skinResource, skinTexture); - - return skinTexture; - + public static PreviewTextureManager getPreviewTextureManager(GameProfile profile) { + return new PreviewTextureManager(INSTANCE.getGatewayServer().getPreviewTextures(profile)); } public void addClearListener(ISkinCacheClearListener listener) { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java index ee6ce18e..e5430ee2 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java @@ -12,10 +12,10 @@ public class PreviewTexture extends ThreadDownloadImageData { private String model; - public PreviewTexture(String model, String url, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) { + public PreviewTexture(@Nullable String model, String url, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) { super(null, url, fallbackTexture, imageBuffer); - this.model = model; + this.model = model == null ? "default" : model; } public boolean isTextureUploaded() { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java new file mode 100644 index 00000000..057fd56f --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java @@ -0,0 +1,54 @@ +package com.voxelmodpack.hdskins; + +import com.google.common.collect.Maps; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.IImageBuffer; +import net.minecraft.client.resources.SkinManager; +import net.minecraft.util.ResourceLocation; + +import java.awt.image.BufferedImage; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * Manager for fetching preview textures. This ensures that multiple calls + * to the skin server aren't done when fetching preview textures. + */ +public class PreviewTextureManager { + + private final Map textures; + + PreviewTextureManager(Map textures) { + this.textures = textures; + } + + @Nullable + public PreviewTexture getPreviewTexture(ResourceLocation location, MinecraftProfileTexture.Type type, ResourceLocation def, + @Nullable SkinManager.SkinAvailableCallback callback) { + if (!textures.containsKey(type)) { + return null; + } + MinecraftProfileTexture texture = textures.get(type); + IImageBuffer buffer = new ImageBufferDownloadHD(); + PreviewTexture skinTexture = new PreviewTexture(texture.getMetadata("model"), texture.getUrl(), def, + type == MinecraftProfileTexture.Type.SKIN ? new IImageBuffer() { + @Override + @Nullable + public BufferedImage parseUserSkin(BufferedImage image) { + return buffer.parseUserSkin(image); + } + + @Override + public void skinAvailable() { + if (callback != null) { + callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap())); + } + } + } : null); + Minecraft.getMinecraft().getTextureManager().loadTexture(location, skinTexture); + + return skinTexture; + } +} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java index 94b1b2db..f363b58f 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java @@ -8,6 +8,7 @@ import com.voxelmodpack.hdskins.DynamicTextureImage; import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.ImageBufferDownloadHD; import com.voxelmodpack.hdskins.PreviewTexture; +import com.voxelmodpack.hdskins.PreviewTextureManager; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.texture.TextureManager; @@ -76,8 +77,10 @@ public class EntityPlayerModel extends EntityLivingBase { this.textureManager.deleteTexture(this.remoteElytraResource); } - this.remoteSkinTexture = HDSkinManager.getPreviewTexture(this.remoteSkinResource, this.profile, Type.SKIN, getBlankSkin(), listener); - this.remoteElytraTexture = HDSkinManager.getPreviewTexture(this.remoteElytraResource, this.profile, Type.ELYTRA, getBlankElytra(), null); + PreviewTextureManager ptm = HDSkinManager.getPreviewTextureManager(this.profile); + + this.remoteSkinTexture = ptm.getPreviewTexture(this.remoteSkinResource, Type.SKIN, getBlankSkin(), listener); + this.remoteElytraTexture = ptm.getPreviewTexture(this.remoteElytraResource, Type.ELYTRA, getBlankElytra(), null); } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java index 766b4dac..c31a7c66 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; import java.net.URL; +import java.util.Collections; +import java.util.EnumMap; import java.util.Locale; import java.util.Map; import java.util.Optional; @@ -48,10 +50,15 @@ public class LegacySkinServer implements SkinServer { } @Override - public Optional getPreviewTexture(MinecraftProfileTexture.Type type, GameProfile profile) { - if (Strings.isNullOrEmpty(this.gateway)) - return Optional.empty(); - return Optional.of(new MinecraftProfileTexture(getPath(this.gateway, type, profile), null)); + public Map getPreviewTextures(GameProfile profile) { + if (Strings.isNullOrEmpty(this.gateway)) { + return Collections.emptyMap(); + } + Map map = new EnumMap<>(MinecraftProfileTexture.Type.class); + for (MinecraftProfileTexture.Type type : MinecraftProfileTexture.Type.values()) { + map.put(type, new MinecraftProfileTexture(getPath(gateway, type, profile), null)); + } + return map; } @Override @@ -101,8 +108,9 @@ public class LegacySkinServer implements SkinServer { Map data = image == null ? getClearData(session, type) : getUploadData(session, type, model, image); ThreadMultipartPostUpload upload = new ThreadMultipartPostUpload(this.gateway, data); String response = upload.uploadMultipart(); - if (response.startsWith("ERROR: ")) + if (response.startsWith("ERROR: ")) { response = response.substring(7); + } return new SkinUploadResponse(response.equalsIgnoreCase("OK"), response); }, HDSkinManager.skinUploadExecutor); diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java index 2aca2d0f..142e7840 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java @@ -7,6 +7,7 @@ import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import net.minecraft.util.Session; import java.net.URI; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -20,8 +21,8 @@ public interface SkinServer { Optional loadProfileData(GameProfile profile); - default Optional getPreviewTexture(MinecraftProfileTexture.Type type, GameProfile profile) { - return loadProfileData(profile).map(data -> data.getTextures().get(type)); + default Map getPreviewTextures(GameProfile profile) { + return loadProfileData(profile).map(MinecraftTexturesPayload::getTextures).orElse(Collections.emptyMap()); } CompletableFuture uploadSkin(Session session, @Nullable URI image, @@ -41,5 +42,4 @@ public interface SkinServer { } throw new IllegalArgumentException(); } - } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java index 7116fac8..e1e92470 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java @@ -43,7 +43,6 @@ import javax.annotation.Nullable; public class ValhallaSkinServer implements SkinServer { - @SuppressWarnings("unused") private final String baseURL; private final Gson gson = new GsonBuilder() .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()) @@ -51,7 +50,7 @@ public class ValhallaSkinServer implements SkinServer { private String accessToken; - public ValhallaSkinServer(String baseURL) { + private ValhallaSkinServer(String baseURL) { this.baseURL = baseURL; }