mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2024-11-26 22:38:00 +01:00
Split up the GuiSkins by concern (There is now a skin chooser and an uploader, and the gui only has gui stuff)
This commit is contained in:
parent
e0e2598cd0
commit
475d545887
13 changed files with 601 additions and 366 deletions
|
@ -7,6 +7,9 @@ import net.minecraft.client.gui.GuiButton;
|
||||||
|
|
||||||
public class Button extends GuiButton implements IActionable, IGuiTooltipped {
|
public class Button extends GuiButton implements IActionable, IGuiTooltipped {
|
||||||
|
|
||||||
|
private int tipX = 0;
|
||||||
|
private int tipY = 0;
|
||||||
|
|
||||||
protected IGuiAction<Button> action;
|
protected IGuiAction<Button> action;
|
||||||
|
|
||||||
private List<String> tooltip = null;
|
private List<String> tooltip = null;
|
||||||
|
@ -36,7 +39,14 @@ public class Button extends GuiButton implements IActionable, IGuiTooltipped {
|
||||||
@Override
|
@Override
|
||||||
public void renderToolTip(Minecraft mc, int mouseX, int mouseY) {
|
public void renderToolTip(Minecraft mc, int mouseX, int mouseY) {
|
||||||
if (visible && isMouseOver() && tooltip != null) {
|
if (visible && isMouseOver() && tooltip != null) {
|
||||||
mc.currentScreen.drawHoveringText(tooltip, mouseX, mouseY);
|
mc.currentScreen.drawHoveringText(tooltip, mouseX + tipX, mouseY + tipY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IGuiTooltipped setTooltipOffset(int x, int y) {
|
||||||
|
tipX = x;
|
||||||
|
tipY = y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@ import net.minecraft.client.resources.I18n;
|
||||||
*/
|
*/
|
||||||
public class Checkbox extends GuiCheckbox implements IActionable, IGuiTooltipped {
|
public class Checkbox extends GuiCheckbox implements IActionable, IGuiTooltipped {
|
||||||
|
|
||||||
|
private int tipX = 0;
|
||||||
|
private int tipY = 0;
|
||||||
|
|
||||||
private List<String> tooltip = null;
|
private List<String> tooltip = null;
|
||||||
|
|
||||||
private final IGuiCallback<Boolean> action;
|
private final IGuiCallback<Boolean> action;
|
||||||
|
@ -39,7 +42,14 @@ public class Checkbox extends GuiCheckbox implements IActionable, IGuiTooltipped
|
||||||
@Override
|
@Override
|
||||||
public void renderToolTip(Minecraft mc, int mouseX, int mouseY) {
|
public void renderToolTip(Minecraft mc, int mouseX, int mouseY) {
|
||||||
if (visible && isMouseOver() && tooltip != null) {
|
if (visible && isMouseOver() && tooltip != null) {
|
||||||
mc.currentScreen.drawHoveringText(tooltip, mouseX, mouseY);
|
mc.currentScreen.drawHoveringText(tooltip, mouseX + tipX, mouseY + tipY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IGuiTooltipped setTooltipOffset(int x, int y) {
|
||||||
|
tipX = x;
|
||||||
|
tipY = y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,12 @@ import org.apache.commons.lang3.text.WordUtils;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||||
import net.minecraft.client.gui.FontRenderer;
|
import net.minecraft.client.gui.FontRenderer;
|
||||||
import net.minecraft.client.gui.GuiButton;
|
import net.minecraft.client.gui.GuiButton;
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.resources.I18n;
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import net.minecraft.util.SoundEvent;
|
||||||
|
|
||||||
public abstract class GameGui extends GuiScreen {
|
public abstract class GameGui extends GuiScreen {
|
||||||
|
|
||||||
|
@ -20,7 +22,7 @@ public abstract class GameGui extends GuiScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static String format(String string, Object... pars) {
|
protected static String format(String string, Object... pars) {
|
||||||
return I18n.format(string, pars);
|
return string == null ? null : I18n.format(string, pars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,6 +39,10 @@ public abstract class GameGui extends GuiScreen {
|
||||||
return fr.listFormattedStringToWidth(format(string, pars), width);
|
return fr.listFormattedStringToWidth(format(string, pars), width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void playSound(SoundEvent event) {
|
||||||
|
mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(event, 1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a given string to title case regardless of initial case.
|
* Converts a given string to title case regardless of initial case.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,8 @@ public interface IGuiTooltipped {
|
||||||
|
|
||||||
IGuiTooltipped setTooltip(List<String> tooltip);
|
IGuiTooltipped setTooltip(List<String> tooltip);
|
||||||
|
|
||||||
|
IGuiTooltipped setTooltipOffset(int x, int y);
|
||||||
|
|
||||||
default IGuiTooltipped setTooltip(String tooltip) {
|
default IGuiTooltipped setTooltip(String tooltip) {
|
||||||
return setTooltip(Splitter.onPattern("\r?\n|\\\\n").splitToList(GameGui.format(tooltip)));
|
return setTooltip(Splitter.onPattern("\r?\n|\\\\n").splitToList(GameGui.format(tooltip)));
|
||||||
}
|
}
|
||||||
|
|
134
src/hdskins/java/com/voxelmodpack/hdskins/SkinChooser.java
Normal file
134
src/hdskins/java/com/voxelmodpack/hdskins/SkinChooser.java
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
package com.voxelmodpack.hdskins;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFile;
|
||||||
|
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFileFolder;
|
||||||
|
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class SkinChooser {
|
||||||
|
public static final int MAX_SKIN_DIMENSION = 1024;
|
||||||
|
|
||||||
|
public static final String ERR_UNREADABLE = "hdskins.error.unreadable";
|
||||||
|
public static final String ERR_EXT = "hdskins.error.ext";
|
||||||
|
public static final String ERR_OPEN = "hdskins.error.open";
|
||||||
|
public static final String ERR_INVALID = "hdskins.error.invalid";
|
||||||
|
|
||||||
|
public static final String MSG_CHOOSE = "hdskins.choose";
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPowerOfTwo(int number) {
|
||||||
|
return number != 0 && (number & number - 1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ThreadOpenFile openFileThread;
|
||||||
|
|
||||||
|
private final SkinUploader uploader;
|
||||||
|
|
||||||
|
|
||||||
|
private volatile String status = MSG_CHOOSE;
|
||||||
|
|
||||||
|
|
||||||
|
public SkinChooser(SkinUploader uploader) {
|
||||||
|
this.uploader = uploader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean pickingInProgress() {
|
||||||
|
return openFileThread != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openBrowsePNG(Minecraft mc, String title, Runnable callback) {
|
||||||
|
openFileThread = new ThreadOpenFilePNG(mc, title, (fileDialog, dialogResult) -> {
|
||||||
|
openFileThread = null;
|
||||||
|
if (dialogResult == 0) {
|
||||||
|
selectFile(fileDialog.getSelectedFile());
|
||||||
|
callback.run();
|
||||||
|
} else {
|
||||||
|
callback.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
openFileThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openSavePNG(Minecraft mc, String title, Runnable callback) {
|
||||||
|
uploader.downloadSkin().thenAccept(response -> {
|
||||||
|
openFileThread = new ThreadOpenFileFolder(mc, title, (fileDialog, dialogResult) -> {
|
||||||
|
openFileThread = null;
|
||||||
|
callback.run();
|
||||||
|
if (dialogResult == 0) {
|
||||||
|
File out = fileDialog.getSelectedFile();
|
||||||
|
|
||||||
|
try {
|
||||||
|
out.createNewFile();
|
||||||
|
|
||||||
|
FileUtils.copyInputStreamToFile(response.getInputStream(), out);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
openFileThread.start();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectFile(File skinFile) {
|
||||||
|
status = evaluateAndSelect(skinFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String evaluateAndSelect(File skinFile) {
|
||||||
|
if (!skinFile.exists()) {
|
||||||
|
return ERR_UNREADABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FilenameUtils.isExtension(skinFile.getName(), new String[]{"png", "PNG"})) {
|
||||||
|
return ERR_EXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedImage chosenImage = ImageIO.read(skinFile);
|
||||||
|
|
||||||
|
if (chosenImage == null) {
|
||||||
|
return ERR_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!acceptsSkinDimensions(chosenImage.getWidth(), chosenImage.getHeight())) {
|
||||||
|
return ERR_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uploader.setLocalSkin(skinFile);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERR_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean acceptsSkinDimensions(int w, int h) {
|
||||||
|
return isPowerOfTwo(w) && w == h * 2 || w == h && w <= MAX_SKIN_DIMENSION && h <= MAX_SKIN_DIMENSION;
|
||||||
|
}
|
||||||
|
}
|
284
src/hdskins/java/com/voxelmodpack/hdskins/SkinUploader.java
Normal file
284
src/hdskins/java/com/voxelmodpack/hdskins/SkinUploader.java
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
package com.voxelmodpack.hdskins;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.init.Items;
|
||||||
|
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
|
||||||
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
||||||
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
||||||
|
import com.mumfrey.liteloader.util.log.LiteLoaderLogger;
|
||||||
|
import com.voxelmodpack.hdskins.gui.EntityPlayerModel;
|
||||||
|
import com.voxelmodpack.hdskins.skins.MoreHttpResponses;
|
||||||
|
import com.voxelmodpack.hdskins.skins.NetClient;
|
||||||
|
import com.voxelmodpack.hdskins.skins.SkinServer;
|
||||||
|
import com.voxelmodpack.hdskins.skins.SkinUpload;
|
||||||
|
import com.voxelmodpack.hdskins.skins.SkinUploadResponse;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class SkinUploader implements Closeable {
|
||||||
|
|
||||||
|
private final Iterator<SkinServer> skinServers;
|
||||||
|
|
||||||
|
public static final String ERR_NO_SERVER = "hdskins.error.noserver";
|
||||||
|
public static final String ERR_OFFLINE = "hdskins.error.offline";
|
||||||
|
|
||||||
|
public static final String ERR_MOJANG = "hdskins.error.mojang";
|
||||||
|
public static final String ERR_WAIT = "hdskins.error.mojang.wait";
|
||||||
|
|
||||||
|
public static final String STATUS_FETCH = "hdskins.fetch";
|
||||||
|
|
||||||
|
private SkinServer gateway;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
private Type skinType;
|
||||||
|
|
||||||
|
private Map<String, String> skinMetadata = new HashMap<String, String>();
|
||||||
|
|
||||||
|
private volatile boolean fetchingSkin = false;
|
||||||
|
private volatile boolean throttlingNeck = false;
|
||||||
|
private volatile boolean offline = false;
|
||||||
|
|
||||||
|
private volatile boolean sendingSkin = false;
|
||||||
|
|
||||||
|
private int reloadCounter = 0;
|
||||||
|
private int retries = 1;
|
||||||
|
|
||||||
|
private final EntityPlayerModel remotePlayer;
|
||||||
|
private final EntityPlayerModel localPlayer;
|
||||||
|
|
||||||
|
private final Object skinLock = new Object();
|
||||||
|
|
||||||
|
private File pendingLocalSkin;
|
||||||
|
private File localSkin;
|
||||||
|
|
||||||
|
private final ISkinUploadHandler listener;
|
||||||
|
|
||||||
|
private final Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
private static <T> Iterator<T> cycle(List<T> list, Predicate<T> filter) {
|
||||||
|
return Iterables.cycle(Iterables.filter(list, filter::test)).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinUploader(List<SkinServer> servers, EntityPlayerModel local, EntityPlayerModel remote, ISkinUploadHandler listener) {
|
||||||
|
|
||||||
|
localPlayer = local;
|
||||||
|
remotePlayer = remote;
|
||||||
|
|
||||||
|
skinType = Type.SKIN;
|
||||||
|
skinMetadata.put("model", "default");
|
||||||
|
|
||||||
|
this.listener = listener;
|
||||||
|
skinServers = cycle(servers, SkinServer::verifyGateway);
|
||||||
|
cycleGateway();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cycleGateway() {
|
||||||
|
if (skinServers.hasNext()) {
|
||||||
|
gateway = skinServers.next();
|
||||||
|
fetchRemote();
|
||||||
|
} else {
|
||||||
|
setError(ERR_NO_SERVER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGateway() {
|
||||||
|
return gateway == null ? "" : gateway.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setError(String er) {
|
||||||
|
status = er;
|
||||||
|
sendingSkin = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkinType(Type type) {
|
||||||
|
skinType = type;
|
||||||
|
|
||||||
|
ItemStack stack = type == Type.ELYTRA ? new ItemStack(Items.ELYTRA) : ItemStack.EMPTY;
|
||||||
|
// put on or take off the elytra
|
||||||
|
localPlayer.setItemStackToSlot(EntityEquipmentSlot.CHEST, stack);
|
||||||
|
remotePlayer.setItemStackToSlot(EntityEquipmentSlot.CHEST, stack);
|
||||||
|
|
||||||
|
listener.onSkinTypeChanged(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean uploadInProgress() {
|
||||||
|
return sendingSkin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean downloadInProgress() {
|
||||||
|
return fetchingSkin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isThrottled() {
|
||||||
|
return throttlingNeck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOffline() {
|
||||||
|
return offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRetries() {
|
||||||
|
return retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canUpload() {
|
||||||
|
return !isOffline() && !hasStatus() && !uploadInProgress() && pendingLocalSkin == null && localSkin != null && localPlayer.isUsingLocalTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canClear() {
|
||||||
|
return !isOffline() && !hasStatus() && !downloadInProgress() && remotePlayer.isTextureSetupComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasStatus() {
|
||||||
|
return status != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatusMessage() {
|
||||||
|
return hasStatus() ? status : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMetadataField(String field, String value) {
|
||||||
|
localPlayer.releaseTextures();
|
||||||
|
skinMetadata.put(field, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMetadataField(String field) {
|
||||||
|
return skinMetadata.getOrDefault(field, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getSkinType() {
|
||||||
|
return skinType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tryClearStatus() {
|
||||||
|
if (!hasStatus() || !uploadInProgress()) {
|
||||||
|
status = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> uploadSkin(String statusMsg) {
|
||||||
|
sendingSkin = true;
|
||||||
|
status = statusMsg;
|
||||||
|
|
||||||
|
return gateway.uploadSkin(mc.getSession(), new SkinUpload(skinType, localSkin.toURI(), skinMetadata))
|
||||||
|
.thenAccept(this::onUploadCompleted)
|
||||||
|
.exceptionally(this::onUploadFailure);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onUploadCompleted(SkinUploadResponse response) {
|
||||||
|
LiteLoaderLogger.info("Upload completed with: %s", response);
|
||||||
|
sendingSkin = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Void onUploadFailure(Throwable response) {
|
||||||
|
response = Throwables.getRootCause(response);
|
||||||
|
setError(response.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<MoreHttpResponses> downloadSkin() {
|
||||||
|
String loc = remotePlayer.getLocal(skinType).getRemote().getUrl();
|
||||||
|
|
||||||
|
return new NetClient("GET", loc).async(HDSkinManager.skinDownloadExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fetchRemote() {
|
||||||
|
fetchingSkin = true;
|
||||||
|
throttlingNeck = false;
|
||||||
|
|
||||||
|
remotePlayer.reloadRemoteSkin(this, this::onSetRemoteSkin).exceptionally(throwable -> {
|
||||||
|
throwable = throwable.getCause();
|
||||||
|
|
||||||
|
throwable.printStackTrace();
|
||||||
|
|
||||||
|
fetchingSkin = false;
|
||||||
|
|
||||||
|
|
||||||
|
if (throwable instanceof AuthenticationUnavailableException) {
|
||||||
|
offline = true;
|
||||||
|
} else {
|
||||||
|
throttlingNeck = true;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSetRemoteSkin(Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) {
|
||||||
|
if (fetchingSkin && remotePlayer.isTextureSetupComplete()) {
|
||||||
|
fetchingSkin = false;
|
||||||
|
listener.onSetRemoteSkin(type, location, profileTexture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
localPlayer.releaseTextures();
|
||||||
|
remotePlayer.releaseTextures();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalSkin(File skinFile) {
|
||||||
|
mc.addScheduledTask(localPlayer::releaseTextures);
|
||||||
|
|
||||||
|
synchronized (skinLock) {
|
||||||
|
pendingLocalSkin = skinFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
localPlayer.updateModel();
|
||||||
|
remotePlayer.updateModel();
|
||||||
|
|
||||||
|
synchronized (skinLock) {
|
||||||
|
if (pendingLocalSkin != null) {
|
||||||
|
System.out.println("Set " + skinType + " " + pendingLocalSkin);
|
||||||
|
localPlayer.setLocalTexture(pendingLocalSkin, skinType);
|
||||||
|
localSkin = pendingLocalSkin;
|
||||||
|
pendingLocalSkin = null;
|
||||||
|
listener.onSetLocalSkin(skinType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isThrottled()) {
|
||||||
|
reloadCounter = (reloadCounter + 1) % (200 * retries);
|
||||||
|
if (reloadCounter == 0) {
|
||||||
|
retries++;
|
||||||
|
fetchRemote();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<PreviewTextureManager> loadTextures(GameProfile profile) {
|
||||||
|
return gateway.getPreviewTextures(profile).thenApply(PreviewTextureManager::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ISkinUploadHandler {
|
||||||
|
default void onSetRemoteSkin(Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) {
|
||||||
|
}
|
||||||
|
|
||||||
|
default void onSetLocalSkin(Type type) {
|
||||||
|
}
|
||||||
|
|
||||||
|
default void onSkinTypeChanged(Type newType) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
||||||
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.SkinUploader;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -16,6 +18,7 @@ import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@SuppressWarnings("EntityConstructor")
|
@SuppressWarnings("EntityConstructor")
|
||||||
public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSupplier {
|
public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSupplier {
|
||||||
|
@ -36,21 +39,20 @@ public class EntityPlayerModel extends EntityLivingBase implements IBlankSkinSup
|
||||||
|
|
||||||
|
|
||||||
private final GameProfile profile;
|
private final GameProfile profile;
|
||||||
private final GuiSkins skins;
|
|
||||||
|
|
||||||
protected boolean previewThinArms = false;
|
protected boolean previewThinArms = false;
|
||||||
|
|
||||||
public EntityPlayerModel(GuiSkins skins, GameProfile gameprofile) {
|
public EntityPlayerModel(GameProfile gameprofile) {
|
||||||
super(new DummyWorld());
|
super(new DummyWorld());
|
||||||
this.skins = skins;
|
|
||||||
profile = gameprofile;
|
profile = gameprofile;
|
||||||
|
|
||||||
skin = new LocalTexture(profile, Type.SKIN, this);
|
skin = new LocalTexture(profile, Type.SKIN, this);
|
||||||
elytra = new LocalTexture(profile, Type.ELYTRA, this);
|
elytra = new LocalTexture(profile, Type.ELYTRA, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reloadRemoteSkin(SkinManager.SkinAvailableCallback listener) {
|
public CompletableFuture<Void> reloadRemoteSkin(SkinUploader uploader, SkinManager.SkinAvailableCallback listener) {
|
||||||
this.skins.loadTextures(profile).thenAcceptAsync(ptm -> {
|
return uploader.loadTextures(profile).thenAcceptAsync(ptm -> {
|
||||||
skin.setRemote(ptm, listener);
|
skin.setRemote(ptm, listener);
|
||||||
elytra.setRemote(ptm, listener);
|
elytra.setRemote(ptm, listener);
|
||||||
}, Minecraft.getMinecraft()::addScheduledTask); // run on main thread
|
}, Minecraft.getMinecraft()::addScheduledTask); // run on main thread
|
||||||
|
|
|
@ -1,74 +1,43 @@
|
||||||
package com.voxelmodpack.hdskins.gui;
|
package com.voxelmodpack.hdskins.gui;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.minelittlepony.gui.Button;
|
import com.minelittlepony.gui.Button;
|
||||||
import com.minelittlepony.gui.GameGui;
|
import com.minelittlepony.gui.GameGui;
|
||||||
import com.minelittlepony.gui.IconicButton;
|
import com.minelittlepony.gui.IconicButton;
|
||||||
import com.minelittlepony.gui.Label;
|
import com.minelittlepony.gui.Label;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
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.voxelmodpack.hdskins.HDSkinManager;
|
import com.voxelmodpack.hdskins.HDSkinManager;
|
||||||
import com.voxelmodpack.hdskins.PreviewTextureManager;
|
import com.voxelmodpack.hdskins.SkinChooser;
|
||||||
import com.voxelmodpack.hdskins.skins.NetClient;
|
import com.voxelmodpack.hdskins.SkinUploader;
|
||||||
|
import com.voxelmodpack.hdskins.SkinUploader.ISkinUploadHandler;
|
||||||
|
import com.voxelmodpack.hdskins.skins.CallableFutures;
|
||||||
import com.voxelmodpack.hdskins.skins.SkinServer;
|
import com.voxelmodpack.hdskins.skins.SkinServer;
|
||||||
import com.voxelmodpack.hdskins.skins.SkinUpload;
|
|
||||||
import com.voxelmodpack.hdskins.skins.SkinUploadResponse;
|
|
||||||
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFile;
|
|
||||||
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFileFolder;
|
|
||||||
import com.voxelmodpack.hdskins.upload.awt.ThreadOpenFilePNG;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
|
||||||
import net.minecraft.client.gui.Gui;
|
|
||||||
import net.minecraft.client.gui.GuiButton;
|
import net.minecraft.client.gui.GuiButton;
|
||||||
import net.minecraft.client.gui.GuiMainMenu;
|
import net.minecraft.client.gui.GuiMainMenu;
|
||||||
import net.minecraft.client.renderer.RenderHelper;
|
import net.minecraft.client.renderer.RenderHelper;
|
||||||
import net.minecraft.client.renderer.entity.RenderManager;
|
import net.minecraft.client.renderer.entity.RenderManager;
|
||||||
import net.minecraft.init.Items;
|
import net.minecraft.init.Items;
|
||||||
import net.minecraft.init.SoundEvents;
|
import net.minecraft.init.SoundEvents;
|
||||||
import net.minecraft.inventory.EntityEquipmentSlot;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.ResourceLocation;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
|
||||||
import org.lwjgl.BufferUtils;
|
import org.lwjgl.BufferUtils;
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.DoubleBuffer;
|
import java.nio.DoubleBuffer;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
|
|
||||||
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 static net.minecraft.client.renderer.GlStateManager.*;
|
||||||
|
|
||||||
public class GuiSkins extends GameGui {
|
public class GuiSkins extends GameGui implements ISkinUploadHandler {
|
||||||
|
|
||||||
private static final int MAX_SKIN_DIMENSION = 1024;
|
|
||||||
private int updateCounter = 0;
|
private int updateCounter = 0;
|
||||||
|
|
||||||
private final Iterator<SkinServer> skinServers;
|
|
||||||
private SkinServer gateway;
|
|
||||||
|
|
||||||
private Button btnUpload;
|
private Button btnUpload;
|
||||||
private Button btnDownload;
|
private Button btnDownload;
|
||||||
private Button btnClear;
|
private Button btnClear;
|
||||||
|
@ -84,82 +53,39 @@ public class GuiSkins extends GameGui {
|
||||||
|
|
||||||
private DoubleBuffer doubleBuffer;
|
private DoubleBuffer doubleBuffer;
|
||||||
|
|
||||||
private boolean showMessage;
|
private float msgFadeOpacity = 0;
|
||||||
private float uploadOpacity = 0;
|
|
||||||
|
|
||||||
private String uploadError = "";
|
|
||||||
private String uploadMessage = format("hdskins.request");
|
|
||||||
|
|
||||||
private volatile String localMessage = format("hdskins.choose");
|
|
||||||
|
|
||||||
private volatile boolean fetchingSkin;
|
|
||||||
private volatile boolean uploadingSkin;
|
|
||||||
private volatile boolean pendingRemoteSkinRefresh;
|
|
||||||
private volatile boolean throttledByMojang;
|
|
||||||
|
|
||||||
private int refreshCounter = 0;
|
|
||||||
|
|
||||||
private ThreadOpenFile openFileThread;
|
|
||||||
|
|
||||||
private final Object skinLock = new Object();
|
|
||||||
|
|
||||||
private File pendingSkinFile;
|
|
||||||
private File selectedSkin;
|
|
||||||
|
|
||||||
private int lastMouseX = 0;
|
private int lastMouseX = 0;
|
||||||
|
|
||||||
protected CubeMap panorama;
|
protected final SkinUploader uploader;
|
||||||
|
protected final SkinChooser chooser;
|
||||||
|
|
||||||
private MinecraftProfileTexture.Type textureType = SKIN;
|
protected final CubeMap panorama;
|
||||||
private boolean thinArmType = false;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GuiSkins(List<SkinServer> servers) {
|
public GuiSkins(List<SkinServer> servers) {
|
||||||
// Generate a cycled iterator that will never run out of entries.
|
mc = Minecraft.getMinecraft();
|
||||||
this.skinServers = cycle(servers, SkinServer::verifyGateway);
|
GameProfile profile = mc.getSession().getProfile();
|
||||||
if (this.skinServers.hasNext()) {
|
|
||||||
this.gateway = this.skinServers.next();
|
|
||||||
} else {
|
|
||||||
this.uploadError = "There are no valid skin servers available! Check your config.";
|
|
||||||
}
|
|
||||||
|
|
||||||
Minecraft minecraft = Minecraft.getMinecraft();
|
|
||||||
GameProfile profile = minecraft.getSession().getProfile();
|
|
||||||
|
|
||||||
localPlayer = getModel(profile);
|
localPlayer = getModel(profile);
|
||||||
remotePlayer = getModel(profile);
|
remotePlayer = getModel(profile);
|
||||||
|
|
||||||
RenderManager rm = minecraft.getRenderManager();
|
RenderManager rm = mc.getRenderManager();
|
||||||
rm.renderEngine = minecraft.getTextureManager();
|
rm.renderEngine = mc.getTextureManager();
|
||||||
rm.options = minecraft.gameSettings;
|
rm.options = mc.gameSettings;
|
||||||
rm.renderViewEntity = localPlayer;
|
rm.renderViewEntity = localPlayer;
|
||||||
|
|
||||||
if (gateway != null) {
|
uploader = new SkinUploader(servers, localPlayer, remotePlayer, this);
|
||||||
reloadRemoteSkin();
|
chooser = new SkinChooser(uploader);
|
||||||
fetchingSkin = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
panorama = new CubeMap(this);
|
panorama = new CubeMap(this);
|
||||||
initPanorama();
|
initPanorama();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> Iterator<T> cycle(List<T> list, Predicate<T> filter) {
|
|
||||||
return Iterables.cycle(Iterables.filter(list, filter::test)).iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initPanorama() {
|
protected void initPanorama() {
|
||||||
panorama.setSource("hdskins:textures/cubemaps/cubemap0_%d.png");
|
panorama.setSource("hdskins:textures/cubemaps/cubemap0_%d.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EntityPlayerModel getModel(GameProfile profile) {
|
protected EntityPlayerModel getModel(GameProfile profile) {
|
||||||
return new EntityPlayerModel(this, profile);
|
return new EntityPlayerModel(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -170,65 +96,19 @@ public class GuiSkins extends GameGui {
|
||||||
}
|
}
|
||||||
|
|
||||||
panorama.update();
|
panorama.update();
|
||||||
|
uploader.update();
|
||||||
|
|
||||||
localPlayer.updateModel();
|
btnClear.enabled = uploader.canClear();
|
||||||
remotePlayer.updateModel();
|
btnDownload.enabled = uploader.canClear();
|
||||||
|
|
||||||
if (fetchingSkin && remotePlayer.isTextureSetupComplete()) {
|
|
||||||
fetchingSkin = false;
|
|
||||||
btnClear.enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (skinLock) {
|
|
||||||
if (pendingSkinFile != null) {
|
|
||||||
System.out.println("Set " + textureType + " " + pendingSkinFile);
|
|
||||||
localPlayer.setLocalTexture(pendingSkinFile, textureType);
|
|
||||||
selectedSkin = pendingSkinFile;
|
|
||||||
pendingSkinFile = null;
|
|
||||||
btnUpload.enabled = true;
|
|
||||||
btnDownload.enabled = true;
|
|
||||||
onSetLocalSkin(textureType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pendingRemoteSkinRefresh) {
|
|
||||||
pendingRemoteSkinRefresh = false;
|
|
||||||
fetchingSkin = true;
|
|
||||||
btnClear.enabled = false;
|
|
||||||
reloadRemoteSkin();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (throttledByMojang) {
|
|
||||||
refreshCounter = (refreshCounter + 1) % 200;
|
|
||||||
if (refreshCounter == 0) {
|
|
||||||
reloadRemoteSkin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onSetRemoteSkin(Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onSetLocalSkin(Type type) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reloadRemoteSkin() {
|
|
||||||
throttledByMojang = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
remotePlayer.reloadRemoteSkin(this::onSetRemoteSkin);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throttledByMojang = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initGui() {
|
public void initGui() {
|
||||||
GLWindow.current().setDropTargetListener(files -> {
|
GLWindow.current().setDropTargetListener(files -> {
|
||||||
files.stream().findFirst().ifPresent(this::loadLocalFile);
|
files.stream().findFirst().ifPresent(file -> {
|
||||||
|
chooser.selectFile(file);
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
panorama.init();
|
panorama.init();
|
||||||
|
@ -238,161 +118,111 @@ public class GuiSkins extends GameGui {
|
||||||
addButton(new Label(width / 2 + 34, 34, "hdskins.server", 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) -> {
|
|
||||||
openFileThread = null;
|
|
||||||
sender.enabled = true;
|
|
||||||
if (dialogResult == 0) {
|
|
||||||
loadLocalFile(fileDialog.getSelectedFile());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
openFileThread.start();
|
|
||||||
sender.enabled = false;
|
sender.enabled = false;
|
||||||
|
chooser.openBrowsePNG(mc, format("hdskins.open.title"), () -> {
|
||||||
|
sender.enabled = true;
|
||||||
|
updateButtons();
|
||||||
|
});
|
||||||
})).setEnabled(!mc.isFullScreen());
|
})).setEnabled(!mc.isFullScreen());
|
||||||
|
|
||||||
addButton(btnUpload = new Button(width / 2 - 24, height / 2 - 20, 48, 20, "hdskins.options.chevy", sender -> {
|
addButton(btnUpload = new Button(width / 2 - 24, height / 2 - 20, 48, 20, "hdskins.options.chevy", sender -> {
|
||||||
punchServer("hdskins.upload", selectedSkin.toURI());
|
if (uploader.canUpload()) {
|
||||||
})).setEnabled(canUpload()).setTooltip("hdskins.options.chevy.title");
|
punchServer("hdskins.upload");
|
||||||
|
}
|
||||||
|
})).setEnabled(uploader.canUpload()).setTooltip("hdskins.options.chevy.title");
|
||||||
|
|
||||||
addButton(btnDownload = new Button(width / 2 - 24, height / 2 + 20, 48, 20, "hdskins.options.download", sender -> {
|
addButton(btnDownload = new Button(width / 2 - 24, height / 2 + 20, 48, 20, "hdskins.options.download", sender -> {
|
||||||
launchSkinDownload(sender);
|
if (uploader.canClear()) {
|
||||||
})).setEnabled(canDownload()).setTooltip("hdskins.options.download.title");
|
sender.enabled = false;
|
||||||
|
chooser.openSavePNG(mc, format("hdskins.open.title"), () -> {
|
||||||
|
sender.enabled = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})).setEnabled(uploader.canClear()).setTooltip("hdskins.options.download.title");
|
||||||
|
|
||||||
addButton(btnClear = new Button(width / 2 + 60, height - 27, 90, 20, "hdskins.options.clear", sender -> {
|
addButton(btnClear = new Button(width / 2 + 60, height - 27, 90, 20, "hdskins.options.clear", sender -> {
|
||||||
if (remotePlayer.isTextureSetupComplete()) {
|
if (uploader.canClear()) {
|
||||||
punchServer("hdskins.request", null);
|
punchServer("hdskins.request");
|
||||||
}
|
}
|
||||||
})).setEnabled(!fetchingSkin);
|
})).setEnabled(uploader.canClear());
|
||||||
|
|
||||||
addButton(new Button(width / 2 - 50, height - 25, 100, 20, "hdskins.options.close", sender -> {
|
addButton(new Button(width / 2 - 50, height - 25, 100, 20, "hdskins.options.close", sender -> {
|
||||||
mc.displayGuiScreen(new GuiMainMenu());
|
mc.displayGuiScreen(new GuiMainMenu());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
addButton(btnModeSteve = new IconicButton(width - 25, 32, sender -> {
|
addButton(btnModeSteve = new IconicButton(width - 25, 32, sender -> {
|
||||||
switchSkinMode(false);
|
switchSkinMode("default");
|
||||||
}).setIcon(new ItemStack(Items.LEATHER_LEGGINGS), 0x3c5dcb)).setEnabled(thinArmType).setTooltip("hdskins.mode.steve");
|
}).setIcon(new ItemStack(Items.LEATHER_LEGGINGS), 0x3c5dcb)).setEnabled("slim".equals(uploader.getMetadataField("model"))).setTooltip("hdskins.mode.steve").setTooltipOffset(0, 10);
|
||||||
|
|
||||||
addButton(btnModeAlex = new IconicButton(width - 25, 51, sender -> {
|
addButton(btnModeAlex = new IconicButton(width - 25, 51, sender -> {
|
||||||
switchSkinMode(true);
|
switchSkinMode("slim");
|
||||||
}).setIcon(new ItemStack(Items.LEATHER_LEGGINGS), 0xfff500)).setEnabled(!thinArmType).setTooltip("hdskins.mode.alex");
|
}).setIcon(new ItemStack(Items.LEATHER_LEGGINGS), 0xfff500)).setEnabled("default".equals(uploader.getMetadataField("model"))).setTooltip("hdskins.mode.alex").setTooltipOffset(0, 10);
|
||||||
|
|
||||||
|
|
||||||
addButton(btnModeSkin = new IconicButton(width - 25, 75, sender -> {
|
addButton(btnModeSkin = new IconicButton(width - 25, 75, sender -> {
|
||||||
switchSkinType(sender, SKIN);
|
uploader.setSkinType(Type.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(uploader.getSkinType() == Type.ELYTRA).setTooltip(format("hdskins.mode.skin", toTitleCase(Type.SKIN.name()))).setTooltipOffset(0, 10);
|
||||||
|
|
||||||
addButton(btnModeElytra = new IconicButton(width - 25, 94, sender -> {
|
addButton(btnModeElytra = new IconicButton(width - 25, 94, sender -> {
|
||||||
switchSkinType(sender, ELYTRA);
|
uploader.setSkinType(Type.ELYTRA);
|
||||||
}).setIcon(new ItemStack(Items.ELYTRA))).setEnabled(textureType == SKIN).setTooltip(format("hdskins.mode.skin", toTitleCase(ELYTRA.name())));
|
}).setIcon(new ItemStack(Items.ELYTRA))).setEnabled(uploader.getSkinType() == Type.SKIN).setTooltip(format("hdskins.mode.skin", toTitleCase(Type.ELYTRA.name()))).setTooltipOffset(0, 10);
|
||||||
|
|
||||||
|
addButton(new Button(width - 25, height - 65, 20, 20, "?", sender -> {
|
||||||
addButton(new Button(width - 25, height - 65, 20, 20, "?", this::switchServer))
|
uploader.cycleGateway();
|
||||||
.setTooltip(Splitter.on("\r\n").splitToList(gateway == null ? "" : gateway.toString()));
|
playSound(SoundEvents.ENTITY_VILLAGER_YES);
|
||||||
}
|
sender.setTooltip(uploader.getGateway());
|
||||||
|
})).setTooltip(uploader.getGateway()).setTooltipOffset(0, 10);
|
||||||
private void switchServer(Button sender) {
|
|
||||||
mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.ENTITY_VILLAGER_YES, 1));
|
|
||||||
gateway = skinServers.next();
|
|
||||||
if (gateway != null) {
|
|
||||||
sender.setTooltip(Splitter.on("\r\n").splitToList(gateway.toString()));
|
|
||||||
reloadRemoteSkin();
|
|
||||||
fetchingSkin = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGuiClosed() {
|
public void onGuiClosed() {
|
||||||
super.onGuiClosed();
|
super.onGuiClosed();
|
||||||
localPlayer.releaseTextures();
|
try {
|
||||||
remotePlayer.releaseTextures();
|
uploader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
HDSkinManager.INSTANCE.clearSkinCache();
|
HDSkinManager.INSTANCE.clearSkinCache();
|
||||||
|
|
||||||
GLWindow.current().clearDropTargetListener();
|
GLWindow.current().clearDropTargetListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadLocalFile(File skinFile) {
|
@Override
|
||||||
mc.addScheduledTask(localPlayer::releaseTextures);
|
public void onSkinTypeChanged(Type newType) {
|
||||||
|
playSound(SoundEvents.BLOCK_BREWING_STAND_BREW);
|
||||||
|
|
||||||
if (!skinFile.exists()) {
|
btnModeSkin.enabled = newType == Type.ELYTRA;
|
||||||
localMessage = format("hdskins.error.unreadable");
|
btnModeElytra.enabled = newType == Type.SKIN;
|
||||||
} else if (!FilenameUtils.isExtension(skinFile.getName(), new String[]{"png", "PNG"})) {
|
|
||||||
localMessage = format("hdskins.error.ext");
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
BufferedImage chosenImage = ImageIO.read(skinFile);
|
|
||||||
|
|
||||||
if (chosenImage == null) {
|
|
||||||
localMessage = format("hdskins.error.open");
|
|
||||||
} else if (!acceptsSkinDimensions(chosenImage.getWidth(), chosenImage.getHeight())) {
|
|
||||||
localMessage = format("hdskins.error.invalid");
|
|
||||||
} else {
|
|
||||||
synchronized (skinLock) {
|
|
||||||
pendingSkinFile = skinFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
localMessage = format("hdskins.error.open");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean acceptsSkinDimensions(int w, int h) {
|
protected void switchSkinMode(String model) {
|
||||||
return isPowerOfTwo(w) && w == h * 2 || w == h && w <= MAX_SKIN_DIMENSION && h <= MAX_SKIN_DIMENSION;
|
playSound(SoundEvents.BLOCK_BREWING_STAND_BREW);
|
||||||
}
|
|
||||||
|
|
||||||
protected void switchSkinType(Button sender, Type newType) {
|
boolean thinArmType = model == "slim";
|
||||||
mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.BLOCK_BREWING_STAND_BREW, 1));
|
|
||||||
|
|
||||||
textureType = newType;
|
|
||||||
|
|
||||||
btnModeSkin.enabled = textureType == ELYTRA;
|
|
||||||
btnModeElytra.enabled = textureType == SKIN;
|
|
||||||
|
|
||||||
ItemStack stack = newType == ELYTRA ? new ItemStack(Items.ELYTRA) : ItemStack.EMPTY;
|
|
||||||
// put on or take off the elytra
|
|
||||||
localPlayer.setItemStackToSlot(EntityEquipmentSlot.CHEST, stack);
|
|
||||||
remotePlayer.setItemStackToSlot(EntityEquipmentSlot.CHEST, stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void switchSkinMode(boolean thin) {
|
|
||||||
mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.BLOCK_BREWING_STAND_BREW, 1));
|
|
||||||
|
|
||||||
thinArmType = thin;
|
|
||||||
|
|
||||||
btnModeSteve.enabled = thinArmType;
|
btnModeSteve.enabled = thinArmType;
|
||||||
btnModeAlex.enabled = !thinArmType;
|
btnModeAlex.enabled = !thinArmType;
|
||||||
|
|
||||||
// clear currently selected skin
|
uploader.setMetadataField("model", model);
|
||||||
selectedSkin = null;
|
|
||||||
localPlayer.releaseTextures();
|
|
||||||
|
|
||||||
localPlayer.setPreviewThinArms(thinArmType);
|
localPlayer.setPreviewThinArms(thinArmType);
|
||||||
remotePlayer.setPreviewThinArms(thinArmType);
|
remotePlayer.setPreviewThinArms(thinArmType);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean clearMessage() {
|
protected boolean canTakeEvents() {
|
||||||
showMessage = false;
|
return !chooser.pickingInProgress() && uploader.tryClearStatus() && msgFadeOpacity == 0;
|
||||||
|
|
||||||
return uploadOpacity == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void actionPerformed(GuiButton guiButton) {
|
protected void actionPerformed(GuiButton guiButton) {
|
||||||
|
if (canTakeEvents()) {
|
||||||
if (openFileThread == null && !uploadingSkin && clearMessage()) {
|
|
||||||
super.actionPerformed(guiButton);
|
super.actionPerformed(guiButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void mouseClicked(int mouseX, int mouseY, int button) throws IOException {
|
protected void mouseClicked(int mouseX, int mouseY, int button) throws IOException {
|
||||||
if (this.gateway == null) {
|
if (canTakeEvents()) {
|
||||||
// doing things might break everything if there is no gateway
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (clearMessage()) {
|
|
||||||
super.mouseClicked(mouseX, mouseY, button);
|
super.mouseClicked(mouseX, mouseY, button);
|
||||||
|
|
||||||
int bottom = height - 40;
|
int bottom = height - 40;
|
||||||
|
@ -409,7 +239,7 @@ public class GuiSkins extends GameGui {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
|
protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
|
||||||
if (clearMessage()) {
|
if (canTakeEvents()) {
|
||||||
updateCounter -= (lastMouseX - mouseX);
|
updateCounter -= (lastMouseX - mouseX);
|
||||||
}
|
}
|
||||||
lastMouseX = mouseX;
|
lastMouseX = mouseX;
|
||||||
|
@ -417,14 +247,14 @@ public class GuiSkins extends GameGui {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void keyTyped(char keyChar, int keyCode) throws IOException {
|
protected void keyTyped(char keyChar, int keyCode) throws IOException {
|
||||||
if (clearMessage()) {
|
if (canTakeEvents()) {
|
||||||
if (keyCode == Keyboard.KEY_LEFT) {
|
if (keyCode == Keyboard.KEY_LEFT) {
|
||||||
updateCounter -= 5;
|
updateCounter -= 5;
|
||||||
} else if (keyCode == Keyboard.KEY_RIGHT) {
|
} else if (keyCode == Keyboard.KEY_RIGHT) {
|
||||||
updateCounter += 5;
|
updateCounter += 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openFileThread == null && !uploadingSkin) {
|
if (!chooser.pickingInProgress() && !uploader.uploadInProgress()) {
|
||||||
super.keyTyped(keyChar, keyCode);
|
super.keyTyped(keyChar, keyCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -432,8 +262,6 @@ public class GuiSkins extends GameGui {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void drawContents(int mouseX, int mouseY, float partialTick) {
|
protected void drawContents(int mouseX, int mouseY, float partialTick) {
|
||||||
|
|
||||||
|
|
||||||
boolean sneak = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
|
boolean sneak = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
|
||||||
|
|
||||||
localPlayer.setSneaking(sneak);
|
localPlayer.setSneaking(sneak);
|
||||||
|
@ -452,8 +280,8 @@ public class GuiSkins extends GameGui {
|
||||||
|
|
||||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||||
|
|
||||||
Gui.drawRect(30, 30, mid - 30, bottom, Integer.MIN_VALUE);
|
drawRect(30, 30, mid - 30, bottom, Integer.MIN_VALUE);
|
||||||
Gui.drawRect(mid + 30, 30, width - 30, bottom, Integer.MIN_VALUE);
|
drawRect(mid + 30, 30, width - 30, bottom, Integer.MIN_VALUE);
|
||||||
|
|
||||||
drawGradientRect(30, horizon, mid - 30, bottom, 0x80FFFFFF, 0xffffff);
|
drawGradientRect(30, horizon, mid - 30, bottom, 0x80FFFFFF, 0xffffff);
|
||||||
drawGradientRect(mid + 30, horizon, width - 30, bottom, 0x80FFFFFF, 0xffffff);
|
drawGradientRect(mid + 30, horizon, width - 30, bottom, 0x80FFFFFF, 0xffffff);
|
||||||
|
@ -473,47 +301,54 @@ public class GuiSkins extends GameGui {
|
||||||
|
|
||||||
disableClipping();
|
disableClipping();
|
||||||
|
|
||||||
if (!localPlayer.isUsingLocalTexture()) {
|
if (chooser.getStatus() != null && !uploader.canUpload()) {
|
||||||
Gui.drawRect(40, height / 2 - 12, width / 2 - 40, height / 2 + 12, 0xB0000000);
|
drawRect(40, height / 2 - 12, width / 2 - 40, height / 2 + 12, 0xB0000000);
|
||||||
drawCenteredString(fontRenderer, localMessage, (int) xPos1, height / 2 - 4, 0xffffff);
|
drawCenteredString(fontRenderer, format(chooser.getStatus()), (int) xPos1, height / 2 - 4, 0xffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fetchingSkin) {
|
if (uploader.downloadInProgress() || uploader.isThrottled() || uploader.isOffline()) {
|
||||||
|
|
||||||
int lineHeight = throttledByMojang ? 18 : 12;
|
int lineHeight = uploader.isThrottled() ? 18 : 12;
|
||||||
|
|
||||||
Gui.drawRect((int) (xPos2 - width / 4 + 40), height / 2 - lineHeight, width - 40, height / 2 + lineHeight, 0xB0000000);
|
drawRect((int) (xPos2 - width / 4 + 40), height / 2 - lineHeight, width - 40, height / 2 + lineHeight, 0xB0000000);
|
||||||
|
|
||||||
if (throttledByMojang) {
|
if (uploader.isThrottled()) {
|
||||||
drawCenteredString(fontRenderer, format("hdskins.error.mojang"), (int) xPos2, height / 2 - 10, 0xffffff);
|
drawCenteredString(fontRenderer, format(SkinUploader.ERR_MOJANG), (int) xPos2, height / 2 - 10, 0xff5555);
|
||||||
drawCenteredString(fontRenderer, format("hdskins.error.mojang.wait"), (int) xPos2, height / 2 + 2, 0xffffff);
|
drawCenteredString(fontRenderer, format(SkinUploader.ERR_WAIT, uploader.getRetries()), (int) xPos2, height / 2 + 2, 0xff5555);
|
||||||
|
} else if (uploader.isOffline()) {
|
||||||
|
drawCenteredString(fontRenderer, format(SkinUploader.ERR_OFFLINE), (int) xPos2, height / 2 - 4, 0xff5555);
|
||||||
} else {
|
} else {
|
||||||
drawCenteredString(fontRenderer, format("hdskins.fetch"), (int) xPos2, height / 2 - 4, 0xffffff);
|
drawCenteredString(fontRenderer, format(SkinUploader.STATUS_FETCH), (int) xPos2, height / 2 - 4, 0xffffff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uploadingSkin || showMessage || uploadOpacity > 0) {
|
boolean uploadInProgress = uploader.uploadInProgress();
|
||||||
if (!uploadingSkin && !showMessage) {
|
boolean showError = uploader.hasStatus();
|
||||||
uploadOpacity -= deltaTime / 10;
|
|
||||||
} else if (uploadOpacity < 1) {
|
if (uploadInProgress || showError || msgFadeOpacity > 0) {
|
||||||
uploadOpacity += deltaTime / 10;
|
if (!uploadInProgress && !showError) {
|
||||||
|
msgFadeOpacity -= deltaTime / 10;
|
||||||
|
} else if (msgFadeOpacity < 1) {
|
||||||
|
msgFadeOpacity += deltaTime / 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadOpacity = MathHelper.clamp(uploadOpacity, 0, 1);
|
msgFadeOpacity = MathHelper.clamp(msgFadeOpacity, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uploadOpacity > 0) {
|
if (msgFadeOpacity > 0) {
|
||||||
int opacity = (Math.min(180, (int) (uploadOpacity * 180)) & 255) << 24;
|
int opacity = (Math.min(180, (int) (msgFadeOpacity * 180)) & 255) << 24;
|
||||||
|
|
||||||
Gui.drawRect(0, 0, width, height, opacity);
|
drawRect(0, 0, width, height, opacity);
|
||||||
|
|
||||||
if (uploadingSkin) {
|
String errorMsg = uploader.getStatusMessage();
|
||||||
drawCenteredString(fontRenderer, uploadMessage, width / 2, height / 2, 0xffffff);
|
|
||||||
} else if (showMessage) {
|
if (uploadInProgress) {
|
||||||
int blockHeight = (height - fontRenderer.getWordWrappedHeight(uploadError, width - 10)) / 2;
|
drawCenteredString(fontRenderer, errorMsg, width / 2, height / 2, 0xffffff);
|
||||||
|
} else if (showError) {
|
||||||
|
int blockHeight = (height - fontRenderer.getWordWrappedHeight(errorMsg, width - 10)) / 2;
|
||||||
|
|
||||||
drawCenteredString(fontRenderer, format("hdskins.failed"), width / 2, blockHeight - fontRenderer.FONT_HEIGHT * 2, 0xffff55);
|
drawCenteredString(fontRenderer, format("hdskins.failed"), width / 2, blockHeight - fontRenderer.FONT_HEIGHT * 2, 0xffff55);
|
||||||
fontRenderer.drawSplitString(uploadError, 5, blockHeight, width - 10, 0xff5555);
|
fontRenderer.drawSplitString(errorMsg, 5, blockHeight, width - 10, 0xff5555);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,79 +408,14 @@ public class GuiSkins extends GameGui {
|
||||||
depthMask(false);
|
depthMask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPowerOfTwo(int number) {
|
private void punchServer(String uploadMsg) {
|
||||||
return number != 0 && (number & number - 1) == 0;
|
uploader.uploadSkin(format(uploadMsg)).handle(CallableFutures.callback(this::updateButtons));
|
||||||
|
|
||||||
|
updateButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void punchServer(String uploadMsg, @Nullable URI path) {
|
private void updateButtons() {
|
||||||
uploadingSkin = true;
|
btnUpload.enabled = uploader.canUpload();
|
||||||
uploadMessage = format(uploadMsg);
|
btnDownload.enabled = uploader.canUpload();
|
||||||
btnUpload.enabled = canUpload();
|
|
||||||
btnDownload.enabled = canDownload();
|
|
||||||
|
|
||||||
gateway.uploadSkin(mc.getSession(), new SkinUpload(textureType, path, getMetadata()))
|
|
||||||
.thenAccept(this::onUploadComplete)
|
|
||||||
.exceptionally(this::onUploadFailure);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchSkinDownload(Button sender) {
|
|
||||||
sender.enabled = false;
|
|
||||||
String loc = remotePlayer.getLocal(textureType).getRemote().getUrl();
|
|
||||||
|
|
||||||
new NetClient("GET", loc).async(HDSkinManager.skinDownloadExecutor).thenAccept(response -> {
|
|
||||||
openFileThread = new ThreadOpenFileFolder(mc, format("hdskins.open.title"), (fileDialog, dialogResult) -> {
|
|
||||||
openFileThread = null;
|
|
||||||
sender.enabled = true;
|
|
||||||
if (dialogResult == 0) {
|
|
||||||
File out = fileDialog.getSelectedFile();
|
|
||||||
|
|
||||||
try {
|
|
||||||
out.createNewFile();
|
|
||||||
|
|
||||||
FileUtils.copyInputStreamToFile(response.getInputStream(), out);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
openFileThread.start();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, String> getMetadata() {
|
|
||||||
return ImmutableMap.of("model", thinArmType ? "slim" : "default");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Void onUploadFailure(Throwable t) {
|
|
||||||
t = Throwables.getRootCause(t);
|
|
||||||
LogManager.getLogger().warn("Upload failed", t);
|
|
||||||
uploadError = t.toString();
|
|
||||||
showMessage = true;
|
|
||||||
uploadingSkin = false;
|
|
||||||
btnUpload.enabled = canUpload();
|
|
||||||
btnDownload.enabled = canDownload();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onUploadComplete(SkinUploadResponse response) {
|
|
||||||
LiteLoaderLogger.info("Upload completed with: %s", response);
|
|
||||||
pendingRemoteSkinRefresh = true;
|
|
||||||
uploadingSkin = false;
|
|
||||||
btnUpload.enabled = canUpload();
|
|
||||||
btnDownload.enabled = canDownload();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean canUpload() {
|
|
||||||
return selectedSkin != null && !uploadingSkin && !pendingRemoteSkinRefresh;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean canDownload() {
|
|
||||||
return remotePlayer.getLocal(textureType).hasRemote();
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletableFuture<PreviewTextureManager> loadTextures(GameProfile profile) {
|
|
||||||
return gateway.getPreviewTextures(profile).thenApply(PreviewTextureManager::new);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.voxelmodpack.hdskins.skins;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
public class CallableFutures {
|
public class CallableFutures {
|
||||||
|
|
||||||
|
@ -23,4 +24,11 @@ public class CallableFutures {
|
||||||
ret.completeExceptionally(e);
|
ret.completeExceptionally(e);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <U, T> BiFunction<? super T, Throwable, ? extends U> callback(Runnable c) {
|
||||||
|
return (o, t) -> {
|
||||||
|
c.run();
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||||
import com.mojang.util.UUIDTypeAdapter;
|
import com.mojang.util.UUIDTypeAdapter;
|
||||||
import com.voxelmodpack.hdskins.HDSkinManager;
|
import com.voxelmodpack.hdskins.HDSkinManager;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.util.Session;
|
import net.minecraft.util.Session;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
@ -44,6 +45,12 @@ public class LegacySkinServer implements SkinServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<MinecraftTexturesPayload> getPreviewTextures(GameProfile profile) {
|
public CompletableFuture<MinecraftTexturesPayload> getPreviewTextures(GameProfile profile) {
|
||||||
|
try {
|
||||||
|
SkinServer.verifyServerConnection(Minecraft.getMinecraft().getSession(), SERVER_ID);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return CallableFutures.failedFuture(e);
|
||||||
|
}
|
||||||
|
|
||||||
if (Strings.isNullOrEmpty(gateway)) {
|
if (Strings.isNullOrEmpty(gateway)) {
|
||||||
return CallableFutures.failedFuture(gatewayUnsupported());
|
return CallableFutures.failedFuture(gatewayUnsupported());
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ public interface SkinServer extends Exposable {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verifyServerConnection(Session session, String serverId) throws AuthenticationException {
|
public 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.minelittlepony.hdskins.gui;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type;
|
||||||
import com.voxelmodpack.hdskins.gui.EntityPlayerModel;
|
import com.voxelmodpack.hdskins.gui.EntityPlayerModel;
|
||||||
import com.voxelmodpack.hdskins.gui.GuiSkins;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,8 +15,8 @@ public class EntityPonyModel extends EntityPlayerModel {
|
||||||
|
|
||||||
public boolean wet = false;
|
public boolean wet = false;
|
||||||
|
|
||||||
public EntityPonyModel(GuiSkins skins, GameProfile profile) {
|
public EntityPonyModel(GameProfile profile) {
|
||||||
super(skins, profile);
|
super(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class GuiSkinsMineLP extends GuiSkins {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected EntityPlayerModel getModel(GameProfile profile) {
|
protected EntityPlayerModel getModel(GameProfile profile) {
|
||||||
return new EntityPonyModel(this, profile);
|
return new EntityPonyModel(profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,11 +50,11 @@ public class GuiSkinsMineLP extends GuiSkins {
|
||||||
|
|
||||||
addButton(btnModeWet = new IconicButton(width - 25, 137, sender -> {
|
addButton(btnModeWet = new IconicButton(width - 25, 137, sender -> {
|
||||||
setWet(true);
|
setWet(true);
|
||||||
}).setIcon(new ItemStack(Items.WATER_BUCKET))).setEnabled(!isWet).setTooltip("minelp.mode.wet");
|
}).setIcon(new ItemStack(Items.WATER_BUCKET))).setEnabled(!isWet).setTooltip("minelp.mode.wet").setTooltipOffset(0, 10);
|
||||||
|
|
||||||
addButton(btnModeDry = new IconicButton(width - 25, 118, sender -> {
|
addButton(btnModeDry = new IconicButton(width - 25, 118, sender -> {
|
||||||
setWet(false);
|
setWet(false);
|
||||||
}).setIcon(new ItemStack(Items.BUCKET))).setEnabled(isWet).setTooltip("minelp.mode.dry");
|
}).setIcon(new ItemStack(Items.BUCKET))).setEnabled(isWet).setTooltip("minelp.mode.dry").setTooltipOffset(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -82,7 +82,8 @@ public class GuiSkinsMineLP extends GuiSkins {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSetLocalSkin(Type type) {
|
public void onSetLocalSkin(Type type) {
|
||||||
|
super.onSetLocalSkin(type);
|
||||||
MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin");
|
MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin");
|
||||||
if (type == Type.SKIN) {
|
if (type == Type.SKIN) {
|
||||||
ponyManager.removePony(localPlayer.getLocal(Type.SKIN).getTexture());
|
ponyManager.removePony(localPlayer.getLocal(Type.SKIN).getTexture());
|
||||||
|
@ -90,10 +91,12 @@ public class GuiSkinsMineLP extends GuiSkins {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSetRemoteSkin(Type type, ResourceLocation resource, MinecraftProfileTexture profileTexture) {
|
public void onSetRemoteSkin(Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) {
|
||||||
|
super.onSetRemoteSkin(type, location, profileTexture);
|
||||||
|
|
||||||
MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin");
|
MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin");
|
||||||
if (type == Type.SKIN) {
|
if (type == Type.SKIN) {
|
||||||
ponyManager.removePony(resource);
|
ponyManager.removePony(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue