mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2025-02-13 16:24:23 +01:00
Rewrite a bulk of ThreadDownloadImageETag to be more modern.
This commit is contained in:
parent
1b8333e130
commit
fbd7528993
1 changed files with 79 additions and 63 deletions
|
@ -1,40 +1,45 @@
|
||||||
package com.voxelmodpack.hdskins;
|
package com.voxelmodpack.hdskins;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.voxelmodpack.hdskins.skins.MoreHttpResponses;
|
||||||
import com.google.common.io.Files;
|
|
||||||
import net.minecraft.client.renderer.IImageBuffer;
|
import net.minecraft.client.renderer.IImageBuffer;
|
||||||
import net.minecraft.client.renderer.texture.SimpleTexture;
|
import net.minecraft.client.renderer.texture.SimpleTexture;
|
||||||
import net.minecraft.client.renderer.texture.TextureUtil;
|
import net.minecraft.client.renderer.texture.TextureUtil;
|
||||||
import net.minecraft.client.resources.IResourceManager;
|
import net.minecraft.client.resources.IResourceManager;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHeaders;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.client.HttpClient;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.client.methods.HttpHead;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.imageio.ImageIO;
|
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 {
|
public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private static final AtomicInteger THREAD_ID = new AtomicInteger(0);
|
private static final AtomicInteger THREAD_ID = new AtomicInteger(0);
|
||||||
|
private static CloseableHttpClient client = HttpClients.createSystem();
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final File cacheFile;
|
private final Path cacheFile;
|
||||||
private final File eTagFile;
|
private final Path eTagFile;
|
||||||
private final String imageUrl;
|
private final String imageUrl;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final IImageBuffer imageBuffer;
|
private final IImageBuffer imageBuffer;
|
||||||
|
@ -47,8 +52,8 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
|
|
||||||
public ThreadDownloadImageETag(@Nonnull File cacheFileIn, String imageUrlIn, ResourceLocation defLocation, @Nullable IImageBuffer imageBufferIn) {
|
public ThreadDownloadImageETag(@Nonnull File cacheFileIn, String imageUrlIn, ResourceLocation defLocation, @Nullable IImageBuffer imageBufferIn) {
|
||||||
super(defLocation);
|
super(defLocation);
|
||||||
this.cacheFile = cacheFileIn;
|
this.cacheFile = cacheFileIn.toPath();
|
||||||
this.eTagFile = new File(cacheFile.getParentFile(), cacheFile.getName() + ".etag");
|
this.eTagFile = cacheFile.resolveSibling(cacheFile.getFileName() + ".etag");
|
||||||
this.imageUrl = imageUrlIn;
|
this.imageUrl = imageUrlIn;
|
||||||
this.imageBuffer = imageBufferIn;
|
this.imageBuffer = imageBufferIn;
|
||||||
}
|
}
|
||||||
|
@ -66,6 +71,7 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getGlTextureId() {
|
public int getGlTextureId() {
|
||||||
this.checkTextureUploaded();
|
this.checkTextureUploaded();
|
||||||
return super.getGlTextureId();
|
return super.getGlTextureId();
|
||||||
|
@ -84,6 +90,7 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
return bufferedImage;
|
return bufferedImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void loadTexture(IResourceManager resourceManager) throws IOException {
|
public void loadTexture(IResourceManager resourceManager) throws IOException {
|
||||||
if (this.bufferedImage == null && this.textureLocation != null) {
|
if (this.bufferedImage == null && this.textureLocation != null) {
|
||||||
super.loadTexture(resourceManager);
|
super.loadTexture(resourceManager);
|
||||||
|
@ -97,66 +104,76 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadTexture() {
|
private void loadTexture() {
|
||||||
HttpResponse response = null;
|
switch(checkLocalCache()) {
|
||||||
try {
|
case GONE:
|
||||||
HttpClient client = HttpClientBuilder.create().build();
|
|
||||||
response = client.execute(new HttpGet(imageUrl));
|
|
||||||
int status = response.getStatusLine().getStatusCode();
|
|
||||||
if (status == HttpStatus.SC_NOT_FOUND) {
|
|
||||||
// delete the cache files in case we can't connect in the future
|
|
||||||
clearCache();
|
clearCache();
|
||||||
} else if (checkETag(response)) {
|
break;
|
||||||
|
case OK:
|
||||||
|
case NOPE:
|
||||||
LOGGER.debug("Loading http texture from local cache ({})", cacheFile);
|
LOGGER.debug("Loading http texture from local cache ({})", cacheFile);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// e-tag check passed. Load the local file
|
// e-tag check passed. Load the local file
|
||||||
setLocalCache();
|
setLocalCache();
|
||||||
} catch (IOException ioexception) {
|
break;
|
||||||
|
} catch (IOException e) {
|
||||||
// Nope. Local cache is corrupt. Re-download it.
|
// Nope. Local cache is corrupt. Re-download it.
|
||||||
LOGGER.error("Couldn't load skin {}", cacheFile, ioexception);
|
// fallthrough to load from network
|
||||||
loadTextureFromServer(response);
|
LOGGER.error("Couldn't load skin {}", cacheFile, e);
|
||||||
}
|
}
|
||||||
} else {
|
case OUTDATED:
|
||||||
// there's an updated file. Download it again.
|
loadTextureFromServer();
|
||||||
loadTextureFromServer(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
|
||||||
// connection failed
|
|
||||||
if (cacheFile.isFile()) {
|
|
||||||
try {
|
|
||||||
// try to load from cache anyway
|
|
||||||
setLocalCache();
|
|
||||||
return;
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOGGER.error("Couldn't load skin {} ", imageUrl, e);
|
|
||||||
} finally {
|
|
||||||
if (response != null)
|
|
||||||
EntityUtils.consumeQuietly(response.getEntity());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setLocalCache() throws IOException {
|
private void setLocalCache() throws IOException {
|
||||||
if (cacheFile.isFile()) {
|
if (Files.isRegularFile(cacheFile)) {
|
||||||
BufferedImage image = ImageIO.read(cacheFile);
|
try (InputStream in = Files.newInputStream(cacheFile)) {
|
||||||
if (imageBuffer != null) {
|
BufferedImage image = ImageIO.read(in);
|
||||||
image = imageBuffer.parseUserSkin(image);
|
if (imageBuffer != null) {
|
||||||
|
image = imageBuffer.parseUserSkin(image);
|
||||||
|
}
|
||||||
|
setBufferedImage(image);
|
||||||
}
|
}
|
||||||
setBufferedImage(image);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearCache() {
|
private void clearCache() {
|
||||||
FileUtils.deleteQuietly(this.cacheFile);
|
try {
|
||||||
FileUtils.deleteQuietly(this.eTagFile);
|
Files.deleteIfExists(this.cacheFile);
|
||||||
|
Files.deleteIfExists(this.eTagFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum State {
|
||||||
|
OUTDATED,
|
||||||
|
GONE,
|
||||||
|
NOPE,
|
||||||
|
OK
|
||||||
|
}
|
||||||
|
|
||||||
|
private State checkLocalCache() {
|
||||||
|
try (CloseableHttpResponse response = client.execute(new HttpHead(imageUrl))) {
|
||||||
|
int code = response.getStatusLine().getStatusCode();
|
||||||
|
if (code == HttpStatus.SC_NOT_FOUND) {
|
||||||
|
return State.GONE;
|
||||||
|
}
|
||||||
|
if (code != HttpStatus.SC_OK) {
|
||||||
|
return State.NOPE;
|
||||||
|
}
|
||||||
|
return checkETag(response) ? State.OK : State.OUTDATED;
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error("Couldn't load skin {} ", imageUrl, e);
|
||||||
|
return State.NOPE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkETag(HttpResponse response) {
|
private boolean checkETag(HttpResponse response) {
|
||||||
try {
|
try {
|
||||||
if (cacheFile.isFile()) {
|
if (Files.isRegularFile(cacheFile)) {
|
||||||
String localETag = Files.readFirstLine(eTagFile, Charsets.UTF_8);
|
String localETag = Files.lines(eTagFile).limit(1).findFirst().orElse("");
|
||||||
Header remoteETag = response.getFirstHeader(HttpHeaders.ETAG);
|
Header remoteETag = response.getFirstHeader(HttpHeaders.ETAG);
|
||||||
// true if no remote etag or does match
|
// true if no remote etag or does match
|
||||||
return remoteETag == null || localETag.equals(remoteETag.getValue());
|
return remoteETag == null || localETag.equals(remoteETag.getValue());
|
||||||
|
@ -168,20 +185,19 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadTextureFromServer(HttpResponse response) {
|
private void loadTextureFromServer() {
|
||||||
LOGGER.debug("Downloading http texture from {} to {}", imageUrl, cacheFile);
|
LOGGER.debug("Downloading http texture from {} to {}", imageUrl, cacheFile);
|
||||||
try {
|
try (MoreHttpResponses resp = MoreHttpResponses.execute(client, new HttpGet(imageUrl))) {
|
||||||
if (response.getStatusLine().getStatusCode() / 100 == 2) {
|
if (resp.ok()) {
|
||||||
BufferedImage bufferedimage;
|
|
||||||
|
|
||||||
// write the image to disk
|
// write the image to disk
|
||||||
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), cacheFile);
|
Files.copy(resp.getInputStream(), cacheFile);
|
||||||
bufferedimage = ImageIO.read(cacheFile);
|
|
||||||
|
BufferedImage bufferedimage = ImageIO.read(Files.newInputStream(cacheFile));
|
||||||
|
|
||||||
// maybe write the etag to disk
|
// maybe write the etag to disk
|
||||||
Header eTag = response.getFirstHeader(HttpHeaders.ETAG);
|
Header eTag = resp.getResponse().getFirstHeader(HttpHeaders.ETAG);
|
||||||
if (eTag != null) {
|
if (eTag != null) {
|
||||||
FileUtils.write(eTagFile, eTag.getValue(), Charsets.UTF_8);
|
Files.write(eTagFile, Collections.singleton(eTag.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageBuffer != null) {
|
if (imageBuffer != null) {
|
||||||
|
|
Loading…
Reference in a new issue