Prevent preview textures from calling the skin server multiple times for each skin time.

This commit is contained in:
Matthew Messinger 2018-07-09 11:53:22 -04:00
parent abf27e13e1
commit a34cfed3bf
7 changed files with 80 additions and 39 deletions

View file

@ -223,31 +223,8 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
this.enabled = enabled; this.enabled = enabled;
} }
public static PreviewTexture getPreviewTexture(ResourceLocation skinResource, GameProfile profile, Type type, ResourceLocation def, @Nullable final SkinAvailableCallback callback) { public static PreviewTextureManager getPreviewTextureManager(GameProfile profile) {
TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); return new PreviewTextureManager(INSTANCE.getGatewayServer().getPreviewTextures(profile));
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 void addClearListener(ISkinCacheClearListener listener) { public void addClearListener(ISkinCacheClearListener listener) {

View file

@ -12,10 +12,10 @@ public class PreviewTexture extends ThreadDownloadImageData {
private String model; 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); super(null, url, fallbackTexture, imageBuffer);
this.model = model; this.model = model == null ? "default" : model;
} }
public boolean isTextureUploaded() { public boolean isTextureUploaded() {

View file

@ -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<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures;
PreviewTextureManager(Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> 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;
}
}

View file

@ -8,6 +8,7 @@ import com.voxelmodpack.hdskins.DynamicTextureImage;
import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.HDSkinManager;
import com.voxelmodpack.hdskins.ImageBufferDownloadHD; import com.voxelmodpack.hdskins.ImageBufferDownloadHD;
import com.voxelmodpack.hdskins.PreviewTexture; import com.voxelmodpack.hdskins.PreviewTexture;
import com.voxelmodpack.hdskins.PreviewTextureManager;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.texture.TextureManager;
@ -76,8 +77,10 @@ public class EntityPlayerModel extends EntityLivingBase {
this.textureManager.deleteTexture(this.remoteElytraResource); this.textureManager.deleteTexture(this.remoteElytraResource);
} }
this.remoteSkinTexture = HDSkinManager.getPreviewTexture(this.remoteSkinResource, this.profile, Type.SKIN, getBlankSkin(), listener); PreviewTextureManager ptm = HDSkinManager.getPreviewTextureManager(this.profile);
this.remoteElytraTexture = HDSkinManager.getPreviewTexture(this.remoteElytraResource, this.profile, Type.ELYTRA, getBlankElytra(), null);
this.remoteSkinTexture = ptm.getPreviewTexture(this.remoteSkinResource, Type.SKIN, getBlankSkin(), listener);
this.remoteElytraTexture = ptm.getPreviewTexture(this.remoteElytraResource, Type.ELYTRA, getBlankElytra(), null);
} }

View file

@ -20,6 +20,8 @@ import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -48,10 +50,15 @@ public class LegacySkinServer implements SkinServer {
} }
@Override @Override
public Optional<MinecraftProfileTexture> getPreviewTexture(MinecraftProfileTexture.Type type, GameProfile profile) { public Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getPreviewTextures(GameProfile profile) {
if (Strings.isNullOrEmpty(this.gateway)) if (Strings.isNullOrEmpty(this.gateway)) {
return Optional.empty(); return Collections.emptyMap();
return Optional.of(new MinecraftProfileTexture(getPath(this.gateway, type, profile), null)); }
Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> 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 @Override
@ -101,8 +108,9 @@ public class LegacySkinServer implements SkinServer {
Map<String, ?> data = image == null ? getClearData(session, type) : getUploadData(session, type, model, image); Map<String, ?> data = image == null ? getClearData(session, type) : getUploadData(session, type, model, image);
ThreadMultipartPostUpload upload = new ThreadMultipartPostUpload(this.gateway, data); ThreadMultipartPostUpload upload = new ThreadMultipartPostUpload(this.gateway, data);
String response = upload.uploadMultipart(); String response = upload.uploadMultipart();
if (response.startsWith("ERROR: ")) if (response.startsWith("ERROR: ")) {
response = response.substring(7); response = response.substring(7);
}
return new SkinUploadResponse(response.equalsIgnoreCase("OK"), response); return new SkinUploadResponse(response.equalsIgnoreCase("OK"), response);
}, HDSkinManager.skinUploadExecutor); }, HDSkinManager.skinUploadExecutor);

View file

@ -7,6 +7,7 @@ import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
import net.minecraft.util.Session; import net.minecraft.util.Session;
import java.net.URI; import java.net.URI;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -20,8 +21,8 @@ public interface SkinServer {
Optional<MinecraftTexturesPayload> loadProfileData(GameProfile profile); Optional<MinecraftTexturesPayload> loadProfileData(GameProfile profile);
default Optional<MinecraftProfileTexture> getPreviewTexture(MinecraftProfileTexture.Type type, GameProfile profile) { default Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getPreviewTextures(GameProfile profile) {
return loadProfileData(profile).map(data -> data.getTextures().get(type)); return loadProfileData(profile).map(MinecraftTexturesPayload::getTextures).orElse(Collections.emptyMap());
} }
CompletableFuture<SkinUploadResponse> uploadSkin(Session session, @Nullable URI image, CompletableFuture<SkinUploadResponse> uploadSkin(Session session, @Nullable URI image,
@ -41,5 +42,4 @@ public interface SkinServer {
} }
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
} }

View file

@ -43,7 +43,6 @@ import javax.annotation.Nullable;
public class ValhallaSkinServer implements SkinServer { public class ValhallaSkinServer implements SkinServer {
@SuppressWarnings("unused")
private final String baseURL; private final String baseURL;
private final Gson gson = new GsonBuilder() private final Gson gson = new GsonBuilder()
.registerTypeAdapter(UUID.class, new UUIDTypeAdapter()) .registerTypeAdapter(UUID.class, new UUIDTypeAdapter())
@ -51,7 +50,7 @@ public class ValhallaSkinServer implements SkinServer {
private String accessToken; private String accessToken;
public ValhallaSkinServer(String baseURL) { private ValhallaSkinServer(String baseURL) {
this.baseURL = baseURL; this.baseURL = baseURL;
} }