174 lines
7.1 KiB
Java
174 lines
7.1 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.logging.LogUtils
|
|
* org.slf4j.Logger
|
|
*/
|
|
package net.minecraft.client.renderer.texture;
|
|
|
|
import com.mojang.blaze3d.platform.NativeImage;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.UncheckedIOException;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.Proxy;
|
|
import java.net.URI;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.LinkOption;
|
|
import java.nio.file.OpenOption;
|
|
import java.nio.file.Path;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.Executor;
|
|
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
import net.minecraft.client.renderer.texture.TextureManager;
|
|
import net.minecraft.core.ClientAsset;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.util.ARGB;
|
|
import net.minecraft.util.FileUtil;
|
|
import net.minecraft.util.Util;
|
|
import org.slf4j.Logger;
|
|
|
|
public class SkinTextureDownloader {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final int SKIN_WIDTH = 64;
|
|
private static final int SKIN_HEIGHT = 64;
|
|
private static final int LEGACY_SKIN_HEIGHT = 32;
|
|
private final Proxy proxy;
|
|
private final TextureManager textureManager;
|
|
private final Executor mainThreadExecutor;
|
|
|
|
public SkinTextureDownloader(Proxy proxy, TextureManager textureManager, Executor mainThreadExecutor) {
|
|
this.proxy = proxy;
|
|
this.textureManager = textureManager;
|
|
this.mainThreadExecutor = mainThreadExecutor;
|
|
}
|
|
|
|
public CompletableFuture<ClientAsset.Texture> downloadAndRegisterSkin(Identifier textureId, Path localCopy, String url, boolean processLegacySkin) {
|
|
ClientAsset.DownloadedTexture texture = new ClientAsset.DownloadedTexture(textureId, url);
|
|
return CompletableFuture.supplyAsync(() -> {
|
|
NativeImage loadedSkin;
|
|
try {
|
|
loadedSkin = this.downloadSkin(localCopy, texture.url());
|
|
}
|
|
catch (IOException e) {
|
|
throw new UncheckedIOException(e);
|
|
}
|
|
return processLegacySkin ? SkinTextureDownloader.processLegacySkin(loadedSkin, texture.url()) : loadedSkin;
|
|
}, Util.nonCriticalIoPool().forName("downloadTexture")).thenCompose(fixedSkin -> this.registerTextureInManager(texture, (NativeImage)fixedSkin));
|
|
}
|
|
|
|
/*
|
|
* WARNING - Removed try catching itself - possible behaviour change.
|
|
*/
|
|
private NativeImage downloadSkin(Path localCopy, String url) throws IOException {
|
|
if (Files.isRegularFile(localCopy, new LinkOption[0])) {
|
|
LOGGER.debug("Loading HTTP texture from local cache ({})", (Object)localCopy);
|
|
try (InputStream inputStream = Files.newInputStream(localCopy, new OpenOption[0]);){
|
|
NativeImage nativeImage = NativeImage.read(inputStream);
|
|
return nativeImage;
|
|
}
|
|
}
|
|
HttpURLConnection connection = null;
|
|
LOGGER.debug("Downloading HTTP texture from {} to {}", (Object)url, (Object)localCopy);
|
|
URI uri = URI.create(url);
|
|
try {
|
|
connection = (HttpURLConnection)uri.toURL().openConnection(this.proxy);
|
|
connection.setDoInput(true);
|
|
connection.setDoOutput(false);
|
|
connection.connect();
|
|
int responseCode = connection.getResponseCode();
|
|
if (responseCode / 100 != 2) {
|
|
throw new IOException("Failed to open " + String.valueOf(uri) + ", HTTP error code: " + responseCode);
|
|
}
|
|
byte[] imageContents = connection.getInputStream().readAllBytes();
|
|
try {
|
|
FileUtil.createDirectoriesSafe(localCopy.getParent());
|
|
Files.write(localCopy, imageContents, new OpenOption[0]);
|
|
}
|
|
catch (IOException e) {
|
|
LOGGER.warn("Failed to cache texture {} in {}", (Object)url, (Object)localCopy);
|
|
}
|
|
NativeImage nativeImage = NativeImage.read(imageContents);
|
|
return nativeImage;
|
|
}
|
|
finally {
|
|
if (connection != null) {
|
|
connection.disconnect();
|
|
}
|
|
}
|
|
}
|
|
|
|
private CompletableFuture<ClientAsset.Texture> registerTextureInManager(ClientAsset.Texture textureId, NativeImage contents) {
|
|
return CompletableFuture.supplyAsync(() -> {
|
|
DynamicTexture texture = new DynamicTexture(textureId.texturePath()::toString, contents);
|
|
this.textureManager.register(textureId.texturePath(), texture);
|
|
return textureId;
|
|
}, this.mainThreadExecutor);
|
|
}
|
|
|
|
private static NativeImage processLegacySkin(NativeImage image, String url) {
|
|
boolean isLegacy;
|
|
int height = image.getHeight();
|
|
int width = image.getWidth();
|
|
if (width != 64 || height != 32 && height != 64) {
|
|
image.close();
|
|
throw new IllegalStateException("Discarding incorrectly sized (" + width + "x" + height + ") skin texture from " + url);
|
|
}
|
|
boolean bl = isLegacy = height == 32;
|
|
if (isLegacy) {
|
|
NativeImage newImage = new NativeImage(64, 64, true);
|
|
newImage.copyFrom(image);
|
|
image.close();
|
|
image = newImage;
|
|
image.fillRect(0, 32, 64, 32, 0);
|
|
image.copyRect(4, 16, 16, 32, 4, 4, true, false);
|
|
image.copyRect(8, 16, 16, 32, 4, 4, true, false);
|
|
image.copyRect(0, 20, 24, 32, 4, 12, true, false);
|
|
image.copyRect(4, 20, 16, 32, 4, 12, true, false);
|
|
image.copyRect(8, 20, 8, 32, 4, 12, true, false);
|
|
image.copyRect(12, 20, 16, 32, 4, 12, true, false);
|
|
image.copyRect(44, 16, -8, 32, 4, 4, true, false);
|
|
image.copyRect(48, 16, -8, 32, 4, 4, true, false);
|
|
image.copyRect(40, 20, 0, 32, 4, 12, true, false);
|
|
image.copyRect(44, 20, -8, 32, 4, 12, true, false);
|
|
image.copyRect(48, 20, -16, 32, 4, 12, true, false);
|
|
image.copyRect(52, 20, -8, 32, 4, 12, true, false);
|
|
}
|
|
SkinTextureDownloader.setNoAlpha(image, 0, 0, 32, 16);
|
|
if (isLegacy) {
|
|
SkinTextureDownloader.doNotchTransparencyHack(image, 32, 0, 64, 32);
|
|
}
|
|
SkinTextureDownloader.setNoAlpha(image, 0, 16, 64, 32);
|
|
SkinTextureDownloader.setNoAlpha(image, 16, 48, 48, 64);
|
|
return image;
|
|
}
|
|
|
|
private static void doNotchTransparencyHack(NativeImage image, int x0, int y0, int x1, int y1) {
|
|
int y;
|
|
int x;
|
|
for (x = x0; x < x1; ++x) {
|
|
for (y = y0; y < y1; ++y) {
|
|
int pix = image.getPixel(x, y);
|
|
if (ARGB.alpha(pix) >= 128) continue;
|
|
return;
|
|
}
|
|
}
|
|
for (x = x0; x < x1; ++x) {
|
|
for (y = y0; y < y1; ++y) {
|
|
image.setPixel(x, y, image.getPixel(x, y) & 0xFFFFFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void setNoAlpha(NativeImage image, int x0, int y0, int x1, int y1) {
|
|
for (int x = x0; x < x1; ++x) {
|
|
for (int y = y0; y < y1; ++y) {
|
|
image.setPixel(x, y, ARGB.opaque(image.getPixel(x, y)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|