177 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| 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.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 net.fabricmc.api.EnvType;
 | |
| import net.fabricmc.api.Environment;
 | |
| import net.minecraft.FileUtil;
 | |
| import net.minecraft.Util;
 | |
| import net.minecraft.client.Minecraft;
 | |
| import net.minecraft.resources.ResourceLocation;
 | |
| import net.minecraft.util.ARGB;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| @Environment(EnvType.CLIENT)
 | |
| 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;
 | |
| 
 | |
| 	public static CompletableFuture<ResourceLocation> downloadAndRegisterSkin(ResourceLocation textureLocation, Path path, String url, boolean isLegacySkin) {
 | |
| 		return CompletableFuture.supplyAsync(() -> {
 | |
| 			NativeImage nativeImage;
 | |
| 			try {
 | |
| 				nativeImage = downloadSkin(path, url);
 | |
| 			} catch (IOException var5) {
 | |
| 				throw new UncheckedIOException(var5);
 | |
| 			}
 | |
| 
 | |
| 			return isLegacySkin ? processLegacySkin(nativeImage, url) : nativeImage;
 | |
| 		}, Util.nonCriticalIoPool().forName("downloadTexture")).thenCompose(nativeImage -> registerTextureInManager(textureLocation, nativeImage));
 | |
| 	}
 | |
| 
 | |
| 	private static NativeImage downloadSkin(Path path, String url) throws IOException {
 | |
| 		if (Files.isRegularFile(path, new LinkOption[0])) {
 | |
| 			LOGGER.debug("Loading HTTP texture from local cache ({})", path);
 | |
| 			InputStream inputStream = Files.newInputStream(path);
 | |
| 
 | |
| 			NativeImage var17;
 | |
| 			try {
 | |
| 				var17 = NativeImage.read(inputStream);
 | |
| 			} catch (Throwable var14) {
 | |
| 				if (inputStream != null) {
 | |
| 					try {
 | |
| 						inputStream.close();
 | |
| 					} catch (Throwable var12) {
 | |
| 						var14.addSuppressed(var12);
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				throw var14;
 | |
| 			}
 | |
| 
 | |
| 			if (inputStream != null) {
 | |
| 				inputStream.close();
 | |
| 			}
 | |
| 
 | |
| 			return var17;
 | |
| 		} else {
 | |
| 			HttpURLConnection httpURLConnection = null;
 | |
| 			LOGGER.debug("Downloading HTTP texture from {} to {}", url, path);
 | |
| 			URI uRI = URI.create(url);
 | |
| 
 | |
| 			NativeImage iOException;
 | |
| 			try {
 | |
| 				httpURLConnection = (HttpURLConnection)uRI.toURL().openConnection(Minecraft.getInstance().getProxy());
 | |
| 				httpURLConnection.setDoInput(true);
 | |
| 				httpURLConnection.setDoOutput(false);
 | |
| 				httpURLConnection.connect();
 | |
| 				int i = httpURLConnection.getResponseCode();
 | |
| 				if (i / 100 != 2) {
 | |
| 					throw new IOException("Failed to open " + uRI + ", HTTP error code: " + i);
 | |
| 				}
 | |
| 
 | |
| 				byte[] bs = httpURLConnection.getInputStream().readAllBytes();
 | |
| 
 | |
| 				try {
 | |
| 					FileUtil.createDirectoriesSafe(path.getParent());
 | |
| 					Files.write(path, bs, new OpenOption[0]);
 | |
| 				} catch (IOException var13) {
 | |
| 					LOGGER.warn("Failed to cache texture {} in {}", url, path);
 | |
| 				}
 | |
| 
 | |
| 				iOException = NativeImage.read(bs);
 | |
| 			} finally {
 | |
| 				if (httpURLConnection != null) {
 | |
| 					httpURLConnection.disconnect();
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return iOException;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private static CompletableFuture<ResourceLocation> registerTextureInManager(ResourceLocation location, NativeImage image) {
 | |
| 		Minecraft minecraft = Minecraft.getInstance();
 | |
| 		return CompletableFuture.supplyAsync(() -> {
 | |
| 			DynamicTexture dynamicTexture = new DynamicTexture(location::toString, image);
 | |
| 			minecraft.getTextureManager().register(location, dynamicTexture);
 | |
| 			return location;
 | |
| 		}, minecraft);
 | |
| 	}
 | |
| 
 | |
| 	private static NativeImage processLegacySkin(NativeImage image, String url) {
 | |
| 		int i = image.getHeight();
 | |
| 		int j = image.getWidth();
 | |
| 		if (j == 64 && (i == 32 || i == 64)) {
 | |
| 			boolean bl = i == 32;
 | |
| 			if (bl) {
 | |
| 				NativeImage nativeImage = new NativeImage(64, 64, true);
 | |
| 				nativeImage.copyFrom(image);
 | |
| 				image.close();
 | |
| 				image = nativeImage;
 | |
| 				nativeImage.fillRect(0, 32, 64, 32, 0);
 | |
| 				nativeImage.copyRect(4, 16, 16, 32, 4, 4, true, false);
 | |
| 				nativeImage.copyRect(8, 16, 16, 32, 4, 4, true, false);
 | |
| 				nativeImage.copyRect(0, 20, 24, 32, 4, 12, true, false);
 | |
| 				nativeImage.copyRect(4, 20, 16, 32, 4, 12, true, false);
 | |
| 				nativeImage.copyRect(8, 20, 8, 32, 4, 12, true, false);
 | |
| 				nativeImage.copyRect(12, 20, 16, 32, 4, 12, true, false);
 | |
| 				nativeImage.copyRect(44, 16, -8, 32, 4, 4, true, false);
 | |
| 				nativeImage.copyRect(48, 16, -8, 32, 4, 4, true, false);
 | |
| 				nativeImage.copyRect(40, 20, 0, 32, 4, 12, true, false);
 | |
| 				nativeImage.copyRect(44, 20, -8, 32, 4, 12, true, false);
 | |
| 				nativeImage.copyRect(48, 20, -16, 32, 4, 12, true, false);
 | |
| 				nativeImage.copyRect(52, 20, -8, 32, 4, 12, true, false);
 | |
| 			}
 | |
| 
 | |
| 			setNoAlpha(image, 0, 0, 32, 16);
 | |
| 			if (bl) {
 | |
| 				doNotchTransparencyHack(image, 32, 0, 64, 32);
 | |
| 			}
 | |
| 
 | |
| 			setNoAlpha(image, 0, 16, 64, 32);
 | |
| 			setNoAlpha(image, 16, 48, 48, 64);
 | |
| 			return image;
 | |
| 		} else {
 | |
| 			image.close();
 | |
| 			throw new IllegalStateException("Discarding incorrectly sized (" + j + "x" + i + ") skin texture from " + url);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private static void doNotchTransparencyHack(NativeImage image, int minX, int minY, int maxX, int maxY) {
 | |
| 		for (int i = minX; i < maxX; i++) {
 | |
| 			for (int j = minY; j < maxY; j++) {
 | |
| 				int k = image.getPixel(i, j);
 | |
| 				if (ARGB.alpha(k) < 128) {
 | |
| 					return;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		for (int i = minX; i < maxX; i++) {
 | |
| 			for (int jx = minY; jx < maxY; jx++) {
 | |
| 				image.setPixel(i, jx, image.getPixel(i, jx) & 16777215);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private static void setNoAlpha(NativeImage image, int minX, int minY, int maxX, int maxY) {
 | |
| 		for (int i = minX; i < maxX; i++) {
 | |
| 			for (int j = minY; j < maxY; j++) {
 | |
| 				image.setPixel(i, j, ARGB.opaque(image.getPixel(i, j)));
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 |