package me.km.entities; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.HashSet; import java.util.function.Consumer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.DynamicTexture; import net.minecraft.client.renderer.texture.NativeImage; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.util.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import org.apache.logging.log4j.LogManager; @OnlyIn(Dist.CLIENT) public class HumanSkinLoader { public final static HumanSkinLoader INSTANCE = new HumanSkinLoader(); private static final ResourceLocation TEXTURE_STEVE = new ResourceLocation("textures/entity/steve.png"); private final HashMap skins = new HashMap<>(); private final HashSet loading = new HashSet<>(); private final TextureManager manager = Minecraft.getInstance().getRenderManager().textureManager; private HumanSkinLoader() { } public ResourceLocation getTexture(String name) { ResourceLocation loc = skins.get(name); if(loc != null) { return loc; } if(loading.add(name)) { downloadSkin(name, image -> { ResourceLocation rloc = manager.getDynamicTextureLocation("skin_" + name.toLowerCase(), new DynamicTexture(image)); skins.put(name, rloc); loading.remove(name); }); } return TEXTURE_STEVE; } private void downloadSkin(String name, Consumer delayed) { new Thread(() -> { HttpURLConnection httpurlconnection = null; try { URL url = new URL("http://skins.hammerle.me/skins/" + name + ".png"); httpurlconnection = (HttpURLConnection) url.openConnection(Minecraft.getInstance().getProxy()); httpurlconnection.setDoInput(true); httpurlconnection.setDoOutput(false); httpurlconnection.connect(); int code = httpurlconnection.getResponseCode(); if(code != 200) { // Failed own server, trying crafatar httpurlconnection.disconnect(); httpurlconnection = (HttpURLConnection) (new URL("https://crafatar.com/skins/" + name + ".png")) .openConnection(Minecraft.getInstance().getProxy()); httpurlconnection.setDoInput(true); httpurlconnection.setDoOutput(false); httpurlconnection.connect(); code = httpurlconnection.getResponseCode(); if(code != 200) { LogManager.getLogger().warn("Server response code did return " + code + ", skin servers might be down."); return; } } NativeImage image = convert(NativeImage.read(httpurlconnection.getInputStream())); Minecraft.getInstance().enqueue(() -> delayed.accept(image)); } catch(Exception ex) { LogManager.getLogger().warn("Error occurred when downloading skin, however, skin servers seem to be up."); } finally { if(httpurlconnection != null) { httpurlconnection.disconnect(); } } }).start(); } private NativeImage convert(NativeImage old) { boolean flag = old.getHeight() == 32; if (flag) { NativeImage nativeimage = new NativeImage(64, 64, true); nativeimage.copyImageData(old); old.close(); old = nativeimage; nativeimage.fillAreaRGBA(0, 32, 64, 32, 0); nativeimage.copyAreaRGBA(4, 16, 16, 32, 4, 4, true, false); nativeimage.copyAreaRGBA(8, 16, 16, 32, 4, 4, true, false); nativeimage.copyAreaRGBA(0, 20, 24, 32, 4, 12, true, false); nativeimage.copyAreaRGBA(4, 20, 16, 32, 4, 12, true, false); nativeimage.copyAreaRGBA(8, 20, 8, 32, 4, 12, true, false); nativeimage.copyAreaRGBA(12, 20, 16, 32, 4, 12, true, false); nativeimage.copyAreaRGBA(44, 16, -8, 32, 4, 4, true, false); nativeimage.copyAreaRGBA(48, 16, -8, 32, 4, 4, true, false); nativeimage.copyAreaRGBA(40, 20, 0, 32, 4, 12, true, false); nativeimage.copyAreaRGBA(44, 20, -8, 32, 4, 12, true, false); nativeimage.copyAreaRGBA(48, 20, -16, 32, 4, 12, true, false); nativeimage.copyAreaRGBA(52, 20, -8, 32, 4, 12, true, false); } setAreaOpaque(old, 0, 0, 32, 16); if (flag) { setAreaTransparent(old, 32, 0, 64, 32); } setAreaOpaque(old, 0, 16, 64, 32); setAreaOpaque(old, 16, 48, 48, 64); return old; } private static void setAreaTransparent(NativeImage image, int x, int y, int width, int height) { for(int i = x; i < width; ++i) { for(int j = y; j < height; ++j) { int k = image.getPixelRGBA(i, j); if((k >> 24 & 255) < 128) { return; } } } for(int l = x; l < width; ++l) { for(int i1 = y; i1 < height; ++i1) { image.setPixelRGBA(l, i1, image.getPixelRGBA(l, i1) & 16777215); } } } private static void setAreaOpaque(NativeImage image, int x, int y, int width, int height) { for(int i = x; i < width; ++i) { for(int j = y; j < height; ++j) { image.setPixelRGBA(i, j, image.getPixelRGBA(i, j) | -16777216); } } } }