diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java index f8b139b5..7f0b378d 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java @@ -11,14 +11,11 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mojang.authlib.properties.Property; import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; -import com.mojang.util.UUIDTypeAdapter; import com.mumfrey.liteloader.core.LiteLoader; import com.mumfrey.liteloader.util.log.LiteLoaderLogger; import com.voxelmodpack.hdskins.gui.GuiSkins; @@ -31,7 +28,6 @@ import com.voxelmodpack.hdskins.skins.SkinServer; import com.voxelmodpack.hdskins.skins.ValhallaSkinServer; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IImageBuffer; -import net.minecraft.client.renderer.texture.ITextureObject; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.resources.DefaultPlayerSkin; import net.minecraft.client.resources.IResourceManager; @@ -63,9 +59,6 @@ import javax.annotation.Nonnull; public final class HDSkinManager implements IResourceManagerReloadListener { private static final ResourceLocation LOADING = new ResourceLocation("LOADING"); - private static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()) - .create(); private static final ExecutorService skinDownloadExecutor = Executors.newFixedThreadPool(8); public static final ListeningExecutorService skinUploadExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()); @@ -90,12 +83,14 @@ public final class HDSkinManager implements IResourceManagerReloadListener { private List skinModifiers = Lists.newArrayList(); private SkinResourceManager resources = new SkinResourceManager(); - // private ExecutorService executor = Executors.newCachedThreadPool(); private Class skinsClass = null; - private HDSkinManager() { + public static PreviewTextureManager getPreviewTextureManager(GameProfile profile) { + return new PreviewTextureManager(INSTANCE.getGatewayServer().getPreviewTextures(profile)); + } + private HDSkinManager() { // register default skin server types addSkinServerType(LegacySkinServer.class); addSkinServerType(ValhallaSkinServer.class); @@ -133,7 +128,7 @@ public final class HDSkinManager implements IResourceManagerReloadListener { Property textures = Iterables.getFirst(profile1.getProperties().get("textures"), null); if (textures != null) { String json = new String(Base64.getDecoder().decode(textures.getValue()), StandardCharsets.UTF_8); - MinecraftTexturesPayload texturePayload = GSON.fromJson(json, MinecraftTexturesPayload.class); + MinecraftTexturesPayload texturePayload = SkinServer.gson.fromJson(json, MinecraftTexturesPayload.class); if (texturePayload != null) { // name is optional String name = texturePayload.getProfileName(); @@ -175,125 +170,114 @@ public final class HDSkinManager implements IResourceManagerReloadListener { return url + (url.indexOf('?') > -1 ? '&' : '?') + Long.toString(new Date().getTime() / 1000); } - private void loadTexture(GameProfile profile, final Type type, final SkinAvailableCallback callback) { - if (profile.getId() != null) { - Map data = getProfileData(profile); - final MinecraftProfileTexture texture = data.get(type); - - String skinDir = type.toString().toLowerCase() + "s/"; - final ResourceLocation skin = new ResourceLocation("hdskins", skinDir + texture.getHash()); - File file2 = new File(LiteLoader.getAssetsDirectory(), "hd/" + skinDir + texture.getHash().substring(0, 2) + "/" + texture.getHash()); - - final IImageBuffer imagebufferdownload = type == Type.SKIN ? new ImageBufferDownloadHD() : null; - - ITextureObject texObject = new ThreadDownloadImageETag(file2, bustCache(texture.getUrl()), - DefaultPlayerSkin.getDefaultSkinLegacy(), - new IImageBuffer() { - @Nonnull - @Override - public BufferedImage parseUserSkin(@Nonnull BufferedImage image) { - BufferedImage image1 = image; - if (imagebufferdownload != null) { - image1 = imagebufferdownload.parseUserSkin(image); - } - return image1 == null ? image : image1; - } - - @Override - public void skinAvailable() { - if (imagebufferdownload != null) { - imagebufferdownload.skinAvailable(); - } - callback.skinAvailable(type, skin, texture); - } - }); - - // schedule texture loading on the main thread. - TextureLoader.loadTexture(skin, texObject); + private void loadTexture(GameProfile profile, Type type, SkinAvailableCallback callback) { + if (profile.getId() == null) { + return; } + + MinecraftProfileTexture texture = getProfileData(profile).get(type); + + String skinDir = type.toString().toLowerCase() + "s/"; + + ResourceLocation skin = new ResourceLocation("hdskins", skinDir + texture.getHash()); + + File etag = new File(LiteLoader.getAssetsDirectory(), "hd/" + skinDir + texture.getHash().substring(0, 2) + "/" + texture.getHash()); + + IImageBuffer buffer = new ImageBufferDownloadHD() { + @Nonnull + @Override + public BufferedImage parseUserSkin(@Nonnull BufferedImage image) { + if (type != Type.SKIN) { + return image; + } + + BufferedImage converted = super.parseUserSkin(image); + + return converted == null ? image : converted; + } + }.withCallback(() -> callback.skinAvailable(type, skin, texture)); + + // schedule texture loading on the main thread. + TextureLoader.loadTexture(skin, new ThreadDownloadImageETag(etag, bustCache(texture.getUrl()), DefaultPlayerSkin.getDefaultSkinLegacy(), buffer)); } private Map loadProfileData(GameProfile profile) { Map textures = Maps.newEnumMap(Type.class); - for (SkinServer server : skinServers) { - Optional profileData = server.loadProfileData(profile); - profileData.map(MinecraftTexturesPayload::getTextures).ifPresent(it -> it.forEach(textures::putIfAbsent)); - if (textures.size() == Type.values().length) { - break; - } - } + skinServers.forEach(server -> server + .loadProfileData(profile) + .map(MinecraftTexturesPayload::getTextures) + .ifPresent(a -> a.forEach(textures::putIfAbsent))); + return textures; } public Map getProfileData(GameProfile profile) { boolean was = !skins.asMap().containsKey(profile); + Map textures = skins.getUnchecked(profile); + // This is the initial value. Refreshing will load it asynchronously. if (was) { skins.refresh(profile); } + return textures; } public void addSkinServerType(Class type) { Preconditions.checkArgument(!type.isInterface(), "type cannot be an interface"); Preconditions.checkArgument(!Modifier.isAbstract(type.getModifiers()), "type cannot be abstract"); + ServerType st = type.getAnnotation(ServerType.class); - if (st == null) { - throw new IllegalArgumentException("class is not annotated with @ServerType"); - } - this.skinServerTypes.put(st.value(), type); + + Preconditions.checkArgument(st != null, "class is not annotated with @ServerType"); + + skinServerTypes.put(st.value(), type); } public Class getSkinServerClass(String type) { - return this.skinServerTypes.get(type); + return skinServerTypes.get(type); } public void addSkinServer(SkinServer skinServer) { - this.skinServers.add(skinServer); + skinServers.add(skinServer); } // TODO: Why is this deprecated? @Deprecated public SkinServer getGatewayServer() { - return this.skinServers.get(0); + return skinServers.get(0); } public void setEnabled(boolean enabled) { this.enabled = enabled; } - public static PreviewTextureManager getPreviewTextureManager(GameProfile profile) { - return new PreviewTextureManager(INSTANCE.getGatewayServer().getPreviewTextures(profile)); - } - public void addClearListener(ISkinCacheClearListener listener) { clearListeners.add(listener); } - public static void clearSkinCache() { + public void clearSkinCache() { LiteLoaderLogger.info("Clearing local player skin cache"); try { FileUtils.deleteDirectory(new File(LiteLoader.getAssetsDirectory(), "skins")); FileUtils.deleteDirectory(new File(LiteLoader.getAssetsDirectory(), "hd")); + TextureManager textures = Minecraft.getMinecraft().getTextureManager(); - INSTANCE.skinCache.values().stream() - .flatMap(m -> m.values().stream()) - .forEach(textures::deleteTexture); - INSTANCE.skinCache.clear(); - INSTANCE.skins.invalidateAll(); + + skinCache.values().stream().flatMap(m -> m.values().stream()).forEach(textures::deleteTexture); + skinCache.clear(); + skins.invalidateAll(); } catch (IOException var1) { var1.printStackTrace(); } - INSTANCE.clearListeners = INSTANCE.clearListeners.stream() - .filter(HDSkinManager::onSkinCacheCleared) - .collect(Collectors.toList()); + clearListeners = clearListeners.stream().filter(this::onSkinCacheCleared).collect(Collectors.toList()); } - private static boolean onSkinCacheCleared(ISkinCacheClearListener callback) { + private boolean onSkinCacheCleared(ISkinCacheClearListener callback) { try { return callback.onSkinCacheCleared(); } catch (Exception e) { @@ -312,14 +296,18 @@ public final class HDSkinManager implements IResourceManagerReloadListener { return loc == null ? res : loc; } + public void convertSkin(BufferedImage image) { + Graphics graphics = image.getGraphics(); + convertSkin(image, graphics); + graphics.dispose(); + } + public void convertSkin(BufferedImage image, Graphics dest) { - for (ISkinModifier skin : skinModifiers) { - skin.convertSkin(image, dest); - } + skinModifiers.forEach(a -> a.convertSkin(image, dest)); } @Override public void onResourceManagerReload(IResourceManager resourceManager) { - this.resources.onResourceManagerReload(resourceManager); + resources.onResourceManagerReload(resourceManager); } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/ImageBufferDownloadHD.java b/src/hdskins/java/com/voxelmodpack/hdskins/ImageBufferDownloadHD.java index a8257be3..7829408d 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/ImageBufferDownloadHD.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/ImageBufferDownloadHD.java @@ -3,6 +3,7 @@ package com.voxelmodpack.hdskins; import net.minecraft.client.renderer.IImageBuffer; import javax.annotation.Nullable; + import java.awt.Graphics; import java.awt.image.BufferedImage; @@ -12,6 +13,13 @@ public class ImageBufferDownloadHD implements IImageBuffer { private Graphics graphics; private BufferedImage image; + private Runnable callback; + + public ImageBufferDownloadHD withCallback(Runnable callback) { + this.callback = callback; + return this; + } + @Override @Nullable @SuppressWarnings({"SuspiciousNameCombination", "NullableProblems"}) @@ -19,6 +27,7 @@ public class ImageBufferDownloadHD implements IImageBuffer { if (downloadedImage == null) { return null; } + int imageWidth = downloadedImage.getWidth(); int imageHeight = downloadedImage.getHeight(); if (imageHeight == imageWidth) { @@ -61,5 +70,8 @@ public class ImageBufferDownloadHD implements IImageBuffer { @Override public void skinAvailable() { + if (callback != null) { + callback.run(); + } } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java b/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java index 2b9d17a3..9fe6d085 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/LiteModHDSkins.java @@ -55,7 +55,7 @@ public class LiteModHDSkins implements InitCompleteListener, ViewportListener, C @Override public void upgradeSettings(String version, File configPath, File oldConfigPath) { - HDSkinManager.clearSkinCache(); + HDSkinManager.INSTANCE.clearSkinCache(); } @Override diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java index e5430ee2..8db435a8 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java @@ -6,26 +6,31 @@ import net.minecraft.util.ResourceLocation; import javax.annotation.Nullable; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; + public class PreviewTexture extends ThreadDownloadImageData { private boolean uploaded; private String model; - public PreviewTexture(@Nullable String model, String url, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) { - super(null, url, fallbackTexture, imageBuffer); + public PreviewTexture(MinecraftProfileTexture texture, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) { + super(null, texture.getUrl(), fallbackTexture, imageBuffer); - this.model = model == null ? "default" : model; + model = texture.getMetadata("model"); + if (model == null) { + model = "default"; + } } public boolean isTextureUploaded() { - return uploaded && this.getGlTextureId() > -1; + return uploaded && getGlTextureId() > -1; } @Override public void deleteGlTexture() { super.deleteGlTexture(); - this.uploaded = true; + uploaded = true; } public boolean hasModel() { @@ -35,4 +40,8 @@ public class PreviewTexture extends ThreadDownloadImageData { public boolean usesThinArms() { return "thin".equals(model); } + + public String getModel() { + return model; + } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java index 057fd56f..4b5ccd8d 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java @@ -2,12 +2,13 @@ package com.voxelmodpack.hdskins; import com.google.common.collect.Maps; import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; + import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IImageBuffer; -import net.minecraft.client.resources.SkinManager; +import net.minecraft.client.resources.SkinManager.SkinAvailableCallback; import net.minecraft.util.ResourceLocation; -import java.awt.image.BufferedImage; import java.util.Map; import javax.annotation.Nullable; @@ -18,35 +19,28 @@ import javax.annotation.Nullable; */ public class PreviewTextureManager { - private final Map textures; + private final Map textures; - PreviewTextureManager(Map textures) { + PreviewTextureManager(Map textures) { this.textures = textures; } @Nullable - public PreviewTexture getPreviewTexture(ResourceLocation location, MinecraftProfileTexture.Type type, ResourceLocation def, - @Nullable SkinManager.SkinAvailableCallback callback) { + public PreviewTexture getPreviewTexture(ResourceLocation location, Type type, ResourceLocation def, @Nullable SkinAvailableCallback callback) { if (!textures.containsKey(type)) { return null; } - MinecraftProfileTexture texture = textures.get(type); - IImageBuffer buffer = new ImageBufferDownloadHD(); - PreviewTexture skinTexture = new PreviewTexture(texture.getMetadata("model"), texture.getUrl(), def, - type == MinecraftProfileTexture.Type.SKIN ? new IImageBuffer() { - @Override - @Nullable - public BufferedImage parseUserSkin(BufferedImage image) { - return buffer.parseUserSkin(image); - } - @Override - public void skinAvailable() { - if (callback != null) { - callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap())); - } - } - } : null); + MinecraftProfileTexture texture = textures.get(type); + + IImageBuffer buffer = type != Type.SKIN ? null : new ImageBufferDownloadHD().withCallback(() -> { + if (callback != null) { + callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap())); + } + }); + + PreviewTexture skinTexture = new PreviewTexture(texture, def, buffer); + Minecraft.getMinecraft().getTextureManager().loadTexture(location, skinTexture); return skinTexture; diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java index db26b9c3..6718b149 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java @@ -12,9 +12,9 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mumfrey.liteloader.util.log.LiteLoaderLogger; import com.voxelmodpack.hdskins.HDSkinManager; -import com.voxelmodpack.hdskins.skins.SkinServer; import com.voxelmodpack.hdskins.skins.SkinUploadResponse; import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; @@ -93,20 +93,23 @@ public class GuiSkins extends GuiScreen { private boolean thinArmType = false; public GuiSkins() { + instance = this; + Minecraft minecraft = Minecraft.getMinecraft(); GameProfile profile = minecraft.getSession().getProfile(); localPlayer = getModel(profile); remotePlayer = getModel(profile); - RenderManager rm = Minecraft.getMinecraft().getRenderManager(); + + RenderManager rm = minecraft.getRenderManager(); rm.renderEngine = minecraft.getTextureManager(); rm.options = minecraft.gameSettings; rm.renderViewEntity = localPlayer; - reloadRemoteSkin(); - fetchingSkin = true; - instance = this; + reloadRemoteSkin(); + + fetchingSkin = true; panorama = new CubeMap(this); initPanorama(); @@ -126,6 +129,7 @@ public class GuiSkins extends GuiScreen { if (!(Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT))) { updateCounter++; } + panorama.update(); localPlayer.updateModel(); @@ -186,7 +190,9 @@ public class GuiSkins extends GuiScreen { @Override public void initGui() { - enableDnd(); + GLWindow.current().setDropTargetListener((FileDropListener) files -> { + files.stream().findFirst().ifPresent(instance::loadLocalFile); + }); panorama.init(); @@ -215,18 +221,12 @@ public class GuiSkins extends GuiScreen { } - private void enableDnd() { - GLWindow.current().setDropTargetListener((FileDropListener) files -> { - files.stream().findFirst().ifPresent(instance::loadLocalFile); - }); - } - @Override public void onGuiClosed() { super.onGuiClosed(); localPlayer.releaseTextures(); remotePlayer.releaseTextures(); - HDSkinManager.clearSkinCache(); + HDSkinManager.INSTANCE.clearSkinCache(); GLWindow.current().clearDropTargetListener(); } @@ -438,8 +438,7 @@ public class GuiSkins extends GuiScreen { drawHoveringText(I18n.format(text), mouseX, y); } if (btnAbout.isMouseOver()) { - SkinServer gateway = HDSkinManager.INSTANCE.getGatewayServer(); - drawHoveringText(Splitter.on("\r\n").splitToList(gateway.toString()), mouseX, mouseY); + drawHoveringText(Splitter.on("\r\n").splitToList(HDSkinManager.INSTANCE.getGatewayServer().toString()), mouseX, mouseY); } if (fetchingSkin) { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/HDSkinsConfigPanel.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/HDSkinsConfigPanel.java index ed2b89e5..27c91c90 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/HDSkinsConfigPanel.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/HDSkinsConfigPanel.java @@ -41,7 +41,7 @@ public class HDSkinsConfigPanel implements ConfigPanel { Minecraft mc = Minecraft.getMinecraft(); if (button.mousePressed(mc, mouseX, mouseY)) { - HDSkinManager.clearSkinCache(); + HDSkinManager.INSTANCE.clearSkinCache(); } else if (checkbox.mousePressed(mc, mouseX, mouseY)) { checkbox.checked = !checkbox.checked; mod.experimentalSkinDrop = checkbox.checked; diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinImageBufferDownload.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinImageBufferDownload.java index 58be43b9..1640eadd 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinImageBufferDownload.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinImageBufferDownload.java @@ -8,25 +8,18 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.awt.Graphics; import java.awt.image.BufferedImage; @Mixin(ImageBufferDownload.class) public abstract class MixinImageBufferDownload implements IImageBuffer { - @Inject( - method = "parseUserSkin(Ljava/awt/image/BufferedImage;)Ljava/awt/image/BufferedImage;", + @Inject(method = "parseUserSkin(Ljava/awt/image/BufferedImage;)Ljava/awt/image/BufferedImage;", at = @At("RETURN"), cancellable = true) private void update(BufferedImage image, CallbackInfoReturnable ci) { // convert skins from mojang server - BufferedImage image2 = ci.getReturnValue(); - boolean isLegacy = image.getHeight() == 32; - if (isLegacy) { - Graphics graphics = image2.getGraphics(); - HDSkinManager.INSTANCE.convertSkin(image2, graphics); - graphics.dispose(); + if (image.getHeight() == 32) { + HDSkinManager.INSTANCE.convertSkin(ci.getReturnValue()); } } - } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java index 432c383d..8575b7f3 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java @@ -12,32 +12,27 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Optional; - @Mixin(NetworkPlayerInfo.class) public abstract class MixinPlayerInfo { @Shadow public abstract GameProfile getGameProfile(); - @Inject( - method = "getLocationSkin", + @Inject(method = "getLocationSkin", cancellable = true, at = @At("RETURN")) private void getLocationSkin(CallbackInfoReturnable ci) { getTextureLocation(ci, Type.SKIN); } - @Inject( - method = "getLocationCape", + @Inject(method = "getLocationCape", cancellable = true, at = @At("RETURN")) private void getLocationCape(CallbackInfoReturnable ci) { getTextureLocation(ci, Type.CAPE); } - @Inject( - method = "getLocationElytra", + @Inject(method = "getLocationElytra", cancellable = true, at = @At("RETURN")) private void getLocationElytra(CallbackInfoReturnable ci) { @@ -45,24 +40,20 @@ public abstract class MixinPlayerInfo { } private void getTextureLocation(CallbackInfoReturnable ci, Type type) { - Optional texture = HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), type, true); - texture.ifPresent(ci::setReturnValue); + HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), type, true).ifPresent(ci::setReturnValue); } - @Inject( - method = "getSkinType", + @Inject(method = "getSkinType", cancellable = true, at = @At("RETURN")) private void getSkinType(CallbackInfoReturnable ci) { MinecraftProfileTexture skin = HDSkinManager.INSTANCE.getProfileData(getGameProfile()).get(Type.SKIN); if (skin != null) { - String type = skin.getMetadata("model"); - if (type == null) - type = "default"; - String type1 = type; - Optional texture = HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), Type.SKIN, false); + HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), Type.SKIN, false).ifPresent(res -> { + String type = skin.getMetadata("model"); - texture.ifPresent((res) -> ci.setReturnValue(type1)); + ci.setReturnValue(type == null ? "default" : type); + }); } } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java index dda9662c..cf49650c 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java @@ -3,6 +3,7 @@ package com.voxelmodpack.hdskins.mixin; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.voxelmodpack.hdskins.HDSkinManager; + import net.minecraft.client.renderer.tileentity.TileEntitySkullRenderer; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.tileentity.TileEntitySkull; @@ -13,27 +14,20 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import javax.annotation.Nullable; -import java.util.Optional; @Mixin(TileEntitySkullRenderer.class) public abstract class MixinSkullRenderer extends TileEntitySpecialRenderer { - @Redirect( - method = "renderSkull", - at = @At( - value = "INVOKE", + @Redirect(method = "renderSkull", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/tileentity/TileEntitySkullRenderer;bindTexture(Lnet/minecraft/util/ResourceLocation;)V", ordinal = 4)) - private void onBindTexture(TileEntitySkullRenderer tesr, ResourceLocation rl, float x, float y, float z, EnumFacing facing, float rotation, int meta, - @Nullable GameProfile profile, int p_180543_8_, float ticks) { + private void onBindTexture(TileEntitySkullRenderer tesr, ResourceLocation rl, float x, float y, float z, // ow my back + EnumFacing facing, float rotation, int meta, @Nullable GameProfile profile, int a, float ticks) { if (profile != null) { - Optional skin = HDSkinManager.INSTANCE.getSkinLocation(profile, Type.SKIN, true); - if (skin.isPresent()) - // rebind - bindTexture(skin.get()); - else - bindTexture(rl); - } else + bindTexture(HDSkinManager.INSTANCE.getSkinLocation(profile, Type.SKIN, true).orElse(rl)); + } else { bindTexture(rl); + } } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/resource/ImageLoader.java b/src/hdskins/java/com/voxelmodpack/hdskins/resource/ImageLoader.java index 6a4ff50f..59bbd11a 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/resource/ImageLoader.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/resource/ImageLoader.java @@ -21,7 +21,7 @@ public class ImageLoader implements Supplier { private final ResourceLocation original; public ImageLoader(ResourceLocation loc) { - this.original = loc; + original = loc; } @Override @@ -49,7 +49,6 @@ public class ImageLoader implements Supplier { @Nullable private static BufferedImage getImage(ResourceLocation res) { - try (InputStream in = mc.getResourceManager().getResource(res).getInputStream()) { return TextureUtil.readBufferedImage(in); } catch (IOException e) { @@ -59,9 +58,9 @@ public class ImageLoader implements Supplier { @Nullable private ResourceLocation loadSkin(BufferedImage image) { - ResourceLocation conv = new ResourceLocation(original.getResourceDomain() + "-converted", original.getResourcePath()); boolean success = mc.getTextureManager().loadTexture(conv, new DynamicTextureImage(image)); + return success ? conv : null; } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java index d02b22df..59999b75 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java @@ -17,6 +17,7 @@ import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -25,6 +26,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; public class SkinResourceManager implements IResourceManagerReloadListener { + private final Gson GSON = new Gson(); private ExecutorService executor = Executors.newSingleThreadExecutor(); @@ -41,15 +43,16 @@ public class SkinResourceManager implements IResourceManagerReloadListener { executor = Executors.newSingleThreadExecutor(); inProgress.clear(); converted.clear(); + for (String domain : resourceManager.getResourceDomains()) { try { for (IResource res : resourceManager.getAllResources(new ResourceLocation(domain, "textures/skins/skins.json"))) { try { - SkinData data = getSkinData(res.getInputStream()); - for (Skin s : data.skins) { + for (Skin s : getSkinData(res.getInputStream())) { if (s.uuid != null) { uuidSkins.put(s.uuid, s); } + if (s.name != null) { namedSkins.put(s.name, s); } @@ -58,16 +61,13 @@ public class SkinResourceManager implements IResourceManagerReloadListener { LiteLoaderLogger.warning(je, "Invalid skins.json in %s", res.getResourcePackName()); } } - } catch (IOException e) { - // ignore - } + } catch (IOException ignored) { } } - } - private SkinData getSkinData(InputStream stream) { + private List getSkinData(InputStream stream) { try { - return new Gson().fromJson(new InputStreamReader(stream), SkinData.class); + return GSON.fromJson(new InputStreamReader(stream), SkinData.class).skins; } finally { IOUtils.closeQuietly(stream); } @@ -75,16 +75,14 @@ public class SkinResourceManager implements IResourceManagerReloadListener { @Nullable public ResourceLocation getPlayerTexture(GameProfile profile, Type type) { - if (type != Type.SKIN) - // not supported - return null; - - Skin skin = getSkin(profile); - if (skin != null) { - final ResourceLocation res = skin.getTexture(); - return getConvertedResource(res); + if (type == Type.SKIN) { + Skin skin = getSkin(profile); + if (skin != null) { + return getConvertedResource(skin.getTexture()); + } } - return null; + + return null; // not supported } /** @@ -99,31 +97,35 @@ public class SkinResourceManager implements IResourceManagerReloadListener { return converted.get(res); } - private void loadSkinResource(@Nullable final ResourceLocation res) { + /** + * read and convert in a new thread + */ + private void loadSkinResource(@Nullable ResourceLocation res) { if (res != null) { - // read and convert in a new thread - this.inProgress.computeIfAbsent(res, r -> CompletableFuture.supplyAsync(new ImageLoader(r), executor) - .whenComplete((loc, t) -> { - if (loc != null) - converted.put(res, loc); - else { - LogManager.getLogger().warn("Errored while processing {}. Using original.", res, t); - converted.put(res, res); - } - })); - - + if (!inProgress.containsKey(res)) { + inProgress.put(res, scheduleConvertion(res)); + } } + } + private Future scheduleConvertion(ResourceLocation res) { + return CompletableFuture.supplyAsync(new ImageLoader(res), executor).whenComplete((result, error) -> { + if (result == null) { + result = res; + LogManager.getLogger().warn("Errored while processing {}. Using original.", res, error); + } + + converted.put(res, result); + }); } @Nullable private Skin getSkin(GameProfile profile) { - Skin skin = this.uuidSkins.get(profile.getId()); - if (skin == null) { - skin = this.namedSkins.get(profile.getName()); + Skin skin = uuidSkins.get(profile.getId()); + if (skin != null) { + return skin; } - return skin; - } + return namedSkins.get(profile.getName()); + } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java index 74137ea8..90ba0420 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java @@ -25,7 +25,7 @@ import javax.annotation.Nullable; public interface SkinServer extends Exposable { - static final Gson gson = new GsonBuilder() + Gson gson = new GsonBuilder() .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()) .create();