mirror of
https://github.com/MineLittlePony/MineLittlePony.git
synced 2025-02-13 16:24:23 +01:00
Disable buttons on the interface if a skin server doesn't support/permit that particular functionality
This commit is contained in:
parent
26fb289be1
commit
664f8ac6a4
10 changed files with 257 additions and 21 deletions
|
@ -36,8 +36,14 @@ public class Button extends GuiButton implements IActionable, IGuiTooltipped<But
|
|||
return this;
|
||||
}
|
||||
|
||||
protected List<String> getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToolTip(Minecraft mc, int mouseX, int mouseY) {
|
||||
List<String> tooltip = getTooltip();
|
||||
|
||||
if (visible && isMouseOver() && tooltip != null) {
|
||||
mc.currentScreen.drawHoveringText(tooltip, mouseX + tipX, mouseY + tipY);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ 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.gui.Feature;
|
||||
import com.voxelmodpack.hdskins.resources.PreviewTextureManager;
|
||||
import com.voxelmodpack.hdskins.server.SkinServer;
|
||||
import com.voxelmodpack.hdskins.server.SkinUpload;
|
||||
|
@ -102,6 +103,10 @@ public class SkinUploader implements Closeable {
|
|||
return gateway == null ? "" : gateway.toString();
|
||||
}
|
||||
|
||||
public boolean supportsFeature(Feature feature) {
|
||||
return gateway != null && gateway.supportsFeature(feature);
|
||||
}
|
||||
|
||||
protected void setError(String er) {
|
||||
status = er;
|
||||
sendingSkin = false;
|
||||
|
|
50
src/hdskins/java/com/voxelmodpack/hdskins/gui/Feature.java
Normal file
50
src/hdskins/java/com/voxelmodpack/hdskins/gui/Feature.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
package com.voxelmodpack.hdskins.gui;
|
||||
|
||||
/**
|
||||
* Represents the possible features that a skin server can implement.
|
||||
*/
|
||||
public enum Feature {
|
||||
/**
|
||||
* Whether a server has write access.
|
||||
* i.e. If the server allows for users to upload a new skin.
|
||||
*/
|
||||
UPLOAD_USER_SKIN,
|
||||
/**
|
||||
* Whether a server allows for downloading and saving a user's skin.
|
||||
* Most servers should support this.
|
||||
*/
|
||||
DOWNLOAD_USER_SKIN,
|
||||
/**
|
||||
* Whether a server has delete access.
|
||||
* i.e. If the server allows a user to deleted a previously uploaded skin.
|
||||
*/
|
||||
DELETE_USER_SKIN,
|
||||
/**
|
||||
* Whether a server can send a full list of skins for a given profile.
|
||||
* Typically used for servers that keep a record of past uploads
|
||||
* and/or allow for switching between past skins.
|
||||
*/
|
||||
FETCH_SKIN_LIST,
|
||||
/**
|
||||
* Whether a server supports thin (Alex) skins or just default (Steve) skins.
|
||||
* Servers without this will typically fall back to using the player's uuid on the client side.
|
||||
*
|
||||
* (unused)
|
||||
*/
|
||||
MODEL_VARIANTS,
|
||||
/**
|
||||
* Whether a server allows for uploading alternative skin types. i.e. Cape, Elytra, Hats and wears.
|
||||
*/
|
||||
MODEL_TYPES,
|
||||
/**
|
||||
* Whether a server will accept arbitrary extra metadata values with skin uploads.
|
||||
*
|
||||
* (unused)
|
||||
*/
|
||||
MODEL_METADATA,
|
||||
/**
|
||||
* Whether a server can provide a link to view a user's profile online,
|
||||
* typically through a web-portal.
|
||||
*/
|
||||
LINK_PROFILE
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package com.voxelmodpack.hdskins.gui;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.minelittlepony.gui.Button;
|
||||
import com.minelittlepony.gui.GameGui;
|
||||
import com.minelittlepony.gui.IGuiAction;
|
||||
import com.minelittlepony.gui.IconicButton;
|
||||
import com.minelittlepony.gui.IconicToggle;
|
||||
import com.minelittlepony.gui.Label;
|
||||
|
@ -44,15 +46,15 @@ public class GuiSkins extends GameGui implements ISkinUploadHandler {
|
|||
private int updateCounter = 0;
|
||||
|
||||
private Button btnBrowse;
|
||||
private Button btnUpload;
|
||||
private Button btnDownload;
|
||||
private Button btnClear;
|
||||
private FeatureButton btnUpload;
|
||||
private FeatureButton btnDownload;
|
||||
private FeatureButton btnClear;
|
||||
|
||||
private Button btnModeSteve;
|
||||
private Button btnModeAlex;
|
||||
private FeatureSwitch btnModeSteve;
|
||||
private FeatureSwitch btnModeAlex;
|
||||
|
||||
private Button btnModeSkin;
|
||||
private Button btnModeElytra;
|
||||
private FeatureSwitch btnModeSkin;
|
||||
private FeatureSwitch btnModeElytra;
|
||||
|
||||
protected EntityPlayerModel localPlayer;
|
||||
protected EntityPlayerModel remotePlayer;
|
||||
|
@ -148,21 +150,21 @@ public class GuiSkins extends GameGui implements ISkinUploadHandler {
|
|||
chooser.openBrowsePNG(mc, format("hdskins.open.title"))))
|
||||
.setEnabled(!mc.isFullScreen());
|
||||
|
||||
addButton(btnUpload = new Button(width / 2 - 24, height / 2 - 20, 48, 20, "hdskins.options.chevy", sender -> {
|
||||
addButton(btnUpload = new FeatureButton(width / 2 - 24, height / 2 - 20, 48, 20, "hdskins.options.chevy", sender -> {
|
||||
if (uploader.canUpload()) {
|
||||
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 FeatureButton(width / 2 - 24, height / 2 + 20, 48, 20, "hdskins.options.download", sender -> {
|
||||
if (uploader.canClear()) {
|
||||
chooser.openSavePNG(mc, format("hdskins.save.title"));
|
||||
}
|
||||
})).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 FeatureButton(width / 2 + 60, height - 27, 90, 20, "hdskins.options.clear", sender -> {
|
||||
if (uploader.canClear()) {
|
||||
punchServer("hdskins.request");
|
||||
}
|
||||
|
@ -171,26 +173,26 @@ public class GuiSkins extends GameGui implements ISkinUploadHandler {
|
|||
addButton(new Button(width / 2 - 50, height - 25, 100, 20, "hdskins.options.close", sender ->
|
||||
mc.displayGuiScreen(new GuiMainMenu())));
|
||||
|
||||
addButton(btnModeSteve = new IconicButton(width - 25, 32, sender -> switchSkinMode("default"))
|
||||
.setIcon(new ItemStack(Items.LEATHER_LEGGINGS), 0x3c5dcb))
|
||||
addButton(btnModeSteve = new FeatureSwitch(width - 25, 32, sender -> switchSkinMode("default")))
|
||||
.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 -> switchSkinMode("slim"))
|
||||
.setIcon(new ItemStack(Items.LEATHER_LEGGINGS), 0xfff500))
|
||||
addButton(btnModeAlex = new FeatureSwitch(width - 25, 51, sender -> switchSkinMode("slim")))
|
||||
.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 -> uploader.setSkinType(Type.SKIN))
|
||||
.setIcon(new ItemStack(Items.LEATHER_CHESTPLATE)))
|
||||
addButton(btnModeSkin = new FeatureSwitch(width - 25, 75, sender -> uploader.setSkinType(Type.SKIN)))
|
||||
.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 -> uploader.setSkinType(Type.ELYTRA))
|
||||
.setIcon(new ItemStack(Items.ELYTRA)))
|
||||
addButton(btnModeElytra = new FeatureSwitch(width - 25, 94, sender -> uploader.setSkinType(Type.ELYTRA)))
|
||||
.setIcon(new ItemStack(Items.ELYTRA))
|
||||
.setEnabled(uploader.getSkinType() == Type.SKIN)
|
||||
.setTooltip(format("hdskins.mode.skin", toTitleCase(Type.ELYTRA.name())))
|
||||
.setTooltipOffset(0, 10);
|
||||
|
@ -506,8 +508,85 @@ public class GuiSkins extends GameGui implements ISkinUploadHandler {
|
|||
|
||||
private void updateButtons() {
|
||||
btnClear.enabled = uploader.canClear();
|
||||
btnUpload.enabled = uploader.canUpload();
|
||||
btnUpload.enabled = uploader.canUpload() && uploader.supportsFeature(Feature.UPLOAD_USER_SKIN);
|
||||
btnDownload.enabled = uploader.canClear() && !chooser.pickingInProgress();
|
||||
btnBrowse.enabled = !chooser.pickingInProgress();
|
||||
|
||||
boolean types = !uploader.supportsFeature(Feature.MODEL_TYPES);
|
||||
boolean variants = !uploader.supportsFeature(Feature.MODEL_VARIANTS);
|
||||
|
||||
btnModeSkin.setLocked(types);
|
||||
btnModeElytra.setLocked(types);
|
||||
|
||||
btnModeSteve.setLocked(variants);
|
||||
btnModeAlex.setLocked(variants);
|
||||
|
||||
btnClear.setLocked(!uploader.supportsFeature(Feature.DELETE_USER_SKIN));
|
||||
btnUpload.setLocked(!uploader.supportsFeature(Feature.UPLOAD_USER_SKIN));
|
||||
btnDownload.setLocked(!uploader.supportsFeature(Feature.DOWNLOAD_USER_SKIN));
|
||||
}
|
||||
|
||||
protected class FeatureButton extends Button {
|
||||
private List<String> disabledTooltip = Splitter.onPattern("\r?\n|\\\\n").splitToList(format("hdskins.warning.disabled.description"));
|
||||
|
||||
protected boolean locked;
|
||||
|
||||
public FeatureButton(int x, int y, int width, int height, String label, IGuiAction<? extends Button> callback) {
|
||||
super(x, y, width, height, label, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTooltip() {
|
||||
if (locked) {
|
||||
return disabledTooltip;
|
||||
}
|
||||
return super.getTooltip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button setTooltip(String tooltip) {
|
||||
disabledTooltip = Splitter.onPattern("\r?\n|\\\\n").splitToList(
|
||||
format("hdskins.warning.disabled.title",
|
||||
format(tooltip),
|
||||
format("hdskins.warning.disabled.description")));
|
||||
return super.setTooltip(tooltip);
|
||||
}
|
||||
|
||||
public void setLocked(boolean lock) {
|
||||
locked = lock;
|
||||
enabled &= !lock;
|
||||
}
|
||||
}
|
||||
|
||||
protected class FeatureSwitch extends IconicButton {
|
||||
private List<String> disabledTooltip = null;
|
||||
|
||||
protected boolean locked;
|
||||
|
||||
public FeatureSwitch(int x, int y, IGuiAction<? extends IconicButton> callback) {
|
||||
super(x, y, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTooltip() {
|
||||
if (locked) {
|
||||
return disabledTooltip;
|
||||
}
|
||||
return super.getTooltip();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button setTooltip(String tooltip) {
|
||||
disabledTooltip = Splitter.onPattern("\r?\n|\\\\n").splitToList(
|
||||
format("hdskins.warning.disabled.title",
|
||||
format(tooltip),
|
||||
format("hdskins.warning.disabled.description")));
|
||||
return super.setTooltip(tooltip);
|
||||
}
|
||||
|
||||
public void setLocked(boolean lock) {
|
||||
locked = lock;
|
||||
enabled &= !lock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.mojang.authlib.GameProfile;
|
|||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||
import com.mojang.util.UUIDTypeAdapter;
|
||||
import com.voxelmodpack.hdskins.gui.Feature;
|
||||
import com.voxelmodpack.hdskins.util.IndentedToStringStyle;
|
||||
import com.voxelmodpack.hdskins.util.MoreHttpResponses;
|
||||
import com.voxelmodpack.hdskins.util.NetClient;
|
||||
|
@ -84,4 +85,17 @@ public class BethlehemSkinServer implements SkinServer {
|
|||
.append("address", address)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFeature(Feature feature) {
|
||||
switch (feature) {
|
||||
case DOWNLOAD_USER_SKIN:
|
||||
case UPLOAD_USER_SKIN:
|
||||
case MODEL_VARIANTS:
|
||||
case MODEL_TYPES:
|
||||
case LINK_PROFILE:
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
|||
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||
import com.mojang.util.UUIDTypeAdapter;
|
||||
import com.voxelmodpack.hdskins.HDSkinManager;
|
||||
import com.voxelmodpack.hdskins.gui.Feature;
|
||||
import com.voxelmodpack.hdskins.util.CallableFutures;
|
||||
import com.voxelmodpack.hdskins.util.IndentedToStringStyle;
|
||||
import com.voxelmodpack.hdskins.util.MoreHttpResponses;
|
||||
|
@ -164,6 +165,17 @@ public class LegacySkinServer implements SkinServer {
|
|||
return !Strings.isNullOrEmpty(gateway);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFeature(Feature feature) {
|
||||
switch (feature) {
|
||||
case DOWNLOAD_USER_SKIN:
|
||||
case UPLOAD_USER_SKIN:
|
||||
case DELETE_USER_SKIN:
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new IndentedToStringStyle.Builder(this)
|
||||
|
|
|
@ -5,6 +5,14 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* The remote server API level that this skin server implements.
|
||||
*
|
||||
* Current values are:
|
||||
* - legacy
|
||||
* - valhalla
|
||||
* - bethlehem
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ServerType {
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
|||
import com.mojang.util.UUIDTypeAdapter;
|
||||
import com.mumfrey.liteloader.modconfig.Exposable;
|
||||
import com.voxelmodpack.hdskins.HDSkinManager;
|
||||
import com.voxelmodpack.hdskins.gui.Feature;
|
||||
import com.voxelmodpack.hdskins.util.CallableFutures;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.Session;
|
||||
|
@ -30,22 +31,67 @@ public interface SkinServer extends Exposable {
|
|||
"http://skinmanager.voxelmodpack.com")
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns true for any features that this skin server supports.
|
||||
*/
|
||||
boolean supportsFeature(Feature feature);
|
||||
|
||||
/**
|
||||
* Synchronously loads texture information for the provided profile.
|
||||
*
|
||||
* @return The parsed server response as a textures payload.
|
||||
*
|
||||
* @throws IOException If any authenticaiton or network error occurs.
|
||||
*/
|
||||
MinecraftTexturesPayload loadProfileData(GameProfile profile) throws IOException;
|
||||
|
||||
/**
|
||||
* Synchronously uploads a skin to this server.
|
||||
*
|
||||
* @param upload The payload to send.
|
||||
*
|
||||
* @return A server response object.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
SkinUploadResponse performSkinUpload(SkinUpload upload) throws IOException, AuthenticationException;
|
||||
|
||||
/**
|
||||
* Asynchronously uploads a skin to the server.
|
||||
*
|
||||
* Returns an incomplete future for chaining other actions to be performed after this method completes.
|
||||
* Actions are dispatched to the default skinUploadExecutor
|
||||
*
|
||||
* @param upload The payload to send.
|
||||
*/
|
||||
default CompletableFuture<SkinUploadResponse> uploadSkin(SkinUpload upload) {
|
||||
return CallableFutures.asyncFailableFuture(() -> performSkinUpload(upload), HDSkinManager.skinUploadExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously loads texture information for the provided profile.
|
||||
*
|
||||
* Returns an incomplete future for chaining other actions to be performed after this method completes.
|
||||
* Actions are dispatched to the default skinDownloadExecutor
|
||||
*/
|
||||
default CompletableFuture<MinecraftTexturesPayload> getPreviewTextures(GameProfile profile) {
|
||||
return CallableFutures.asyncFailableFuture(() -> loadProfileData(profile), HDSkinManager.skinDownloadExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to validate this skin server's state.
|
||||
* Any servers with an invalid gateway format will not be loaded and generate an exception.
|
||||
*/
|
||||
default boolean verifyGateway() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins with the Mojang API to verify the current user's session.
|
||||
|
||||
* @throws AuthenticationException if authentication failed or the session is invalid.
|
||||
*/
|
||||
static void verifyServerConnection(Session session, String serverId) throws AuthenticationException {
|
||||
MinecraftSessionService service = Minecraft.getMinecraft().getSessionService();
|
||||
service.joinServer(session.getProfile(), session.getToken(), serverId);
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.mojang.authlib.minecraft.MinecraftProfileTexture;
|
|||
import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload;
|
||||
import com.mojang.util.UUIDTypeAdapter;
|
||||
import com.voxelmodpack.hdskins.HDSkinManager;
|
||||
import com.voxelmodpack.hdskins.gui.Feature;
|
||||
import com.voxelmodpack.hdskins.util.IndentedToStringStyle;
|
||||
import com.voxelmodpack.hdskins.util.MoreHttpResponses;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -176,6 +177,19 @@ public class ValhallaSkinServer implements SkinServer {
|
|||
return URI.create(String.format("%s/auth/response", this.address));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFeature(Feature feature) {
|
||||
switch (feature) {
|
||||
case DOWNLOAD_USER_SKIN:
|
||||
case UPLOAD_USER_SKIN:
|
||||
case DELETE_USER_SKIN:
|
||||
case MODEL_VARIANTS:
|
||||
case MODEL_TYPES:
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new IndentedToStringStyle.Builder(this)
|
||||
|
|
|
@ -25,7 +25,7 @@ hdskins.server=Server Skin
|
|||
hdskins.mode.steve=Steve Model
|
||||
hdskins.mode.alex=Alex Model
|
||||
|
||||
hdskins.mode.skin=%s
|
||||
hdskins.mode.skin=%s Texture
|
||||
|
||||
hdskins.mode.stand=Standing
|
||||
hdskins.mode.sleep=Sleeping
|
||||
|
@ -43,4 +43,6 @@ hdskins.options.browse=Browse
|
|||
hdskins.options.skindrops=Experimental Skin Drop
|
||||
hdskins.options.cache=Clear Skin Cache
|
||||
|
||||
hdskins.warning.experimental=§6WARNING: This feature is §4experimental§6, meaning things may break or derp or even slurp. Enabling this means you accept responsibility for what may happen to your chickens.
|
||||
hdskins.warning.experimental=§6WARNING: This feature is §4experimental§6, meaning things may break or derp or even slurp. Enabling this means you accept responsibility for what may happen to your chickens.
|
||||
hdskins.warning.disabled.title=§c%s %s
|
||||
hdskins.warning.disabled.description=§4(DISABLED)\n§7This feature is not supported by your current skin server.\n§7Please choose a different one to proceed.
|
Loading…
Reference in a new issue