From a24b6a108c403bbec3b7bba40ce79fde23acd410 Mon Sep 17 00:00:00 2001 From: Matthew Messinger Date: Sat, 18 Aug 2018 23:40:28 -0400 Subject: [PATCH] Refactors for AvatarAPI Won't compile yet because AvatarAPI isn't on maven yet. --- build.gradle | 4 + .../voxelmodpack/hdskins/HDSkinManager.java | 46 ++++-- .../hdskins/HDSkinTextureService.java | 149 ++++++++++++++++++ .../voxelmodpack/hdskins/LocalTexture.java | 28 ++-- .../voxelmodpack/hdskins/PreviewTexture.java | 7 +- .../hdskins/PreviewTextureManager.java | 27 ++-- .../hdskins/gui/EntityPlayerModel.java | 25 +-- .../voxelmodpack/hdskins/gui/GuiSkins.java | 59 ++++--- .../hdskins/gui/RenderPlayerModel.java | 17 +- .../hdskins/mixin/MixinPlayerInfo.java | 68 -------- .../hdskins/mixin/MixinSkullRenderer.java | 39 ----- .../hdskins/mixin/package-info.java | 7 - .../hdskins/resource/SkinResourceManager.java | 9 +- .../hdskins/skins/BethlehemSkinServer.java | 5 +- .../hdskins/skins/LegacySkinServer.java | 47 +++--- .../hdskins/skins/SkinServer.java | 10 +- .../hdskins/skins/SkinUpload.java | 8 +- .../hdskins/skins/TexturesPayload.java | 51 ++++++ .../hdskins/skins/ValhallaSkinServer.java | 21 ++- .../java/com/minelittlepony/PonyManager.java | 3 - .../hdskins/gui/EntityPonyModel.java | 7 +- .../hdskins/gui/GuiSkinsMineLP.java | 18 +-- .../hdskins/gui/RenderPonyModel.java | 9 +- .../mixin/MixinNetworkPlayerInfo.java | 22 ++- .../render/player/RenderPonyPlayer.java | 15 +- 25 files changed, 408 insertions(+), 293 deletions(-) create mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/HDSkinTextureService.java delete mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java delete mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java delete mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/mixin/package-info.java create mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/skins/TexturesPayload.java diff --git a/build.gradle b/build.gradle index 03d2586a..59efd0c3 100644 --- a/build.gradle +++ b/build.gradle @@ -45,12 +45,16 @@ sourceSets { ext.refMap = 'minelp.mixin.refmap.json' } } +repositories { + mavenLocal() +} dependencies { // use the same version as httpclient compile('org.apache.httpcomponents:httpmime:4.3.2') { transitive = false } + deobfCompile 'com.minelittlepony:AvatarAPI:1.0-SNAPSHOT' } litemod { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java index 4daeaf5d..d756d630 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinManager.java @@ -6,11 +6,14 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureProfile; +import com.minelittlepony.avatar.texture.TextureType; 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; @@ -31,7 +34,6 @@ import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.resources.DefaultPlayerSkin; import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.IResourceManagerReloadListener; -import net.minecraft.client.resources.SkinManager.SkinAvailableCallback; import net.minecraft.util.ResourceLocation; import org.apache.commons.io.FileUtils; import org.apache.http.impl.client.CloseableHttpClient; @@ -55,6 +57,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; import java.util.stream.Collectors; import javax.annotation.Nonnull; @@ -76,9 +79,10 @@ public final class HDSkinManager implements IResourceManagerReloadListener { private BiMap> skinServerTypes = HashBiMap.create(2); private List skinServers = Lists.newArrayList(); - private Map> skinCache = Maps.newHashMap(); + private Map> skinCache = Maps.newHashMap(); - private LoadingCache> skins = CacheBuilder.newBuilder() + @Deprecated + private LoadingCache> skins = CacheBuilder.newBuilder() .initialCapacity(20) .maximumSize(100) .expireAfterWrite(4, TimeUnit.HOURS) @@ -115,7 +119,8 @@ public final class HDSkinManager implements IResourceManagerReloadListener { return new GuiSkins(); } - public Optional getSkinLocation(GameProfile profile1, final Type type, boolean loadIfAbsent) { + @Deprecated + public Optional getSkinLocation(GameProfile profile1, final TextureType type, boolean loadIfAbsent) { if (!enabled) { return Optional.empty(); } @@ -161,7 +166,7 @@ public final class HDSkinManager implements IResourceManagerReloadListener { if (skin == null) { if (loadIfAbsent && getProfileData(profile).containsKey(type)) { skinCache.get(profile.getId()).put(type, LOADING); - loadTexture(profile, type, (t, loc, tex) -> skinCache.get(profile.getId()).put(t, loc)); + loadTexture(profile, type, (t, loc) -> skinCache.get(profile.getId()).put(t, loc.getLocation())); } return Optional.empty(); } @@ -172,18 +177,19 @@ 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) { + @Deprecated + private void loadTexture(GameProfile profile, final TextureType type, final BiConsumer callback) { if (profile.getId() != null) { - Map data = getProfileData(profile); - final MinecraftProfileTexture texture = data.get(type); + Map data = getProfileData(profile); + final TextureProfile 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; + final IImageBuffer imagebufferdownload = type == TextureType.SKIN ? new ImageBufferDownloadHD() : null; - ITextureObject texObject = new ThreadDownloadImageETag(file2, bustCache(texture.getUrl()), + ITextureObject texObject = new ThreadDownloadImageETag(file2, bustCache(texture.getUrl().toString()), DefaultPlayerSkin.getDefaultSkinLegacy(), new IImageBuffer() { @Nonnull @@ -201,7 +207,7 @@ public final class HDSkinManager implements IResourceManagerReloadListener { if (imagebufferdownload != null) { imagebufferdownload.skinAvailable(); } - callback.skinAvailable(type, skin, texture); + callback.accept(type, new TextureData(skin, texture)); } }); @@ -210,8 +216,9 @@ public final class HDSkinManager implements IResourceManagerReloadListener { } } - private Map loadProfileData(GameProfile profile) { - Map textures = Maps.newEnumMap(Type.class); + @Deprecated + private Map loadProfileData(GameProfile profile) { + Map textures = Maps.newHashMap(); for (SkinServer server : skinServers) { try { server.loadProfileData(profile).getTextures().forEach(textures::putIfAbsent); @@ -226,9 +233,10 @@ public final class HDSkinManager implements IResourceManagerReloadListener { return textures; } - public Map getProfileData(GameProfile profile) { + @Deprecated + public Map getProfileData(GameProfile profile) { boolean was = !skins.asMap().containsKey(profile); - Map textures = skins.getUnchecked(profile); + Map textures = skins.getUnchecked(profile); // This is the initial value. Refreshing will load it asynchronously. if (was) { skins.refresh(profile); @@ -259,12 +267,16 @@ public final class HDSkinManager implements IResourceManagerReloadListener { return this.skinServers.get(0); } + public List getSkinServers() { + return ImmutableList.copyOf(skinServers); + } + public void setEnabled(boolean enabled) { this.enabled = enabled; } public static CompletableFuture getPreviewTextureManager(GameProfile profile) { - return INSTANCE.getGatewayServer().getPreviewTextures(profile).thenApply(PreviewTextureManager::new); + return INSTANCE.getGatewayServer().getPreviewTextures(profile).thenApply(p -> new PreviewTextureManager(p.getTextures())); } public void addClearListener(ISkinCacheClearListener listener) { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinTextureService.java b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinTextureService.java new file mode 100644 index 00000000..20e384d4 --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/HDSkinTextureService.java @@ -0,0 +1,149 @@ +package com.voxelmodpack.hdskins; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Iterables; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureProfile; +import com.minelittlepony.avatar.texture.TextureService; +import com.minelittlepony.avatar.texture.TextureType; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; +import com.voxelmodpack.hdskins.skins.CallableFutures; +import com.voxelmodpack.hdskins.skins.SkinServer; +import net.minecraft.client.renderer.IImageBuffer; +import net.minecraft.client.renderer.texture.ITextureObject; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.util.ResourceLocation; +import org.apache.http.client.utils.URIBuilder; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Calendar; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; + +import javax.annotation.Nullable; + +public class HDSkinTextureService implements TextureService { + + private static final Logger logger = LogManager.getLogger(); + private static ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); + + private final LoadingCache>> cache = CacheBuilder.newBuilder() + .expireAfterAccess(15, TimeUnit.SECONDS) + .build(new CacheLoader>>() { + @Override + public CompletableFuture> load(GameProfile key) { + return CallableFutures.asyncFailableFuture(() -> loadTexturesFromServer(key), THREAD_POOL) + .exceptionally(e -> { + logger.catching(e); + return Collections.emptyMap(); + }); + } + }); + + private BiMap> skinServerTypes = HashBiMap.create(2); + + @Override + public CompletableFuture> loadProfileTextures(GameProfile profile) { + // try to recreate a broken gameprofile + // happens when server sends a random profile with skin and displayname + Property textures = Iterables.getFirst(profile.getProperties().get("textures"), null); + if (textures != null) { + String json = new String(Base64.getDecoder().decode(textures.getValue()), StandardCharsets.UTF_8); + MinecraftTexturesPayload texturePayload = SkinServer.gson.fromJson(json, MinecraftTexturesPayload.class); + if (texturePayload != null) { + // name is optional + String name = texturePayload.getProfileName(); + UUID uuid = texturePayload.getProfileId(); + // uuid is required + if (uuid != null) { + profile = new GameProfile(uuid, name); + } + + // probably uses this texture for a reason. Don't mess with it. + if (!texturePayload.getTextures().isEmpty() && texturePayload.getProfileId() == null) { + return CompletableFuture.completedFuture(Collections.emptyMap()); + } + } + } + return cache.getUnchecked(profile); + } + + private Map loadTexturesFromServer(GameProfile profile) throws IOException { + + Map textures = new HashMap<>(); + for (SkinServer server : HDSkinManager.INSTANCE.getSkinServers()) { + Map payload = server.loadProfileData(profile).getTextures(); + if (payload != null) { + payload.forEach(textures::putIfAbsent); + } + } + return textures; + } + + @Override + public TextureData loadTexture(TextureType type, TextureProfile texture, @Nullable BiConsumer callback) { + + String url = bustCache(texture.getUrl()); + String skinDir = type.toString().toLowerCase() + "s/"; + final ResourceLocation skin = new ResourceLocation("hdskins", skinDir + texture.getHash()); + TextureData data = new TextureData(skin, texture); + + File file2 = new File(Launch.assetsDir, "hd/" + skinDir + texture.getHash().substring(0, 2) + "/" + texture.getHash()); + + final IImageBuffer buffer = type == TextureType.SKIN ? new ImageBufferDownloadHD() : null; + + + // an actual callback is not needed because that is handled by CompletableFuture + ITextureObject texObject = new ThreadDownloadImageETag(file2, url, DefaultPlayerSkin.getDefaultSkinLegacy(), + new IImageBuffer() { + @Override + public BufferedImage parseUserSkin(BufferedImage image) { + BufferedImage image1 = image; + if (buffer != null) { + image1 = buffer.parseUserSkin(image); + } + return image1 == null ? image : image1; + } + + @Override + public void skinAvailable() { + if (callback != null) { + callback.accept(type, data); + } + } + + }); + TextureLoader.loadTexture(skin, texObject); + + return new TextureData(skin, texture); + } + + private static String bustCache(URI url) { + + long time = Calendar.getInstance().getTimeInMillis(); + + return new URIBuilder(url).addParameter(Long.toString(time), null).toString(); + } + +} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/LocalTexture.java b/src/hdskins/java/com/voxelmodpack/hdskins/LocalTexture.java index 6b2ee1a7..1b416191 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/LocalTexture.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/LocalTexture.java @@ -1,20 +1,20 @@ package com.voxelmodpack.hdskins; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureType; +import com.mojang.authlib.GameProfile; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.util.ResourceLocation; + import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.util.function.BiConsumer; import javax.imageio.ImageIO; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.texture.DynamicTexture; -import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.client.resources.SkinManager.SkinAvailableCallback; -import net.minecraft.util.ResourceLocation; - public class LocalTexture { private final TextureManager textureManager = Minecraft.getMinecraft().getTextureManager(); @@ -27,13 +27,13 @@ public class LocalTexture { private final IBlankSkinSupplier blank; - private final Type type; + private final TextureType type; - public LocalTexture(GameProfile profile, Type type, IBlankSkinSupplier blank) { + public LocalTexture(GameProfile profile, TextureType type, IBlankSkinSupplier blank) { this.blank = blank; this.type = type; - String file = type.name().toLowerCase() + "s/preview_${profile.getName()}.png"; + String file = type.toString().toLowerCase() + "s/preview_${profile.getName()}.png"; remoteResource = new ResourceLocation(file); textureManager.deleteTexture(remoteResource); @@ -73,7 +73,7 @@ public class LocalTexture { return remote; } - public void setRemote(PreviewTextureManager ptm, SkinAvailableCallback callback) { + public void setRemote(PreviewTextureManager ptm, BiConsumer callback) { clearRemote(); remote = ptm.getPreviewTexture(remoteResource, type, blank.getBlankSkin(type), callback); @@ -113,6 +113,6 @@ public class LocalTexture { } public interface IBlankSkinSupplier { - ResourceLocation getBlankSkin(Type type); + ResourceLocation getBlankSkin(TextureType type); } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java index e5430ee2..abbc638b 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTexture.java @@ -1,5 +1,6 @@ package com.voxelmodpack.hdskins; +import com.minelittlepony.avatar.texture.TextureProfile; import net.minecraft.client.renderer.IImageBuffer; import net.minecraft.client.renderer.ThreadDownloadImageData; import net.minecraft.util.ResourceLocation; @@ -12,10 +13,10 @@ public class PreviewTexture extends ThreadDownloadImageData { private String model; - public PreviewTexture(@Nullable String model, String url, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) { - super(null, url, fallbackTexture, imageBuffer); + public PreviewTexture(TextureProfile profile, ResourceLocation fallbackTexture, @Nullable IImageBuffer imageBuffer) { + super(null, profile.getUrl().toString(), fallbackTexture, imageBuffer); - this.model = model == null ? "default" : model; + this.model = profile.getMetadata("model").orElse("default"); } public boolean isTextureUploaded() { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java index 18cf587d..535961a8 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/PreviewTextureManager.java @@ -1,14 +1,14 @@ package com.voxelmodpack.hdskins; -import com.google.common.collect.Maps; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureProfile; +import com.minelittlepony.avatar.texture.TextureType; import net.minecraft.client.renderer.IImageBuffer; -import net.minecraft.client.resources.SkinManager; import net.minecraft.util.ResourceLocation; import java.awt.image.BufferedImage; import java.util.Map; +import java.util.function.BiConsumer; import javax.annotation.Nullable; @@ -18,22 +18,22 @@ import javax.annotation.Nullable; */ public class PreviewTextureManager { - private final Map textures; + private final Map textures; - PreviewTextureManager(MinecraftTexturesPayload payload) { - this.textures = payload.getTextures(); + 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, TextureType type, ResourceLocation def, + @Nullable BiConsumer callback) { if (!textures.containsKey(type)) { return null; } - MinecraftProfileTexture texture = textures.get(type); + TextureProfile texture = textures.get(type); IImageBuffer buffer = new ImageBufferDownloadHD(); - PreviewTexture skinTexture = new PreviewTexture(texture.getMetadata("model"), texture.getUrl(), def, - type == MinecraftProfileTexture.Type.SKIN ? new IImageBuffer() { + PreviewTexture skinTexture = new PreviewTexture(texture, def, + type == TextureType.SKIN ? new IImageBuffer() { @Override @Nullable public BufferedImage parseUserSkin(BufferedImage image) { @@ -43,7 +43,7 @@ public class PreviewTextureManager { @Override public void skinAvailable() { if (callback != null) { - callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap())); + callback.accept(type, new TextureData(location, texture)); } } } : null); @@ -52,4 +52,5 @@ public class PreviewTextureManager { return skinTexture; } + } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java index ede55f4f..f857c144 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/EntityPlayerModel.java @@ -2,13 +2,13 @@ package com.voxelmodpack.hdskins.gui; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureType; import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.LocalTexture; import com.voxelmodpack.hdskins.LocalTexture.IBlankSkinSupplier; import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.SkinManager; import net.minecraft.entity.EntityLivingBase; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; @@ -17,6 +17,7 @@ import net.minecraft.util.ResourceLocation; import java.io.File; import java.util.Map; +import java.util.function.BiConsumer; @SuppressWarnings("EntityConstructor") public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSupplier { @@ -43,28 +44,28 @@ public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSup super(new DummyWorld()); profile = gameprofile; - skin = new LocalTexture(profile, Type.SKIN, this); - elytra = new LocalTexture(profile, Type.ELYTRA, this); + skin = new LocalTexture(profile, TextureType.SKIN, this); + elytra = new LocalTexture(profile, TextureType.ELYTRA, this); } - public void reloadRemoteSkin(SkinManager.SkinAvailableCallback listener) { + public void reloadRemoteSkin(BiConsumer listener) { HDSkinManager.getPreviewTextureManager(profile).thenAccept(ptm -> { skin.setRemote(ptm, listener); elytra.setRemote(ptm, listener); }); } - public void setLocalTexture(File skinTextureFile, Type type) { - if (type == Type.SKIN) { + public void setLocalTexture(File skinTextureFile, TextureType type) { + if (type == TextureType.SKIN) { skin.setLocal(skinTextureFile); - } else if (type == Type.ELYTRA) { + } else if (type == TextureType.ELYTRA) { elytra.setLocal(skinTextureFile); } } @Override - public ResourceLocation getBlankSkin(Type type) { - return type == Type.SKIN ? NO_SKIN : NO_ELYTRA; + public ResourceLocation getBlankSkin(TextureType type) { + return type == TextureType.SKIN ? NO_SKIN : NO_ELYTRA; } public boolean isUsingLocalTexture() { @@ -80,8 +81,8 @@ public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSup elytra.clearLocal(); } - public LocalTexture getLocal(Type type) { - return type == Type.SKIN ? skin : elytra; + public LocalTexture getLocal(TextureType type) { + return type == TextureType.SKIN ? skin : elytra; } public void setPreviewThinArms(boolean thinArms) { diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java index 5a98ef9e..6b05c8e6 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java @@ -1,25 +1,20 @@ package com.voxelmodpack.hdskins.gui; -import static com.mojang.authlib.minecraft.MinecraftProfileTexture.Type.ELYTRA; -import static com.mojang.authlib.minecraft.MinecraftProfileTexture.Type.SKIN; -import static net.minecraft.client.renderer.GlStateManager.*; - import com.google.common.base.Splitter; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureType; import com.minelittlepony.gui.Button; import com.minelittlepony.gui.GameGui; import com.minelittlepony.gui.IconicButton; import com.minelittlepony.gui.Label; import com.mojang.authlib.GameProfile; -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.SkinUpload; import com.voxelmodpack.hdskins.skins.SkinUploadResponse; import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG; - import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.Gui; @@ -32,9 +27,7 @@ import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumHand; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; - import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; import org.lwjgl.BufferUtils; @@ -52,6 +45,21 @@ import javax.annotation.Nullable; import javax.imageio.ImageIO; import javax.swing.UIManager; +import static com.minelittlepony.avatar.texture.TextureType.ELYTRA; +import static com.minelittlepony.avatar.texture.TextureType.SKIN; +import static net.minecraft.client.renderer.GlStateManager.depthMask; +import static net.minecraft.client.renderer.GlStateManager.disableColorMaterial; +import static net.minecraft.client.renderer.GlStateManager.disableDepth; +import static net.minecraft.client.renderer.GlStateManager.enableBlend; +import static net.minecraft.client.renderer.GlStateManager.enableColorMaterial; +import static net.minecraft.client.renderer.GlStateManager.enableDepth; +import static net.minecraft.client.renderer.GlStateManager.popAttrib; +import static net.minecraft.client.renderer.GlStateManager.popMatrix; +import static net.minecraft.client.renderer.GlStateManager.pushMatrix; +import static net.minecraft.client.renderer.GlStateManager.rotate; +import static net.minecraft.client.renderer.GlStateManager.scale; +import static net.minecraft.client.renderer.GlStateManager.translate; + public class GuiSkins extends GameGui { private static final int MAX_SKIN_DIMENSION = 1024; @@ -94,14 +102,13 @@ public class GuiSkins extends GameGui { private File selectedSkin; - private int lastMouseX = 0; private static GuiSkins instance; protected CubeMap panorama; - private MinecraftProfileTexture.Type textureType = SKIN; + private TextureType textureType = SKIN; private boolean thinArmType = false; static { @@ -186,10 +193,10 @@ public class GuiSkins extends GameGui { } - protected void onSetRemoteSkin(Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) { + protected void onSetRemoteSkin(TextureType type, TextureData texture) { } - protected void onSetLocalSkin(Type type) { + protected void onSetLocalSkin(TextureType type) { } private void reloadRemoteSkin() { @@ -216,7 +223,7 @@ public class GuiSkins extends GameGui { addButton(new Label(34, 34, "hdskins.local", 0xffffff)); addButton(new Label(width / 2 + 34, 34, "hdskins.server", 0xffffff)); - addButton(new Button(width / 2 - 150, height - 27, 90, 20, "hdskins.options.browse", sender ->{ + addButton(new Button(width / 2 - 150, height - 27, 90, 20, "hdskins.options.browse", sender -> { selectedSkin = null; localPlayer.releaseTextures(); openFileThread = new ThreadOpenFilePNG(mc, format("hdskins.open.title"), (fileDialog, dialogResult) -> { @@ -255,11 +262,12 @@ public class GuiSkins extends GameGui { addButton(btnModeSkin = new IconicButton(width - 25, 75, sender -> { switchSkinType(sender, SKIN); - }).setIcon(new ItemStack(Items.LEATHER_CHESTPLATE))).setEnabled(textureType == ELYTRA).setTooltip(format("hdskins.mode.skin", toTitleCase(SKIN.name()))); + }).setIcon(new ItemStack(Items.LEATHER_CHESTPLATE))).setEnabled(textureType == ELYTRA) + .setTooltip(format("hdskins.mode.skin", toTitleCase(SKIN.toString()))); addButton(btnModeElytra = new IconicButton(width - 25, 94, sender -> { switchSkinType(sender, ELYTRA); - }).setIcon(new ItemStack(Items.ELYTRA))).setEnabled(textureType == SKIN).setTooltip(format("hdskins.mode.skin", toTitleCase(ELYTRA.name()))); + }).setIcon(new ItemStack(Items.ELYTRA))).setEnabled(textureType == SKIN).setTooltip(format("hdskins.mode.skin", toTitleCase(ELYTRA.toString()))); addButton(new Button(width - 25, height - 65, 20, 20, "?", sender -> { @@ -308,7 +316,7 @@ public class GuiSkins extends GameGui { return isPowerOfTwo(w) && w == h * 2 || w == h && w <= MAX_SKIN_DIMENSION && h <= MAX_SKIN_DIMENSION; } - protected void switchSkinType(Button sender, Type newType) { + protected void switchSkinType(Button sender, TextureType newType) { mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.BLOCK_BREWING_STAND_BREW, 1)); textureType = newType; @@ -436,7 +444,7 @@ public class GuiSkins extends GameGui { if (!localPlayer.isUsingLocalTexture()) { Gui.drawRect(40, height / 2 - 12, width / 2 - 40, height / 2 + 12, 0xB0000000); - drawCenteredString(fontRenderer, localMessage, (int)xPos1, height / 2 - 4, 0xffffff); + drawCenteredString(fontRenderer, localMessage, (int) xPos1, height / 2 - 4, 0xffffff); } if (fetchingSkin) { @@ -446,10 +454,10 @@ public class GuiSkins extends GameGui { Gui.drawRect((int) (xPos2 - width / 4 + 40), height / 2 - lineHeight, width - 40, height / 2 + lineHeight, 0xB0000000); if (throttledByMojang) { - drawCenteredString(fontRenderer, format("hdskins.error.mojang"), (int)xPos2, height / 2 - 10, 0xffffff); - drawCenteredString(fontRenderer, format("hdskins.error.mojang.wait"), (int)xPos2, height / 2 + 2, 0xffffff); + drawCenteredString(fontRenderer, format("hdskins.error.mojang"), (int) xPos2, height / 2 - 10, 0xffffff); + drawCenteredString(fontRenderer, format("hdskins.error.mojang.wait"), (int) xPos2, height / 2 + 2, 0xffffff); } else { - drawCenteredString(fontRenderer, format("hdskins.fetch"), (int)xPos2, height / 2 - 4, 0xffffff); + drawCenteredString(fontRenderer, format("hdskins.fetch"), (int) xPos2, height / 2 - 4, 0xffffff); } } @@ -482,8 +490,9 @@ public class GuiSkins extends GameGui { enableDepth(); } - private void renderPlayerModel(EntityPlayerModel thePlayer, float xPosition, float yPosition, float scale, float mouseY, float mouseX, float partialTick) { - mc.getTextureManager().bindTexture(thePlayer.getLocal(Type.SKIN).getTexture()); + private void renderPlayerModel(EntityPlayerModel thePlayer, float xPosition, float yPosition, float scale, float mouseY, float mouseX, + float partialTick) { + mc.getTextureManager().bindTexture(thePlayer.getLocal(SKIN).getTexture()); enableColorMaterial(); pushMatrix(); @@ -496,8 +505,8 @@ public class GuiSkins extends GameGui { rotate(((updateCounter + partialTick) * 2.5F) % 360, 0, 1, 0); - thePlayer.rotationYawHead = (float)Math.atan(mouseX / 20) * 30; - thePlayer.rotationPitch = (float)Math.atan(mouseY / 40) * -20; + thePlayer.rotationYawHead = (float) Math.atan(mouseX / 20) * 30; + thePlayer.rotationPitch = (float) Math.atan(mouseY / 40) * -20; mc.getRenderManager().renderEntity(thePlayer, 0, 0, 0, 0, 1, false); diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/RenderPlayerModel.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/RenderPlayerModel.java index 9b2d37dd..0f99befa 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/RenderPlayerModel.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/RenderPlayerModel.java @@ -1,5 +1,6 @@ package com.voxelmodpack.hdskins.gui; +import com.minelittlepony.avatar.texture.TextureType; import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBiped.ArmPose; import net.minecraft.client.model.ModelElytra; @@ -14,14 +15,18 @@ import net.minecraft.init.Items; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; - import org.lwjgl.opengl.GL11; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; - import java.util.Set; -import static net.minecraft.client.renderer.GlStateManager.*; +import static net.minecraft.client.renderer.GlStateManager.color; +import static net.minecraft.client.renderer.GlStateManager.disableBlend; +import static net.minecraft.client.renderer.GlStateManager.enableBlend; +import static net.minecraft.client.renderer.GlStateManager.popAttrib; +import static net.minecraft.client.renderer.GlStateManager.popMatrix; +import static net.minecraft.client.renderer.GlStateManager.pushMatrix; +import static net.minecraft.client.renderer.GlStateManager.scale; +import static net.minecraft.client.renderer.GlStateManager.translate; public class RenderPlayerModel extends RenderLivingBase { @@ -51,7 +56,7 @@ public class RenderPlayerModel extends RenderLiving GlStateManager.enableBlend(); GlStateManager.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); - bindTexture(entity.getLocal(Type.ELYTRA).getTexture()); + bindTexture(entity.getLocal(TextureType.ELYTRA).getTexture()); GlStateManager.pushMatrix(); GlStateManager.translate(0, 0, 0.125F); @@ -73,7 +78,7 @@ public class RenderPlayerModel extends RenderLiving @Override protected ResourceLocation getEntityTexture(M entity) { - return entity.getLocal(Type.SKIN).getTexture(); + return entity.getLocal(TextureType.SKIN).getTexture(); } @Override diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java deleted file mode 100644 index 432c383d..00000000 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinPlayerInfo.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.voxelmodpack.hdskins.mixin; - -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; -import com.voxelmodpack.hdskins.HDSkinManager; -import net.minecraft.client.network.NetworkPlayerInfo; -import net.minecraft.util.ResourceLocation; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -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", - cancellable = true, - at = @At("RETURN")) - private void getLocationSkin(CallbackInfoReturnable ci) { - getTextureLocation(ci, Type.SKIN); - } - - @Inject( - method = "getLocationCape", - cancellable = true, - at = @At("RETURN")) - private void getLocationCape(CallbackInfoReturnable ci) { - getTextureLocation(ci, Type.CAPE); - } - - @Inject( - method = "getLocationElytra", - cancellable = true, - at = @At("RETURN")) - private void getLocationElytra(CallbackInfoReturnable ci) { - getTextureLocation(ci, Type.ELYTRA); - } - - private void getTextureLocation(CallbackInfoReturnable ci, Type type) { - Optional texture = HDSkinManager.INSTANCE.getSkinLocation(getGameProfile(), type, true); - texture.ifPresent(ci::setReturnValue); - } - - @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); - - texture.ifPresent((res) -> ci.setReturnValue(type1)); - } - } -} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java deleted file mode 100644 index dda9662c..00000000 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/MixinSkullRenderer.java +++ /dev/null @@ -1,39 +0,0 @@ -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; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import org.spongepowered.asm.mixin.Mixin; -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", - 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) { - if (profile != null) { - Optional skin = HDSkinManager.INSTANCE.getSkinLocation(profile, Type.SKIN, true); - if (skin.isPresent()) - // rebind - bindTexture(skin.get()); - else - bindTexture(rl); - } else - bindTexture(rl); - } -} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/package-info.java b/src/hdskins/java/com/voxelmodpack/hdskins/mixin/package-info.java deleted file mode 100644 index e502527b..00000000 --- a/src/hdskins/java/com/voxelmodpack/hdskins/mixin/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -package com.voxelmodpack.hdskins.mixin; - -import mcp.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java b/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java index d02b22df..4a34778b 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/resource/SkinResourceManager.java @@ -3,8 +3,8 @@ package com.voxelmodpack.hdskins.resource; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.JsonParseException; +import com.minelittlepony.avatar.texture.TextureType; import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mumfrey.liteloader.util.log.LiteLoaderLogger; import net.minecraft.client.resources.IResource; import net.minecraft.client.resources.IResourceManager; @@ -13,7 +13,6 @@ import net.minecraft.util.ResourceLocation; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; -import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -24,6 +23,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import javax.annotation.Nullable; + public class SkinResourceManager implements IResourceManagerReloadListener { private ExecutorService executor = Executors.newSingleThreadExecutor(); @@ -74,8 +75,8 @@ public class SkinResourceManager implements IResourceManagerReloadListener { } @Nullable - public ResourceLocation getPlayerTexture(GameProfile profile, Type type) { - if (type != Type.SKIN) + public ResourceLocation getPlayerTexture(GameProfile profile, TextureType type) { + if (type != TextureType.SKIN) // not supported return null; diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java index 0ae82762..5e8b1509 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/BethlehemSkinServer.java @@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import com.google.gson.annotations.Expose; import com.mojang.authlib.GameProfile; -import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import com.mojang.util.UUIDTypeAdapter; import com.voxelmodpack.hdskins.HDSkinManager; import net.minecraft.util.Session; @@ -27,14 +26,14 @@ public class BethlehemSkinServer implements SkinServer { } @Override - public MinecraftTexturesPayload loadProfileData(GameProfile profile) throws IOException { + public TexturesPayload loadProfileData(GameProfile profile) throws IOException { // TODO: Fix this try (MoreHttpResponses response = new NetClient("GET", getPath(profile)).send()) { if (!response.ok()) { throw new IOException(response.getResponse().getStatusLine().getReasonPhrase()); } - return response.json(MinecraftTexturesPayload.class); + return response.json(TexturesPayload.class); } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java index 9ea4318b..741564b8 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java @@ -3,9 +3,9 @@ package com.voxelmodpack.hdskins.skins; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.Expose; +import com.minelittlepony.avatar.texture.TextureProfile; +import com.minelittlepony.avatar.texture.TextureType; import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import com.mojang.util.UUIDTypeAdapter; import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.upload.ThreadMultipartPostUpload; @@ -16,8 +16,7 @@ import org.apache.logging.log4j.Logger; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; -import java.net.URL; -import java.util.EnumMap; +import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -42,23 +41,23 @@ public class LegacySkinServer implements SkinServer { } @Override - public CompletableFuture getPreviewTextures(GameProfile profile) { + public CompletableFuture getPreviewTextures(GameProfile profile) { if (Strings.isNullOrEmpty(this.gateway)) { return CallableFutures.failedFuture(gatewayUnsupported()); } - Map map = new EnumMap<>(MinecraftProfileTexture.Type.class); - for (MinecraftProfileTexture.Type type : MinecraftProfileTexture.Type.values()) { - map.put(type, new MinecraftProfileTexture(getPath(gateway, type, profile), null)); + Map map = new HashMap<>(); + for (TextureType type : TextureType.values()) { + map.put(type, new TextureProfile(getPath(gateway, type, profile), null)); } - return CompletableFuture.completedFuture(TexturesPayloadBuilder.createTexturesPayload(profile, map)); + return CompletableFuture.completedFuture(new TexturesPayload(profile, map)); } @Override - public MinecraftTexturesPayload loadProfileData(GameProfile profile) throws IOException { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (MinecraftProfileTexture.Type type : MinecraftProfileTexture.Type.values()) { + public TexturesPayload loadProfileData(GameProfile profile) throws IOException { + ImmutableMap.Builder builder = ImmutableMap.builder(); + for (TextureType type : TextureType.values()) { - String url = getPath(this.address, type, profile); + URI url = getPath(this.address, type, profile); try { builder.put(type, loadProfileTexture(profile, url)); } catch (IOException e) { @@ -66,20 +65,20 @@ public class LegacySkinServer implements SkinServer { } } - Map map = builder.build(); + Map map = builder.build(); if (map.isEmpty()) { throw new IOException(String.format("No textures found for %s at %s", profile, this.address)); } - return TexturesPayloadBuilder.createTexturesPayload(profile, map); + return new TexturesPayload(profile, map); } - private MinecraftProfileTexture loadProfileTexture(GameProfile profile, String url) throws IOException { - HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection(); + private TextureProfile loadProfileTexture(GameProfile profile, URI url) throws IOException { + HttpURLConnection urlConnection = (HttpURLConnection) url.toURL().openConnection(); if (urlConnection.getResponseCode() / 100 != 2) { throw new IOException("Bad response code: " + urlConnection.getResponseCode() + ". URL: " + url); } logger.debug("Found skin for {} at {}", profile.getName(), url); - return new MinecraftProfileTexture(url, null); + return new TextureProfile(url, null); } @SuppressWarnings("deprecation") @@ -91,7 +90,7 @@ public class LegacySkinServer implements SkinServer { return CallableFutures.asyncFailableFuture(() -> { URI image = skin.getImage(); - MinecraftProfileTexture.Type type = skin.getType(); + TextureType type = skin.getType(); Map metadata = skin.getMetadata(); SkinServer.verifyServerConnection(session, SERVER_ID); @@ -114,7 +113,7 @@ public class LegacySkinServer implements SkinServer { return new UnsupportedOperationException("Server does not have a gateway."); } - private static Map getData(Session session, MinecraftProfileTexture.Type type, String model, String param, Object val) { + private static Map getData(Session session, TextureType type, String model, String param, Object val) { return ImmutableMap.of( "user", session.getUsername(), "uuid", UUIDTypeAdapter.fromUUID(session.getProfile().getId()), @@ -123,18 +122,18 @@ public class LegacySkinServer implements SkinServer { param, val); } - private static Map getClearData(Session session, MinecraftProfileTexture.Type type) { + private static Map getClearData(Session session, TextureType type) { return getData(session, type, "default", "clear", "1"); } - private static Map getUploadData(Session session, MinecraftProfileTexture.Type type, String model, URI skinFile) { + private static Map getUploadData(Session session, TextureType type, String model, URI skinFile) { return getData(session, type, model, type.toString().toLowerCase(Locale.US), skinFile); } - private static String getPath(String address, MinecraftProfileTexture.Type type, GameProfile profile) { + private static URI getPath(String address, TextureType type, GameProfile profile) { String uuid = UUIDTypeAdapter.fromUUID(profile.getId()); String path = type.toString().toLowerCase() + "s"; - return String.format("%s/%s/%s.png", address, path, uuid); + return URI.create(String.format("%s/%s/%s.png", address, path, uuid)); } @Override diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java index 48f55b51..8ab3b3f9 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java @@ -3,12 +3,11 @@ package com.voxelmodpack.hdskins.skins; import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.minelittlepony.avatar.texture.TextureType; import com.mojang.authlib.GameProfile; import com.mojang.authlib.exceptions.AuthenticationException; import com.mojang.authlib.minecraft.MinecraftSessionService; -import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import com.mojang.util.UUIDTypeAdapter; -import com.mumfrey.liteloader.modconfig.Exposable; import com.voxelmodpack.hdskins.HDSkinManager; import net.minecraft.client.Minecraft; import net.minecraft.util.Session; @@ -18,21 +17,22 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; -public interface SkinServer extends Exposable { +public interface SkinServer { Gson gson = new GsonBuilder() .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()) + .registerTypeAdapter(TextureType.class, new TextureType.Serializer()) .create(); List defaultServers = Lists.newArrayList(new LegacySkinServer( "http://skins.voxelmodpack.com", "http://skinmanager.voxelmodpack.com")); - MinecraftTexturesPayload loadProfileData(GameProfile profile) throws IOException; + TexturesPayload loadProfileData(GameProfile profile) throws IOException; CompletableFuture uploadSkin(Session session, SkinUpload upload); - default CompletableFuture getPreviewTextures(GameProfile profile) { + default CompletableFuture getPreviewTextures(GameProfile profile) { return CallableFutures.asyncFailableFuture(() -> loadProfileData(profile), HDSkinManager.skinDownloadExecutor); } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUpload.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUpload.java index dbcd20bd..e2ae3ad3 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUpload.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUpload.java @@ -1,6 +1,6 @@ package com.voxelmodpack.hdskins.skins; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.minelittlepony.avatar.texture.TextureType; import java.net.URI; import java.util.Map; @@ -11,9 +11,9 @@ public class SkinUpload { private URI image; private Map metadata; - private MinecraftProfileTexture.Type type; + private TextureType type; - public SkinUpload(MinecraftProfileTexture.Type type, @Nullable URI image, Map metadata) { + public SkinUpload(TextureType type, @Nullable URI image, Map metadata) { this.image = image; this.metadata = metadata; this.type = type; @@ -28,7 +28,7 @@ public class SkinUpload { return metadata; } - public MinecraftProfileTexture.Type getType() { + public TextureType getType() { return type; } } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/TexturesPayload.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/TexturesPayload.java new file mode 100644 index 00000000..85c36196 --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/TexturesPayload.java @@ -0,0 +1,51 @@ +package com.voxelmodpack.hdskins.skins; + +import com.minelittlepony.avatar.texture.TextureProfile; +import com.minelittlepony.avatar.texture.TextureType; +import com.mojang.authlib.GameProfile; + +import java.util.Map; +import java.util.UUID; + +import javax.annotation.Nullable; + +public class TexturesPayload { + + private long timestamp; + private UUID profileId; + private String profileName; + private boolean isPublic; + private Map textures; + + public TexturesPayload(GameProfile profile, Map textures) { + this.profileId = profile.getId(); + this.profileName = profile.getName(); + this.timestamp = System.currentTimeMillis(); + + this.isPublic = true; + + this.textures = textures; + } + + public long getTimestamp() { + return timestamp; + } + + public UUID getProfileId() { + return profileId; + } + + public String getProfileName() { + return profileName; + } + + public boolean isPublic() { + return isPublic; + } + + @Nullable + public Map getTextures() { + return textures; + } + +} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java index 4271d36f..22bbd9a0 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/ValhallaSkinServer.java @@ -3,10 +3,9 @@ package com.voxelmodpack.hdskins.skins; import com.google.common.base.Preconditions; import com.google.gson.JsonObject; import com.google.gson.annotations.Expose; +import com.minelittlepony.avatar.texture.TextureType; import com.mojang.authlib.GameProfile; import com.mojang.authlib.exceptions.AuthenticationException; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import com.mojang.util.UUIDTypeAdapter; import com.voxelmodpack.hdskins.HDSkinManager; import net.minecraft.client.Minecraft; @@ -43,12 +42,12 @@ public class ValhallaSkinServer implements SkinServer { } @Override - public MinecraftTexturesPayload loadProfileData(GameProfile profile) throws IOException { + public TexturesPayload loadProfileData(GameProfile profile) throws IOException { try (MoreHttpResponses response = MoreHttpResponses.execute(HDSkinManager.httpClient, new HttpGet(getTexturesURI(profile)))) { if (response.ok()) { - return readJson(response, MinecraftTexturesPayload.class); + return readJson(response, TexturesPayload.class); } throw new IOException("Server sent non-ok response code: " + response.getResponseCode()); } @@ -58,7 +57,7 @@ public class ValhallaSkinServer implements SkinServer { public CompletableFuture uploadSkin(Session session, SkinUpload skin) { URI image = skin.getImage(); Map metadata = skin.getMetadata(); - MinecraftProfileTexture.Type type = skin.getType(); + TextureType type = skin.getType(); return CallableFutures.asyncFailableFuture(() -> { authorize(session); @@ -77,7 +76,7 @@ public class ValhallaSkinServer implements SkinServer { } private SkinUploadResponse upload(Session session, @Nullable URI image, - MinecraftProfileTexture.Type type, Map metadata) + TextureType type, Map metadata) throws IOException { GameProfile profile = session.getProfile(); @@ -96,14 +95,14 @@ public class ValhallaSkinServer implements SkinServer { } - private SkinUploadResponse resetSkin(GameProfile profile, MinecraftProfileTexture.Type type) throws IOException { + private SkinUploadResponse resetSkin(GameProfile profile, TextureType type) throws IOException { return upload(RequestBuilder.delete() .setUri(buildUserTextureUri(profile, type)) .addHeader(HttpHeaders.AUTHORIZATION, this.accessToken) .build()); } - private SkinUploadResponse uploadFile(File file, GameProfile profile, MinecraftProfileTexture.Type type, Map metadata) throws IOException { + private SkinUploadResponse uploadFile(File file, GameProfile profile, TextureType type, Map metadata) throws IOException { MultipartEntityBuilder b = MultipartEntityBuilder.create(); b.addBinaryBody("file", file, ContentType.create("image/png"), file.getName()); metadata.forEach(b::addTextBody); @@ -115,7 +114,7 @@ public class ValhallaSkinServer implements SkinServer { .build()); } - private SkinUploadResponse uploadUrl(URI uri, GameProfile profile, MinecraftProfileTexture.Type type, Map metadata) throws IOException { + private SkinUploadResponse uploadUrl(URI uri, GameProfile profile, TextureType type, Map metadata) throws IOException { return upload(RequestBuilder.post() .setUri(buildUserTextureUri(profile, type)) @@ -186,9 +185,9 @@ public class ValhallaSkinServer implements SkinServer { } } - private URI buildUserTextureUri(GameProfile profile, MinecraftProfileTexture.Type textureType) { + private URI buildUserTextureUri(GameProfile profile, TextureType textureType) { String user = UUIDTypeAdapter.fromUUID(profile.getId()); - String skinType = textureType.name().toLowerCase(Locale.US); + String skinType = textureType.toString().toLowerCase(Locale.US); return URI.create(String.format("%s/user/%s/%s", this.address, user, skinType)); } diff --git a/src/main/java/com/minelittlepony/PonyManager.java b/src/main/java/com/minelittlepony/PonyManager.java index ac31d982..d7c05a6c 100644 --- a/src/main/java/com/minelittlepony/PonyManager.java +++ b/src/main/java/com/minelittlepony/PonyManager.java @@ -6,9 +6,7 @@ import com.google.gson.Gson; import com.google.gson.JsonParseException; import com.minelittlepony.pony.data.Pony; import com.minelittlepony.pony.data.PonyLevel; -import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.ISkinCacheClearListener; - import net.minecraft.client.Minecraft; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.network.NetworkPlayerInfo; @@ -84,7 +82,6 @@ public class PonyManager implements IResourceManagerReloadListener, ISkinCacheCl public Pony getPony(NetworkPlayerInfo playerInfo) { // force load HDSkins if they're not available - HDSkinManager.INSTANCE.getProfileData(playerInfo.getGameProfile()); ResourceLocation skin = playerInfo.getLocationSkin(); UUID uuid = playerInfo.getGameProfile().getId(); diff --git a/src/main/java/com/minelittlepony/hdskins/gui/EntityPonyModel.java b/src/main/java/com/minelittlepony/hdskins/gui/EntityPonyModel.java index 843fdc7c..2c05d0b4 100644 --- a/src/main/java/com/minelittlepony/hdskins/gui/EntityPonyModel.java +++ b/src/main/java/com/minelittlepony/hdskins/gui/EntityPonyModel.java @@ -1,9 +1,8 @@ package com.minelittlepony.hdskins.gui; +import com.minelittlepony.avatar.texture.TextureType; import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.voxelmodpack.hdskins.gui.EntityPlayerModel; - import net.minecraft.util.ResourceLocation; /** @@ -21,8 +20,8 @@ public class EntityPonyModel extends EntityPlayerModel { } @Override - public ResourceLocation getBlankSkin(Type type) { - if (type == Type.SKIN) { + public ResourceLocation getBlankSkin(TextureType type) { + if (type == TextureType.SKIN) { return wet ? NO_SKIN_SEAPONY : NO_SKIN_PONY; } return super.getBlankSkin(type); diff --git a/src/main/java/com/minelittlepony/hdskins/gui/GuiSkinsMineLP.java b/src/main/java/com/minelittlepony/hdskins/gui/GuiSkinsMineLP.java index 2f3afad7..e1e0e87b 100644 --- a/src/main/java/com/minelittlepony/hdskins/gui/GuiSkinsMineLP.java +++ b/src/main/java/com/minelittlepony/hdskins/gui/GuiSkinsMineLP.java @@ -2,19 +2,17 @@ package com.minelittlepony.hdskins.gui; import com.minelittlepony.MineLittlePony; import com.minelittlepony.PonyManager; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureType; import com.minelittlepony.gui.Button; import com.minelittlepony.gui.IconicButton; import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.voxelmodpack.hdskins.gui.EntityPlayerModel; import com.voxelmodpack.hdskins.gui.GuiSkins; - import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.init.Items; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; /** * Skin uploading GUI. Usually displayed over the main menu. @@ -77,18 +75,18 @@ public class GuiSkinsMineLP extends GuiSkins { } @Override - protected void onSetLocalSkin(Type type) { + protected void onSetLocalSkin(TextureType type) { MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin"); - if (type == Type.SKIN) { - ponyManager.removePony(localPlayer.getLocal(Type.SKIN).getTexture()); + if (type == TextureType.SKIN) { + ponyManager.removePony(localPlayer.getLocal(TextureType.SKIN).getTexture()); } } @Override - protected void onSetRemoteSkin(Type type, ResourceLocation resource, MinecraftProfileTexture profileTexture) { + protected void onSetRemoteSkin(TextureType type, TextureData texture) { MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin"); - if (type == Type.SKIN) { - ponyManager.removePony(resource); + if (type == TextureType.SKIN) { + ponyManager.removePony(texture.getLocation()); } } } diff --git a/src/main/java/com/minelittlepony/hdskins/gui/RenderPonyModel.java b/src/main/java/com/minelittlepony/hdskins/gui/RenderPonyModel.java index 27853cae..0c09c601 100644 --- a/src/main/java/com/minelittlepony/hdskins/gui/RenderPonyModel.java +++ b/src/main/java/com/minelittlepony/hdskins/gui/RenderPonyModel.java @@ -1,16 +1,15 @@ package com.minelittlepony.hdskins.gui; import com.minelittlepony.MineLittlePony; +import com.minelittlepony.avatar.texture.TextureType; import com.minelittlepony.ducks.IRenderPony; import com.minelittlepony.model.ModelWrapper; import com.minelittlepony.model.player.PlayerModels; import com.minelittlepony.pony.data.Pony; import com.minelittlepony.pony.data.PonyRace; -import com.minelittlepony.render.layer.LayerPonyElytra; import com.minelittlepony.render.RenderPony; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; +import com.minelittlepony.render.layer.LayerPonyElytra; import com.voxelmodpack.hdskins.gui.RenderPlayerModel; - import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelElytra; import net.minecraft.client.model.ModelPlayer; @@ -79,7 +78,7 @@ public class RenderPonyModel extends RenderPlayerModel implemen return super.getEntityModel(playermodel); } - boolean canWet = playermodel.wet && (loc == playermodel.getBlankSkin(Type.SKIN) || race == PonyRace.SEAPONY); + boolean canWet = playermodel.wet && (loc == playermodel.getBlankSkin(TextureType.SKIN) || race == PonyRace.SEAPONY); playerModel = canWet ? PlayerModels.SEAPONY.getModel(slim) : thePony.getModel(true); playerModel.apply(thePony.getMetadata()); @@ -110,7 +109,7 @@ public class RenderPonyModel extends RenderPlayerModel implemen @Override protected ResourceLocation getElytraTexture(EntityPonyModel entity) { - return entity.getLocal(Type.ELYTRA).getTexture(); + return entity.getLocal(TextureType.ELYTRA).getTexture(); } }; } diff --git a/src/main/java/com/minelittlepony/mixin/MixinNetworkPlayerInfo.java b/src/main/java/com/minelittlepony/mixin/MixinNetworkPlayerInfo.java index a24eb269..4219d09a 100644 --- a/src/main/java/com/minelittlepony/mixin/MixinNetworkPlayerInfo.java +++ b/src/main/java/com/minelittlepony/mixin/MixinNetworkPlayerInfo.java @@ -1,22 +1,20 @@ package com.minelittlepony.mixin; +import com.minelittlepony.MineLittlePony; +import com.minelittlepony.PonyManager; +import com.minelittlepony.avatar.impl.INetworkPlayerInfo; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureType; +import com.minelittlepony.ducks.IPlayerInfo; +import net.minecraft.client.network.NetworkPlayerInfo; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.minelittlepony.MineLittlePony; -import com.minelittlepony.PonyManager; -import com.minelittlepony.ducks.IPlayerInfo; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; -import com.voxelmodpack.hdskins.HDSkinManager; - -import net.minecraft.client.network.NetworkPlayerInfo; - @Mixin(NetworkPlayerInfo.class) -public abstract class MixinNetworkPlayerInfo implements IPlayerInfo { +public abstract class MixinNetworkPlayerInfo implements IPlayerInfo, INetworkPlayerInfo { @Shadow private String skinType; @@ -29,10 +27,10 @@ public abstract class MixinNetworkPlayerInfo implements IPlayerInfo { @Override public boolean usesSlimArms() { if (skinType == null) { - MinecraftProfileTexture skin = HDSkinManager.INSTANCE.getProfileData(unwrap().getGameProfile()).get(Type.SKIN); + TextureData skin = this.getPlayerTexture(TextureType.SKIN).orElse(null); if (skin != null) { - return "slim".equals(skin.getMetadata("model")); + return "slim".equals(skin.getProfile().getMetadata("model").orElse(null)); } return PonyManager.isSlimSkin(unwrap().getGameProfile().getId()); diff --git a/src/main/java/com/minelittlepony/render/player/RenderPonyPlayer.java b/src/main/java/com/minelittlepony/render/player/RenderPonyPlayer.java index dbe19ff7..a40df45a 100644 --- a/src/main/java/com/minelittlepony/render/player/RenderPonyPlayer.java +++ b/src/main/java/com/minelittlepony/render/player/RenderPonyPlayer.java @@ -2,6 +2,10 @@ package com.minelittlepony.render.player; import com.minelittlepony.MineLittlePony; import com.minelittlepony.PonyConfig; +import com.minelittlepony.avatar.ServiceManager; +import com.minelittlepony.avatar.texture.TextureData; +import com.minelittlepony.avatar.texture.TextureService; +import com.minelittlepony.avatar.texture.TextureType; import com.minelittlepony.ducks.IRenderPony; import com.minelittlepony.model.ModelWrapper; import com.minelittlepony.model.components.ModelDeadMau5Ears; @@ -20,7 +24,6 @@ import com.minelittlepony.render.layer.LayerPonyElytra; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; -import com.voxelmodpack.hdskins.HDSkinManager; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.renderer.GlStateManager; @@ -57,7 +60,11 @@ public class RenderPonyPlayer extends RenderPlayer implements IRenderPony skin = HDSkinManager.INSTANCE.getSkinLocation(profile, Type.SKIN, true); + Optional skin = ServiceManager.get(TextureService.class).map(service -> + service.getTextures(profile)) + .map(m -> m.get(TextureType.SKIN)) + .map(TextureData::getLocation); + if (skin.isPresent()) { return skin.get(); } @@ -109,7 +116,7 @@ public class RenderPonyPlayer extends RenderPlayer implements IRenderPony