mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2024-12-02 00:37:59 +01:00
Merge branch 'master' into hdskins_rewrites
This commit is contained in:
parent
fa44676aa7
commit
6995776e72
14 changed files with 253 additions and 193 deletions
|
@ -9,8 +9,7 @@ import com.google.common.collect.HashBiMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
||||||
|
@ -58,10 +57,10 @@ import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public final class HDSkinManager implements IResourceManagerReloadListener {
|
public final class HDSkinManager implements IResourceManagerReloadListener {
|
||||||
|
|
||||||
private static final ResourceLocation LOADING = new ResourceLocation("LOADING");
|
public static final ExecutorService skinUploadExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
public static final ExecutorService skinDownloadExecutor = Executors.newFixedThreadPool(8);
|
||||||
|
|
||||||
private static final ExecutorService skinDownloadExecutor = Executors.newFixedThreadPool(8);
|
private static final ResourceLocation LOADING = new ResourceLocation("LOADING");
|
||||||
public static final ListeningExecutorService skinUploadExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
|
|
||||||
|
|
||||||
public static final HDSkinManager INSTANCE = new HDSkinManager();
|
public static final HDSkinManager INSTANCE = new HDSkinManager();
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.voxelmodpack.hdskins;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
|
||||||
import com.voxelmodpack.hdskins.skins.CallableFutures;
|
import com.voxelmodpack.hdskins.skins.CallableFutures;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.IImageBuffer;
|
import net.minecraft.client.renderer.IImageBuffer;
|
||||||
|
@ -23,20 +22,20 @@ public class PreviewTextureManager {
|
||||||
|
|
||||||
private final GameProfile profile;
|
private final GameProfile profile;
|
||||||
|
|
||||||
private Map<Type, MinecraftProfileTexture> textures = null;
|
private Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures = null;
|
||||||
|
|
||||||
PreviewTextureManager(GameProfile profile) {
|
PreviewTextureManager(GameProfile profile) {
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<PreviewTexture> getPreviewTexture(ResourceLocation location, Type type, ResourceLocation def, @Nullable SkinAvailableCallback callback) {
|
public CompletableFuture<PreviewTexture> getPreviewTexture(ResourceLocation location, MinecraftProfileTexture.Type type, ResourceLocation def, @Nullable SkinAvailableCallback callback) {
|
||||||
return CallableFutures.asyncFailableFuture(() ->
|
return CallableFutures.asyncFailableFuture(() ->
|
||||||
loadPreviewTexture(location, type, def, callback)
|
loadPreviewTexture(location, type, def, callback)
|
||||||
, HDSkinManager.skinUploadExecutor);
|
, HDSkinManager.skinUploadExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private PreviewTexture loadPreviewTexture(ResourceLocation location, Type type, ResourceLocation def, @Nullable SkinAvailableCallback callback) {
|
private PreviewTexture loadPreviewTexture(ResourceLocation location, MinecraftProfileTexture.Type type, ResourceLocation def, @Nullable SkinAvailableCallback callback) {
|
||||||
if (textures == null) {
|
if (textures == null) {
|
||||||
textures = HDSkinManager.INSTANCE.getGatewayServer().getProfileTextures(profile);
|
textures = HDSkinManager.INSTANCE.getGatewayServer().getProfileTextures(profile);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +46,7 @@ public class PreviewTextureManager {
|
||||||
|
|
||||||
MinecraftProfileTexture texture = textures.get(type);
|
MinecraftProfileTexture texture = textures.get(type);
|
||||||
|
|
||||||
IImageBuffer buffer = type != Type.SKIN ? null : new ImageBufferDownloadHD().withCallback(() -> {
|
IImageBuffer buffer = type != MinecraftProfileTexture.Type.SKIN ? null : new ImageBufferDownloadHD().withCallback(() -> {
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap()));
|
callback.skinAvailable(type, location, new MinecraftProfileTexture(texture.getUrl(), Maps.newHashMap()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.voxelmodpack.hdskins;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
|
import com.voxelmodpack.hdskins.skins.MoreHttpResponses;
|
||||||
import com.voxelmodpack.hdskins.skins.NetClient;
|
import com.voxelmodpack.hdskins.skins.NetClient;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.IImageBuffer;
|
import net.minecraft.client.renderer.IImageBuffer;
|
||||||
|
@ -12,9 +13,7 @@ import net.minecraft.util.ResourceLocation;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHeaders;
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
@ -97,9 +96,9 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
|
|
||||||
private void loadTexture() {
|
private void loadTexture() {
|
||||||
try (NetClient client = new NetClient("GET", imageUrl)) {
|
try (NetClient client = new NetClient("GET", imageUrl)) {
|
||||||
CloseableHttpResponse response = client.getResponse();
|
MoreHttpResponses response = client.getResponse();
|
||||||
|
|
||||||
if (client.getResponseCode() == HttpStatus.SC_NOT_FOUND) {
|
if (client.getResponse().getResponseCode() == HttpStatus.SC_NOT_FOUND) {
|
||||||
// delete the cache files in case we can't connect in the future
|
// delete the cache files in case we can't connect in the future
|
||||||
clearCache();
|
clearCache();
|
||||||
} else if (checkETag(response)) {
|
} else if (checkETag(response)) {
|
||||||
|
@ -147,11 +146,11 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
FileUtils.deleteQuietly(eTagFile);
|
FileUtils.deleteQuietly(eTagFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkETag(HttpResponse response) {
|
private boolean checkETag(MoreHttpResponses response) {
|
||||||
try {
|
try {
|
||||||
if (cacheFile.isFile()) {
|
if (cacheFile.isFile()) {
|
||||||
String localETag = Files.readFirstLine(eTagFile, Charsets.UTF_8);
|
String localETag = Files.readFirstLine(eTagFile, Charsets.UTF_8);
|
||||||
Header remoteETag = response.getFirstHeader(HttpHeaders.ETAG);
|
Header remoteETag = response.getResponse().getFirstHeader(HttpHeaders.ETAG);
|
||||||
|
|
||||||
// true if no remote etag or does match
|
// true if no remote etag or does match
|
||||||
return remoteETag == null || localETag.equals(remoteETag.getValue());
|
return remoteETag == null || localETag.equals(remoteETag.getValue());
|
||||||
|
@ -163,18 +162,18 @@ public class ThreadDownloadImageETag extends SimpleTexture {
|
||||||
return false; // it failed, so re-fetch.
|
return false; // it failed, so re-fetch.
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadTextureFromServer(HttpResponse response) {
|
private void loadTextureFromServer(MoreHttpResponses response) {
|
||||||
LOGGER.debug("Downloading http texture from {} to {}", imageUrl, cacheFile);
|
LOGGER.debug("Downloading http texture from {} to {}", imageUrl, cacheFile);
|
||||||
try {
|
try {
|
||||||
if (response.getStatusLine().getStatusCode() / 100 == 2) {
|
if (response.getResponseCode() / 100 == 2) {
|
||||||
BufferedImage bufferedimage;
|
BufferedImage bufferedimage;
|
||||||
|
|
||||||
// write the image to disk
|
// write the image to disk
|
||||||
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), cacheFile);
|
FileUtils.copyInputStreamToFile(response.getInputStream(), cacheFile);
|
||||||
bufferedimage = ImageIO.read(cacheFile);
|
bufferedimage = ImageIO.read(cacheFile);
|
||||||
|
|
||||||
// maybe write the etag to disk
|
// maybe write the etag to disk
|
||||||
Header eTag = response.getFirstHeader(HttpHeaders.ETAG);
|
Header eTag = response.getResponse().getFirstHeader(HttpHeaders.ETAG);
|
||||||
if (eTag != null) {
|
if (eTag != null) {
|
||||||
FileUtils.write(eTagFile, eTag.getValue(), Charsets.UTF_8);
|
FileUtils.write(eTagFile, eTag.getValue(), Charsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import com.voxelmodpack.hdskins.HDSkinManager;
|
||||||
import com.voxelmodpack.hdskins.LocalTexture;
|
import com.voxelmodpack.hdskins.LocalTexture;
|
||||||
import com.voxelmodpack.hdskins.LocalTexture.IBlankSkinSupplier;
|
import com.voxelmodpack.hdskins.LocalTexture.IBlankSkinSupplier;
|
||||||
import com.voxelmodpack.hdskins.PreviewTextureManager;
|
import com.voxelmodpack.hdskins.PreviewTextureManager;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.resources.SkinManager;
|
import net.minecraft.client.resources.SkinManager;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
@ -19,6 +20,7 @@ import net.minecraft.util.ResourceLocation;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("EntityConstructor")
|
@SuppressWarnings("EntityConstructor")
|
||||||
public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSupplier {
|
public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSupplier {
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
||||||
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
|
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
|
||||||
import com.voxelmodpack.hdskins.HDSkinManager;
|
import com.voxelmodpack.hdskins.HDSkinManager;
|
||||||
|
import com.voxelmodpack.hdskins.skins.SkinUpload;
|
||||||
import com.voxelmodpack.hdskins.skins.SkinUploadResponse;
|
import com.voxelmodpack.hdskins.skins.SkinUploadResponse;
|
||||||
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG;
|
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG;
|
||||||
|
|
||||||
|
@ -544,7 +545,7 @@ public class GuiSkins extends GameGui {
|
||||||
btnUpload.enabled = canUpload();
|
btnUpload.enabled = canUpload();
|
||||||
|
|
||||||
HDSkinManager.INSTANCE.getGatewayServer()
|
HDSkinManager.INSTANCE.getGatewayServer()
|
||||||
.uploadSkin(mc.getSession(), path, textureType, getMetadata())
|
.uploadSkin(mc.getSession(), new SkinUpload(textureType, path, getMetadata()))
|
||||||
.thenAccept(this::onUploadComplete)
|
.thenAccept(this::onUploadComplete)
|
||||||
.exceptionally(this::onUploadFailure);
|
.exceptionally(this::onUploadFailure);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
package com.voxelmodpack.hdskins.skins;
|
package com.voxelmodpack.hdskins.skins;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
@ -32,19 +29,23 @@ public abstract class AbstractSkinServer implements SkinServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Type, MinecraftProfileTexture> getProfileTextures(GameProfile profile) {
|
public Map<Type, MinecraftProfileTexture> getProfileTextures(GameProfile profile) {
|
||||||
MinecraftTexturesPayload payload = getProfileData(profile);
|
try {
|
||||||
|
MinecraftTexturesPayload payload = getProfileData(profile);
|
||||||
|
|
||||||
|
if (payload != null && payload.getTextures() != null) {
|
||||||
|
return payload.getTextures();
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
|
||||||
if (payload != null && payload.getTextures() != null) {
|
|
||||||
return payload.getTextures();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final CompletableFuture<SkinUploadResponse> uploadSkin(Session session, @Nullable URI image, Type type, Map<String, String> metadata) {
|
public CompletableFuture<SkinUploadResponse> uploadSkin(Session session, SkinUpload upload) {
|
||||||
return CallableFutures.asyncFailableFuture(() -> {
|
return CallableFutures.asyncFailableFuture(() -> {
|
||||||
return doUpload(session, image, type, metadata);
|
return doUpload(session, upload);
|
||||||
}, HDSkinManager.skinUploadExecutor);
|
}, HDSkinManager.skinUploadExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +56,9 @@ public abstract class AbstractSkinServer implements SkinServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract SkinUploadResponse doUpload(Session session, URI image, Type type, Map<String, String> metadata) throws AuthenticationException, IOException;
|
protected abstract MinecraftTexturesPayload getProfileData(GameProfile profile) throws IOException;
|
||||||
|
|
||||||
|
protected abstract SkinUploadResponse doUpload(Session session, SkinUpload upload) throws AuthenticationException, IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
package com.voxelmodpack.hdskins.skins;
|
package com.voxelmodpack.hdskins.skins;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableMap.Builder;
|
import com.google.common.collect.ImmutableMap.Builder;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
|
||||||
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||||
import com.mojang.util.UUIDTypeAdapter;
|
import com.mojang.util.UUIDTypeAdapter;
|
||||||
|
|
||||||
|
@ -26,47 +23,45 @@ public class BethlehemSkinServer extends AbstractSkinServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MinecraftTexturesPayload getProfileData(GameProfile profile) {
|
public MinecraftTexturesPayload getProfileData(GameProfile profile) throws IOException {
|
||||||
try (NetClient client = new NetClient("GET", getPath(profile))) {
|
try (NetClient client = new NetClient("GET", getPath(profile))) {
|
||||||
if (client.getResponseCode() == HttpStatus.SC_OK) {
|
if (client.getResponse().ok()) {
|
||||||
return gson.fromJson(client.getResponseText(), MinecraftTexturesPayload.class);
|
return client.getResponse().json(MinecraftTexturesPayload.class);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SkinUploadResponse doUpload(Session session, URI image, Type type, Map<String, String> metadata) throws AuthenticationException, IOException {
|
protected SkinUploadResponse doUpload(Session session, SkinUpload upload) throws AuthenticationException, IOException {
|
||||||
SkinServer.verifyServerConnection(session, SERVER_ID);
|
SkinServer.verifyServerConnection(session, SERVER_ID);
|
||||||
|
|
||||||
try (NetClient client = new NetClient("POST", address)) {
|
try (NetClient client = new NetClient("POST", address)) {
|
||||||
client.putHeaders(createHeaders(session, type, image, metadata));
|
client.putHeaders(createHeaders(session, upload));
|
||||||
|
|
||||||
if (image != null) {
|
if (upload.getImage() != null) {
|
||||||
client.putFile(type.toString().toLowerCase(Locale.US), "image/png", image);
|
client.putFile(upload.getType().toString().toLowerCase(Locale.US), "image/png", upload.getImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client.getResponseCode() == HttpStatus.SC_OK) {
|
if (client.getResponse().ok()) {
|
||||||
return new SkinUploadResponse(client.getResponseText());
|
return new SkinUploadResponse(client.getResponse().text());
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IOException(client.getResponseText());
|
throw new IOException(client.getResponse().text());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<String, ?> createHeaders(Session session, Type type, URI image, Map<String, String> metadata) {
|
protected Map<String, ?> createHeaders(Session session, SkinUpload upload) {
|
||||||
Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
|
Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
|
||||||
.put("accessToken", session.getToken())
|
.put("accessToken", session.getToken())
|
||||||
.put("user", session.getUsername())
|
.put("user", session.getUsername())
|
||||||
.put("uuid", UUIDTypeAdapter.fromUUID(session.getProfile().getId()))
|
.put("uuid", UUIDTypeAdapter.fromUUID(session.getProfile().getId()))
|
||||||
.put("type", type.toString().toLowerCase(Locale.US));
|
.put("type", upload.getType().toString().toLowerCase(Locale.US));
|
||||||
|
|
||||||
if (image == null) {
|
if (upload.getImage() == null) {
|
||||||
builder.put("clear", "1");
|
builder.put("clear", "1");
|
||||||
} else {
|
} else {
|
||||||
builder.put("model", metadata.getOrDefault("mode", "default"));
|
builder.put("model", upload.getMetadata().getOrDefault("mode", "default"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -11,16 +11,18 @@ import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||||
import com.mojang.util.UUIDTypeAdapter;
|
import com.mojang.util.UUIDTypeAdapter;
|
||||||
|
|
||||||
import net.minecraft.util.Session;
|
import net.minecraft.util.Session;
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@ServerType("legacy")
|
@ServerType("legacy")
|
||||||
|
@ -49,21 +51,14 @@ public class LegacySkinServer extends AbstractSkinServer {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
@Override
|
||||||
public MinecraftTexturesPayload getProfileData(GameProfile profile) {
|
public MinecraftTexturesPayload getProfileData(GameProfile profile) throws IOException {
|
||||||
ImmutableMap.Builder<Type, MinecraftProfileTexture> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<Type, MinecraftProfileTexture> builder = ImmutableMap.builder();
|
||||||
|
|
||||||
for (Type type : Type.values()) {
|
for (Type type : Type.values()) {
|
||||||
|
|
||||||
String url = getPath(address, type, profile);
|
String url = getPath(address, type, profile);
|
||||||
|
try {
|
||||||
try (NetClient client = new NetClient("GET", url)) {
|
builder.put(type, loadProfileTexture(profile, url));
|
||||||
if (client.getResponseCode() != HttpStatus.SC_OK) {
|
|
||||||
throw new IOException("Bad response code: " + client.getResponseCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.put(type, new MinecraftProfileTexture(url, null));
|
|
||||||
logger.debug("Found skin for {} at {}", profile.getName(), url);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.trace("Couldn't find texture for {} at {}. Does it exist?", profile.getName(), url, e);
|
logger.trace("Couldn't find texture for {} at {}. Does it exist?", profile.getName(), url, e);
|
||||||
}
|
}
|
||||||
|
@ -72,25 +67,32 @@ public class LegacySkinServer extends AbstractSkinServer {
|
||||||
Map<Type, MinecraftProfileTexture> map = builder.build();
|
Map<Type, MinecraftProfileTexture> map = builder.build();
|
||||||
|
|
||||||
if (map.isEmpty()) {
|
if (map.isEmpty()) {
|
||||||
logger.debug("No textures found for {} at {}", profile, address);
|
throw new IOException(String.format("No textures found for %s at %s", profile, address));
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TexturesPayloadBuilder.createTexturesPayload(profile, map);
|
return TexturesPayloadBuilder.createTexturesPayload(profile, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MinecraftProfileTexture loadProfileTexture(GameProfile profile, String url) throws IOException {
|
||||||
|
HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).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);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SkinUploadResponse doUpload(Session session, URI image, Type type, Map<String, String> metadata) throws AuthenticationException, IOException {
|
protected SkinUploadResponse doUpload(Session session, SkinUpload skin) throws AuthenticationException, IOException {
|
||||||
SkinServer.verifyServerConnection(session, SERVER_ID);
|
SkinServer.verifyServerConnection(session, SERVER_ID);
|
||||||
|
|
||||||
try (NetClient client = new NetClient("POST", address)) {
|
try (NetClient client = new NetClient("POST", address)) {
|
||||||
client.putHeaders(createHeaders(session, type, image, metadata));
|
client.putHeaders(createHeaders(session, skin.getType(), skin.getImage(), skin.getMetadata()));
|
||||||
|
|
||||||
if (image != null) {
|
if (skin.getImage() != null) {
|
||||||
client.putFile(type.toString().toLowerCase(Locale.US), "image/png", image);
|
client.putFile(skin.getType().toString().toLowerCase(Locale.US), "image/png", skin.getImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
String response = client.getResponseText();
|
String response = client.getResponse().text();
|
||||||
|
|
||||||
if (response.startsWith("ERROR: ")) { // lol @ "ERROR: OK"
|
if (response.startsWith("ERROR: ")) { // lol @ "ERROR: OK"
|
||||||
response = response.substring(7);
|
response = response.substring(7);
|
||||||
|
@ -104,7 +106,6 @@ public class LegacySkinServer extends AbstractSkinServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Map<String, ?> createHeaders(Session session, Type type, URI image, Map<String, String> metadata) {
|
protected Map<String, ?> createHeaders(Session session, Type type, URI image, Map<String, String> metadata) {
|
||||||
Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
|
Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
|
||||||
.put("user", session.getUsername())
|
.put("user", session.getUsername())
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.voxelmodpack.hdskins.skins;
|
||||||
|
|
||||||
|
import com.google.common.io.CharStreams;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for getting different response types from a http response.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface MoreHttpResponses extends AutoCloseable {
|
||||||
|
|
||||||
|
CloseableHttpResponse getResponse();
|
||||||
|
|
||||||
|
default boolean ok() {
|
||||||
|
return getResponseCode() == HttpStatus.SC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int getResponseCode() {
|
||||||
|
return getResponse().getStatusLine().getStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
default InputStream getInputStream() throws IOException {
|
||||||
|
return getResponse().getEntity().getContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
default BufferedReader getReader() throws IOException {
|
||||||
|
return new BufferedReader(new InputStreamReader(getInputStream(), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
default String text() throws IOException {
|
||||||
|
try (BufferedReader reader = getReader()) {
|
||||||
|
return CharStreams.toString(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default Stream<String> lines() throws IOException {
|
||||||
|
try (BufferedReader reader = getReader()) {
|
||||||
|
return reader.lines();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> T json(Class<T> type) throws IOException {
|
||||||
|
try (Reader reader = new InputStreamReader(getResponse().getEntity().getContent())) {
|
||||||
|
return SkinServer.gson.fromJson(reader, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T> T json(Type type) throws IOException {
|
||||||
|
try (Reader reader = new InputStreamReader(getResponse().getEntity().getContent())) {
|
||||||
|
return SkinServer.gson.fromJson(reader, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void close() throws IOException {
|
||||||
|
this.getResponse().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static MoreHttpResponses execute(CloseableHttpClient client, HttpUriRequest request) throws IOException {
|
||||||
|
CloseableHttpResponse response = client.execute(request);
|
||||||
|
return () -> response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,23 +1,19 @@
|
||||||
package com.voxelmodpack.hdskins.skins;
|
package com.voxelmodpack.hdskins.skins;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.client.methods.RequestBuilder;
|
import org.apache.http.client.methods.RequestBuilder;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
||||||
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.util.EntityUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ew. Why so many builders? >.<
|
* Ew. Why so many builders? >.<
|
||||||
|
@ -26,11 +22,19 @@ public class NetClient implements Closeable {
|
||||||
|
|
||||||
private static CloseableHttpClient client = null;
|
private static CloseableHttpClient client = null;
|
||||||
|
|
||||||
|
public static CloseableHttpClient nativeClient() {
|
||||||
|
if (client == null) {
|
||||||
|
client = HttpClients.createSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
private RequestBuilder rqBuilder;
|
private RequestBuilder rqBuilder;
|
||||||
|
|
||||||
private Map<String, ?> headers;
|
private Map<String, ?> headers;
|
||||||
|
|
||||||
private CloseableHttpResponse response = null;
|
private MoreHttpResponses response;
|
||||||
|
|
||||||
public NetClient(String method, String uri) {
|
public NetClient(String method, String uri) {
|
||||||
start(method, uri);
|
start(method, uri);
|
||||||
|
@ -49,7 +53,9 @@ public class NetClient implements Closeable {
|
||||||
headers = null;
|
headers = null;
|
||||||
|
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
EntityUtils.consumeQuietly(response.getEntity());
|
try {
|
||||||
|
response.close();
|
||||||
|
} catch (IOException ignored) {}
|
||||||
response = null;
|
response = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,17 +103,13 @@ public class NetClient implements Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client == null) {
|
response = MoreHttpResponses.execute(nativeClient(), request);
|
||||||
client = HttpClients.createSystem();
|
|
||||||
}
|
|
||||||
|
|
||||||
response = client.execute(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or obtains the http response body.
|
* Gets or obtains the http response body.
|
||||||
*/
|
*/
|
||||||
public CloseableHttpResponse getResponse() throws IOException {
|
public MoreHttpResponses getResponse() throws IOException {
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
send();
|
send();
|
||||||
}
|
}
|
||||||
|
@ -115,33 +117,6 @@ public class NetClient implements Closeable {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets or obtains a response status code.
|
|
||||||
*/
|
|
||||||
public int getResponseCode() throws IOException {
|
|
||||||
return getResponse().getStatusLine().getStatusCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Consumes and returns the entire response body.
|
|
||||||
*/
|
|
||||||
public String getResponseText() throws IOException {
|
|
||||||
if (getResponse().getEntity() == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(getResponse().getEntity().getContent()))) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
|
|
||||||
int ch;
|
|
||||||
while ((ch = reader.read()) != -1) {
|
|
||||||
builder.append((char)ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -8,21 +8,16 @@ import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||||
import com.mojang.authlib.minecraft.MinecraftSessionService;
|
import com.mojang.authlib.minecraft.MinecraftSessionService;
|
||||||
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
|
||||||
import com.mojang.util.UUIDTypeAdapter;
|
import com.mojang.util.UUIDTypeAdapter;
|
||||||
import com.mumfrey.liteloader.modconfig.Exposable;
|
import com.mumfrey.liteloader.modconfig.Exposable;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.util.Session;
|
import net.minecraft.util.Session;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public interface SkinServer extends Exposable {
|
public interface SkinServer extends Exposable {
|
||||||
|
|
||||||
Gson gson = new GsonBuilder()
|
Gson gson = new GsonBuilder()
|
||||||
|
@ -33,15 +28,13 @@ public interface SkinServer extends Exposable {
|
||||||
"http://skins.voxelmodpack.com",
|
"http://skins.voxelmodpack.com",
|
||||||
"http://skinmanager.voxelmodpack.com"));
|
"http://skinmanager.voxelmodpack.com"));
|
||||||
|
|
||||||
MinecraftTexturesPayload getProfileData(GameProfile profile);
|
|
||||||
|
|
||||||
Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getProfileTextures(GameProfile profile);
|
Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> getProfileTextures(GameProfile profile);
|
||||||
|
|
||||||
CompletableFuture<SkinUploadResponse> uploadSkin(Session session, @Nullable URI image, MinecraftProfileTexture.Type type, Map<String, String> metadata);
|
CompletableFuture<SkinUploadResponse> uploadSkin(Session session, SkinUpload upload);
|
||||||
|
|
||||||
void validate() throws JsonParseException;
|
void validate() throws JsonParseException;
|
||||||
|
|
||||||
public static void verifyServerConnection(Session session, String serverId) throws AuthenticationException {
|
static void verifyServerConnection(Session session, String serverId) throws AuthenticationException {
|
||||||
MinecraftSessionService service = Minecraft.getMinecraft().getSessionService();
|
MinecraftSessionService service = Minecraft.getMinecraft().getSessionService();
|
||||||
service.joinServer(session.getProfile(), session.getToken(), serverId);
|
service.joinServer(session.getProfile(), session.getToken(), serverId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.voxelmodpack.hdskins.skins;
|
||||||
|
|
||||||
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class SkinUpload {
|
||||||
|
|
||||||
|
private final URI image;
|
||||||
|
private final Map<String, String> metadata;
|
||||||
|
private final MinecraftProfileTexture.Type type;
|
||||||
|
|
||||||
|
public SkinUpload(MinecraftProfileTexture.Type type, @Nullable URI image, Map<String, String> metadata) {
|
||||||
|
this.image = image;
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public URI getImage() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinecraftProfileTexture.Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ import com.google.gson.JsonObject;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
|
||||||
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||||
import com.mojang.util.UUIDTypeAdapter;
|
import com.mojang.util.UUIDTypeAdapter;
|
||||||
|
|
||||||
|
@ -14,24 +13,16 @@ import javax.annotation.Nullable;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.util.Session;
|
import net.minecraft.util.Session;
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHeaders;
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.apache.http.NameValuePair;
|
import org.apache.http.NameValuePair;
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.client.methods.RequestBuilder;
|
import org.apache.http.client.methods.RequestBuilder;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClients;
|
|
||||||
import org.apache.http.message.BasicNameValuePair;
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
import org.apache.http.util.EntityUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -46,79 +37,81 @@ public class ValhallaSkinServer extends AbstractSkinServer {
|
||||||
super(address);
|
super(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public MinecraftTexturesPayload getProfileData(GameProfile profile) {
|
|
||||||
try (CloseableHttpClient client = HttpClients.createSystem()) {
|
|
||||||
try (CloseableHttpResponse response = client.execute(new HttpGet(getTexturesURI(profile)))) {
|
|
||||||
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
|
|
||||||
return readJson(response, MinecraftTexturesPayload.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MinecraftTexturesPayload getProfileData(GameProfile profile) throws IOException {
|
||||||
|
|
||||||
|
try (MoreHttpResponses response = MoreHttpResponses.execute(NetClient.nativeClient(), new HttpGet(getTexturesURI(profile)))) {
|
||||||
|
|
||||||
|
if (response.ok()) {
|
||||||
|
return readJson(response, MinecraftTexturesPayload.class);
|
||||||
|
}
|
||||||
|
throw new IOException("Server sent non-ok response code: " + response.getResponseCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SkinUploadResponse doUpload(Session session, SkinUpload skin) throws AuthenticationException, IOException {
|
||||||
|
URI image = skin.getImage();
|
||||||
|
Map<String, String> metadata = skin.getMetadata();
|
||||||
|
MinecraftProfileTexture.Type type = skin.getType();
|
||||||
|
|
||||||
|
authorize(session);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return upload(session, image, type, metadata);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
if (e.getMessage().equals("Authorization failed")) {
|
||||||
}
|
accessToken = null;
|
||||||
|
authorize(session);
|
||||||
return null;
|
return upload(session, image, type, metadata);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected SkinUploadResponse doUpload(Session session, URI image, Type type, Map<String, String> metadata) throws AuthenticationException, IOException {
|
|
||||||
try (CloseableHttpClient client = HttpClients.createSystem()) {
|
|
||||||
authorize(client, session);
|
|
||||||
|
|
||||||
try {
|
|
||||||
return upload(client, session, image, type, metadata);
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (e.getMessage().equals("Authorization failed")) {
|
|
||||||
accessToken = null;
|
|
||||||
authorize(client, session);
|
|
||||||
return upload(client, session, image, type, metadata);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinUploadResponse upload(CloseableHttpClient client, Session session, @Nullable URI image, MinecraftProfileTexture.Type type, Map<String, String> metadata) throws IOException {
|
private SkinUploadResponse upload(Session session, @Nullable URI image,
|
||||||
|
MinecraftProfileTexture.Type type, Map<String, String> metadata)
|
||||||
|
throws IOException {
|
||||||
GameProfile profile = session.getProfile();
|
GameProfile profile = session.getProfile();
|
||||||
|
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
return resetSkin(client, profile, type);
|
return resetSkin(profile, type);
|
||||||
}
|
}
|
||||||
switch (image.getScheme()) {
|
switch (image.getScheme()) {
|
||||||
case "file":
|
case "file":
|
||||||
return uploadFile(client, new File(image), profile, type, metadata);
|
return uploadFile(new File(image), profile, type, metadata);
|
||||||
case "http":
|
case "http":
|
||||||
case "https":
|
case "https":
|
||||||
return uploadUrl(client, image, profile, type, metadata);
|
return uploadUrl(image, profile, type, metadata);
|
||||||
default:
|
default:
|
||||||
throw new IOException("Unsupported URI scheme: " + image.getScheme());
|
throw new IOException("Unsupported URI scheme: " + image.getScheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinUploadResponse resetSkin(CloseableHttpClient client, GameProfile profile, MinecraftProfileTexture.Type type) throws IOException {
|
private SkinUploadResponse resetSkin(GameProfile profile, MinecraftProfileTexture.Type type) throws IOException {
|
||||||
return upload(client, RequestBuilder.delete()
|
return upload(RequestBuilder.delete()
|
||||||
.setUri(buildUserTextureUri(profile, type))
|
.setUri(buildUserTextureUri(profile, type))
|
||||||
.addHeader(HttpHeaders.AUTHORIZATION, this.accessToken)
|
.addHeader(HttpHeaders.AUTHORIZATION, this.accessToken)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinUploadResponse uploadFile(CloseableHttpClient client, File file, GameProfile profile, MinecraftProfileTexture.Type type, Map<String, String> metadata) throws IOException {
|
private SkinUploadResponse uploadFile(File file, GameProfile profile, MinecraftProfileTexture.Type type, Map<String, String> metadata) throws IOException {
|
||||||
MultipartEntityBuilder b = MultipartEntityBuilder.create();
|
MultipartEntityBuilder b = MultipartEntityBuilder.create();
|
||||||
b.addBinaryBody("file", file, ContentType.create("image/png"), file.getName());
|
b.addBinaryBody("file", file, ContentType.create("image/png"), file.getName());
|
||||||
metadata.forEach(b::addTextBody);
|
metadata.forEach(b::addTextBody);
|
||||||
|
|
||||||
return upload(client, RequestBuilder.put()
|
return upload(RequestBuilder.put()
|
||||||
.setUri(buildUserTextureUri(profile, type))
|
.setUri(buildUserTextureUri(profile, type))
|
||||||
.addHeader(HttpHeaders.AUTHORIZATION, this.accessToken)
|
.addHeader(HttpHeaders.AUTHORIZATION, this.accessToken)
|
||||||
.setEntity(b.build())
|
.setEntity(b.build())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinUploadResponse uploadUrl(CloseableHttpClient client, URI uri, GameProfile profile, MinecraftProfileTexture.Type type, Map<String, String> metadata) throws IOException {
|
private SkinUploadResponse uploadUrl(URI uri, GameProfile profile, MinecraftProfileTexture.Type type, Map<String, String> metadata) throws IOException {
|
||||||
return upload(client, RequestBuilder.post()
|
|
||||||
|
return upload(RequestBuilder.post()
|
||||||
.setUri(buildUserTextureUri(profile, type))
|
.setUri(buildUserTextureUri(profile, type))
|
||||||
.addHeader(HttpHeaders.AUTHORIZATION, this.accessToken)
|
.addHeader(HttpHeaders.AUTHORIZATION, this.accessToken)
|
||||||
.addParameter("file", uri.toString())
|
.addParameter("file", uri.toString())
|
||||||
|
@ -128,21 +121,20 @@ public class ValhallaSkinServer extends AbstractSkinServer {
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SkinUploadResponse upload(CloseableHttpClient client, HttpUriRequest request) throws IOException {
|
private SkinUploadResponse upload(HttpUriRequest request) throws IOException {
|
||||||
try (CloseableHttpResponse response = client.execute(request)) {
|
try (MoreHttpResponses response = MoreHttpResponses.execute(NetClient.nativeClient(), request)) {
|
||||||
return readJson(response, SkinUploadResponse.class);
|
return readJson(response, SkinUploadResponse.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void authorize(Session session) throws IOException, AuthenticationException {
|
||||||
private void authorize(CloseableHttpClient client, Session session) throws IOException, AuthenticationException {
|
if (this.accessToken != null) {
|
||||||
if (accessToken != null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameProfile profile = session.getProfile();
|
GameProfile profile = session.getProfile();
|
||||||
|
|
||||||
AuthHandshake handshake = authHandshake(client, profile.getName());
|
AuthHandshake handshake = authHandshake(profile.getName());
|
||||||
|
|
||||||
if (handshake.offline) {
|
if (handshake.offline) {
|
||||||
return;
|
return;
|
||||||
|
@ -151,7 +143,7 @@ public class ValhallaSkinServer extends AbstractSkinServer {
|
||||||
// join the session server
|
// join the session server
|
||||||
Minecraft.getMinecraft().getSessionService().joinServer(profile, session.getToken(), handshake.serverId);
|
Minecraft.getMinecraft().getSessionService().joinServer(profile, session.getToken(), handshake.serverId);
|
||||||
|
|
||||||
AuthResponse response = authResponse(client, profile.getName(), handshake.verifyToken);
|
AuthResponse response = authResponse(profile.getName(), handshake.verifyToken);
|
||||||
if (!response.userId.equals(profile.getId())) {
|
if (!response.userId.equals(profile.getId())) {
|
||||||
throw new IOException("UUID mismatch!"); // probably won't ever throw
|
throw new IOException("UUID mismatch!"); // probably won't ever throw
|
||||||
}
|
}
|
||||||
|
@ -159,29 +151,21 @@ public class ValhallaSkinServer extends AbstractSkinServer {
|
||||||
accessToken = response.accessToken;
|
accessToken = response.accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T readJson(HttpResponse resp, Class<T> cl) throws IOException {
|
private <T> T readJson(MoreHttpResponses resp, Class<T> cl) throws IOException {
|
||||||
String type = resp.getEntity().getContentType().getValue();
|
String type = resp.getResponse().getEntity().getContentType().getValue();
|
||||||
|
|
||||||
if (!"application/json".equals(type)) {
|
if (!"application/json".equals(type)) {
|
||||||
try {
|
throw new IOException("Server returned a non-json response!");
|
||||||
throw new IOException("Server returned a non-json response!");
|
|
||||||
} finally {
|
|
||||||
EntityUtils.consumeQuietly(resp.getEntity());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Reader r = new InputStreamReader(resp.getEntity().getContent())) {
|
if (resp.ok()) {
|
||||||
if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
|
return resp.json(cl);
|
||||||
// TODO specific error handling
|
|
||||||
throw new IOException(gson.fromJson(r, JsonObject.class).get("message").getAsString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return gson.fromJson(r, cl);
|
|
||||||
}
|
}
|
||||||
|
throw new IOException(resp.json(JsonObject.class).get("message").getAsString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthHandshake authHandshake(CloseableHttpClient client, String name) throws IOException {
|
private AuthHandshake authHandshake(String name) throws IOException {
|
||||||
try (CloseableHttpResponse resp = client.execute(RequestBuilder.post()
|
try (MoreHttpResponses resp = MoreHttpResponses.execute(NetClient.nativeClient(), RequestBuilder.post()
|
||||||
.setUri(getHandshakeURI())
|
.setUri(getHandshakeURI())
|
||||||
.addParameter("name", name)
|
.addParameter("name", name)
|
||||||
.build())) {
|
.build())) {
|
||||||
|
@ -189,8 +173,8 @@ public class ValhallaSkinServer extends AbstractSkinServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthResponse authResponse(CloseableHttpClient client, String name, long verifyToken) throws IOException {
|
private AuthResponse authResponse(String name, long verifyToken) throws IOException {
|
||||||
try (CloseableHttpResponse resp = client.execute(RequestBuilder.post()
|
try (MoreHttpResponses resp = MoreHttpResponses.execute(NetClient.nativeClient(), RequestBuilder.post()
|
||||||
.setUri(getResponseURI())
|
.setUri(getResponseURI())
|
||||||
.addParameter("name", name)
|
.addParameter("name", name)
|
||||||
.addParameter("verifyToken", String.valueOf(verifyToken))
|
.addParameter("verifyToken", String.valueOf(verifyToken))
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class LayerPonyCustomHead<T extends EntityLivingBase> implements LayerRen
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModelWrapper getModel() {
|
private ModelWrapper getModel() {
|
||||||
return ((IRenderPony) renderer).getModelWrapper();
|
return ((IRenderPony<?>) renderer).getModelWrapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue