From 89ecc9f916dd3d30e0d38335d623fc16d26e1d1f Mon Sep 17 00:00:00 2001 From: Matthew Messinger Date: Sun, 8 Jul 2018 03:34:35 -0400 Subject: [PATCH] Update SkinServer to be more extensible. --- .../voxelmodpack/hdskins/gui/GuiSkins.java | 49 +++++++++++-------- .../hdskins/skins/CallableFutures.java | 26 ++++++++++ .../hdskins/skins/LegacySkinServer.java | 27 +++++----- .../hdskins/skins/SkinServer.java | 14 ++++-- .../hdskins/skins/SkinUploadResponse.java | 3 -- 5 files changed, 81 insertions(+), 38 deletions(-) create mode 100644 src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java index 4d591a9c..a2a46639 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/gui/GuiSkins.java @@ -4,15 +4,13 @@ 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.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; +import com.google.common.collect.ImmutableMap; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mumfrey.liteloader.util.log.LiteLoaderLogger; import com.voxelmodpack.hdskins.HDSkinManager; import com.voxelmodpack.hdskins.skins.SkinUploadResponse; import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; @@ -37,13 +35,17 @@ import org.lwjgl.opengl.GL11; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.net.URI; import java.nio.DoubleBuffer; -import java.nio.file.Path; +import java.util.Map; + import javax.annotation.Nullable; import javax.imageio.ImageIO; -import javax.swing.*; +import javax.swing.JFileChooser; +import javax.swing.UIManager; + +public class GuiSkins extends GuiScreen { -public class GuiSkins extends GuiScreen implements FutureCallback { private static final int MAX_SKIN_DIMENSION = 1024; private int updateCounter = 0; @@ -86,7 +88,7 @@ public class GuiSkins extends GuiScreen implements FutureCallback getMetadata() { + return ImmutableMap.of("model", this.thinArmType ? "slim" : "default"); } private void setUploadError(@Nullable String error) { - this.uploadError = error != null && error.startsWith("ERROR: ") ? error.substring(7) : error; + this.uploadError = error; this.btnUpload.enabled = true; } - @Override - public void onSuccess(@Nullable SkinUploadResponse result) { - if (result != null) - onUploadComplete(result); - } - @Override - public void onFailure(Throwable t) { + private Void onFailure(Throwable t) { LogManager.getLogger().warn("Upload failed", t); this.setUploadError(t.toString()); this.uploadingSkin = false; + + return null; } private void onUploadComplete(SkinUploadResponse response) { LiteLoaderLogger.info("Upload completed with: %s", response); this.uploadingSkin = false; - if (!"OK".equalsIgnoreCase(response.getMessage())) { + if (!response.isSuccess()) { this.setUploadError(response.getMessage()); } else { this.pendingRemoteSkinRefresh = true; diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java new file mode 100644 index 00000000..53f087a2 --- /dev/null +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/CallableFutures.java @@ -0,0 +1,26 @@ +package com.voxelmodpack.hdskins.skins; + +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +public class CallableFutures { + + public static CompletableFuture asyncFailableFuture(Callable call, Executor exec) { + CompletableFuture ret = new CompletableFuture<>(); + exec.execute(() -> { + try { + ret.complete(call.call()); + } catch (Throwable e) { + ret.completeExceptionally(e); + } + }); + return ret; + } + + public static CompletableFuture failedFuture(Exception e) { + CompletableFuture ret = new CompletableFuture<>(); + ret.completeExceptionally(e); + return ret; + } +} diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java index fe37fb74..766b4dac 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/LegacySkinServer.java @@ -3,8 +3,6 @@ package com.voxelmodpack.hdskins.skins; import com.google.common.base.MoreObjects; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; import com.mojang.authlib.GameProfile; import com.mojang.authlib.exceptions.AuthenticationException; import com.mojang.authlib.minecraft.MinecraftProfileTexture; @@ -20,13 +18,15 @@ import org.apache.logging.log4j.Logger; import java.io.IOException; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; -import java.nio.file.Path; import java.util.Locale; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.regex.Matcher; import java.util.regex.Pattern; + import javax.annotation.Nullable; public class LegacySkinServer implements SkinServer { @@ -88,19 +88,24 @@ public class LegacySkinServer implements SkinServer { } @Override - public ListenableFuture uploadSkin(Session session, @Nullable Path image, MinecraftProfileTexture.Type type, boolean thinSkinType) { + public CompletableFuture uploadSkin(Session session, @Nullable URI image, + MinecraftProfileTexture.Type type, Map metadata) { - if (Strings.isNullOrEmpty(this.gateway)) - return Futures.immediateFailedFuture(new NullPointerException("gateway url is blank")); + if (Strings.isNullOrEmpty(this.gateway)) { + return CallableFutures.failedFuture(new NullPointerException("gateway url is blank")); + } - return HDSkinManager.skinUploadExecutor.submit(() -> { + return CallableFutures.asyncFailableFuture(() -> { verifyServerConnection(session, SERVER_ID); - - Map data = image == null ? getClearData(session, type) : getUploadData(session, type, (thinSkinType ? "slim" : "default"), image); + String model = metadata.getOrDefault("model", "default"); + Map data = image == null ? getClearData(session, type) : getUploadData(session, type, model, image); ThreadMultipartPostUpload upload = new ThreadMultipartPostUpload(this.gateway, data); String response = upload.uploadMultipart(); + if (response.startsWith("ERROR: ")) + response = response.substring(7); return new SkinUploadResponse(response.equalsIgnoreCase("OK"), response); - }); + + }, HDSkinManager.skinUploadExecutor); } private static Map getData(Session session, MinecraftProfileTexture.Type type, String model, String param, Object val) { @@ -116,7 +121,7 @@ public class LegacySkinServer implements SkinServer { return getData(session, type, "default", "clear", "1"); } - private static Map getUploadData(Session session, MinecraftProfileTexture.Type type, String model, Path skinFile) { + private static Map getUploadData(Session session, MinecraftProfileTexture.Type type, String model, URI skinFile) { return getData(session, type, model, type.toString().toLowerCase(Locale.US), skinFile); } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java index a51ec9c7..2aca2d0f 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinServer.java @@ -1,15 +1,17 @@ package com.voxelmodpack.hdskins.skins; import com.google.common.collect.Lists; -import com.google.common.util.concurrent.ListenableFuture; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import net.minecraft.util.Session; -import java.nio.file.Path; +import java.net.URI; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.CompletableFuture; + import javax.annotation.Nullable; public interface SkinServer { @@ -18,9 +20,12 @@ public interface SkinServer { Optional loadProfileData(GameProfile profile); - Optional getPreviewTexture(MinecraftProfileTexture.Type type, GameProfile profile); + default Optional getPreviewTexture(MinecraftProfileTexture.Type type, GameProfile profile) { + return loadProfileData(profile).map(data -> data.getTextures().get(type)); + } - ListenableFuture uploadSkin(Session session, @Nullable Path image, MinecraftProfileTexture.Type type, boolean thinArmType); + CompletableFuture uploadSkin(Session session, @Nullable URI image, + MinecraftProfileTexture.Type type, Map metadata); static SkinServer from(String server) { int i = server.indexOf(':'); @@ -36,4 +41,5 @@ public interface SkinServer { } throw new IllegalArgumentException(); } + } diff --git a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUploadResponse.java b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUploadResponse.java index af0043b5..680d915e 100644 --- a/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUploadResponse.java +++ b/src/hdskins/java/com/voxelmodpack/hdskins/skins/SkinUploadResponse.java @@ -2,8 +2,6 @@ package com.voxelmodpack.hdskins.skins; import com.google.common.base.MoreObjects; -import javax.annotation.Nullable; - public class SkinUploadResponse { private final boolean success; @@ -18,7 +16,6 @@ public class SkinUploadResponse { return success; } - @Nullable public String getMessage() { return message; }