HumanSkinLoader.java 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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(false);
  18. public final static HumanSkinLoader GREY_INSTANCE = new HumanSkinLoader(true);
  19. private static final ResourceLocation TEXTURE_STEVE = new ResourceLocation("textures/entity/steve.png");
  20. private final HashMap<String, ResourceLocation> skins = new HashMap<>();
  21. private final HashSet<String> loading = new HashSet<>();
  22. private final TextureManager manager = Minecraft.getInstance().getRenderManager().textureManager;
  23. private final boolean grey;
  24. private HumanSkinLoader(boolean grey) {
  25. this.grey = grey;
  26. }
  27. public ResourceLocation getTexture(String name) {
  28. ResourceLocation loc = skins.get(name);
  29. if(loc != null) {
  30. return loc;
  31. }
  32. if(loading.add(name)) {
  33. downloadSkin(name, image -> {
  34. ResourceLocation rloc = manager.getDynamicTextureLocation("skin_grey_" + name.toLowerCase(), new DynamicTexture(image));
  35. skins.put(name, rloc);
  36. loading.remove(name);
  37. }, grey);
  38. }
  39. return TEXTURE_STEVE;
  40. }
  41. private void downloadSkin(String name, Consumer<NativeImage> delayed, boolean grey) {
  42. new Thread(() -> {
  43. HttpURLConnection httpurlconnection = null;
  44. try {
  45. URL url = new URL("http://skins.hammerle.me/skins/" + name + ".png");
  46. httpurlconnection = (HttpURLConnection) url.openConnection(Minecraft.getInstance().getProxy());
  47. httpurlconnection.setDoInput(true);
  48. httpurlconnection.setDoOutput(false);
  49. httpurlconnection.connect();
  50. int code = httpurlconnection.getResponseCode();
  51. if(code != 200) {
  52. // Failed own server, trying crafatar
  53. httpurlconnection.disconnect();
  54. httpurlconnection = (HttpURLConnection) (new URL("https://crafatar.com/skins/" + name + ".png"))
  55. .openConnection(Minecraft.getInstance().getProxy());
  56. httpurlconnection.setDoInput(true);
  57. httpurlconnection.setDoOutput(false);
  58. httpurlconnection.connect();
  59. code = httpurlconnection.getResponseCode();
  60. if(code != 200) {
  61. LogManager.getLogger().warn("Server response code did return " + code + ", skin servers might be down.");
  62. return;
  63. }
  64. }
  65. NativeImage image = convert(NativeImage.read(httpurlconnection.getInputStream()));
  66. if(grey) {
  67. for(int x = 0; x < image.getWidth(); x++) {
  68. for(int y = 0; y < image.getHeight(); y++) {
  69. int c = image.getPixelRGBA(x, y);
  70. int r = (c >> 0) & 0xFF;
  71. int g = (c >> 8) & 0xFF;
  72. int b = (c >> 16) & 0xFF;
  73. int a = (c >> 24) & 0xFF;
  74. int mix = (int) (r * 0.3 + g * 0.6 + b * 0.1);
  75. c = (mix << 0) | (mix << 8) | (mix << 16) | (a << 24);
  76. image.setPixelRGBA(x, y, c);
  77. }
  78. }
  79. }
  80. Minecraft.getInstance().enqueue(() -> delayed.accept(image));
  81. } catch(Exception ex) {
  82. LogManager.getLogger().warn("Error occurred when downloading skin, however, skin servers seem to be up.");
  83. } finally {
  84. if(httpurlconnection != null) {
  85. httpurlconnection.disconnect();
  86. }
  87. }
  88. }).start();
  89. }
  90. private NativeImage convert(NativeImage old) {
  91. boolean flag = old.getHeight() == 32;
  92. if(flag) {
  93. NativeImage nativeimage = new NativeImage(64, 64, true);
  94. nativeimage.copyImageData(old);
  95. old.close();
  96. old = nativeimage;
  97. nativeimage.fillAreaRGBA(0, 32, 64, 32, 0);
  98. nativeimage.copyAreaRGBA(4, 16, 16, 32, 4, 4, true, false);
  99. nativeimage.copyAreaRGBA(8, 16, 16, 32, 4, 4, true, false);
  100. nativeimage.copyAreaRGBA(0, 20, 24, 32, 4, 12, true, false);
  101. nativeimage.copyAreaRGBA(4, 20, 16, 32, 4, 12, true, false);
  102. nativeimage.copyAreaRGBA(8, 20, 8, 32, 4, 12, true, false);
  103. nativeimage.copyAreaRGBA(12, 20, 16, 32, 4, 12, true, false);
  104. nativeimage.copyAreaRGBA(44, 16, -8, 32, 4, 4, true, false);
  105. nativeimage.copyAreaRGBA(48, 16, -8, 32, 4, 4, true, false);
  106. nativeimage.copyAreaRGBA(40, 20, 0, 32, 4, 12, true, false);
  107. nativeimage.copyAreaRGBA(44, 20, -8, 32, 4, 12, true, false);
  108. nativeimage.copyAreaRGBA(48, 20, -16, 32, 4, 12, true, false);
  109. nativeimage.copyAreaRGBA(52, 20, -8, 32, 4, 12, true, false);
  110. }
  111. setAreaOpaque(old, 0, 0, 32, 16);
  112. if(flag) {
  113. setAreaTransparent(old, 32, 0, 64, 32);
  114. }
  115. setAreaOpaque(old, 0, 16, 64, 32);
  116. setAreaOpaque(old, 16, 48, 48, 64);
  117. return old;
  118. }
  119. private static void setAreaTransparent(NativeImage image, int x, int y, int width, int height) {
  120. for(int i = x; i < width; ++i) {
  121. for(int j = y; j < height; ++j) {
  122. int k = image.getPixelRGBA(i, j);
  123. if((k >> 24 & 255) < 128) {
  124. return;
  125. }
  126. }
  127. }
  128. for(int l = x; l < width; ++l) {
  129. for(int i1 = y; i1 < height; ++i1) {
  130. image.setPixelRGBA(l, i1, image.getPixelRGBA(l, i1) & 16777215);
  131. }
  132. }
  133. }
  134. private static void setAreaOpaque(NativeImage image, int x, int y, int width, int height) {
  135. for(int i = x; i < width; ++i) {
  136. for(int j = y; j < height; ++j) {
  137. image.setPixelRGBA(i, j, image.getPixelRGBA(i, j) | -16777216);
  138. }
  139. }
  140. }
  141. }