character selection
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.auth;
|
||||
|
||||
import java.net.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -26,15 +27,48 @@ import java.util.Map;
|
||||
*/
|
||||
public abstract class Account {
|
||||
|
||||
/**
|
||||
* @return the account name (mostly email)
|
||||
*/
|
||||
public abstract String getUsername();
|
||||
|
||||
/**
|
||||
* log in.
|
||||
* @param selector selects a character
|
||||
* @return the specific player's info.
|
||||
* @throws AuthenticationException if server error occurred.
|
||||
*/
|
||||
public AuthInfo logIn(MultiCharacterSelector selector) throws AuthenticationException {
|
||||
return logIn(selector, Proxy.NO_PROXY);
|
||||
}
|
||||
|
||||
/**
|
||||
* log in.
|
||||
* @param selector selects a character
|
||||
* @param proxy by which connect to the server
|
||||
* @return the specific player's info.
|
||||
* @throws AuthenticationException if server error occurred.
|
||||
*/
|
||||
public abstract AuthInfo logIn(MultiCharacterSelector selector, Proxy proxy) throws AuthenticationException;
|
||||
|
||||
public abstract void logOut();
|
||||
|
||||
public abstract Map<Object, Object> toStorage();
|
||||
protected abstract Map<Object, Object> toStorageImpl();
|
||||
|
||||
public final Map<Object, Object> toStorage() {
|
||||
Map<Object, Object> storage = toStorageImpl();
|
||||
if (!getProperties().isEmpty())
|
||||
storage.put("properties", getProperties());
|
||||
return storage;
|
||||
}
|
||||
|
||||
private Map<Object, Object> properties = new HashMap<>();
|
||||
|
||||
/**
|
||||
* To save some necessary extra information here.
|
||||
* @return the property map.
|
||||
*/
|
||||
public final Map<Object, Object> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth;
|
||||
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -31,5 +33,13 @@ public abstract class AccountFactory<T extends Account> {
|
||||
|
||||
public abstract T fromUsername(String username, String password);
|
||||
|
||||
public abstract T fromStorage(Map<Object, Object> storage);
|
||||
protected abstract T fromStorageImpl(Map<Object, Object> storage);
|
||||
|
||||
public final T fromStorage(Map<Object, Object> storage) {
|
||||
T account = fromStorageImpl(storage);
|
||||
Map<?, ?> properties = Lang.get(storage, "properties", Map.class, null);
|
||||
if (properties == null) return account;
|
||||
account.getProperties().putAll(properties);
|
||||
return account;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@ package org.jackhuang.hmcl.auth;
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public class AuthenticationException extends Exception {
|
||||
|
||||
public AuthenticationException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AuthenticationException(String message) {
|
||||
@@ -34,4 +32,8 @@ public class AuthenticationException extends Exception {
|
||||
public AuthenticationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public AuthenticationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,23 +15,21 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.yggdrasil;
|
||||
|
||||
import org.jackhuang.hmcl.auth.AuthenticationException;
|
||||
package org.jackhuang.hmcl.auth;
|
||||
|
||||
/**
|
||||
*
|
||||
* throws if wrong password or logging fails for too many times.
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public final class InvalidCredentialsException extends AuthenticationException {
|
||||
|
||||
private final YggdrasilAccount account;
|
||||
private final Account account;
|
||||
|
||||
public InvalidCredentialsException(YggdrasilAccount account) {
|
||||
public InvalidCredentialsException(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public YggdrasilAccount getAccount() {
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth;
|
||||
|
||||
/**
|
||||
* throws if wrong password.
|
||||
*/
|
||||
public class InvalidPasswordException extends AuthenticationException {
|
||||
|
||||
private Account account;
|
||||
|
||||
public InvalidPasswordException(Account account) {
|
||||
super();
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
}
|
||||
@@ -15,9 +15,10 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.yggdrasil;
|
||||
package org.jackhuang.hmcl.auth;
|
||||
|
||||
import org.jackhuang.hmcl.auth.AuthenticationException;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -68,7 +68,7 @@ public class OfflineAccount extends Account {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> toStorage() {
|
||||
public Map<Object, Object> toStorageImpl() {
|
||||
return Lang.mapOf(
|
||||
new Pair<>("uuid", uuid),
|
||||
new Pair<>("username", username)
|
||||
|
||||
@@ -37,7 +37,7 @@ public class OfflineAccountFactory extends AccountFactory<OfflineAccount> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflineAccount fromStorage(Map<Object, Object> storage) {
|
||||
public OfflineAccount fromStorageImpl(Map<Object, Object> storage) {
|
||||
Object username = storage.get("username");
|
||||
if (username == null || !(username instanceof String))
|
||||
throw new IllegalStateException("Offline account configuration malformed.");
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth;
|
||||
|
||||
public class ServerDisconnectException extends AuthenticationException {
|
||||
public ServerDisconnectException() {
|
||||
}
|
||||
|
||||
public ServerDisconnectException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ServerDisconnectException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ServerDisconnectException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth;
|
||||
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Select character by name.
|
||||
*/
|
||||
public class SpecificCharacterSelector implements MultiCharacterSelector {
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param id character's name.
|
||||
*/
|
||||
public SpecificCharacterSelector(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameProfile select(Account account, List<GameProfile> names) throws NoSelectedCharacterException {
|
||||
return names.stream().filter(profile -> profile.getName().equals(id)).findAny().orElseThrow(() -> new NoSelectedCharacterException(account));
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,8 @@ public final class AuthenticationRequest {
|
||||
private final String clientToken;
|
||||
|
||||
private final Map<String, Object> agent = Lang.mapOf(
|
||||
new Pair("name", "minecraft"),
|
||||
new Pair("version", 1));
|
||||
new Pair<>("name", "minecraft"),
|
||||
new Pair<>("version", 1));
|
||||
|
||||
private final boolean requestUser = true;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ package org.jackhuang.hmcl.auth.yggdrasil;
|
||||
*
|
||||
* @author huangyuhui
|
||||
*/
|
||||
public final class Response {
|
||||
public final class AuthenticationResponse {
|
||||
|
||||
private final String accessToken;
|
||||
private final String clientToken;
|
||||
@@ -32,11 +32,11 @@ public final class Response {
|
||||
private final String errorMessage;
|
||||
private final String cause;
|
||||
|
||||
public Response() {
|
||||
public AuthenticationResponse() {
|
||||
this(null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public Response(String accessToken, String clientToken, GameProfile selectedProfile, GameProfile[] availableProfiles, User user, String error, String errorMessage, String cause) {
|
||||
public AuthenticationResponse(String accessToken, String clientToken, GameProfile selectedProfile, GameProfile[] availableProfiles, User user, String error, String errorMessage, String cause) {
|
||||
this.accessToken = accessToken;
|
||||
this.clientToken = clientToken;
|
||||
this.selectedProfile = selectedProfile;
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.yggdrasil;
|
||||
|
||||
public class ProfileResponse {
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final PropertyMap properties;
|
||||
|
||||
public ProfileResponse() {
|
||||
this("", "", null);
|
||||
}
|
||||
|
||||
public ProfileResponse(String id, String name, PropertyMap properties) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public PropertyMap getProperties() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.yggdrasil;
|
||||
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Immutable
|
||||
public final class ProfileTexture {
|
||||
|
||||
private final String url;
|
||||
private final Map<String, String> metadata;
|
||||
|
||||
public ProfileTexture() {
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
public ProfileTexture(String url, Map<String, String> metadata) {
|
||||
this.url = url;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getMetadata(String key) {
|
||||
if (metadata == null)
|
||||
return null;
|
||||
else
|
||||
return metadata.get(key);
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
SKIN, CAPE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher.
|
||||
* Copyright (C) 2017 huangyuhui <huanghongxun2008@126.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.yggdrasil;
|
||||
|
||||
import org.jackhuang.hmcl.util.Immutable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Immutable
|
||||
public final class TextureResponse {
|
||||
private final UUID profileId;
|
||||
private final String profileName;
|
||||
private final Map<ProfileTexture.Type, ProfileTexture> textures;
|
||||
|
||||
public TextureResponse() {
|
||||
this(UUID.randomUUID(), "", Collections.emptyMap());
|
||||
}
|
||||
|
||||
public TextureResponse(UUID profileId, String profileName, Map<ProfileTexture.Type, ProfileTexture> textures) {
|
||||
this.profileId = profileId;
|
||||
this.profileName = profileName;
|
||||
this.textures = textures;
|
||||
}
|
||||
|
||||
public UUID getProfileId() {
|
||||
return profileId;
|
||||
}
|
||||
|
||||
public String getProfileName() {
|
||||
return profileName;
|
||||
}
|
||||
|
||||
public Map<ProfileTexture.Type, ProfileTexture> getTextures() {
|
||||
return textures == null ? null : Collections.unmodifiableMap(textures);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonParseException;
|
||||
import org.jackhuang.hmcl.auth.*;
|
||||
import org.jackhuang.hmcl.util.Charsets;
|
||||
import org.jackhuang.hmcl.util.NetworkUtils;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jackhuang.hmcl.util.UUIDTypeAdapter;
|
||||
@@ -28,10 +29,7 @@ import org.jackhuang.hmcl.util.UUIDTypeAdapter;
|
||||
import java.io.IOException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -63,7 +61,7 @@ public final class YggdrasilAccount extends Account {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
public String getCurrentCharacterName() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
@@ -146,7 +144,7 @@ public final class YggdrasilAccount extends Account {
|
||||
}
|
||||
|
||||
private void logIn1(URL url, Object input, Proxy proxy) throws AuthenticationException {
|
||||
Response response = makeRequest(url, input, proxy);
|
||||
AuthenticationResponse response = makeRequest(url, input, proxy);
|
||||
if (response == null || !clientToken.equals(response.getClientToken()))
|
||||
throw new AuthenticationException("Client token changed");
|
||||
|
||||
@@ -183,13 +181,13 @@ public final class YggdrasilAccount extends Account {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> toStorage() {
|
||||
public Map<Object, Object> toStorageImpl() {
|
||||
HashMap<Object, Object> result = new HashMap<>();
|
||||
|
||||
result.put(STORAGE_KEY_USER_NAME, getUsername());
|
||||
result.put(STORAGE_KEY_CLIENT_TOKEN, getClientToken());
|
||||
if (getUserId() != null)
|
||||
result.put(STORAGE_KEY_USER_ID, getUserId());
|
||||
if (getCurrentCharacterName() != null)
|
||||
result.put(STORAGE_KEY_USER_ID, getCurrentCharacterName());
|
||||
if (!userProperties.isEmpty())
|
||||
result.put(STORAGE_KEY_USER_PROPERTIES, userProperties.toList());
|
||||
GameProfile profile = selectedProfile;
|
||||
@@ -207,10 +205,10 @@ public final class YggdrasilAccount extends Account {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Response makeRequest(URL url, Object input, Proxy proxy) throws AuthenticationException {
|
||||
private AuthenticationResponse makeRequest(URL url, Object input, Proxy proxy) throws AuthenticationException {
|
||||
try {
|
||||
String jsonResult = input == null ? NetworkUtils.doGet(url, proxy) : NetworkUtils.doPost(url, GSON.toJson(input), "application/json", proxy);
|
||||
Response response = GSON.fromJson(jsonResult, Response.class);
|
||||
AuthenticationResponse response = GSON.fromJson(jsonResult, AuthenticationResponse.class);
|
||||
if (response == null)
|
||||
return null;
|
||||
if (!StringUtils.isBlank(response.getError())) {
|
||||
@@ -219,12 +217,14 @@ public final class YggdrasilAccount extends Account {
|
||||
throw new InvalidCredentialsException(this);
|
||||
else if (response.getErrorMessage().contains("Invalid token"))
|
||||
throw new InvalidTokenException(this);
|
||||
else if (response.getErrorMessage().contains("Invalid username or password"))
|
||||
throw new InvalidPasswordException(this);
|
||||
throw new AuthenticationException(response.getError() + ": " + response.getErrorMessage());
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (IOException e) {
|
||||
throw new AuthenticationException("Unable to connect to authentication server", e);
|
||||
throw new ServerDisconnectException(e);
|
||||
} catch (JsonParseException e) {
|
||||
throw new AuthenticationException("Unable to parse server response", e);
|
||||
}
|
||||
@@ -242,12 +242,31 @@ public final class YggdrasilAccount extends Account {
|
||||
}
|
||||
}
|
||||
|
||||
public ProfileTexture getSkin(GameProfile profile) throws IOException, JsonParseException {
|
||||
if (StringUtils.isBlank(userId))
|
||||
throw new IllegalStateException("Not logged in");
|
||||
|
||||
ProfileResponse response = GSON.fromJson(NetworkUtils.doGet(NetworkUtils.toURL(BASE_PROFILE + UUIDTypeAdapter.fromUUID(profile.getId()))), ProfileResponse.class);
|
||||
if (response.getProperties() == null) return null;
|
||||
Property textureProperty = response.getProperties().get("textures");
|
||||
if (textureProperty == null) return null;
|
||||
|
||||
TextureResponse texture;
|
||||
String json = new String(Base64.getDecoder().decode(textureProperty.getValue()), Charsets.UTF_8);
|
||||
texture = GSON.fromJson(json, TextureResponse.class);
|
||||
if (texture == null || texture.getTextures() == null)
|
||||
return null;
|
||||
|
||||
return texture.getTextures().get(ProfileTexture.Type.SKIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "YggdrasilAccount[username=" + getUsername() + "]";
|
||||
}
|
||||
|
||||
private static final String BASE_URL = "https://authserver.mojang.com/";
|
||||
private static final String BASE_URL = "http://localhost:8080/authserver/"; //"https://authserver.mojang.com/";
|
||||
private static final String BASE_PROFILE = "http://localhost:8080/sessionserver/session/minecraft/profile/"; //"https://sessionserver.mojang.com/session/minecraft/profile/";
|
||||
private static final URL ROUTE_AUTHENTICATE = NetworkUtils.toURL(BASE_URL + "authenticate");
|
||||
private static final URL ROUTE_REFRESH = NetworkUtils.toURL(BASE_URL + "refresh");
|
||||
private static final URL ROUTE_VALIDATE = NetworkUtils.toURL(BASE_URL + "validate");
|
||||
|
||||
@@ -45,7 +45,7 @@ public final class YggdrasilAccountFactory extends AccountFactory<YggdrasilAccou
|
||||
}
|
||||
|
||||
@Override
|
||||
public YggdrasilAccount fromStorage(Map<Object, Object> storage) {
|
||||
public YggdrasilAccount fromStorageImpl(Map<Object, Object> storage) {
|
||||
String username = Lang.get(storage, STORAGE_KEY_USER_NAME, String.class)
|
||||
.orElseThrow(() -> new IllegalArgumentException("storage does not have key " + STORAGE_KEY_USER_NAME));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user