SkinTextureDownloader.java

net.minecraft.client.renderer.texture.SkinTextureDownloader

信息

  • 全限定名:net.minecraft.client.renderer.texture.SkinTextureDownloader
  • 类型:public class
  • 包:net.minecraft.client.renderer.texture
  • 源码路径:src/main/java/net/minecraft/client/renderer/texture/SkinTextureDownloader.java
  • 起始行号:L25
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L26
    • 说明:

      TODO

  • SKIN_WIDTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L27
    • 说明:

      TODO

  • SKIN_HEIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L28
    • 说明:

      TODO

  • LEGACY_SKIN_HEIGHT

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L29
    • 说明:

      TODO

  • proxy

    • 类型: Proxy
    • 修饰符: private final
    • 源码定位: L30
    • 说明:

      TODO

  • textureManager

    • 类型: TextureManager
    • 修饰符: private final
    • 源码定位: L31
    • 说明:

      TODO

  • mainThreadExecutor

    • 类型: Executor
    • 修饰符: private final
    • 源码定位: L32
    • 说明:

      TODO

内部类/嵌套类型

构造器

public SkinTextureDownloader(Proxy proxy, TextureManager textureManager, Executor mainThreadExecutor) @ L34

  • 构造器名:SkinTextureDownloader
  • 源码定位:L34
  • 修饰符:public

参数:

  • proxy: Proxy
  • textureManager: TextureManager
  • mainThreadExecutor: Executor

说明:

TODO

方法

下面的方法块按源码顺序生成。

public CompletableFuture<ClientAsset.Texture> downloadAndRegisterSkin(Identifier textureId, Path localCopy, String url, boolean processLegacySkin) @ L40

  • 方法名:downloadAndRegisterSkin
  • 源码定位:L40
  • 返回类型:CompletableFuture<ClientAsset.Texture>
  • 修饰符:public

参数:

  • textureId: Identifier
  • localCopy: Path
  • url: String
  • processLegacySkin: boolean

说明:

TODO

private NativeImage downloadSkin(Path localCopy, String url) @ L54

  • 方法名:downloadSkin
  • 源码定位:L54
  • 返回类型:NativeImage
  • 修饰符:private

参数:

  • localCopy: Path
  • url: String

说明:

TODO

private CompletableFuture<ClientAsset.Texture> registerTextureInManager(ClientAsset.Texture textureId, NativeImage contents) @ L100

  • 方法名:registerTextureInManager
  • 源码定位:L100
  • 返回类型:CompletableFuture<ClientAsset.Texture>
  • 修饰符:private

参数:

  • textureId: ClientAsset.Texture
  • contents: NativeImage

说明:

TODO

private static NativeImage processLegacySkin(NativeImage image, String url) @ L108

  • 方法名:processLegacySkin
  • 源码定位:L108
  • 返回类型:NativeImage
  • 修饰符:private static

参数:

  • image: NativeImage
  • url: String

说明:

TODO

private static void doNotchTransparencyHack(NativeImage image, int x0, int y0, int x1, int y1) @ L147

  • 方法名:doNotchTransparencyHack
  • 源码定位:L147
  • 返回类型:void
  • 修饰符:private static

参数:

  • image: NativeImage
  • x0: int
  • y0: int
  • x1: int
  • y1: int

说明:

TODO

private static void setNoAlpha(NativeImage image, int x0, int y0, int x1, int y1) @ L164

  • 方法名:setNoAlpha
  • 源码定位:L164
  • 返回类型:void
  • 修饰符:private static

参数:

  • image: NativeImage
  • x0: int
  • y0: int
  • x1: int
  • y1: int

说明:

TODO

代码

@OnlyIn(Dist.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;
    private final Proxy proxy;
    private final TextureManager textureManager;
    private final Executor mainThreadExecutor;
 
    public SkinTextureDownloader(Proxy proxy, TextureManager textureManager, Executor mainThreadExecutor) {
        this.proxy = proxy;
        this.textureManager = textureManager;
        this.mainThreadExecutor = mainThreadExecutor;
    }
 
    public CompletableFuture<ClientAsset.Texture> downloadAndRegisterSkin(Identifier textureId, Path localCopy, String url, boolean processLegacySkin) {
        ClientAsset.DownloadedTexture texture = new ClientAsset.DownloadedTexture(textureId, url);
        return CompletableFuture.<NativeImage>supplyAsync(() -> {
            NativeImage loadedSkin;
            try {
                loadedSkin = this.downloadSkin(localCopy, texture.url());
            } catch (IOException var6) {
                throw new UncheckedIOException(var6);
            }
 
            return processLegacySkin ? processLegacySkin(loadedSkin, texture.url()) : loadedSkin;
        }, Util.nonCriticalIoPool().forName("downloadTexture")).thenCompose(fixedSkin -> this.registerTextureInManager(texture, fixedSkin));
    }
 
    private NativeImage downloadSkin(Path localCopy, String url) throws IOException {
        if (Files.isRegularFile(localCopy)) {
            LOGGER.debug("Loading HTTP texture from local cache ({})", localCopy);
 
            NativeImage var18;
            try (InputStream inputStream = Files.newInputStream(localCopy)) {
                var18 = NativeImage.read(inputStream);
            }
 
            return var18;
        } else {
            HttpURLConnection connection = null;
            LOGGER.debug("Downloading HTTP texture from {} to {}", url, localCopy);
            URI uri = URI.create(url);
 
            NativeImage e;
            try {
                connection = (HttpURLConnection)uri.toURL().openConnection(this.proxy);
                connection.setDoInput(true);
                connection.setDoOutput(false);
                connection.connect();
                int responseCode = connection.getResponseCode();
                if (responseCode / 100 != 2) {
                    throw new IOException("Failed to open " + uri + ", HTTP error code: " + responseCode);
                }
 
                byte[] imageContents = connection.getInputStream().readAllBytes();
 
                try {
                    FileUtil.createDirectoriesSafe(localCopy.getParent());
                    Files.write(localCopy, imageContents);
                } catch (IOException var14) {
                    LOGGER.warn("Failed to cache texture {} in {}", url, localCopy);
                }
 
                e = NativeImage.read(imageContents);
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
            }
 
            return e;
        }
    }
 
    private CompletableFuture<ClientAsset.Texture> registerTextureInManager(ClientAsset.Texture textureId, NativeImage contents) {
        return CompletableFuture.supplyAsync(() -> {
            DynamicTexture texture = new DynamicTexture(textureId.texturePath()::toString, contents);
            this.textureManager.register(textureId.texturePath(), texture);
            return textureId;
        }, this.mainThreadExecutor);
    }
 
    private static NativeImage processLegacySkin(NativeImage image, String url) {
        int height = image.getHeight();
        int width = image.getWidth();
        if (width == 64 && (height == 32 || height == 64)) {
            boolean isLegacy = height == 32;
            if (isLegacy) {
                NativeImage newImage = new NativeImage(64, 64, true);
                newImage.copyFrom(image);
                image.close();
                image = newImage;
                newImage.fillRect(0, 32, 64, 32, 0);
                newImage.copyRect(4, 16, 16, 32, 4, 4, true, false);
                newImage.copyRect(8, 16, 16, 32, 4, 4, true, false);
                newImage.copyRect(0, 20, 24, 32, 4, 12, true, false);
                newImage.copyRect(4, 20, 16, 32, 4, 12, true, false);
                newImage.copyRect(8, 20, 8, 32, 4, 12, true, false);
                newImage.copyRect(12, 20, 16, 32, 4, 12, true, false);
                newImage.copyRect(44, 16, -8, 32, 4, 4, true, false);
                newImage.copyRect(48, 16, -8, 32, 4, 4, true, false);
                newImage.copyRect(40, 20, 0, 32, 4, 12, true, false);
                newImage.copyRect(44, 20, -8, 32, 4, 12, true, false);
                newImage.copyRect(48, 20, -16, 32, 4, 12, true, false);
                newImage.copyRect(52, 20, -8, 32, 4, 12, true, false);
            }
 
            setNoAlpha(image, 0, 0, 32, 16);
            if (isLegacy) {
                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 (" + width + "x" + height + ") skin texture from " + url);
        }
    }
 
    private static void doNotchTransparencyHack(NativeImage image, int x0, int y0, int x1, int y1) {
        for (int x = x0; x < x1; x++) {
            for (int y = y0; y < y1; y++) {
                int pix = image.getPixel(x, y);
                if (ARGB.alpha(pix) < 128) {
                    return;
                }
            }
        }
 
        for (int x = x0; x < x1; x++) {
            for (int yx = y0; yx < y1; yx++) {
                image.setPixel(x, yx, image.getPixel(x, yx) & 16777215);
            }
        }
    }
 
    private static void setNoAlpha(NativeImage image, int x0, int y0, int x1, int y1) {
        for (int x = x0; x < x1; x++) {
            for (int y = y0; y < y1; y++) {
                image.setPixel(x, y, ARGB.opaque(image.getPixel(x, y)));
            }
        }
    }
}

引用的其他类

  • NativeImage

    • 引用位置: 参数/方法调用/构造调用/返回值
    • 关联成员: NativeImage(), NativeImage.read()
  • DynamicTexture

    • 引用位置: 构造调用
    • 关联成员: DynamicTexture()
  • TextureManager

    • 引用位置: 参数/字段
  • ClientAsset

    • 引用位置: 参数/方法调用/构造调用/返回值
    • 关联成员: ClientAsset.DownloadedTexture(), DownloadedTexture()
  • Identifier

    • 引用位置: 参数
  • ARGB

    • 引用位置: 方法调用
    • 关联成员: ARGB.alpha(), ARGB.opaque()
  • FileUtil

    • 引用位置: 方法调用
    • 关联成员: FileUtil.createDirectoriesSafe()
  • Util

    • 引用位置: 方法调用
    • 关联成员: Util.nonCriticalIoPool()