更新默认皮肤 (#2943)
* 更新默认皮肤 * update * update * update * update * update * update
@ -12,14 +12,10 @@ import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
import javafx.scene.transform.Translate;
|
||||
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SkinCanvas extends Group {
|
||||
|
||||
public static final Image ALEX = FXUtils.newBuiltinImage("/assets/img/skin/alex.png");
|
||||
public static final Image STEVE = FXUtils.newBuiltinImage("/assets/img/skin/steve.png");
|
||||
|
||||
public static final SkinCube ALEX_LARM = new SkinCube(3, 12, 4, 14F / 64F, 16F / 64F, 32F / 64F, 48F / 64F, 0F, true);
|
||||
public static final SkinCube ALEX_RARM = new SkinCube(3, 12, 4, 14F / 64F, 16F / 64F, 40F / 64F, 16F / 64F, 0F, true);
|
||||
|
||||
@ -152,10 +148,6 @@ public class SkinCanvas extends Group {
|
||||
capeGroup.setVisible(hasCape);
|
||||
}
|
||||
|
||||
public SkinCanvas(double preW, double preH) {
|
||||
this(STEVE, preW, preH, true);
|
||||
}
|
||||
|
||||
public SkinCanvas(Image skin, double preW, double preH, boolean msaa) {
|
||||
this.skin = skin;
|
||||
this.preW = preW;
|
||||
|
@ -25,7 +25,6 @@ import javafx.scene.control.ButtonType;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.DataFormat;
|
||||
import javafx.stage.Stage;
|
||||
import org.jackhuang.hmcl.auth.offline.Skin;
|
||||
import org.jackhuang.hmcl.mod.RemoteMod;
|
||||
import org.jackhuang.hmcl.mod.RemoteModRepository;
|
||||
import org.jackhuang.hmcl.setting.ConfigHolder;
|
||||
@ -129,31 +128,6 @@ public final class Launcher extends Application {
|
||||
}
|
||||
|
||||
private static void register() {
|
||||
Skin.registerDefaultSkinLoader((type) -> {
|
||||
switch (type) {
|
||||
case ALEX:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/alex.png");
|
||||
case ARI:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/ari.png");
|
||||
case EFE:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/efe.png");
|
||||
case KAI:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/kai.png");
|
||||
case MAKENA:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/makena.png");
|
||||
case NOOR:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/noor.png");
|
||||
case STEVE:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/steve.png");
|
||||
case SUNNY:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/sunny.png");
|
||||
case ZURI:
|
||||
return Skin.class.getResourceAsStream("/assets/img/skin/zuri.png");
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
RemoteMod.registerEmptyRemoteMod(new RemoteMod("", "", i18n("mods.broken_dependency.title"), i18n("mods.broken_dependency.desc"), new ArrayList<>(), "", "/assets/img/icon@8x.png", new RemoteMod.IMod() {
|
||||
@Override
|
||||
public List<RemoteMod> loadDependencies(RemoteModRepository modRepository) throws IOException {
|
||||
|
@ -140,23 +140,35 @@ public final class TexturesLoader {
|
||||
// ====
|
||||
|
||||
// ==== Skins ====
|
||||
private final static Map<TextureModel, LoadedTexture> DEFAULT_SKINS = new EnumMap<>(TextureModel.class);
|
||||
private static final String[] DEFAULT_SKINS = {"alex", "ari", "efe", "kai", "makena", "noor", "steve", "sunny", "zuri"};
|
||||
|
||||
static {
|
||||
loadDefaultSkin("/assets/img/skin/steve.png", TextureModel.STEVE);
|
||||
loadDefaultSkin("/assets/img/skin/alex.png", TextureModel.ALEX);
|
||||
public static Image getDefaultSkinImage() {
|
||||
return FXUtils.newBuiltinImage("/assets/img/skin/wide/steve.png");
|
||||
}
|
||||
|
||||
private static void loadDefaultSkin(String path, TextureModel model) {
|
||||
DEFAULT_SKINS.put(model, new LoadedTexture(FXUtils.newBuiltinImage(path), singletonMap("model", model.modelName)));
|
||||
public static LoadedTexture getDefaultSkin(UUID uuid) {
|
||||
int idx = Math.floorMod(uuid.hashCode(), DEFAULT_SKINS.length * 2);
|
||||
TextureModel model;
|
||||
Image skin;
|
||||
if (idx < DEFAULT_SKINS.length) {
|
||||
model = TextureModel.SLIM;
|
||||
skin = FXUtils.newBuiltinImage("/assets/img/skin/slim/" + DEFAULT_SKINS[idx] + ".png");
|
||||
} else {
|
||||
model = TextureModel.WIDE;
|
||||
skin = FXUtils.newBuiltinImage("/assets/img/skin/wide/" + DEFAULT_SKINS[idx - DEFAULT_SKINS.length] + ".png");
|
||||
}
|
||||
|
||||
return new LoadedTexture(skin, singletonMap("model", model.modelName));
|
||||
}
|
||||
|
||||
public static LoadedTexture getDefaultSkin(TextureModel model) {
|
||||
return DEFAULT_SKINS.get(model);
|
||||
public static TextureModel getDefaultModel(UUID uuid) {
|
||||
return TextureModel.WIDE.modelName.equals(getDefaultSkin(uuid).getMetadata().get("model"))
|
||||
? TextureModel.WIDE
|
||||
: TextureModel.SLIM;
|
||||
}
|
||||
|
||||
public static ObjectBinding<LoadedTexture> skinBinding(YggdrasilService service, UUID uuid) {
|
||||
LoadedTexture uuidFallback = getDefaultSkin(TextureModel.detectUUID(uuid));
|
||||
LoadedTexture uuidFallback = getDefaultSkin(uuid);
|
||||
return BindingMapping.of(service.getProfileRepository().binding(uuid))
|
||||
.map(profile -> profile
|
||||
.flatMap(it -> {
|
||||
@ -187,7 +199,7 @@ public final class TexturesLoader {
|
||||
}
|
||||
|
||||
public static ObservableValue<LoadedTexture> skinBinding(Account account) {
|
||||
LoadedTexture uuidFallback = getDefaultSkin(TextureModel.detectUUID(account.getUUID()));
|
||||
LoadedTexture uuidFallback = getDefaultSkin(account.getUUID());
|
||||
if (account instanceof OfflineAccount) {
|
||||
OfflineAccount offlineAccount = (OfflineAccount) account;
|
||||
|
||||
@ -348,7 +360,7 @@ public final class TexturesLoader {
|
||||
fxAvatarBinding(canvas, skinBinding(account));
|
||||
else {
|
||||
unbindAvatar(canvas);
|
||||
drawAvatar(canvas, getDefaultSkin(TextureModel.detectUUID(account.getUUID())).image);
|
||||
drawAvatar(canvas, getDefaultSkin(account.getUUID()).image);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,6 @@ import javafx.scene.control.Tooltip;
|
||||
import org.jackhuang.hmcl.auth.Account;
|
||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
||||
import org.jackhuang.hmcl.game.TexturesLoader;
|
||||
import org.jackhuang.hmcl.setting.Accounts;
|
||||
@ -58,7 +57,7 @@ public class AccountAdvancedListItem extends AdvancedListItem {
|
||||
tooltip.setText(i18n("account.create"));
|
||||
|
||||
TexturesLoader.unbindAvatar(canvas);
|
||||
TexturesLoader.drawAvatar(canvas, TexturesLoader.getDefaultSkin(TextureModel.STEVE).getImage());
|
||||
TexturesLoader.drawAvatar(canvas, TexturesLoader.getDefaultSkinImage());
|
||||
|
||||
} else {
|
||||
titleProperty().bind(BindingMapping.of(account, Account::getCharacter));
|
||||
|
@ -25,7 +25,6 @@ import javafx.application.Platform;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.input.DragEvent;
|
||||
import javafx.scene.input.TransferMode;
|
||||
import javafx.scene.layout.*;
|
||||
@ -35,6 +34,7 @@ import moe.mickey.minecraft.skin.fx.animation.SkinAniWavingArms;
|
||||
import org.jackhuang.hmcl.auth.offline.OfflineAccount;
|
||||
import org.jackhuang.hmcl.auth.offline.Skin;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
|
||||
import org.jackhuang.hmcl.game.TexturesLoader;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
@ -42,6 +42,7 @@ import org.jackhuang.hmcl.ui.construct.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
||||
@ -71,7 +72,7 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
|
||||
BorderPane pane = new BorderPane();
|
||||
|
||||
SkinCanvas canvas = new SkinCanvas(SkinCanvas.STEVE, 300, 300, true);
|
||||
SkinCanvas canvas = new SkinCanvas(TexturesLoader.getDefaultSkinImage(), 300, 300, true);
|
||||
StackPane canvasPane = new StackPane(canvas);
|
||||
canvasPane.setPrefWidth(300);
|
||||
canvasPane.setPrefHeight(300);
|
||||
@ -116,11 +117,11 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
));
|
||||
|
||||
modelCombobox.setConverter(stringConverter(model -> i18n("account.skin.model." + model.modelName)));
|
||||
modelCombobox.getItems().setAll(TextureModel.STEVE, TextureModel.ALEX);
|
||||
modelCombobox.getItems().setAll(TextureModel.WIDE, TextureModel.SLIM);
|
||||
|
||||
if (account.getSkin() == null) {
|
||||
skinItem.setSelectedData(Skin.Type.DEFAULT);
|
||||
modelCombobox.setValue(TextureModel.STEVE);
|
||||
modelCombobox.setValue(TextureModel.WIDE);
|
||||
} else {
|
||||
skinItem.setSelectedData(account.getSkin().getType());
|
||||
cslApiField.setText(account.getSkin().getCslApi());
|
||||
@ -136,13 +137,18 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
LOG.log(Level.WARNING, "Failed to load skin", exception);
|
||||
Controllers.showToast(i18n("message.failed"));
|
||||
} else {
|
||||
UUID uuid = this.account.getUUID();
|
||||
if (result == null || result.getSkin() == null && result.getCape() == null) {
|
||||
canvas.updateSkin(getDefaultTexture(), isDefaultSlim(), null);
|
||||
canvas.updateSkin(
|
||||
TexturesLoader.getDefaultSkin(uuid).getImage(),
|
||||
TexturesLoader.getDefaultModel(uuid) == TextureModel.SLIM,
|
||||
null
|
||||
);
|
||||
return;
|
||||
}
|
||||
canvas.updateSkin(
|
||||
result.getSkin() != null ? result.getSkin().getImage() : getDefaultTexture(),
|
||||
result.getModel() == TextureModel.ALEX,
|
||||
result.getSkin() != null ? result.getSkin().getImage() : TexturesLoader.getDefaultSkin(uuid).getImage(),
|
||||
result.getModel() == TextureModel.SLIM,
|
||||
result.getCape() != null ? result.getCape().getImage() : null);
|
||||
}
|
||||
}).start();
|
||||
@ -198,17 +204,4 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
private Skin getSkin() {
|
||||
return new Skin(skinItem.getSelectedData(), cslApiField.getText(), modelCombobox.getValue(), skinSelector.getValue(), capeSelector.getValue());
|
||||
}
|
||||
|
||||
private boolean isDefaultSlim() {
|
||||
return TextureModel.detectUUID(account.getUUID()) == TextureModel.ALEX;
|
||||
}
|
||||
|
||||
private Image getDefaultTexture() {
|
||||
if (isDefaultSlim()) {
|
||||
return SkinCanvas.ALEX;
|
||||
} else {
|
||||
return SkinCanvas.STEVE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 999 B |
Before Width: | Height: | Size: 912 B |
Before Width: | Height: | Size: 1001 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 861 B |
Before Width: | Height: | Size: 958 B |
Before Width: | Height: | Size: 988 B |
Before Width: | Height: | Size: 947 B |
@ -143,8 +143,8 @@ account.portable=Portable Account
|
||||
account.skin=Skin
|
||||
account.skin.file=Skin File
|
||||
account.skin.model=Model
|
||||
account.skin.model.default=Classic (Steve)
|
||||
account.skin.model.slim=Slim (Alex)
|
||||
account.skin.model.default=Classic
|
||||
account.skin.model.slim=Slim
|
||||
account.skin.type.csl_api=Blessing Skin
|
||||
account.skin.type.csl_api.location=Address
|
||||
account.skin.type.csl_api.location.hint=CustomSkinAPI URL
|
||||
|
@ -125,8 +125,8 @@ account.password=Contraseña
|
||||
account.skin=Skin
|
||||
account.skin.file=Archivo de skin
|
||||
account.skin.model=Modelo
|
||||
account.skin.model.default=Clásico (Steve)
|
||||
account.skin.model.slim=Delgado (Alex)
|
||||
account.skin.model.default=Clásico
|
||||
account.skin.model.slim=Delgado
|
||||
account.skin.type.csl_api=Blessing skin
|
||||
account.skin.type.csl_api.location=URL
|
||||
account.skin.type.csl_api.location.hint=CustomSkinAPI URL
|
||||
|
@ -112,8 +112,8 @@ account.password=パスワード
|
||||
account.skin=スキン
|
||||
account.skin.file=スキンイメージファイル
|
||||
account.skin.model=モデル
|
||||
account.skin.model.default=Classic (Steve)
|
||||
account.skin.model.slim=Slim (Alex)
|
||||
account.skin.model.default=Classic
|
||||
account.skin.model.slim=Slim
|
||||
account.skin.type.csl_api=Blessing Skin
|
||||
account.skin.type.csl_api.location=アドレス
|
||||
account.skin.type.csl_api.location.hint=CustomSkinAPI
|
||||
|
@ -120,8 +120,8 @@ account.password=Пароль
|
||||
account.skin=Скин
|
||||
account.skin.file=Файл скина
|
||||
account.skin.model=Модель
|
||||
account.skin.model.default=Классическая (Стив)
|
||||
account.skin.model.slim=Стройная (Алекс)
|
||||
account.skin.model.default=Классическая
|
||||
account.skin.model.slim=Стройная
|
||||
account.skin.type.csl_api=Blessing Skin
|
||||
account.skin.type.csl_api.location=Адрес
|
||||
account.skin.type.csl_api.location.hint=URL-адрес CustomSkinAPI
|
||||
|
@ -152,8 +152,8 @@ account.portable=便攜帳戶
|
||||
account.skin=皮膚
|
||||
account.skin.file=皮膚圖片檔案
|
||||
account.skin.model=模型
|
||||
account.skin.model.default=經典(Steve)
|
||||
account.skin.model.slim=苗條(Alex)
|
||||
account.skin.model.default=經典
|
||||
account.skin.model.slim=苗條
|
||||
account.skin.type.csl_api=Blessing Skin 伺服器
|
||||
account.skin.type.csl_api.location=伺服器位址
|
||||
account.skin.type.csl_api.location.hint=CustomSkinAPI 位址
|
||||
|
@ -153,8 +153,8 @@ account.portable=便携账户
|
||||
account.skin=皮肤
|
||||
account.skin.file=皮肤图片文件
|
||||
account.skin.model=模型
|
||||
account.skin.model.default=经典(Steve)
|
||||
account.skin.model.slim=苗条(Alex)
|
||||
account.skin.model.default=经典
|
||||
account.skin.model.slim=苗条
|
||||
account.skin.type.csl_api=Blessing Skin 服务器
|
||||
account.skin.type.csl_api.location=服务器地址
|
||||
account.skin.type.csl_api.location.hint=CustomSkinAPI 地址
|
||||
|
@ -8,6 +8,7 @@ import moe.mickey.minecraft.skin.fx.SkinCanvas;
|
||||
import moe.mickey.minecraft.skin.fx.SkinCanvasSupport;
|
||||
import moe.mickey.minecraft.skin.fx.animation.SkinAniRunning;
|
||||
import moe.mickey.minecraft.skin.fx.animation.SkinAniWavingArms;
|
||||
import org.jackhuang.hmcl.game.TexturesLoader;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -16,7 +17,7 @@ public class Test extends Application {
|
||||
public static final String TITLE = "FX - Minecraft skin preview";
|
||||
|
||||
public static SkinCanvas createSkinCanvas() {
|
||||
SkinCanvas canvas = new SkinCanvas(SkinCanvas.STEVE, 400, 400, true);
|
||||
SkinCanvas canvas = new SkinCanvas(TexturesLoader.getDefaultSkinImage(), 400, 400, true);
|
||||
canvas.getAnimationPlayer().addSkinAnimation(new SkinAniWavingArms(100, 2000, 7.5, canvas), new SkinAniRunning(100, 100, 30, canvas));
|
||||
FunctionHelper.alwaysB(Consumer<SkinCanvas>::accept, canvas, new SkinCanvasSupport.Mouse(.5), new SkinCanvasSupport.Drag(TITLE));
|
||||
return canvas;
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.auth.offline;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import javafx.scene.image.Image;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
|
||||
import org.jackhuang.hmcl.task.FetchTask;
|
||||
import org.jackhuang.hmcl.task.GetTask;
|
||||
@ -39,7 +40,6 @@ import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||
@ -99,12 +99,6 @@ public class Skin {
|
||||
}
|
||||
}
|
||||
|
||||
private static Function<Type, InputStream> defaultSkinLoader = null;
|
||||
|
||||
public static void registerDefaultSkinLoader(Function<Type, InputStream> defaultSkinLoader0) {
|
||||
defaultSkinLoader = defaultSkinLoader0;
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
private final String cslApi;
|
||||
private final TextureModel textureModel;
|
||||
@ -128,7 +122,7 @@ public class Skin {
|
||||
}
|
||||
|
||||
public TextureModel getTextureModel() {
|
||||
return textureModel == null ? TextureModel.STEVE : textureModel;
|
||||
return textureModel == null ? TextureModel.WIDE : textureModel;
|
||||
}
|
||||
|
||||
public String getLocalSkinPath() {
|
||||
@ -152,11 +146,14 @@ public class Skin {
|
||||
case STEVE:
|
||||
case SUNNY:
|
||||
case ZURI:
|
||||
if (defaultSkinLoader == null) {
|
||||
return Task.supplyAsync(() -> null);
|
||||
}
|
||||
TextureModel model = type == Type.ALEX ? TextureModel.ALEX : TextureModel.STEVE;
|
||||
return Task.supplyAsync(() -> new LoadedSkin(model, Texture.loadTexture(defaultSkinLoader.apply(type)), null));
|
||||
TextureModel model = this.textureModel != null ? this.textureModel : type == Type.ALEX ? TextureModel.SLIM : TextureModel.WIDE;
|
||||
String resource = (model == TextureModel.SLIM ? "/assets/img/skin/slim/" : "/assets/img/skin/wide/") + type.name().toLowerCase(Locale.ROOT) + ".png";
|
||||
|
||||
return Task.supplyAsync(() -> new LoadedSkin(
|
||||
model,
|
||||
Texture.loadTexture(new Image(resource)),
|
||||
null
|
||||
));
|
||||
case LOCAL_FILE:
|
||||
return Task.supplyAsync(() -> {
|
||||
Texture skin = null, cape = null;
|
||||
@ -227,16 +224,7 @@ public class Skin {
|
||||
String localSkinPath = tryCast(storage.get("localSkinPath"), String.class).orElse(null);
|
||||
String localCapePath = tryCast(storage.get("localCapePath"), String.class).orElse(null);
|
||||
|
||||
TextureModel model;
|
||||
if ("default".equals(textureModel)) {
|
||||
model = TextureModel.STEVE;
|
||||
} else if ("slim".equals(textureModel)) {
|
||||
model = TextureModel.ALEX;
|
||||
} else {
|
||||
model = TextureModel.STEVE;
|
||||
}
|
||||
|
||||
return new Skin(type, cslApi, model, localSkinPath, localCapePath);
|
||||
return new Skin(type, cslApi, "slim".equals(textureModel) ? TextureModel.SLIM : TextureModel.WIDE, localSkinPath, localCapePath);
|
||||
}
|
||||
|
||||
private static class FetchBytesTask extends FetchTask<InputStream> {
|
||||
@ -327,9 +315,9 @@ public class Skin {
|
||||
@Nullable
|
||||
public TextureModel getModel() {
|
||||
if (textures != null && textures.slim != null) {
|
||||
return TextureModel.ALEX;
|
||||
return TextureModel.SLIM;
|
||||
} else if (textures != null && textures.defaultSkin != null) {
|
||||
return TextureModel.STEVE;
|
||||
return TextureModel.WIDE;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -351,9 +339,9 @@ public class Skin {
|
||||
|
||||
public String getHash() {
|
||||
TextureModel model = getModel();
|
||||
if (model == TextureModel.ALEX)
|
||||
if (model == TextureModel.SLIM)
|
||||
return getAlexModelHash();
|
||||
else if (model == TextureModel.STEVE)
|
||||
else if (model == TextureModel.WIDE)
|
||||
return getSteveModelHash();
|
||||
else
|
||||
return null;
|
||||
|
@ -178,7 +178,7 @@ public class YggdrasilServer extends HttpServer {
|
||||
public Object toCompleteResponse(String rootUrl) {
|
||||
Map<String, Object> realTextures = new HashMap<>();
|
||||
if (skin != null && skin.getSkin() != null) {
|
||||
if (skin.getModel() == TextureModel.ALEX) {
|
||||
if (skin.getModel() == TextureModel.SLIM) {
|
||||
realTextures.put("SKIN", mapOf(
|
||||
pair("url", rootUrl + "/textures/" + skin.getSkin().getHash()),
|
||||
pair("metadata", mapOf(
|
||||
|
@ -17,27 +17,12 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.yggdrasil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public enum TextureModel {
|
||||
STEVE("default"), ALEX("slim");
|
||||
WIDE("default"), SLIM("slim");
|
||||
|
||||
public final String modelName;
|
||||
|
||||
TextureModel(String modelName) {
|
||||
this.modelName = modelName;
|
||||
}
|
||||
|
||||
public static TextureModel detectModelName(Map<String, String> metadata) {
|
||||
if (metadata != null && "slim".equals(metadata.get("model"))) {
|
||||
return ALEX;
|
||||
} else {
|
||||
return STEVE;
|
||||
}
|
||||
}
|
||||
|
||||
public static TextureModel detectUUID(UUID uuid) {
|
||||
return (uuid.hashCode() & 1) == 1 ? ALEX : STEVE;
|
||||
}
|
||||
}
|
||||
|
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/alex.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/ari.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/efe.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/kai.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/makena.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/noor.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/steve.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/sunny.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/slim/zuri.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/alex.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/ari.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/efe.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/kai.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/makena.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/noor.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/steve.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/sunny.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
HMCLCore/src/main/resources/assets/img/skin/wide/zuri.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
@ -9,22 +9,19 @@ import java.nio.file.Paths;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class NormalizedSkinTest {
|
||||
private static NormalizedSkin getSkin(String name) throws InvalidSkinException {
|
||||
String path = Paths.get("../HMCL/src/main/resources/assets/img/skin/" + name + ".png").normalize().toAbsolutePath().toUri().toString();
|
||||
private static NormalizedSkin getSkin(String name, boolean slim) throws InvalidSkinException {
|
||||
String path = Paths.get(String.format("../HMCLCore/src/main/resources/assets/img/skin/%s/%s.png", slim ? "slim" : "wide", name)).normalize().toAbsolutePath().toUri().toString();
|
||||
return new NormalizedSkin(new Image(path));
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIf("org.jackhuang.hmcl.JavaFXLauncher#isStarted")
|
||||
public void testIsSlim() throws Exception {
|
||||
assertFalse(getSkin("steve").isSlim());
|
||||
assertTrue(getSkin("alex").isSlim());
|
||||
assertTrue(getSkin("noor").isSlim());
|
||||
assertFalse(getSkin("sunny").isSlim());
|
||||
assertFalse(getSkin("ari").isSlim());
|
||||
assertFalse(getSkin("zuri").isSlim());
|
||||
assertTrue(getSkin("makena").isSlim());
|
||||
assertFalse(getSkin("kai").isSlim());
|
||||
assertTrue(getSkin("efe").isSlim());
|
||||
String[] names = {"alex", "ari", "efe", "kai", "makena", "noor", "steve", "sunny", "zuri"};
|
||||
|
||||
for (String skin : names) {
|
||||
assertTrue(getSkin(skin, true).isSlim());
|
||||
assertFalse(getSkin(skin, false).isSlim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|