HumanSkinLoader.java 6.8 KB

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