diff --git a/Launcher.pro b/Launcher.pro index 33c5b5b..688a459 100644 --- a/Launcher.pro +++ b/Launcher.pro @@ -1,8 +1,11 @@ -injars 'Launcher.jar' -outjars 'Launcher-obf.jar' -libraryjars 'build/libraries/obf' +-libraryjars 'build/libraries/gson-2.8.0.jar' -libraryjars 'build/libraries/guava-17.0.jar' -libraryjars 'build/libraries/jansi-1.11.jar' +-libraryjars 'build/libraries/log4j-api-2.8.1.jar' +-libraryjars 'build/libraries/log4j-core-2.8.1.jar' -libraryjars '/lib/rt.jar' -libraryjars '/lib/jce.jar' -libraryjars '/lib/ext/jfxrt.jar' diff --git a/Launcher/Launcher.iml b/Launcher/Launcher.iml index 8bc22bc..1c93b9c 100644 --- a/Launcher/Launcher.iml +++ b/Launcher/Launcher.iml @@ -12,6 +12,15 @@ + + + + + + + + + diff --git a/Launcher/source-authlib/yggdrasil/CompatBridge.java b/Launcher/source-authlib/yggdrasil/CompatBridge.java new file mode 100644 index 0000000..225f00a --- /dev/null +++ b/Launcher/source-authlib/yggdrasil/CompatBridge.java @@ -0,0 +1,63 @@ +package com.mojang.authlib.yggdrasil; + +import java.util.UUID; + +import launcher.LauncherAPI; +import launcher.client.ClientLauncher; +import launcher.client.PlayerProfile; +import launcher.helper.LogHelper; +import launcher.request.auth.CheckServerRequest; +import launcher.request.auth.JoinServerRequest; +import launcher.request.uuid.BatchProfileByUsernameRequest; +import launcher.request.uuid.ProfileByUUIDRequest; +import launcher.request.uuid.ProfileByUsernameRequest; + +// Used to bypass Launcher's class name obfuscation and access API +@LauncherAPI +public final class CompatBridge { + public static final int PROFILES_MAX_BATCH_SIZE = BatchProfileByUsernameRequest.MAX_BATCH_SIZE; + + private CompatBridge() { + } + + @SuppressWarnings("unused") + public static CompatProfile checkServer(String username, String serverID) throws Exception { + LogHelper.debug("CompatBridge.checkServer, Username: '%s', Server ID: %s", username, serverID); + return CompatProfile.fromPlayerProfile(new CheckServerRequest(username, serverID).request()); + } + + @SuppressWarnings("unused") + public static boolean joinServer(String username, String accessToken, String serverID) throws Exception { + if (!ClientLauncher.isLaunched()) { + throw new IllegalStateException("Bad Login (Cheater)"); + } + + // Join server + LogHelper.debug("LegacyBridge.joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID); + return new JoinServerRequest(username, accessToken, serverID).request(); + } + + @SuppressWarnings("unused") + public static CompatProfile profileByUUID(UUID uuid) throws Exception { + return CompatProfile.fromPlayerProfile(new ProfileByUUIDRequest(uuid).request()); + } + + @SuppressWarnings("unused") + public static CompatProfile profileByUsername(String username) throws Exception { + return CompatProfile.fromPlayerProfile(new ProfileByUsernameRequest(username).request()); + } + + @SuppressWarnings("unused") + public static CompatProfile[] profilesByUsername(String... usernames) throws Exception { + PlayerProfile[] profiles = new BatchProfileByUsernameRequest(usernames).request(); + + // Convert profiles + CompatProfile[] resultProfiles = new CompatProfile[profiles.length]; + for (int i = 0; i < profiles.length; i++) { + resultProfiles[i] = CompatProfile.fromPlayerProfile(profiles[i]); + } + + // We're dones + return resultProfiles; + } +} diff --git a/Launcher/source-authlib/yggdrasil/CompatProfile.java b/Launcher/source-authlib/yggdrasil/CompatProfile.java new file mode 100644 index 0000000..6d3a0e3 --- /dev/null +++ b/Launcher/source-authlib/yggdrasil/CompatProfile.java @@ -0,0 +1,33 @@ +package com.mojang.authlib.yggdrasil; + +import java.util.UUID; + +import launcher.client.ClientLauncher; +import launcher.client.PlayerProfile; +import launcher.helper.SecurityHelper; + +public final class CompatProfile { + public final UUID uuid; + public final String uuidHash, username; + public final String skinURL, skinHash; + public final String cloakURL, cloakHash; + + public CompatProfile(UUID uuid, String username, String skinURL, String skinHash, String cloakURL, String cloakHash) { + this.uuid = uuid; + this.uuidHash = ClientLauncher.toHash(uuid); + this.username = username; + this.skinURL = skinURL; + this.skinHash = skinHash; + this.cloakURL = cloakURL; + this.cloakHash = cloakHash; + } + + public static CompatProfile fromPlayerProfile(PlayerProfile profile) { + return profile == null ? null : new CompatProfile(profile.uuid, profile.username, + profile.skin == null ? null : profile.skin.url, + profile.skin == null ? null : SecurityHelper.toHex(profile.skin.digest), + profile.cloak == null ? null : profile.cloak.url, + profile.cloak == null ? null : SecurityHelper.toHex(profile.cloak.digest) + ); + } +} diff --git a/Launcher/source-authlib/yggdrasil/LegacyBridge.java b/Launcher/source-authlib/yggdrasil/LegacyBridge.java index 56a77da..7cb5747 100644 --- a/Launcher/source-authlib/yggdrasil/LegacyBridge.java +++ b/Launcher/source-authlib/yggdrasil/LegacyBridge.java @@ -1,18 +1,14 @@ package com.mojang.authlib.yggdrasil; -import java.util.HashMap; -import java.util.Map; - import launcher.LauncherAPI; import launcher.client.ClientLauncher; -import launcher.client.PlayerProfile; import launcher.helper.CommonHelper; import launcher.helper.IOHelper; import launcher.helper.LogHelper; -import launcher.helper.SecurityHelper; import launcher.request.auth.CheckServerRequest; import launcher.request.auth.JoinServerRequest; +// Used by 1.6.4 and below versions @LauncherAPI public final class LegacyBridge { private LegacyBridge() { @@ -24,30 +20,6 @@ return new CheckServerRequest(username, serverID).request() != null; } - @SuppressWarnings("unused") // Result is user properties (Used by BungeeCord) - public static Map checkServerWithProperties(String username, String serverID) throws Exception { - PlayerProfile pp = new CheckServerRequest(username, serverID).request(); - if (pp == null) { - return null; - } - - // Add properties - Map properties = new HashMap<>(5); - properties.put("uuid", pp.uuid.toString()); - properties.put("uuid-hash", ClientLauncher.toHash(pp.uuid)); - if (pp.skin != null) { - properties.put(ClientLauncher.SKIN_URL_PROPERTY, pp.skin.url); - properties.put(ClientLauncher.SKIN_DIGEST_PROPERTY, SecurityHelper.toHex(pp.skin.digest)); - } - if (pp.cloak != null) { - properties.put(ClientLauncher.CLOAK_URL_PROPERTY, pp.cloak.url); - properties.put(ClientLauncher.CLOAK_DIGEST_PROPERTY, SecurityHelper.toHex(pp.cloak.digest)); - } - - // We're done - return properties; - } - @SuppressWarnings("unused") public static String getCloakURL(String username) { LogHelper.debug("LegacyBridge.getCloakURL: '%s'", username); diff --git a/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java index 3e24a8b..b46d3b5 100644 --- a/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java +++ b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java @@ -6,10 +6,10 @@ import java.util.Map; import java.util.UUID; -import com.eclipsesource.json.Json; -import com.eclipsesource.json.JsonObject; -import com.eclipsesource.json.JsonValue; import com.google.common.collect.Iterables; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.mojang.authlib.AuthenticationService; import com.mojang.authlib.GameProfile; import com.mojang.authlib.exceptions.AuthenticationException; @@ -29,6 +29,7 @@ import launcher.request.uuid.ProfileByUUIDRequest; public final class YggdrasilMinecraftSessionService extends BaseMinecraftSessionService { + public static final JsonParser JSON_PARSER = new JsonParser(); public static final boolean NO_TEXTURES = Boolean.parseBoolean("launcher.authlib.noTextures"); public YggdrasilMinecraftSessionService(AuthenticationService service) { @@ -68,7 +69,7 @@ @Override public Map getTextures(GameProfile profile, boolean requireSecure) { - LogHelper.debug("getTextures, Username: '%s'", profile.getName()); + LogHelper.debug("getTextures, Username: '%s', UUID: '%s'", profile.getName(), profile.getUUID()); Map textures = new EnumMap<>(Type.class); // Add textures @@ -91,7 +92,7 @@ if (textures.size() != MinecraftProfileTexture.PROFILE_TEXTURE_COUNT) { Property texturesMojang = Iterables.getFirst(profile.getProperties().get("textures"), null); if (texturesMojang != null) { - getTexturesMojang(textures, texturesMojang.getValue(), profile.getName()); + getTexturesMojang(textures, texturesMojang.getValue(), profile); } } } @@ -173,14 +174,14 @@ return profile; } - private static void getTexturesMojang(Map textures, String texturesBase64, String username) { + private static void getTexturesMojang(Map textures, String texturesBase64, GameProfile profile) { // Decode textures payload JsonObject texturesJSON; try { byte[] decoded = Base64.getDecoder().decode(texturesBase64); - texturesJSON = Json.parse(new String(decoded, IOHelper.UNICODE_CHARSET)).asObject().get("textures").asObject(); + texturesJSON = JSON_PARSER.parse(new String(decoded, IOHelper.UNICODE_CHARSET)).getAsJsonObject().getAsJsonObject("textures"); } catch (Exception ignored) { - LogHelper.error("Could not decode textures payload, username: '%s'", username); + LogHelper.error("Could not decode textures payload, Username: '%s', UUID: '%s'", profile.getName(), profile.getUUID()); return; } @@ -191,11 +192,11 @@ } // Get texture from JSON - JsonValue textureJSON = texturesJSON.get(type.name()); - if (textureJSON != null && textureJSON.isObject()) { - JsonValue urlValue = textureJSON.asObject().get("url"); - if (urlValue.isString()) { - textures.put(type, new MinecraftProfileTexture(urlValue.asString())); + JsonElement textureJSON = texturesJSON.get(type.name()); + if (textureJSON != null && textureJSON.isJsonObject()) { + JsonElement urlValue = textureJSON.getAsJsonObject().get("url"); + if (urlValue.isJsonPrimitive()) { + textures.put(type, new MinecraftProfileTexture(urlValue.getAsString())); } } }