diff --git a/.idea/artifacts/Launcher.xml b/.idea/artifacts/Launcher.xml index 4610f79..09af903 100644 --- a/.idea/artifacts/Launcher.xml +++ b/.idea/artifacts/Launcher.xml @@ -7,6 +7,7 @@ + \ No newline at end of file diff --git a/.idea/artifacts/LauncherAuthlib.xml b/.idea/artifacts/LauncherAuthlib.xml deleted file mode 100644 index 4775b7d..0000000 --- a/.idea/artifacts/LauncherAuthlib.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - $PROJECT_DIR$/ - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 78ef274..6d11769 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -4,7 +4,6 @@ - \ No newline at end of file diff --git a/LaunchServer/LaunchServer.iml b/LaunchServer/LaunchServer.iml index 1e1f432..6c20146 100644 --- a/LaunchServer/LaunchServer.iml +++ b/LaunchServer/LaunchServer.iml @@ -9,7 +9,7 @@ - + @@ -18,9 +18,9 @@ - - - + + + diff --git a/Launcher.pro b/Launcher.pro index 11b76aa..6ea75d3 100644 --- a/Launcher.pro +++ b/Launcher.pro @@ -1,5 +1,7 @@ -injars 'Launcher.jar' -outjars 'Launcher-obf.jar' +-libraryjars 'build/libraries/obf' +-libraryjars 'build/libraries/guava-17.0.jar' -libraryjars 'build/libraries/jansi-1.11.jar' -libraryjars '/lib/rt.jar' -libraryjars '/lib/jce.jar' @@ -24,9 +26,9 @@ -renamesourcefileattribute SourceFile -adaptresourcefilecontents META-INF/MANIFEST.MF --keeppackagenames com.eclipsesource.json.** +-keeppackagenames com.eclipsesource.json.**,com.mojang.** --keep class com.eclipsesource.json.** { +-keep class com.eclipsesource.json.**,com.mojang.** { ; ; } diff --git a/Launcher.stringer b/Launcher.stringer index 7fd8144..8918ace 100644 --- a/Launcher.stringer +++ b/Launcher.stringer @@ -2,17 +2,22 @@ true none - build/dictionary.pro - - - glob:launcher/** - - - - - true - false - false - - + build/mapping.pro + + + + filter + true + + + filter + + + filter + true + false + false + + + diff --git a/Launcher/Launcher.iml b/Launcher/Launcher.iml index 21cb0d9..8bc22bc 100644 --- a/Launcher/Launcher.iml +++ b/Launcher/Launcher.iml @@ -5,10 +5,29 @@ + - + + + + + + + + + + + + + + + + + + + diff --git a/Launcher/MANIFEST.MF b/Launcher/MANIFEST.MF index 60cd9e0..752edd1 100644 --- a/Launcher/MANIFEST.MF +++ b/Launcher/MANIFEST.MF @@ -3,3 +3,10 @@ Name: launcher/ Sealed: true + +Name: com/mojang/authlib/ +Sealed: true + +Name: com/mojang/util/ +Sealed: true + diff --git a/Launcher/source-authlib/minecraft/MinecraftProfileTexture.java b/Launcher/source-authlib/minecraft/MinecraftProfileTexture.java new file mode 100644 index 0000000..0d8434c --- /dev/null +++ b/Launcher/source-authlib/minecraft/MinecraftProfileTexture.java @@ -0,0 +1,40 @@ +package com.mojang.authlib.minecraft; + +public final class MinecraftProfileTexture { + public static final int PROFILE_TEXTURE_COUNT = Type.values().length; + + // Instance + private final String url; + private final String hash; + + public MinecraftProfileTexture(String url, String hash) { + this.url = url; + this.hash = hash; + } + + @Override + public String toString() { + return String.format("MinecraftProfileTexture{url='%s',hash=%s}", url, hash); + } + + @SuppressWarnings("unused") + public String getHash() { + return hash; + } + + @SuppressWarnings({ "unused", "SameReturnValue" }) + public String getMetadata(String key) { + return null; + } + + @SuppressWarnings("unused") + public String getUrl() { + return url; + } + + public enum Type { + SKIN, + CAPE, + ELYTRA + } +} diff --git a/Launcher/source-authlib/yggdrasil/LegacyBridge.java b/Launcher/source-authlib/yggdrasil/LegacyBridge.java new file mode 100644 index 0000000..018f669 --- /dev/null +++ b/Launcher/source-authlib/yggdrasil/LegacyBridge.java @@ -0,0 +1,49 @@ +package com.mojang.authlib.yggdrasil; + +import launcher.client.ClientLauncher; +import launcher.helper.CommonHelper; +import launcher.helper.IOHelper; +import launcher.helper.LogHelper; +import launcher.request.auth.CheckServerRequest; +import launcher.request.auth.JoinServerRequest; + +public final class LegacyBridge { + private LegacyBridge() { + } + + @SuppressWarnings("unused") + public static boolean checkServer(String username, String serverID) throws Exception { + LogHelper.debug("LegacyBridge.checkServer, Username: '%s', Server ID: %s", username, serverID); + return new CheckServerRequest(username, serverID).request() != null; + } + + @SuppressWarnings("unused") + public static String getCloakURL(String username) { + LogHelper.debug("LegacyBridge.getCloakURL: '%s'", username); + return CommonHelper.replace(System.getProperty("launcher.legacy.cloaksURL", + "http://skins.minecraft.net/MinecraftCloaks/%username%.png"), "username", IOHelper.urlEncode(username)); + } + + @SuppressWarnings("unused") + public static String getSkinURL(String username) { + LogHelper.debug("LegacyBridge.getSkinURL: '%s'", username); + return CommonHelper.replace(System.getProperty("launcher.legacy.skinsURL", + "http://skins.minecraft.net/MinecraftSkins/%username%.png"), "username", IOHelper.urlEncode(username)); + } + + @SuppressWarnings("unused") + public static String joinServer(String username, String accessToken, String serverID) { + if (!ClientLauncher.isLaunched()) { + return "Bad Login (Cheater)"; + } + + // Join server + LogHelper.debug("LegacyBridge.joinServer, Username: '%s', Access token: %s, Server ID: %s", + username, accessToken, serverID); + try { + return new JoinServerRequest(username, accessToken, serverID).request() ? "OK" : "Bad Login (Clientside)"; + } catch (Exception e) { + return e.toString(); + } + } +} diff --git a/Launcher/source-authlib/yggdrasil/YggdrasilAuthenticationService.java b/Launcher/source-authlib/yggdrasil/YggdrasilAuthenticationService.java new file mode 100644 index 0000000..d30bfde --- /dev/null +++ b/Launcher/source-authlib/yggdrasil/YggdrasilAuthenticationService.java @@ -0,0 +1,32 @@ +package com.mojang.authlib.yggdrasil; + +import java.net.Proxy; + +import com.mojang.authlib.Agent; +import com.mojang.authlib.AuthenticationService; +import com.mojang.authlib.GameProfileRepository; +import com.mojang.authlib.UserAuthentication; +import com.mojang.authlib.minecraft.MinecraftSessionService; +import launcher.helper.LogHelper; + +public final class YggdrasilAuthenticationService implements AuthenticationService { + @SuppressWarnings("UnusedParameters") + public YggdrasilAuthenticationService(Proxy proxy, String clientToken) { + LogHelper.debug("Patched AuthenticationService created: '%s'", clientToken); + } + + @Override + public MinecraftSessionService createMinecraftSessionService() { + return new YggdrasilMinecraftSessionService(this); + } + + @Override + public GameProfileRepository createProfileRepository() { + return new YggdrasilGameProfileRepository(); + } + + @Override + public UserAuthentication createUserAuthentication(Agent agent) { + throw new UnsupportedOperationException("createUserAuthentication is used only by Mojang Launcher"); + } +} diff --git a/Launcher/source-authlib/yggdrasil/YggdrasilGameProfileRepository.java b/Launcher/source-authlib/yggdrasil/YggdrasilGameProfileRepository.java new file mode 100644 index 0000000..1232bad --- /dev/null +++ b/Launcher/source-authlib/yggdrasil/YggdrasilGameProfileRepository.java @@ -0,0 +1,76 @@ +package com.mojang.authlib.yggdrasil; + +import java.util.Arrays; +import java.util.UUID; + +import com.mojang.authlib.Agent; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.GameProfileRepository; +import com.mojang.authlib.ProfileLookupCallback; +import launcher.client.PlayerProfile; +import launcher.helper.LogHelper; +import launcher.helper.VerifyHelper; +import launcher.request.uuid.BatchProfileByUsernameRequest; + +public final class YggdrasilGameProfileRepository implements GameProfileRepository { + private static final long BUSY_WAIT_MS = VerifyHelper.verifyLong( + Long.parseLong(System.getProperty("launcher.authlib.busyWait", Long.toString(100L))), + VerifyHelper.L_NOT_NEGATIVE, "launcher.authlib.busyWait can't be < 0"); + private static final long ERROR_BUSY_WAIT_MS = VerifyHelper.verifyLong( + Long.parseLong(System.getProperty("launcher.authlib.errorBusyWait", Long.toString(500L))), + VerifyHelper.L_NOT_NEGATIVE, "launcher.authlib.errorBusyWait can't be < 0"); + + public YggdrasilGameProfileRepository() { + LogHelper.debug("Patched GameProfileRepository created"); + } + + @Override + public void findProfilesByNames(String[] usernames, Agent agent, ProfileLookupCallback callback) { + int offset = 0; + while (offset < usernames.length) { + String[] sliceUsernames = Arrays.copyOfRange(usernames, offset, Math.min(offset + BatchProfileByUsernameRequest.MAX_BATCH_SIZE, usernames.length)); + offset += BatchProfileByUsernameRequest.MAX_BATCH_SIZE; + + // Batch Username-To-UUID request + PlayerProfile[] sliceProfiles; + try { + sliceProfiles = new BatchProfileByUsernameRequest(sliceUsernames).request(); + } catch (Exception e) { + for (String username : sliceUsernames) { + LogHelper.debug("Couldn't find profile '%s': %s", username, e); + callback.onProfileLookupFailed(new GameProfile((UUID) null, username), e); + } + + // Busy wait, like in standard authlib + busyWait(ERROR_BUSY_WAIT_MS); + continue; + } + + // Request succeeded! + for (int i = 0; i < sliceProfiles.length; i++) { + PlayerProfile pp = sliceProfiles[i]; + if (pp == null) { + String username = sliceUsernames[i]; + LogHelper.debug("Couldn't find profile '%s'", username); + callback.onProfileLookupFailed(new GameProfile((UUID) null, username), new ProfileNotFoundException("Server did not find the requested profile")); + continue; + } + + // Report as looked up + LogHelper.debug("Successfully looked up profile '%s'", pp.username); + callback.onProfileLookupSucceeded(YggdrasilMinecraftSessionService.toGameProfile(pp)); + } + + // Busy wait, like in standard authlib + busyWait(BUSY_WAIT_MS); + } + } + + private static void busyWait(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + LogHelper.error(e); + } + } +} diff --git a/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java new file mode 100644 index 0000000..8342dc9 --- /dev/null +++ b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java @@ -0,0 +1,153 @@ +package com.mojang.authlib.yggdrasil; + +import java.net.InetAddress; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +import com.mojang.authlib.AuthenticationService; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.exceptions.AuthenticationException; +import com.mojang.authlib.exceptions.AuthenticationUnavailableException; +import com.mojang.authlib.minecraft.BaseMinecraftSessionService; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; +import launcher.client.ClientLauncher; +import launcher.client.PlayerProfile; +import launcher.helper.LogHelper; +import launcher.helper.SecurityHelper; +import launcher.request.auth.CheckServerRequest; +import launcher.request.auth.JoinServerRequest; +import launcher.request.uuid.ProfileByUUIDRequest; + +public final class YggdrasilMinecraftSessionService extends BaseMinecraftSessionService { + public YggdrasilMinecraftSessionService(AuthenticationService service) { + super(service); + LogHelper.debug("Patched MinecraftSessionService created"); + } + + @Override + public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { + // Verify has UUID + UUID uuid = profile.getUUID(); + LogHelper.debug("fillProfileProperties, UUID: %s", uuid); + if (uuid == null) { + return profile; + } + + // Make profile request + PlayerProfile pp; + try { + pp = new ProfileByUUIDRequest(uuid).request(); + } catch (Exception e) { + LogHelper.debug("Couldn't fetch profile properties for '%s': %s", profile, e); + return profile; + } + + // Verify is found + if (pp == null) { + LogHelper.debug("Couldn't fetch profile properties for '%s' as the profile does not exist", profile); + return profile; + } + + // Create new game profile from player profile + LogHelper.debug("Successfully fetched profile properties for '%s'", profile); + fillTextureProperties(profile, pp); + return toGameProfile(pp); + } + + @Override + public Map getTextures(GameProfile profile, boolean requireSecure) { + LogHelper.debug("getTextures, Username: '%s'", profile.getName()); + Map textures = new EnumMap<>(Type.class); + + // Add skin URL to textures map + Iterator skinURL = profile.getProperties().get(ClientLauncher.SKIN_URL_PROPERTY).iterator(); + Iterator skinHash = profile.getProperties().get(ClientLauncher.SKIN_DIGEST_PROPERTY).iterator(); + if (skinURL.hasNext() && skinHash.hasNext()) { + String urlValue = skinURL.next().getValue(); + String hashValue = skinHash.next().getValue(); + textures.put(Type.SKIN, new MinecraftProfileTexture(urlValue, hashValue)); + } + + // Add cloak URL to textures map + Iterator cloakURL = profile.getProperties().get(ClientLauncher.CLOAK_URL_PROPERTY).iterator(); + Iterator cloakHash = profile.getProperties().get(ClientLauncher.CLOAK_DIGEST_PROPERTY).iterator(); + if (cloakURL.hasNext() && cloakHash.hasNext()) { + String urlValue = cloakURL.next().getValue(); + String hashValue = cloakHash.next().getValue(); + textures.put(Type.CAPE, new MinecraftProfileTexture(urlValue, hashValue)); + } + + // Return filled textures + return textures; + } + + @Override + public GameProfile hasJoinedServer(GameProfile profile, String serverID) throws AuthenticationUnavailableException { + String username = profile.getName(); + LogHelper.debug("checkServer, Username: '%s', Server ID: %s", username, serverID); + + // Make checkServer request + PlayerProfile pp; + try { + pp = new CheckServerRequest(username, serverID).request(); + } catch (Exception e) { + LogHelper.error(e); + throw new AuthenticationUnavailableException(e); + } + + // Return profile if found + return pp == null ? null : toGameProfile(pp); + } + + @Override + public GameProfile hasJoinedServer(GameProfile profile, String serverID, InetAddress address) throws AuthenticationUnavailableException { + return hasJoinedServer(profile, serverID); + } + + @Override + public void joinServer(GameProfile profile, String accessToken, String serverID) throws AuthenticationException { + if (!ClientLauncher.isLaunched()) { + throw new AuthenticationException("Bad Login (Cheater)"); + } + + // Join server + String username = profile.getName(); + LogHelper.debug("joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID); + + // Make joinServer request + boolean success; + try { + success = new JoinServerRequest(username, accessToken, serverID).request(); + } catch (Exception e) { + throw new AuthenticationUnavailableException(e); + } + + // Verify is success + if (!success) { + throw new AuthenticationException("Bad Login (Clientside)"); + } + } + + public static void fillTextureProperties(GameProfile profile, PlayerProfile pp) { + PropertyMap properties = profile.getProperties(); + if (pp.skin != null) { + properties.put(ClientLauncher.SKIN_URL_PROPERTY, new Property(ClientLauncher.SKIN_URL_PROPERTY, pp.skin.url, "")); + properties.put(ClientLauncher.SKIN_DIGEST_PROPERTY, new Property(ClientLauncher.SKIN_DIGEST_PROPERTY, SecurityHelper.toHex(pp.skin.digest), "")); + } + if (pp.cloak != null) { + properties.put(ClientLauncher.CLOAK_URL_PROPERTY, new Property(ClientLauncher.CLOAK_URL_PROPERTY, pp.cloak.url, "")); + properties.put(ClientLauncher.CLOAK_DIGEST_PROPERTY, new Property(ClientLauncher.CLOAK_DIGEST_PROPERTY, SecurityHelper.toHex(pp.cloak.digest), "")); + } + } + + public static GameProfile toGameProfile(PlayerProfile pp) { + GameProfile profile = new GameProfile(pp.uuid, pp.username); + fillTextureProperties(profile, pp); + return profile; + } +} diff --git a/LauncherAuthlib/LauncherAuthlib.iml b/LauncherAuthlib/LauncherAuthlib.iml deleted file mode 100644 index af1f8b3..0000000 --- a/LauncherAuthlib/LauncherAuthlib.iml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/LauncherAuthlib/MANIFEST.MF b/LauncherAuthlib/MANIFEST.MF deleted file mode 100644 index 2263df0..0000000 --- a/LauncherAuthlib/MANIFEST.MF +++ /dev/null @@ -1,7 +0,0 @@ -Manifest-Version: 1.0 - -Name: com/mojang/authlib/ -Sealed: true - -Name: com/mojang/util/ -Sealed: true diff --git a/LauncherAuthlib/source/minecraft/MinecraftProfileTexture.java b/LauncherAuthlib/source/minecraft/MinecraftProfileTexture.java deleted file mode 100644 index 0d8434c..0000000 --- a/LauncherAuthlib/source/minecraft/MinecraftProfileTexture.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.mojang.authlib.minecraft; - -public final class MinecraftProfileTexture { - public static final int PROFILE_TEXTURE_COUNT = Type.values().length; - - // Instance - private final String url; - private final String hash; - - public MinecraftProfileTexture(String url, String hash) { - this.url = url; - this.hash = hash; - } - - @Override - public String toString() { - return String.format("MinecraftProfileTexture{url='%s',hash=%s}", url, hash); - } - - @SuppressWarnings("unused") - public String getHash() { - return hash; - } - - @SuppressWarnings({ "unused", "SameReturnValue" }) - public String getMetadata(String key) { - return null; - } - - @SuppressWarnings("unused") - public String getUrl() { - return url; - } - - public enum Type { - SKIN, - CAPE, - ELYTRA - } -} diff --git a/LauncherAuthlib/source/yggdrasil/LegacyBridge.java b/LauncherAuthlib/source/yggdrasil/LegacyBridge.java deleted file mode 100644 index 018f669..0000000 --- a/LauncherAuthlib/source/yggdrasil/LegacyBridge.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.mojang.authlib.yggdrasil; - -import launcher.client.ClientLauncher; -import launcher.helper.CommonHelper; -import launcher.helper.IOHelper; -import launcher.helper.LogHelper; -import launcher.request.auth.CheckServerRequest; -import launcher.request.auth.JoinServerRequest; - -public final class LegacyBridge { - private LegacyBridge() { - } - - @SuppressWarnings("unused") - public static boolean checkServer(String username, String serverID) throws Exception { - LogHelper.debug("LegacyBridge.checkServer, Username: '%s', Server ID: %s", username, serverID); - return new CheckServerRequest(username, serverID).request() != null; - } - - @SuppressWarnings("unused") - public static String getCloakURL(String username) { - LogHelper.debug("LegacyBridge.getCloakURL: '%s'", username); - return CommonHelper.replace(System.getProperty("launcher.legacy.cloaksURL", - "http://skins.minecraft.net/MinecraftCloaks/%username%.png"), "username", IOHelper.urlEncode(username)); - } - - @SuppressWarnings("unused") - public static String getSkinURL(String username) { - LogHelper.debug("LegacyBridge.getSkinURL: '%s'", username); - return CommonHelper.replace(System.getProperty("launcher.legacy.skinsURL", - "http://skins.minecraft.net/MinecraftSkins/%username%.png"), "username", IOHelper.urlEncode(username)); - } - - @SuppressWarnings("unused") - public static String joinServer(String username, String accessToken, String serverID) { - if (!ClientLauncher.isLaunched()) { - return "Bad Login (Cheater)"; - } - - // Join server - LogHelper.debug("LegacyBridge.joinServer, Username: '%s', Access token: %s, Server ID: %s", - username, accessToken, serverID); - try { - return new JoinServerRequest(username, accessToken, serverID).request() ? "OK" : "Bad Login (Clientside)"; - } catch (Exception e) { - return e.toString(); - } - } -} diff --git a/LauncherAuthlib/source/yggdrasil/YggdrasilAuthenticationService.java b/LauncherAuthlib/source/yggdrasil/YggdrasilAuthenticationService.java deleted file mode 100644 index d30bfde..0000000 --- a/LauncherAuthlib/source/yggdrasil/YggdrasilAuthenticationService.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mojang.authlib.yggdrasil; - -import java.net.Proxy; - -import com.mojang.authlib.Agent; -import com.mojang.authlib.AuthenticationService; -import com.mojang.authlib.GameProfileRepository; -import com.mojang.authlib.UserAuthentication; -import com.mojang.authlib.minecraft.MinecraftSessionService; -import launcher.helper.LogHelper; - -public final class YggdrasilAuthenticationService implements AuthenticationService { - @SuppressWarnings("UnusedParameters") - public YggdrasilAuthenticationService(Proxy proxy, String clientToken) { - LogHelper.debug("Patched AuthenticationService created: '%s'", clientToken); - } - - @Override - public MinecraftSessionService createMinecraftSessionService() { - return new YggdrasilMinecraftSessionService(this); - } - - @Override - public GameProfileRepository createProfileRepository() { - return new YggdrasilGameProfileRepository(); - } - - @Override - public UserAuthentication createUserAuthentication(Agent agent) { - throw new UnsupportedOperationException("createUserAuthentication is used only by Mojang Launcher"); - } -} diff --git a/LauncherAuthlib/source/yggdrasil/YggdrasilGameProfileRepository.java b/LauncherAuthlib/source/yggdrasil/YggdrasilGameProfileRepository.java deleted file mode 100644 index 1232bad..0000000 --- a/LauncherAuthlib/source/yggdrasil/YggdrasilGameProfileRepository.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.mojang.authlib.yggdrasil; - -import java.util.Arrays; -import java.util.UUID; - -import com.mojang.authlib.Agent; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.GameProfileRepository; -import com.mojang.authlib.ProfileLookupCallback; -import launcher.client.PlayerProfile; -import launcher.helper.LogHelper; -import launcher.helper.VerifyHelper; -import launcher.request.uuid.BatchProfileByUsernameRequest; - -public final class YggdrasilGameProfileRepository implements GameProfileRepository { - private static final long BUSY_WAIT_MS = VerifyHelper.verifyLong( - Long.parseLong(System.getProperty("launcher.authlib.busyWait", Long.toString(100L))), - VerifyHelper.L_NOT_NEGATIVE, "launcher.authlib.busyWait can't be < 0"); - private static final long ERROR_BUSY_WAIT_MS = VerifyHelper.verifyLong( - Long.parseLong(System.getProperty("launcher.authlib.errorBusyWait", Long.toString(500L))), - VerifyHelper.L_NOT_NEGATIVE, "launcher.authlib.errorBusyWait can't be < 0"); - - public YggdrasilGameProfileRepository() { - LogHelper.debug("Patched GameProfileRepository created"); - } - - @Override - public void findProfilesByNames(String[] usernames, Agent agent, ProfileLookupCallback callback) { - int offset = 0; - while (offset < usernames.length) { - String[] sliceUsernames = Arrays.copyOfRange(usernames, offset, Math.min(offset + BatchProfileByUsernameRequest.MAX_BATCH_SIZE, usernames.length)); - offset += BatchProfileByUsernameRequest.MAX_BATCH_SIZE; - - // Batch Username-To-UUID request - PlayerProfile[] sliceProfiles; - try { - sliceProfiles = new BatchProfileByUsernameRequest(sliceUsernames).request(); - } catch (Exception e) { - for (String username : sliceUsernames) { - LogHelper.debug("Couldn't find profile '%s': %s", username, e); - callback.onProfileLookupFailed(new GameProfile((UUID) null, username), e); - } - - // Busy wait, like in standard authlib - busyWait(ERROR_BUSY_WAIT_MS); - continue; - } - - // Request succeeded! - for (int i = 0; i < sliceProfiles.length; i++) { - PlayerProfile pp = sliceProfiles[i]; - if (pp == null) { - String username = sliceUsernames[i]; - LogHelper.debug("Couldn't find profile '%s'", username); - callback.onProfileLookupFailed(new GameProfile((UUID) null, username), new ProfileNotFoundException("Server did not find the requested profile")); - continue; - } - - // Report as looked up - LogHelper.debug("Successfully looked up profile '%s'", pp.username); - callback.onProfileLookupSucceeded(YggdrasilMinecraftSessionService.toGameProfile(pp)); - } - - // Busy wait, like in standard authlib - busyWait(BUSY_WAIT_MS); - } - } - - private static void busyWait(long ms) { - try { - Thread.sleep(ms); - } catch (InterruptedException e) { - LogHelper.error(e); - } - } -} diff --git a/LauncherAuthlib/source/yggdrasil/YggdrasilMinecraftSessionService.java b/LauncherAuthlib/source/yggdrasil/YggdrasilMinecraftSessionService.java deleted file mode 100644 index 8342dc9..0000000 --- a/LauncherAuthlib/source/yggdrasil/YggdrasilMinecraftSessionService.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.mojang.authlib.yggdrasil; - -import java.net.InetAddress; -import java.util.EnumMap; -import java.util.Iterator; -import java.util.Map; -import java.util.UUID; - -import com.mojang.authlib.AuthenticationService; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.exceptions.AuthenticationException; -import com.mojang.authlib.exceptions.AuthenticationUnavailableException; -import com.mojang.authlib.minecraft.BaseMinecraftSessionService; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; -import com.mojang.authlib.properties.Property; -import com.mojang.authlib.properties.PropertyMap; -import launcher.client.ClientLauncher; -import launcher.client.PlayerProfile; -import launcher.helper.LogHelper; -import launcher.helper.SecurityHelper; -import launcher.request.auth.CheckServerRequest; -import launcher.request.auth.JoinServerRequest; -import launcher.request.uuid.ProfileByUUIDRequest; - -public final class YggdrasilMinecraftSessionService extends BaseMinecraftSessionService { - public YggdrasilMinecraftSessionService(AuthenticationService service) { - super(service); - LogHelper.debug("Patched MinecraftSessionService created"); - } - - @Override - public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) { - // Verify has UUID - UUID uuid = profile.getUUID(); - LogHelper.debug("fillProfileProperties, UUID: %s", uuid); - if (uuid == null) { - return profile; - } - - // Make profile request - PlayerProfile pp; - try { - pp = new ProfileByUUIDRequest(uuid).request(); - } catch (Exception e) { - LogHelper.debug("Couldn't fetch profile properties for '%s': %s", profile, e); - return profile; - } - - // Verify is found - if (pp == null) { - LogHelper.debug("Couldn't fetch profile properties for '%s' as the profile does not exist", profile); - return profile; - } - - // Create new game profile from player profile - LogHelper.debug("Successfully fetched profile properties for '%s'", profile); - fillTextureProperties(profile, pp); - return toGameProfile(pp); - } - - @Override - public Map getTextures(GameProfile profile, boolean requireSecure) { - LogHelper.debug("getTextures, Username: '%s'", profile.getName()); - Map textures = new EnumMap<>(Type.class); - - // Add skin URL to textures map - Iterator skinURL = profile.getProperties().get(ClientLauncher.SKIN_URL_PROPERTY).iterator(); - Iterator skinHash = profile.getProperties().get(ClientLauncher.SKIN_DIGEST_PROPERTY).iterator(); - if (skinURL.hasNext() && skinHash.hasNext()) { - String urlValue = skinURL.next().getValue(); - String hashValue = skinHash.next().getValue(); - textures.put(Type.SKIN, new MinecraftProfileTexture(urlValue, hashValue)); - } - - // Add cloak URL to textures map - Iterator cloakURL = profile.getProperties().get(ClientLauncher.CLOAK_URL_PROPERTY).iterator(); - Iterator cloakHash = profile.getProperties().get(ClientLauncher.CLOAK_DIGEST_PROPERTY).iterator(); - if (cloakURL.hasNext() && cloakHash.hasNext()) { - String urlValue = cloakURL.next().getValue(); - String hashValue = cloakHash.next().getValue(); - textures.put(Type.CAPE, new MinecraftProfileTexture(urlValue, hashValue)); - } - - // Return filled textures - return textures; - } - - @Override - public GameProfile hasJoinedServer(GameProfile profile, String serverID) throws AuthenticationUnavailableException { - String username = profile.getName(); - LogHelper.debug("checkServer, Username: '%s', Server ID: %s", username, serverID); - - // Make checkServer request - PlayerProfile pp; - try { - pp = new CheckServerRequest(username, serverID).request(); - } catch (Exception e) { - LogHelper.error(e); - throw new AuthenticationUnavailableException(e); - } - - // Return profile if found - return pp == null ? null : toGameProfile(pp); - } - - @Override - public GameProfile hasJoinedServer(GameProfile profile, String serverID, InetAddress address) throws AuthenticationUnavailableException { - return hasJoinedServer(profile, serverID); - } - - @Override - public void joinServer(GameProfile profile, String accessToken, String serverID) throws AuthenticationException { - if (!ClientLauncher.isLaunched()) { - throw new AuthenticationException("Bad Login (Cheater)"); - } - - // Join server - String username = profile.getName(); - LogHelper.debug("joinServer, Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID); - - // Make joinServer request - boolean success; - try { - success = new JoinServerRequest(username, accessToken, serverID).request(); - } catch (Exception e) { - throw new AuthenticationUnavailableException(e); - } - - // Verify is success - if (!success) { - throw new AuthenticationException("Bad Login (Clientside)"); - } - } - - public static void fillTextureProperties(GameProfile profile, PlayerProfile pp) { - PropertyMap properties = profile.getProperties(); - if (pp.skin != null) { - properties.put(ClientLauncher.SKIN_URL_PROPERTY, new Property(ClientLauncher.SKIN_URL_PROPERTY, pp.skin.url, "")); - properties.put(ClientLauncher.SKIN_DIGEST_PROPERTY, new Property(ClientLauncher.SKIN_DIGEST_PROPERTY, SecurityHelper.toHex(pp.skin.digest), "")); - } - if (pp.cloak != null) { - properties.put(ClientLauncher.CLOAK_URL_PROPERTY, new Property(ClientLauncher.CLOAK_URL_PROPERTY, pp.cloak.url, "")); - properties.put(ClientLauncher.CLOAK_DIGEST_PROPERTY, new Property(ClientLauncher.CLOAK_DIGEST_PROPERTY, SecurityHelper.toHex(pp.cloak.digest), "")); - } - } - - public static GameProfile toGameProfile(PlayerProfile pp) { - GameProfile profile = new GameProfile(pp.uuid, pp.username); - fillTextureProperties(profile, pp); - return profile; - } -} diff --git a/build.bat b/build.bat index 33ffc31..6e8a511 100644 --- a/build.bat +++ b/build.bat @@ -6,16 +6,11 @@ java -jar build/proguard.jar @Launcher.pro del Launcher.jar ren Launcher-obf.jar Launcher.jar -pack200 -E9 -Htrue -mlatest -Uerror -r Launcher.jar java -jar build/stringer.jar -configFile Launcher.stringer Launcher.jar Launcher.jar +pack200 -E9 -Htrue -mlatest -Uerror -r Launcher.jar jarsigner -keystore build/sashok724.jks -storepass PSP1004 -sigfile LAUNCHER Launcher.jar sashok724 pack200 Launcher.pack.gz Launcher.jar -REM Build LauncherAuthlib.jar -echo Building LauncherAuthlib.jar... -pack200 -E9 -Htrue -mlatest -Uerror -r LauncherAuthlib.jar -jarsigner -keystore build/sashok724.jks -storepass PSP1004 -sigfile LAUNCHER LauncherAuthlib.jar sashok724 - REM Build LaunchServer.jar echo Building LaunchServer.jar... jar -uf LaunchServer.jar Launcher.pack.gz buildnumber