mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2024-11-22 12:37:59 +01:00
Use an etag for caching instead of md5.
Release for 1.11.2
This commit is contained in:
parent
50e29823d7
commit
e87c550f2b
7 changed files with 183 additions and 47 deletions
|
@ -24,7 +24,7 @@ apply plugin: 'net.minecraftforge.gradle.liteloader'
|
||||||
apply plugin: 'org.spongepowered.mixin'
|
apply plugin: 'org.spongepowered.mixin'
|
||||||
|
|
||||||
group = 'com.minelittlepony'
|
group = 'com.minelittlepony'
|
||||||
version = '1.11.2.0-SNAPSHOT'
|
version = '1.11.2.0'
|
||||||
description = 'Mine Little Pony'
|
description = 'Mine Little Pony'
|
||||||
|
|
||||||
targetCompatibility = 1.8
|
targetCompatibility = 1.8
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#Build Number for ANT. Do not edit!
|
#Build Number for ANT. Do not edit!
|
||||||
#Sat Dec 24 04:16:32 EST 2016
|
#Tue Dec 27 18:55:42 EST 2016
|
||||||
build.number=295
|
build.number=300
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package com.voxelmodpack.hdskins;
|
|
||||||
|
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Profile texture with a custom hash which is not the file name.
|
|
||||||
*/
|
|
||||||
public class HDProfileTexture extends MinecraftProfileTexture {
|
|
||||||
|
|
||||||
private String hash;
|
|
||||||
|
|
||||||
public HDProfileTexture(String url, @Nullable String hash, Map<String, String> metadata) {
|
|
||||||
super(url, metadata);
|
|
||||||
this.hash = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHash() {
|
|
||||||
return this.hash == null ? super.getHash() : this.hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,12 +1,10 @@
|
||||||
package com.voxelmodpack.hdskins;
|
package com.voxelmodpack.hdskins;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.io.Resources;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
@ -21,7 +19,6 @@ import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
|
||||||
import com.voxelmodpack.hdskins.resource.SkinResourceManager;
|
import com.voxelmodpack.hdskins.resource.SkinResourceManager;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.IImageBuffer;
|
import net.minecraft.client.renderer.IImageBuffer;
|
||||||
import net.minecraft.client.renderer.ThreadDownloadImageData;
|
|
||||||
import net.minecraft.client.renderer.texture.ITextureObject;
|
import net.minecraft.client.renderer.texture.ITextureObject;
|
||||||
import net.minecraft.client.renderer.texture.TextureManager;
|
import net.minecraft.client.renderer.texture.TextureManager;
|
||||||
import net.minecraft.client.resources.DefaultPlayerSkin;
|
import net.minecraft.client.resources.DefaultPlayerSkin;
|
||||||
|
@ -38,7 +35,6 @@ import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
@ -127,9 +123,11 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
|
||||||
|
|
||||||
String skinDir = type.toString().toLowerCase() + "s/";
|
String skinDir = type.toString().toLowerCase() + "s/";
|
||||||
final ResourceLocation skin = new ResourceLocation("hdskins", skinDir + texture.getHash());
|
final ResourceLocation skin = new ResourceLocation("hdskins", skinDir + texture.getHash());
|
||||||
File file2 = new File(LiteLoader.getAssetsDirectory(), "skins/" + skinDir + texture.getHash().substring(0, 2) + "/" + texture.getHash());
|
File file2 = new File(LiteLoader.getAssetsDirectory(), "hd/" + skinDir + texture.getHash().substring(0, 2) + "/" + texture.getHash());
|
||||||
|
|
||||||
final IImageBuffer imagebufferdownload = type == Type.SKIN ? new ImageBufferDownloadHD() : null;
|
final IImageBuffer imagebufferdownload = type == Type.SKIN ? new ImageBufferDownloadHD() : null;
|
||||||
ThreadDownloadImageData threaddownloadimagedata = new ThreadDownloadImageData(file2, texture.getUrl(),
|
|
||||||
|
ITextureObject texObject = new ThreadDownloadImageETag(file2, texture.getUrl(),
|
||||||
DefaultPlayerSkin.getDefaultSkinLegacy(),
|
DefaultPlayerSkin.getDefaultSkinLegacy(),
|
||||||
new IImageBuffer() {
|
new IImageBuffer() {
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -152,7 +150,7 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
|
||||||
});
|
});
|
||||||
|
|
||||||
// schedule texture loading on the main thread.
|
// schedule texture loading on the main thread.
|
||||||
TextureLoader.loadTexture(skin, threaddownloadimagedata);
|
TextureLoader.loadTexture(skin, texObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,9 +169,8 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
|
||||||
ImmutableMap.Builder<Type, MinecraftProfileTexture> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<Type, MinecraftProfileTexture> builder = ImmutableMap.builder();
|
||||||
for (Type type : Type.values()) {
|
for (Type type : Type.values()) {
|
||||||
String url = getCustomTextureURLForId(type, uuid);
|
String url = getCustomTextureURLForId(type, uuid);
|
||||||
String hash = getTextureHash(type, uuid);
|
|
||||||
|
|
||||||
builder.put(type, new HDProfileTexture(url, hash, null));
|
builder.put(type, new MinecraftProfileTexture(url, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Type, MinecraftProfileTexture> textures = builder.build();
|
Map<Type, MinecraftProfileTexture> textures = builder.build();
|
||||||
|
@ -224,15 +221,6 @@ public final class HDSkinManager implements IResourceManagerReloadListener {
|
||||||
return getCustomTextureURLForId(type, uuid, false);
|
return getCustomTextureURLForId(type, uuid, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTextureHash(Type type, String uuid) {
|
|
||||||
try {
|
|
||||||
URL url = new URL(getCustomTextureURLForId(type, uuid) + ".md5");
|
|
||||||
return Resources.asCharSource(url, Charsets.UTF_8).readFirstLine();
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
package com.voxelmodpack.hdskins;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import net.minecraft.client.renderer.IImageBuffer;
|
||||||
|
import net.minecraft.client.renderer.texture.SimpleTexture;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureUtil;
|
||||||
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HttpHeaders;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
private static final AtomicInteger THREAD_ID = new AtomicInteger(0);
|
||||||
|
@Nonnull
|
||||||
|
private final File cacheFile;
|
||||||
|
private final File eTagFile;
|
||||||
|
private final String imageUrl;
|
||||||
|
@Nullable
|
||||||
|
private final IImageBuffer imageBuffer;
|
||||||
|
@Nullable
|
||||||
|
private BufferedImage bufferedImage;
|
||||||
|
@Nullable
|
||||||
|
private Thread imageThread;
|
||||||
|
private boolean textureUploaded;
|
||||||
|
|
||||||
|
public ThreadDownloadImageETag(@Nonnull File cacheFileIn, String imageUrlIn, ResourceLocation defLocation, @Nullable IImageBuffer imageBufferIn) {
|
||||||
|
super(defLocation);
|
||||||
|
this.cacheFile = cacheFileIn;
|
||||||
|
this.eTagFile = new File(cacheFile.getParentFile(), cacheFile.getName() + ".etag");
|
||||||
|
this.imageUrl = imageUrlIn;
|
||||||
|
this.imageBuffer = imageBufferIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTextureUploaded() {
|
||||||
|
if (!this.textureUploaded) {
|
||||||
|
if (this.bufferedImage != null) {
|
||||||
|
if (this.textureLocation != null) {
|
||||||
|
this.deleteGlTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureUtil.uploadTextureImage(super.getGlTextureId(), this.bufferedImage);
|
||||||
|
this.textureUploaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlTextureId() {
|
||||||
|
this.checkTextureUploaded();
|
||||||
|
return super.getGlTextureId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBufferedImage(BufferedImage bufferedImageIn) {
|
||||||
|
this.bufferedImage = bufferedImageIn;
|
||||||
|
|
||||||
|
if (this.imageBuffer != null) {
|
||||||
|
this.imageBuffer.skinAvailable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BufferedImage getBufferedImage() {
|
||||||
|
return bufferedImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadTexture(IResourceManager resourceManager) throws IOException {
|
||||||
|
if (this.bufferedImage == null && this.textureLocation != null) {
|
||||||
|
super.loadTexture(resourceManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.imageThread == null) {
|
||||||
|
loadTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadTexture() {
|
||||||
|
this.imageThread = new Thread("Texture Downloader #" + THREAD_ID.incrementAndGet()) {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
HttpResponse response = null;
|
||||||
|
try {
|
||||||
|
HttpClient client = HttpClientBuilder.create().build();
|
||||||
|
response = client.execute(new HttpGet(ThreadDownloadImageETag.this.imageUrl));
|
||||||
|
if (checkEtag(response)) {
|
||||||
|
LOGGER.debug("Loading http texture from local cache ({})", cacheFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
bufferedImage = ImageIO.read(cacheFile);
|
||||||
|
|
||||||
|
if (imageBuffer != null) {
|
||||||
|
setBufferedImage(imageBuffer.parseUserSkin(bufferedImage));
|
||||||
|
}
|
||||||
|
} catch (IOException ioexception) {
|
||||||
|
LOGGER.error("Couldn't load skin {}", cacheFile, ioexception);
|
||||||
|
loadTextureFromServer(response);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loadTextureFromServer(response);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error("Couldn't load skin {} ", imageUrl, e);
|
||||||
|
} finally {
|
||||||
|
if (response != null)
|
||||||
|
EntityUtils.consumeQuietly(response.getEntity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.imageThread.setDaemon(true);
|
||||||
|
this.imageThread.start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkEtag(HttpResponse response) {
|
||||||
|
try {
|
||||||
|
if (cacheFile.isFile()) {
|
||||||
|
String localEtag = Files.readFirstLine(eTagFile, Charsets.UTF_8);
|
||||||
|
Header remoteEtag = response.getFirstHeader(HttpHeaders.ETAG);
|
||||||
|
// true if no remote etag or does match
|
||||||
|
return remoteEtag == null || localEtag.equals(remoteEtag.getValue());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// it failed, so re-fetch.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void loadTextureFromServer(HttpResponse response) {
|
||||||
|
LOGGER.debug("Downloading http texture from {} to {}", imageUrl, cacheFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (response.getStatusLine().getStatusCode() / 100 == 2) {
|
||||||
|
BufferedImage bufferedimage;
|
||||||
|
|
||||||
|
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), cacheFile);
|
||||||
|
bufferedimage = ImageIO.read(cacheFile);
|
||||||
|
|
||||||
|
Header etag = response.getFirstHeader(HttpHeaders.ETAG);
|
||||||
|
if (etag != null) {
|
||||||
|
FileUtils.write(eTagFile, etag.getValue(), Charsets.UTF_8);
|
||||||
|
}
|
||||||
|
if (imageBuffer != null) {
|
||||||
|
bufferedimage = imageBuffer.parseUserSkin(bufferedimage);
|
||||||
|
}
|
||||||
|
|
||||||
|
setBufferedImage(bufferedimage);
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
LOGGER.error("Couldn\'t download http texture", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -83,7 +83,6 @@ public class MineLittlePony {
|
||||||
|
|
||||||
void postInit(Minecraft minecraft) {
|
void postInit(Minecraft minecraft) {
|
||||||
|
|
||||||
HDSkinManager.clearSkinCache();
|
|
||||||
HDSkinManager manager = HDSkinManager.INSTANCE;
|
HDSkinManager manager = HDSkinManager.INSTANCE;
|
||||||
manager.setSkinUrl(SKIN_SERVER_URL);
|
manager.setSkinUrl(SKIN_SERVER_URL);
|
||||||
manager.setGatewayURL(GATEWAY_URL);
|
manager.setGatewayURL(GATEWAY_URL);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.minelittlepony.model.PMAPI;
|
||||||
import com.minelittlepony.model.PlayerModel;
|
import com.minelittlepony.model.PlayerModel;
|
||||||
import com.minelittlepony.util.PonyFields;
|
import com.minelittlepony.util.PonyFields;
|
||||||
import com.voxelmodpack.hdskins.DynamicTextureImage;
|
import com.voxelmodpack.hdskins.DynamicTextureImage;
|
||||||
|
import com.voxelmodpack.hdskins.ThreadDownloadImageETag;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.entity.AbstractClientPlayer;
|
import net.minecraft.client.entity.AbstractClientPlayer;
|
||||||
import net.minecraft.client.renderer.ThreadDownloadImageData;
|
import net.minecraft.client.renderer.ThreadDownloadImageData;
|
||||||
|
@ -79,6 +80,8 @@ public class Pony {
|
||||||
MineLittlePony.logger.debug("Successfully reflected downloadedImage from texture object", e);
|
MineLittlePony.logger.debug("Successfully reflected downloadedImage from texture object", e);
|
||||||
// this.checkSkin(skinImage);
|
// this.checkSkin(skinImage);
|
||||||
}
|
}
|
||||||
|
} else if (e2 instanceof ThreadDownloadImageETag) {
|
||||||
|
skinImage = ((ThreadDownloadImageETag) e2).getBufferedImage();
|
||||||
} else if (e2 instanceof DynamicTextureImage) {
|
} else if (e2 instanceof DynamicTextureImage) {
|
||||||
skinImage = ((DynamicTextureImage) e2).getImage();
|
skinImage = ((DynamicTextureImage) e2).getImage();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue