diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/GameProfile.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/GameProfile.java index 5dce59bc3..6be6f1685 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/GameProfile.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/GameProfile.java @@ -34,6 +34,7 @@ public class GameProfile { public final UUID id; public final String name; public final PropertyMap properties = new PropertyMap(); + private boolean legacy; public GameProfile(UUID id, String name) { if (id == null && StrUtils.isBlank(name)) @@ -47,6 +48,10 @@ public class GameProfile { return id != null && StrUtils.isNotBlank(name); } + public boolean isLegacy() { + return legacy; + } + @Override public int hashCode() { int hash = 7; diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/YggdrasilAuthentication.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/YggdrasilAuthentication.java index 17f11de54..1129f43c9 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/YggdrasilAuthentication.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/auth/yggdrasil/YggdrasilAuthentication.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import org.jackhuang.hellominecraft.util.ArrayUtils; import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.log.HMCLog; import org.jackhuang.hellominecraft.util.net.NetUtils; @@ -36,13 +37,14 @@ import org.jackhuang.hellominecraft.util.StrUtils; public class YggdrasilAuthentication { public static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(GameProfile.class, new GameProfile.GameProfileSerializer()) - .registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()) - .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create(); + .registerTypeAdapter(GameProfile.class, new GameProfile.GameProfileSerializer()) + .registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()) + .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create(); protected static final String BASE_URL = "https://authserver.mojang.com/"; protected static final URL ROUTE_AUTHENTICATE = NetUtils.constantURL(BASE_URL + "authenticate"); protected static final URL ROUTE_REFRESH = NetUtils.constantURL(BASE_URL + "refresh"); + protected static final URL ROUTE_VALIDATE = NetUtils.constantURL(BASE_URL + "validate"); protected static final String STORAGE_KEY_ACCESS_TOKEN = "accessToken"; protected static final String STORAGE_KEY_PROFILE_NAME = "displayName"; @@ -57,6 +59,7 @@ public class YggdrasilAuthentication { private final PropertyMap userProperties = new PropertyMap(); private String userid, username, password, accessToken; + private UserType userType; private GameProfile selectedProfile; private GameProfile[] profiles; private boolean isOnline; @@ -106,6 +109,10 @@ public class YggdrasilAuthentication { return this.accessToken; } + public String getClientToken() { + return clientToken; + } + // // public boolean canPlayOnline() { @@ -130,21 +137,48 @@ public class YggdrasilAuthentication { userid = username; else throw new AuthenticationException(C.i18n("login.invalid_uuid_and_username")); - - loggedIn(ROUTE_REFRESH, new RefreshRequest(getAuthenticatedToken(), clientToken)); + if (checkTokenValidity()) { + isOnline = true; + return; + } + logInImpl(ROUTE_REFRESH, new RefreshRequest(getAuthenticatedToken(), clientToken)); } else if (StrUtils.isNotBlank(password)) - loggedIn(ROUTE_AUTHENTICATE, new AuthenticationRequest(username, password, clientToken)); + logInImpl(ROUTE_AUTHENTICATE, new AuthenticationRequest(username, password, clientToken)); else throw new AuthenticationException(C.i18n("login.invalid_password")); } - private void loggedIn(URL url, Object input) throws AuthenticationException { + private void logInImpl(URL url, Object input) throws AuthenticationException { + Response response = makeRequest(url, input, Response.class); + + if (!clientToken.equals(response.clientToken)) + throw new AuthenticationException(C.i18n("login.changed_client_token")); + + if (response.selectedProfile != null) + userType = UserType.byLegacy(response.selectedProfile.isLegacy()); + else if (ArrayUtils.isNotEmpty(response.availableProfiles)) + userType = UserType.byLegacy(response.availableProfiles[0].isLegacy()); + + User user = response.user; + userid = user != null && user.getId() != null ? user.getId() : username; + + isOnline = true; + profiles = response.availableProfiles; + selectedProfile = response.selectedProfile; + userProperties.clear(); + this.accessToken = response.accessToken; + + if (user != null && user.getProperties() != null) + userProperties.putAll(user.getProperties()); + } + + protected T makeRequest(URL url, Object input, Class clazz) + throws AuthenticationException { try { String jsonResult = input == null ? NetUtils.get(url, proxy) : NetUtils.post(url, GSON.toJson(input), "application/json", proxy); - Response response = (Response) GSON.fromJson(jsonResult, Response.class); - + T response = (T) GSON.fromJson(jsonResult, clazz); if (response == null) - throw new AuthenticationException("No valid response here"); + return null; if (StrUtils.isNotBlank(response.error)) { HMCLog.err("Failed to log in, the auth server returned an error: " + response.error + ", message: " + response.errorMessage + ", cause: " + response.cause); @@ -153,25 +187,22 @@ public class YggdrasilAuthentication { throw new AuthenticationException("Request error: " + response.errorMessage); } - if (!clientToken.equals(response.clientToken)) - throw new AuthenticationException(C.i18n("login.changed_client_token")); - - User user = response.user; - userid = user != null && user.getId() != null ? user.getId() : username; - - isOnline = true; - profiles = response.availableProfiles; - selectedProfile = response.selectedProfile; - userProperties.clear(); - this.accessToken = response.accessToken; - - if (user != null && user.getProperties() != null) - userProperties.putAll(user.getProperties()); + return response; } catch (IOException | IllegalStateException | JsonParseException e) { throw new AuthenticationException(C.i18n("login.failed.connect_authentication_server"), e); } } + protected boolean checkTokenValidity() { + ValidateRequest request = new ValidateRequest(this); + try { + makeRequest(ROUTE_VALIDATE, request, Response.class); + return true; + } catch (AuthenticationException ex) { + return false; + } + } + public void logOut() { password = null; userid = null; @@ -207,9 +238,9 @@ public class YggdrasilAuthentication { } this.accessToken = (String) credentials.get(STORAGE_KEY_ACCESS_TOKEN); - } catch(Exception e) { + } catch (Exception e) { HMCLog.err("Failed to load yggdrasil authenticator settings, maybe its format is malformed.", e); - + logOut(); } } diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java index 9a5ac015b..08b2e2e17 100644 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/LibraryDownloadInfo.java @@ -37,7 +37,7 @@ public class LibraryDownloadInfo extends GameDownloadInfo { public String getUrl(DownloadType dt, boolean allowSelf) { String myURL = (forgeURL == null ? dt.getProvider().getLibraryDownloadURL() : forgeURL); if (StrUtils.isNotBlank(url) && allowSelf) - myURL = url; + myURL = dt.getProvider().getParsedDownloadURL(url); if (!myURL.endsWith(".jar")) if (path == null) return null; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Profile.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Profile.java index 73c8780eb..841096b41 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Profile.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/Profile.java @@ -81,19 +81,15 @@ public final class Profile { return launcher; } - private transient final VersionSetting defaultVersionSetting = new VersionSetting(); - public VersionSetting getSelectedVersionSetting() { - VersionSetting vs = getVersionSetting(getSelectedVersion()); - if (vs == null) - vs = defaultVersionSetting; - return vs; + return getVersionSetting(getSelectedVersion()); } public VersionSetting getVersionSetting(String id) { VersionSetting vs = ((HMCLMinecraftService) service()).getVersionSetting(id); if (vs == null || vs.isUsesGlobal()) { global.isGlobal = true; + global.id = id; return global; } else return vs; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/VersionSetting.java index 8f9d4157b..b34f18399 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/VersionSetting.java @@ -90,8 +90,7 @@ public class VersionSetting { public transient final EventHandler propertyChanged = new EventHandler<>(this); public VersionSetting() { - fullscreen = false; - usesGlobal = true; + fullscreen = usesGlobal = false; launcherVisibility = 1; gameDirType = 0; javaDir = java = minecraftArgs = serverIp = precalledCommand = wrapper = "";