HumanSkinLoader.java 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package me.km.entities;
  2. import java.net.HttpURLConnection;
  3. import java.net.URL;
  4. import java.util.HashMap;
  5. import java.util.HashSet;
  6. import java.util.function.Consumer;
  7. import net.minecraft.client.Minecraft;
  8. import net.minecraft.client.renderer.texture.DynamicTexture;
  9. import net.minecraft.client.renderer.texture.NativeImage;
  10. import net.minecraft.client.renderer.texture.TextureManager;
  11. import net.minecraft.util.ResourceLocation;
  12. import net.minecraftforge.api.distmarker.Dist;
  13. import net.minecraftforge.api.distmarker.OnlyIn;
  14. import org.apache.logging.log4j.LogManager;
  15. @OnlyIn(Dist.CLIENT)
  16. public class HumanSkinLoader {
  17. public final static HumanSkinLoader INSTANCE = new HumanSkinLoader();
  18. private static final ResourceLocation TEXTURE_STEVE = new ResourceLocation("textures/entity/steve.png");
  19. private final HashMap<String, ResourceLocation> skins = new HashMap<>();
  20. private final HashSet<String> loading = new HashSet<>();
  21. private final TextureManager manager = Minecraft.getInstance().getRenderManager().textureManager;
  22. private HumanSkinLoader() {
  23. }
  24. public ResourceLocation getTexture(String name) {
  25. ResourceLocation loc = skins.get(name);
  26. if(loc != null) {
  27. return loc;
  28. }
  29. if(loading.add(name)) {
  30. downloadSkin(name, image -> {
  31. ResourceLocation rloc = manager.getDynamicTextureLocation("skin_" + name.toLowerCase(), new DynamicTexture(image));
  32. skins.put(name, rloc);
  33. loading.remove(name);
  34. });
  35. }
  36. return TEXTURE_STEVE;
  37. }
  38. private void downloadSkin(String name, Consumer<NativeImage> delayed) {
  39. new Thread(() -> {
  40. HttpURLConnection httpurlconnection = null;
  41. try {
  42. URL url = new URL("http://skins.hammerle.me/skins/" + name + ".png");
  43. httpurlconnection = (HttpURLConnection) url.openConnection(Minecraft.getInstance().getProxy());
  44. httpurlconnection.setDoInput(true);
  45. httpurlconnection.setDoOutput(false);
  46. httpurlconnection.connect();
  47. int code = httpurlconnection.getResponseCode();
  48. if(code != 200) {
  49. // Failed own server, trying crafatar
  50. httpurlconnection.disconnect();
  51. httpurlconnection = (HttpURLConnection) (new URL("https://crafatar.com/skins/" + name + ".png"))
  52. .openConnection(Minecraft.getInstance().getProxy());
  53. httpurlconnection.setDoInput(true);
  54. httpurlconnection.setDoOutput(false);
  55. httpurlconnection.connect();
  56. code = httpurlconnection.getResponseCode();
  57. if(code != 200) {
  58. LogManager.getLogger().warn("Server response code did return " + code + ", skin servers might be down.");
  59. return;
  60. }
  61. }
  62. NativeImage image = convert(NativeImage.read(httpurlconnection.getInputStream()));
  63. Minecraft.getInstance().enqueue(() -> delayed.accept(image));
  64. } catch(Exception ex) {
  65. LogManager.getLogger().warn("Error occurred when downloading skin, however, skin servers seem to be up.");
  66. } finally {
  67. if(httpurlconnection != null) {
  68. httpurlconnection.disconnect();
  69. }
  70. }
  71. }).start();
  72. }
  73. private NativeImage convert(NativeImage old) {
  74. boolean flag = old.getHeight() == 32;
  75. if(flag) {
  76. NativeImage nativeimage = new NativeImage(64, 64, true);
  77. nativeimage.copyImageData(old);
  78. old.close();
  79. old = nativeimage;
  80. nativeimage.fillAreaRGBA(0, 32, 64, 32, 0);
  81. nativeimage.copyAreaRGBA(4, 16, 16, 32, 4, 4, true, false);
  82. nativeimage.copyAreaRGBA(8, 16, 16, 32, 4, 4, true, false);
  83. nativeimage.copyAreaRGBA(0, 20, 24, 32, 4, 12, true, false);
  84. nativeimage.copyAreaRGBA(4, 20, 16, 32, 4, 12, true, false);
  85. nativeimage.copyAreaRGBA(8, 20, 8, 32, 4, 12, true, false);
  86. nativeimage.copyAreaRGBA(12, 20, 16, 32, 4, 12, true, false);
  87. nativeimage.copyAreaRGBA(44, 16, -8, 32, 4, 4, true, false);
  88. nativeimage.copyAreaRGBA(48, 16, -8, 32, 4, 4, true, false);
  89. nativeimage.copyAreaRGBA(40, 20, 0, 32, 4, 12, true, false);
  90. nativeimage.copyAreaRGBA(44, 20, -8, 32, 4, 12, true, false);
  91. nativeimage.copyAreaRGBA(48, 20, -16, 32, 4, 12, true, false);
  92. nativeimage.copyAreaRGBA(52, 20, -8, 32, 4, 12, true, false);
  93. }
  94. setAreaOpaque(old, 0, 0, 32, 16);
  95. if(flag) {
  96. setAreaTransparent(old, 32, 0, 64, 32);
  97. }
  98. setAreaOpaque(old, 0, 16, 64, 32);
  99. setAreaOpaque(old, 16, 48, 48, 64);
  100. return old;
  101. }
  102. private static void setAreaTransparent(NativeImage image, int x, int y, int width, int height) {
  103. for(int i = x; i < width; ++i) {
  104. for(int j = y; j < height; ++j) {
  105. int k = image.getPixelRGBA(i, j);
  106. if((k >> 24 & 255) < 128) {
  107. return;
  108. }
  109. }
  110. }
  111. for(int l = x; l < width; ++l) {
  112. for(int i1 = y; i1 < height; ++i1) {
  113. image.setPixelRGBA(l, i1, image.getPixelRGBA(l, i1) & 16777215);
  114. }
  115. }
  116. }
  117. private static void setAreaOpaque(NativeImage image, int x, int y, int width, int height) {
  118. for(int i = x; i < width; ++i) {
  119. for(int j = y; j < height; ++j) {
  120. image.setPixelRGBA(i, j, image.getPixelRGBA(i, j) | -16777216);
  121. }
  122. }
  123. }
  124. }