diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java index d7b0d901..6b39fcc1 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; @@ -32,7 +29,6 @@ import com.voxelmodpack.hdskins.util.AsyncCacheLoader; 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; @@ -61,12 +57,9 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; -public final class HDSkinManager implements IResourceManagerReloadListener { +public final class HDSkinManager implements IResourceManagerReloadListener, ISkinModifier { 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()); @@ -92,12 +85,18 @@ 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 void clearSkinCache() { + INSTANCE.clearSKinCache(); + } + 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); @@ -135,7 +134,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(); @@ -177,75 +176,77 @@ 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 (profileData.isPresent()) { + profileData.get().getTextures().forEach(textures::putIfAbsent); + } + if (textures.size() == Type.values().length) { - break; + return textures; } } + 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) { @@ -265,15 +266,11 @@ public final class HDSkinManager implements IResourceManagerReloadListener { 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() { + private void clearSKinCache() { LiteLoaderLogger.info("Clearing local player skin cache"); try { @@ -282,20 +279,17 @@ public final class HDSkinManager implements IResourceManagerReloadListener { 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) { @@ -314,6 +308,13 @@ 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(); + } + + @Override public void convertSkin(BufferedImage image, Graphics dest) { skinModifiers.forEach(a -> a.convertSkin(image, dest)); } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/ISkinAvailableCallback.java b/src/hdskins/java/com/voxelmodpack/hdskins/ISkinAvailableCallback.java new file mode 100644 index 00000000..33b94406 --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/ISkinAvailableCallback.java @@ -0,0 +1,13 @@ +package com.voxelmodpack.hdskins; + +/** + * Callback for when a skin is loaded. + * + */ +@FunctionalInterface +public interface ISkinAvailableCallback { + /** + * Called when a skin loads. + */ + void skinAvailable(); +} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/ImageBufferDownloadHD.java b/src/hdskins/java/com/voxelmodpack/hdskins/ImageBufferDownloadHD.java index a8257be3..e6b981b7 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 ISkinAvailableCallback callback; + + public ImageBufferDownloadHD withCallback(ISkinAvailableCallback 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.skinAvailable(); + } } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java index 336657ec..8db435a8 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java @@ -24,7 +24,7 @@ public class PreviewTexture extends ThreadDownloadImageData { } public boolean isTextureUploaded() { - return uploaded && this.getGlTextureId() > -1; + return uploaded && getGlTextureId() > -1; } @Override diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java index 23159208..4b5ccd8d 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java @@ -6,10 +6,9 @@ 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; @@ -26,37 +25,21 @@ public class PreviewTextureManager { this.textures = textures; } - private IImageBuffer getPreviewImageBuffer(MinecraftProfileTexture texture, ResourceLocation location, Type type, SkinManager.SkinAvailableCallback callback) { - if (type != Type.SKIN) { - return null; - } - - IImageBuffer buffer = new ImageBufferDownloadHD(); - - return 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())); - } - } - }; - } - @Nullable - public PreviewTexture getPreviewTexture(ResourceLocation location, 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); - PreviewTexture skinTexture = new PreviewTexture(texture, def, getPreviewImageBuffer(texture, location, type, callback)); + + 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); diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java index d6d6051c..2f8590b6 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java @@ -93,19 +93,22 @@ 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(); @@ -125,6 +128,7 @@ public class GuiSkins extends GuiScreen { if (!(Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT))) { updateCounter++; } + panorama.update(); localPlayer.updateModel(); @@ -185,7 +189,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,12 +221,6 @@ 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(); @@ -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/mixin/MixinImageBufferDownload.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinImageBufferDownload.java index 58be43b9..987dcf92 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;", + // convert skins from the mojang server + @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..7abf90e6 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java @@ -3,6 +3,8 @@ package com.voxelmodpack.hdskins.mixin; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.voxelmodpack.hdskins.HDSkinManager; +import com.voxelmodpack.hdskins.util.Optionals; + import net.minecraft.client.renderer.tileentity.TileEntitySkullRenderer; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.tileentity.TileEntitySkull; @@ -13,27 +15,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) { + @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(Optionals.getOrDefault(HDSkinManager.INSTANCE.getSkinLocation(profile, Type.SKIN, true), rl)); + } else { bindTexture(rl); + } } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/resources/ImageLoader.java b/src/hdskins/java/com/voxelmodpack/hdskins/resources/ImageLoader.java index 8e24cf4b..714ba2f3 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/resources/ImageLoader.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/resources/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/resources/SkinResourceManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/resources/SkinResourceManager.java index d894617f..19f5b71e 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/resources/SkinResourceManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/resources/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,8 +26,9 @@ 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(); + private ExecutorService executor; private Map uuidSkins = Maps.newHashMap(); private Map namedSkins = Maps.newHashMap(); @@ -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,29 @@ 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); - } - })); - - + 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); + } + })); } - } @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/server/SkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/server/SkinServer.java index 07259feb..267867b8 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/server/SkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/server/SkinServer.java @@ -25,7 +25,7 @@ import javax.annotation.Nullable; public interface SkinServer extends Exposable { - static final Gson gson = new GsonBuilder() + public static final Gson gson = new GsonBuilder() .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()) .create(); diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/upload/ThreadOpenFile.java b/src/hdskins/java/com/voxelmodpack/hdskins/upload/ThreadOpenFile.java index 409785d6..ebf8cb14 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/upload/ThreadOpenFile.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/upload/ThreadOpenFile.java @@ -21,12 +21,9 @@ public abstract class ThreadOpenFile extends Thread { */ protected final IOpenFileCallback parentScreen; - private JFileChooser fileDialog; - private static String lastChosenFile = null; - protected ThreadOpenFile(Minecraft minecraft, String dialogTitle, IOpenFileCallback callback) - throws IllegalStateException { + protected ThreadOpenFile(Minecraft minecraft, String dialogTitle, IOpenFileCallback callback) throws IllegalStateException { if (minecraft.isFullScreen()) { throw new IllegalStateException("Cannot open an awt window whilst minecraft is in full screen mode!"); } @@ -37,13 +34,13 @@ public abstract class ThreadOpenFile extends Thread { @Override public void run() { - fileDialog = new JFileChooser(); - fileDialog.setDialogTitle(this.dialogTitle); + JFileChooser fileDialog = new JFileChooser(); + fileDialog.setDialogTitle(dialogTitle); if (lastChosenFile != null) { fileDialog.setSelectedFile(new File(lastChosenFile)); } - fileDialog.setFileFilter(this.getFileFilter()); + fileDialog.setFileFilter(getFileFilter()); int dialogResult = fileDialog.showOpenDialog(InternalDialog.getAWTContext()); @@ -53,7 +50,7 @@ public abstract class ThreadOpenFile extends Thread { lastChosenFile = f.getAbsolutePath(); } - this.parentScreen.onFileOpenDialogClosed(fileDialog, dialogResult); + parentScreen.onFileOpenDialogClosed(fileDialog, dialogResult); } /** diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/util/Optionals.java b/src/hdskins/java/com/voxelmodpack/hdskins/util/Optionals.java new file mode 100644 index 00000000..e9f53347 --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/util/Optionals.java @@ -0,0 +1,16 @@ +package com.voxelmodpack.hdskins.util; + +import java.util.Optional; + +/** + * Silly optionals + */ +public final class Optionals { + public static T nullableOf(Optional optional) { + return getOrDefault(optional, null); + } + + public static T getOrDefault(Optional optional, T def) { + return optional.isPresent() ? optional.get() : def; + } +}