214 lines
6.5 KiB
Java
214 lines
6.5 KiB
Java
package net.minecraft.client.renderer.texture;
|
|
|
|
import com.mojang.blaze3d.platform.NativeImage;
|
|
import com.mojang.blaze3d.platform.TextureUtil;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.URL;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.server.packs.resources.ResourceManager;
|
|
import org.apache.commons.io.FileUtils;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class HttpTexture extends SimpleTexture {
|
|
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;
|
|
@Nullable
|
|
private final File file;
|
|
private final String urlString;
|
|
private final boolean processLegacySkin;
|
|
@Nullable
|
|
private final Runnable onDownloaded;
|
|
@Nullable
|
|
private CompletableFuture<?> future;
|
|
private boolean uploaded;
|
|
|
|
public HttpTexture(@Nullable File file, String urlString, ResourceLocation location, boolean processLegacySkin, @Nullable Runnable onDownloaded) {
|
|
super(location);
|
|
this.file = file;
|
|
this.urlString = urlString;
|
|
this.processLegacySkin = processLegacySkin;
|
|
this.onDownloaded = onDownloaded;
|
|
}
|
|
|
|
private void loadCallback(NativeImage image) {
|
|
if (this.onDownloaded != null) {
|
|
this.onDownloaded.run();
|
|
}
|
|
|
|
Minecraft.getInstance().execute(() -> {
|
|
this.uploaded = true;
|
|
if (!RenderSystem.isOnRenderThread()) {
|
|
RenderSystem.recordRenderCall(() -> this.upload(image));
|
|
} else {
|
|
this.upload(image);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void upload(NativeImage image) {
|
|
TextureUtil.prepareImage(this.getId(), image.getWidth(), image.getHeight());
|
|
image.upload(0, 0, 0, true);
|
|
}
|
|
|
|
@Override
|
|
public void load(ResourceManager resourceManager) throws IOException {
|
|
Minecraft.getInstance().execute(() -> {
|
|
if (!this.uploaded) {
|
|
try {
|
|
super.load(resourceManager);
|
|
} catch (IOException var3x) {
|
|
LOGGER.warn("Failed to load texture: {}", this.location, var3x);
|
|
}
|
|
|
|
this.uploaded = true;
|
|
}
|
|
});
|
|
if (this.future == null) {
|
|
NativeImage nativeImage;
|
|
if (this.file != null && this.file.isFile()) {
|
|
LOGGER.debug("Loading http texture from local cache ({})", this.file);
|
|
FileInputStream fileInputStream = new FileInputStream(this.file);
|
|
nativeImage = this.load(fileInputStream);
|
|
} else {
|
|
nativeImage = null;
|
|
}
|
|
|
|
if (nativeImage != null) {
|
|
this.loadCallback(nativeImage);
|
|
} else {
|
|
this.future = CompletableFuture.runAsync(() -> {
|
|
HttpURLConnection httpURLConnection = null;
|
|
LOGGER.debug("Downloading http texture from {} to {}", this.urlString, this.file);
|
|
|
|
try {
|
|
httpURLConnection = (HttpURLConnection)new URL(this.urlString).openConnection(Minecraft.getInstance().getProxy());
|
|
httpURLConnection.setDoInput(true);
|
|
httpURLConnection.setDoOutput(false);
|
|
httpURLConnection.connect();
|
|
if (httpURLConnection.getResponseCode() / 100 == 2) {
|
|
InputStream inputStream;
|
|
if (this.file != null) {
|
|
FileUtils.copyInputStreamToFile(httpURLConnection.getInputStream(), this.file);
|
|
inputStream = new FileInputStream(this.file);
|
|
} else {
|
|
inputStream = httpURLConnection.getInputStream();
|
|
}
|
|
|
|
Minecraft.getInstance().execute(() -> {
|
|
NativeImage nativeImagex = this.load(inputStream);
|
|
if (nativeImagex != null) {
|
|
this.loadCallback(nativeImagex);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
} catch (Exception var6) {
|
|
LOGGER.error("Couldn't download http texture", (Throwable)var6);
|
|
return;
|
|
} finally {
|
|
if (httpURLConnection != null) {
|
|
httpURLConnection.disconnect();
|
|
}
|
|
}
|
|
}, Util.backgroundExecutor());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Nullable
|
|
private NativeImage load(InputStream stream) {
|
|
NativeImage nativeImage = null;
|
|
|
|
try {
|
|
nativeImage = NativeImage.read(stream);
|
|
if (this.processLegacySkin) {
|
|
nativeImage = this.processLegacySkin(nativeImage);
|
|
}
|
|
} catch (Exception var4) {
|
|
LOGGER.warn("Error while loading the skin texture", (Throwable)var4);
|
|
}
|
|
|
|
return nativeImage;
|
|
}
|
|
|
|
@Nullable
|
|
private NativeImage processLegacySkin(NativeImage image) {
|
|
int i = image.getHeight();
|
|
int j = image.getWidth();
|
|
if (j == 64 && (i == 32 || i == 64)) {
|
|
boolean bl = i == 32;
|
|
if (bl) {
|
|
NativeImage nativeImage = new NativeImage(64, 64, true);
|
|
nativeImage.copyFrom(image);
|
|
image.close();
|
|
image = nativeImage;
|
|
nativeImage.fillRect(0, 32, 64, 32, 0);
|
|
nativeImage.copyRect(4, 16, 16, 32, 4, 4, true, false);
|
|
nativeImage.copyRect(8, 16, 16, 32, 4, 4, true, false);
|
|
nativeImage.copyRect(0, 20, 24, 32, 4, 12, true, false);
|
|
nativeImage.copyRect(4, 20, 16, 32, 4, 12, true, false);
|
|
nativeImage.copyRect(8, 20, 8, 32, 4, 12, true, false);
|
|
nativeImage.copyRect(12, 20, 16, 32, 4, 12, true, false);
|
|
nativeImage.copyRect(44, 16, -8, 32, 4, 4, true, false);
|
|
nativeImage.copyRect(48, 16, -8, 32, 4, 4, true, false);
|
|
nativeImage.copyRect(40, 20, 0, 32, 4, 12, true, false);
|
|
nativeImage.copyRect(44, 20, -8, 32, 4, 12, true, false);
|
|
nativeImage.copyRect(48, 20, -16, 32, 4, 12, true, false);
|
|
nativeImage.copyRect(52, 20, -8, 32, 4, 12, true, false);
|
|
}
|
|
|
|
setNoAlpha(image, 0, 0, 32, 16);
|
|
if (bl) {
|
|
doNotchTransparencyHack(image, 32, 0, 64, 32);
|
|
}
|
|
|
|
setNoAlpha(image, 0, 16, 64, 32);
|
|
setNoAlpha(image, 16, 48, 48, 64);
|
|
return image;
|
|
} else {
|
|
image.close();
|
|
LOGGER.warn("Discarding incorrectly sized ({}x{}) skin texture from {}", j, i, this.urlString);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static void doNotchTransparencyHack(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 & 0xFF) < 128) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = x; i < width; i++) {
|
|
for (int jx = y; jx < height; jx++) {
|
|
image.setPixelRGBA(i, jx, image.getPixelRGBA(i, jx) & 16777215);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void setNoAlpha(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) | 0xFF000000);
|
|
}
|
|
}
|
|
}
|
|
}
|