mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2026-10-29 15:10:30 +08:00
[Chore] auth 有关的部分类转换为记录类 (#6268)
This commit is contained in:
@@ -87,7 +87,7 @@ public final class TexturesLoader {
|
||||
private static final Path TEXTURES_DIR = Metadata.HMCL_USER_HOME.resolve("skins");
|
||||
|
||||
private static Path getTexturePath(Texture texture) {
|
||||
String url = texture.getUrl();
|
||||
String url = texture.url();
|
||||
int slash = url.lastIndexOf('/');
|
||||
int dot = url.lastIndexOf('.');
|
||||
if (dot < slash) {
|
||||
@@ -99,7 +99,7 @@ public final class TexturesLoader {
|
||||
}
|
||||
|
||||
public static LoadedTexture loadTexture(Texture texture) throws Throwable {
|
||||
if (StringUtils.isBlank(texture.getUrl())) {
|
||||
if (StringUtils.isBlank(texture.url())) {
|
||||
throw new IOException("Texture url is empty");
|
||||
}
|
||||
|
||||
@@ -107,14 +107,14 @@ public final class TexturesLoader {
|
||||
if (!Files.isRegularFile(file)) {
|
||||
// download it
|
||||
try {
|
||||
new FileDownloadTask(texture.getUrl(), file).run();
|
||||
LOG.info("Texture downloaded: " + texture.getUrl());
|
||||
new FileDownloadTask(texture.url(), file).run();
|
||||
LOG.info("Texture downloaded: " + texture.url());
|
||||
} catch (Exception e) {
|
||||
if (Files.isRegularFile(file)) {
|
||||
// concurrency conflict?
|
||||
LOG.warning("Failed to download texture " + texture.getUrl() + ", but the file is available", e);
|
||||
LOG.warning("Failed to download texture " + texture.url() + ", but the file is available", e);
|
||||
} else {
|
||||
throw new IOException("Failed to download texture " + texture.getUrl());
|
||||
throw new IOException("Failed to download texture " + texture.url());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ public final class TexturesLoader {
|
||||
if (img.isError())
|
||||
throw img.getException();
|
||||
|
||||
Map<String, String> metadata = texture.getMetadata();
|
||||
Map<String, String> metadata = texture.metadata();
|
||||
if (metadata == null) {
|
||||
metadata = emptyMap();
|
||||
}
|
||||
@@ -176,7 +176,7 @@ public final class TexturesLoader {
|
||||
}
|
||||
})
|
||||
.flatMap(it -> Optional.ofNullable(it.get(TextureType.SKIN)))
|
||||
.filter(it -> StringUtils.isNotBlank(it.getUrl())))
|
||||
.filter(it -> StringUtils.isNotBlank(it.url())))
|
||||
.asyncMap(it -> {
|
||||
if (it.isPresent()) {
|
||||
Texture texture = it.get();
|
||||
@@ -184,7 +184,7 @@ public final class TexturesLoader {
|
||||
try {
|
||||
return loadTexture(texture);
|
||||
} catch (Throwable e) {
|
||||
LOG.warning("Failed to load texture " + texture.getUrl() + ", using fallback texture", e);
|
||||
LOG.warning("Failed to load texture " + texture.url() + ", using fallback texture", e);
|
||||
return uuidFallback;
|
||||
}
|
||||
}, POOL);
|
||||
@@ -209,15 +209,15 @@ public final class TexturesLoader {
|
||||
skin.load(profileName).setExecutor(POOL).whenComplete(Schedulers.javafx(), (result, exception) -> {
|
||||
if (exception != null) {
|
||||
LOG.warning("Failed to load texture", exception);
|
||||
} else if (result != null && result.getSkin() != null && result.getSkin().getImage() != null) {
|
||||
} else if (result != null && result.skin() != null && result.skin().image() != null) {
|
||||
Map<String, String> metadata;
|
||||
if (result.getModel() != null) {
|
||||
metadata = singletonMap("model", result.getModel().modelName);
|
||||
if (result.model() != null) {
|
||||
metadata = singletonMap("model", result.model().modelName);
|
||||
} else {
|
||||
metadata = emptyMap();
|
||||
}
|
||||
|
||||
binding.set(new LoadedTexture(result.getSkin().getImage(), metadata));
|
||||
binding.set(new LoadedTexture(result.skin().image(), metadata));
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -234,12 +234,12 @@ public final class TexturesLoader {
|
||||
.asyncMap(textures -> {
|
||||
if (textures.isPresent()) {
|
||||
Texture texture = textures.get().get(TextureType.SKIN);
|
||||
if (texture != null && StringUtils.isNotBlank(texture.getUrl())) {
|
||||
if (texture != null && StringUtils.isNotBlank(texture.url())) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return loadTexture(texture);
|
||||
} catch (Throwable e) {
|
||||
LOG.warning("Failed to load texture " + texture.getUrl() + ", using fallback texture", e);
|
||||
LOG.warning("Failed to load texture " + texture.url() + ", using fallback texture", e);
|
||||
return uuidFallback;
|
||||
}
|
||||
}, POOL);
|
||||
|
||||
@@ -130,11 +130,11 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
skinItem.setSelectedData(Skin.Type.DEFAULT);
|
||||
modelCombobox.setValue(TextureModel.WIDE);
|
||||
} else {
|
||||
skinItem.setSelectedData(account.getSkin().getType());
|
||||
cslApiField.setText(account.getSkin().getCslApi());
|
||||
modelCombobox.setValue(account.getSkin().getTextureModel());
|
||||
skinSelector.setValue(account.getSkin().getLocalSkinPath());
|
||||
capeSelector.setValue(account.getSkin().getLocalCapePath());
|
||||
skinItem.setSelectedData(account.getSkin().type());
|
||||
cslApiField.setText(account.getSkin().cslApi());
|
||||
modelCombobox.setValue(account.getSkin().textureModel());
|
||||
skinSelector.setValue(account.getSkin().localSkinPath());
|
||||
capeSelector.setValue(account.getSkin().localCapePath());
|
||||
}
|
||||
|
||||
PauseTransition pauseTransition = new PauseTransition(Duration.seconds(1));
|
||||
@@ -147,7 +147,7 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
Controllers.showToast(i18n("message.failed"));
|
||||
} else {
|
||||
UUID uuid = this.account.getProfileID();
|
||||
if (result == null || result.getSkin() == null && result.getCape() == null) {
|
||||
if (result == null || result.skin() == null && result.cape() == null) {
|
||||
canvas.updateSkin(
|
||||
TexturesLoader.getDefaultSkin(uuid).getImage(),
|
||||
TexturesLoader.getDefaultModel(uuid) == TextureModel.SLIM,
|
||||
@@ -156,9 +156,9 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
return;
|
||||
}
|
||||
canvas.updateSkin(
|
||||
result.getSkin() != null ? result.getSkin().getImage() : TexturesLoader.getDefaultSkin(uuid).getImage(),
|
||||
result.getModel() == TextureModel.SLIM,
|
||||
result.getCape() != null ? result.getCape().getImage() : null);
|
||||
result.skin() != null ? result.skin().image() : TexturesLoader.getDefaultSkin(uuid).getImage(),
|
||||
result.model() == TextureModel.SLIM,
|
||||
result.cape() != null ? result.cape().image() : null);
|
||||
}
|
||||
}).start();
|
||||
};
|
||||
|
||||
@@ -288,22 +288,7 @@ public class OAuth {
|
||||
DEVICE,
|
||||
}
|
||||
|
||||
public static final class Result {
|
||||
private final String accessToken;
|
||||
private final String refreshToken;
|
||||
|
||||
public Result(String accessToken, String refreshToken) {
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
public record Result(String accessToken, String refreshToken) {
|
||||
}
|
||||
|
||||
private final static class DeviceTokenResponse extends ErrorResponse {
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ public class AuthlibInjectorAccount extends YggdrasilAccount {
|
||||
@Override
|
||||
public Arguments getLaunchArguments(LaunchOptions options) {
|
||||
return new Arguments().addJVMArguments(
|
||||
"-javaagent:" + artifact.getLocation().toString() + "=" + server.getUrl(),
|
||||
"-javaagent:" + artifact.location().toString() + "=" + server.getUrl(),
|
||||
"-Dauthlibinjector.side=client",
|
||||
"-Dauthlibinjector.yggdrasil.prefetched=" + Base64.getEncoder().encodeToString(prefetchedMeta.getBytes(UTF_8)));
|
||||
}
|
||||
|
||||
+4
-24
@@ -17,13 +17,15 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.authlibinjector;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class AuthlibInjectorArtifactInfo {
|
||||
public record AuthlibInjectorArtifactInfo(int buildNumber, String version, Path location) {
|
||||
|
||||
public static AuthlibInjectorArtifactInfo from(Path location) throws IOException {
|
||||
try (JarFile jarFile = new JarFile(location.toFile())) {
|
||||
@@ -50,30 +52,8 @@ public class AuthlibInjectorArtifactInfo {
|
||||
}
|
||||
}
|
||||
|
||||
private int buildNumber;
|
||||
private String version;
|
||||
private Path location;
|
||||
|
||||
public AuthlibInjectorArtifactInfo(int buildNumber, String version, Path location) {
|
||||
this.buildNumber = buildNumber;
|
||||
this.version = version;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public int getBuildNumber() {
|
||||
return buildNumber;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public Path getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public @NotNull String toString() {
|
||||
return "authlib-injector [buildNumber=" + buildNumber + ", version=" + version + "]";
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ public class AuthlibInjectorDownloader implements AuthlibInjectorArtifactProvide
|
||||
AuthlibInjectorVersionInfo latest = getLatestArtifactInfo();
|
||||
|
||||
Optional<AuthlibInjectorArtifactInfo> local = getLocalArtifact();
|
||||
if (local.isPresent() && local.get().getBuildNumber() >= latest.buildNumber) {
|
||||
if (local.isPresent() && local.get().buildNumber() >= latest.buildNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class MicrosoftAccount extends OAuthAccount {
|
||||
super(accountID);
|
||||
this.service = requireNonNull(service);
|
||||
this.session = requireNonNull(session);
|
||||
this.profileID = requireNonNull(session.getProfile().id());
|
||||
this.profileID = requireNonNull(session.profile().id());
|
||||
}
|
||||
|
||||
protected MicrosoftAccount(MicrosoftService service, OAuth.GrantFlow flow) throws AuthenticationException {
|
||||
@@ -54,35 +54,35 @@ public final class MicrosoftAccount extends OAuthAccount {
|
||||
this.service = requireNonNull(service);
|
||||
|
||||
MicrosoftSession acquiredSession = service.authenticate(flow);
|
||||
if (acquiredSession.getProfile() == null) {
|
||||
if (acquiredSession.profile() == null) {
|
||||
session = service.refresh(acquiredSession);
|
||||
} else {
|
||||
session = acquiredSession;
|
||||
}
|
||||
|
||||
profileID = session.getProfile().id();
|
||||
profileID = session.profile().id();
|
||||
authenticated = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProfileName() {
|
||||
return session.getProfile().name();
|
||||
return session.profile().name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getProfileID() {
|
||||
return session.getProfile().id();
|
||||
return session.profile().id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthInfo logIn() throws AuthenticationException {
|
||||
if (!authenticated || !session.hasProfileName() || System.currentTimeMillis() > session.getNotAfter()) {
|
||||
if (!authenticated || !session.hasProfileName() || System.currentTimeMillis() > session.notAfter()) {
|
||||
if (session.hasProfileName()
|
||||
&& service.validate(session.getNotAfter(), session.getTokenType(), session.getAccessToken())) {
|
||||
&& service.validate(session.notAfter(), session.tokenType(), session.accessToken())) {
|
||||
authenticated = true;
|
||||
} else {
|
||||
MicrosoftSession acquiredSession = service.refresh(session);
|
||||
if (!Objects.equals(acquiredSession.getProfile().id(), session.getProfile().id())) {
|
||||
if (!Objects.equals(acquiredSession.profile().id(), session.profile().id())) {
|
||||
throw new ServerResponseMalformedException("Selected profile changed");
|
||||
}
|
||||
if (!acquiredSession.hasProfileName()) {
|
||||
@@ -102,11 +102,11 @@ public final class MicrosoftAccount extends OAuthAccount {
|
||||
@Override
|
||||
public AuthInfo logInWhenCredentialsExpired() throws AuthenticationException {
|
||||
MicrosoftSession acquiredSession = service.authenticate(OAuth.GrantFlow.DEVICE);
|
||||
if (!Objects.equals(profileID, acquiredSession.getProfile().id())) {
|
||||
throw new WrongAccountException(profileID, acquiredSession.getProfile().id());
|
||||
if (!Objects.equals(profileID, acquiredSession.profile().id())) {
|
||||
throw new WrongAccountException(profileID, acquiredSession.profile().id());
|
||||
}
|
||||
|
||||
if (acquiredSession.getProfile() == null) {
|
||||
if (acquiredSession.profile() == null) {
|
||||
session = service.refresh(acquiredSession);
|
||||
} else {
|
||||
session = acquiredSession;
|
||||
@@ -133,7 +133,7 @@ public final class MicrosoftAccount extends OAuthAccount {
|
||||
|
||||
@Override
|
||||
public void uploadSkin(boolean isSlim, Path file) throws AuthenticationException, UnsupportedOperationException {
|
||||
service.uploadSkin(session.getAccessToken(), isSlim, file);
|
||||
service.uploadSkin(session.accessToken(), isSlim, file);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -77,7 +77,7 @@ public class MicrosoftService {
|
||||
public MicrosoftSession authenticate(OAuth.GrantFlow flow) throws AuthenticationException {
|
||||
try {
|
||||
OAuth.Result result = OAuth.MICROSOFT.authenticate(flow, new OAuth.Options(SCOPE, callback));
|
||||
return authenticateViaLiveAccessToken(result.getAccessToken(), result.getRefreshToken());
|
||||
return authenticateViaLiveAccessToken(result.accessToken(), result.refreshToken());
|
||||
} catch (IOException e) {
|
||||
throw new ServerDisconnectException(e);
|
||||
} catch (JsonParseException e) {
|
||||
@@ -87,8 +87,8 @@ public class MicrosoftService {
|
||||
|
||||
public MicrosoftSession refresh(MicrosoftSession oldSession) throws AuthenticationException {
|
||||
try {
|
||||
OAuth.Result result = OAuth.MICROSOFT.refresh(oldSession.getRefreshToken(), new OAuth.Options(SCOPE, callback));
|
||||
return authenticateViaLiveAccessToken(result.getAccessToken(), result.getRefreshToken());
|
||||
OAuth.Result result = OAuth.MICROSOFT.refresh(oldSession.refreshToken(), new OAuth.Options(SCOPE, callback));
|
||||
return authenticateViaLiveAccessToken(result.accessToken(), result.refreshToken());
|
||||
} catch (IOException e) {
|
||||
throw new ServerDisconnectException(e);
|
||||
} catch (JsonParseException e) {
|
||||
|
||||
@@ -30,13 +30,7 @@ import java.util.UUID;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class MicrosoftSession {
|
||||
private final String tokenType;
|
||||
private final long notAfter;
|
||||
private final String accessToken;
|
||||
private final String refreshToken;
|
||||
private final User user;
|
||||
private final GameProfile profile;
|
||||
public record MicrosoftSession(String tokenType, String accessToken, long notAfter, String refreshToken, User user, GameProfile profile) {
|
||||
|
||||
public MicrosoftSession(String tokenType, String accessToken, long notAfter, String refreshToken, User user, GameProfile profile) {
|
||||
this.tokenType = tokenType;
|
||||
@@ -49,32 +43,8 @@ public class MicrosoftSession {
|
||||
if (accessToken != null) Logger.registerAccessToken(accessToken);
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public long getNotAfter() {
|
||||
return notAfter;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public String getAuthorization() {
|
||||
return String.format("%s %s", getTokenType(), getAccessToken());
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public GameProfile getProfile() {
|
||||
return profile;
|
||||
return String.format("%s %s", tokenType(), accessToken());
|
||||
}
|
||||
|
||||
/// Returns whether the stored session contains a usable Minecraft profile name.
|
||||
|
||||
@@ -97,7 +97,7 @@ public class OfflineAccount extends Account {
|
||||
}
|
||||
|
||||
protected boolean loadAuthlibInjector(Skin skin) {
|
||||
return skin != null && skin.getType() != Skin.Type.DEFAULT;
|
||||
return skin != null && skin.type() != Skin.Type.DEFAULT;
|
||||
}
|
||||
|
||||
public AuthInfo logInWithoutSkin() throws AuthenticationException {
|
||||
@@ -169,7 +169,7 @@ public class OfflineAccount extends Account {
|
||||
}
|
||||
|
||||
return new Arguments().addJVMArguments(
|
||||
"-javaagent:" + artifact.getLocation().toString() + "=" + "http://localhost:" + server.getListeningPort(),
|
||||
"-javaagent:" + artifact.location().toString() + "=" + "http://localhost:" + server.getListeningPort(),
|
||||
"-Dauthlibinjector.side=client"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,9 +38,11 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Skin {
|
||||
public record Skin(Type type, String cslApi, TextureModel textureModel, String localSkinPath, String localCapePath) {
|
||||
|
||||
public enum Type {
|
||||
DEFAULT,
|
||||
@@ -59,75 +61,31 @@ public class Skin {
|
||||
YGGDRASIL_API;
|
||||
|
||||
public static Type fromStorage(String type) {
|
||||
switch (type) {
|
||||
case "default":
|
||||
return DEFAULT;
|
||||
case "alex":
|
||||
return ALEX;
|
||||
case "ari":
|
||||
return ARI;
|
||||
case "efe":
|
||||
return EFE;
|
||||
case "kai":
|
||||
return KAI;
|
||||
case "makena":
|
||||
return MAKENA;
|
||||
case "noor":
|
||||
return NOOR;
|
||||
case "steve":
|
||||
return STEVE;
|
||||
case "sunny":
|
||||
return SUNNY;
|
||||
case "zuri":
|
||||
return ZURI;
|
||||
case "local_file":
|
||||
return LOCAL_FILE;
|
||||
case "little_skin":
|
||||
return LITTLE_SKIN;
|
||||
case "custom_skin_loader_api":
|
||||
return CUSTOM_SKIN_LOADER_API;
|
||||
case "yggdrasil_api":
|
||||
return YGGDRASIL_API;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return switch (type) {
|
||||
case "default" -> DEFAULT;
|
||||
case "alex" -> ALEX;
|
||||
case "ari" -> ARI;
|
||||
case "efe" -> EFE;
|
||||
case "kai" -> KAI;
|
||||
case "makena" -> MAKENA;
|
||||
case "noor" -> NOOR;
|
||||
case "steve" -> STEVE;
|
||||
case "sunny" -> SUNNY;
|
||||
case "zuri" -> ZURI;
|
||||
case "local_file" -> LOCAL_FILE;
|
||||
case "little_skin" -> LITTLE_SKIN;
|
||||
case "custom_skin_loader_api" -> CUSTOM_SKIN_LOADER_API;
|
||||
case "yggdrasil_api" -> YGGDRASIL_API;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private final Type type;
|
||||
private final String cslApi;
|
||||
private final TextureModel textureModel;
|
||||
private final String localSkinPath;
|
||||
private final String localCapePath;
|
||||
|
||||
public Skin(Type type, String cslApi, TextureModel textureModel, String localSkinPath, String localCapePath) {
|
||||
this.type = type;
|
||||
this.cslApi = cslApi;
|
||||
this.textureModel = textureModel;
|
||||
this.localSkinPath = localSkinPath;
|
||||
this.localCapePath = localCapePath;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getCslApi() {
|
||||
return cslApi;
|
||||
}
|
||||
|
||||
public TextureModel getTextureModel() {
|
||||
@Override
|
||||
public TextureModel textureModel() {
|
||||
return textureModel == null ? TextureModel.WIDE : textureModel;
|
||||
}
|
||||
|
||||
public String getLocalSkinPath() {
|
||||
return localSkinPath;
|
||||
}
|
||||
|
||||
public String getLocalCapePath() {
|
||||
return localCapePath;
|
||||
}
|
||||
|
||||
public Task<LoadedSkin> load(String username) {
|
||||
switch (type) {
|
||||
case DEFAULT:
|
||||
@@ -156,7 +114,7 @@ public class Skin {
|
||||
Optional<Path> capePath = FileUtils.tryGetPath(localCapePath);
|
||||
if (skinPath.isPresent()) skin = Texture.loadTexture(Files.newInputStream(skinPath.get()));
|
||||
if (capePath.isPresent()) cape = Texture.loadTexture(Files.newInputStream(capePath.get()));
|
||||
return new LoadedSkin(getTextureModel(), skin, cape);
|
||||
return new LoadedSkin(textureModel(), skin, cape);
|
||||
});
|
||||
case LITTLE_SKIN:
|
||||
case CUSTOM_SKIN_LOADER_API:
|
||||
@@ -204,7 +162,7 @@ public class Skin {
|
||||
public void writeStorage(JsonObject storage) {
|
||||
storage.addProperty("type", type.name().toLowerCase(Locale.ROOT));
|
||||
storage.addProperty("cslApi", cslApi);
|
||||
storage.addProperty("textureModel", getTextureModel().modelName);
|
||||
storage.addProperty("textureModel", textureModel().modelName);
|
||||
storage.addProperty("localSkinPath", localSkinPath);
|
||||
storage.addProperty("localCapePath", localCapePath);
|
||||
}
|
||||
@@ -270,46 +228,11 @@ public class Skin {
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoadedSkin {
|
||||
private final TextureModel model;
|
||||
private final Texture skin;
|
||||
private final Texture cape;
|
||||
|
||||
public LoadedSkin(TextureModel model, Texture skin, Texture cape) {
|
||||
this.model = model;
|
||||
this.skin = skin;
|
||||
this.cape = cape;
|
||||
}
|
||||
|
||||
public TextureModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public Texture getSkin() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
public Texture getCape() {
|
||||
return cape;
|
||||
}
|
||||
public record LoadedSkin(TextureModel model, Texture skin, Texture cape) {
|
||||
}
|
||||
|
||||
private static class SkinJson {
|
||||
private final String username;
|
||||
private final String skin;
|
||||
private final String cape;
|
||||
private final String elytra;
|
||||
|
||||
@SerializedName(value = "textures", alternate = { "skins" })
|
||||
private final TextureJson textures;
|
||||
|
||||
public SkinJson(String username, String skin, String cape, String elytra, TextureJson textures) {
|
||||
this.username = username;
|
||||
this.skin = skin;
|
||||
this.cape = cape;
|
||||
this.elytra = elytra;
|
||||
this.textures = textures;
|
||||
}
|
||||
private record SkinJson(String username, String skin, String cape, String elytra,
|
||||
@SerializedName(value = "textures", alternate = {"skins"}) TextureJson textures) {
|
||||
|
||||
public boolean hasSkin() {
|
||||
return StringUtils.isNotBlank(username);
|
||||
@@ -356,20 +279,7 @@ public class Skin {
|
||||
} else return cape;
|
||||
}
|
||||
|
||||
public static class TextureJson {
|
||||
@SerializedName("default")
|
||||
private final String defaultSkin;
|
||||
|
||||
private final String slim;
|
||||
private final String cape;
|
||||
private final String elytra;
|
||||
|
||||
public TextureJson(String defaultSkin, String slim, String cape, String elytra) {
|
||||
this.defaultSkin = defaultSkin;
|
||||
this.slim = slim;
|
||||
this.cape = cape;
|
||||
this.elytra = elytra;
|
||||
}
|
||||
public record TextureJson(@SerializedName("default") String defaultSkin, String slim, String cape, String elytra) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,23 +30,12 @@ import java.util.Map;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class Texture {
|
||||
private final String hash;
|
||||
private final Image image;
|
||||
|
||||
public record Texture(String hash, Image image) {
|
||||
public Texture(String hash, Image image) {
|
||||
this.hash = requireNonNull(hash);
|
||||
this.image = requireNonNull(image);
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public Image getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
private static final Map<String, Texture> textures = new HashMap<>();
|
||||
|
||||
public static boolean hasTexture(String hash) {
|
||||
|
||||
@@ -129,7 +129,7 @@ public class YggdrasilServer extends HttpServer {
|
||||
|
||||
if (Texture.hasTexture(hash)) {
|
||||
Texture texture = Texture.getTexture(hash);
|
||||
byte[] data = PNGJavaFXUtils.writeImageToArray(texture.getImage());
|
||||
byte[] data = PNGJavaFXUtils.writeImageToArray(texture.image());
|
||||
Response response = newFixedLengthResponse(Response.Status.OK, "image/png", new ByteArrayInputStream(data), data.length);
|
||||
response.addHeader("Etag", String.format("\"%s\"", hash));
|
||||
response.addHeader("Cache-Control", "max-age=2592000, public");
|
||||
@@ -177,19 +177,19 @@ 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.SLIM) {
|
||||
if (skin != null && skin.skin() != null) {
|
||||
if (skin.model() == TextureModel.SLIM) {
|
||||
realTextures.put("SKIN", mapOf(
|
||||
pair("url", rootUrl + "/textures/" + skin.getSkin().getHash()),
|
||||
pair("url", rootUrl + "/textures/" + skin.skin().hash()),
|
||||
pair("metadata", mapOf(
|
||||
pair("model", "slim")
|
||||
))));
|
||||
} else {
|
||||
realTextures.put("SKIN", mapOf(pair("url", rootUrl + "/textures/" + skin.getSkin().getHash())));
|
||||
realTextures.put("SKIN", mapOf(pair("url", rootUrl + "/textures/" + skin.skin().hash())));
|
||||
}
|
||||
}
|
||||
if (skin != null && skin.getCape() != null) {
|
||||
realTextures.put("CAPE", mapOf(pair("url", rootUrl + "/textures/" + skin.getCape().getHash())));
|
||||
if (skin != null && skin.cape() != null) {
|
||||
realTextures.put("CAPE", mapOf(pair("url", rootUrl + "/textures/" + skin.cape().hash())));
|
||||
}
|
||||
|
||||
Map<String, Object> textureResponse = mapOf(
|
||||
|
||||
@@ -23,27 +23,21 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Map;
|
||||
|
||||
@Immutable
|
||||
public final class Texture {
|
||||
|
||||
private final String url;
|
||||
private final Map<String, String> metadata;
|
||||
public record Texture(String url, Map<String, String> metadata) {
|
||||
|
||||
public Texture() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public Texture(String url, Map<String, String> metadata) {
|
||||
this.url = url;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getUrl() {
|
||||
public String url() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Map<String, String> getMetadata() {
|
||||
public Map<String, String> metadata() {
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,32 +32,12 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author huang
|
||||
*/
|
||||
@Immutable
|
||||
public final class User implements Validation {
|
||||
|
||||
private final String id;
|
||||
|
||||
@Nullable
|
||||
@JsonAdapter(PropertyMapSerializer.class)
|
||||
private final Map<String, String> properties;
|
||||
public record User(String id, @JsonAdapter(PropertyMapSerializer.class) @Nullable Map<String, String> properties) implements Validation {
|
||||
|
||||
public User(String id) {
|
||||
this(id, null);
|
||||
}
|
||||
|
||||
public User(String id, @Nullable Map<String, String> properties) {
|
||||
this.id = id;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, String> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws JsonParseException {
|
||||
if (StringUtils.isBlank(id))
|
||||
|
||||
@@ -211,7 +211,7 @@ public class YggdrasilService {
|
||||
response.accessToken,
|
||||
response.selectedProfile,
|
||||
response.availableProfiles == null ? null : unmodifiableList(response.availableProfiles),
|
||||
response.user == null ? null : response.user.getProperties());
|
||||
response.user == null ? null : response.user.properties());
|
||||
}
|
||||
|
||||
private static void requireEmpty(String response) throws AuthenticationException {
|
||||
|
||||
@@ -37,6 +37,7 @@ public class YggdrasilSession {
|
||||
private final String accessToken;
|
||||
private final GameProfile selectedProfile;
|
||||
private final List<GameProfile> availableProfiles;
|
||||
|
||||
@Nullable
|
||||
private final Map<String, String> userProperties;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user