diff --git a/LaunchServer/runtime/api.js b/LaunchServer/runtime/api.js
old mode 120000
new mode 100644
diff --git a/Launcher.stringer b/Launcher.stringer
index 5934982..5bdfae7 100644
--- a/Launcher.stringer
+++ b/Launcher.stringer
@@ -10,14 +10,12 @@
true
glob:launcher/**
- glob:com/mojang/authlib/**
filter
glob:launcher/**
- glob:com/mojang/authlib/**
@@ -27,7 +25,6 @@
false
glob:launcher/**
- glob:com/mojang/authlib/**
diff --git a/Launcher/source-authlib/minecraft/MinecraftProfileTexture.java b/Launcher/source-authlib/minecraft/MinecraftProfileTexture.java
index 0d8434c..c3e30a6 100644
--- a/Launcher/source-authlib/minecraft/MinecraftProfileTexture.java
+++ b/Launcher/source-authlib/minecraft/MinecraftProfileTexture.java
@@ -1,12 +1,21 @@
package com.mojang.authlib.minecraft;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
public final class MinecraftProfileTexture {
- public static final int PROFILE_TEXTURE_COUNT = Type.values().length;
+ public static final Set PROFILE_TEXTURE_TYPES = Collections.unmodifiableSet(EnumSet.allOf(Type.class));
+ public static final int PROFILE_TEXTURE_COUNT = PROFILE_TEXTURE_TYPES.size();
// Instance
private final String url;
private final String hash;
+ public MinecraftProfileTexture(String url) {
+ this(url, baseName(url));
+ }
+
public MinecraftProfileTexture(String url, String hash) {
this.url = url;
this.hash = hash;
@@ -32,6 +41,19 @@
return url;
}
+ private static String baseName(String url) {
+ String name = url.substring(url.lastIndexOf('/') + 1);
+
+ // Remove index
+ int extensionIndex = name.lastIndexOf('.');
+ if (extensionIndex >= 0) {
+ name = name.substring(0, extensionIndex);
+ }
+
+ // We're done
+ return name;
+ }
+
public enum Type {
SKIN,
CAPE,
diff --git a/Launcher/source-authlib/yggdrasil/LegacyBridge.java b/Launcher/source-authlib/yggdrasil/LegacyBridge.java
index 9d77fd1..30d0d94 100644
--- a/Launcher/source-authlib/yggdrasil/LegacyBridge.java
+++ b/Launcher/source-authlib/yggdrasil/LegacyBridge.java
@@ -69,8 +69,7 @@
}
// Join server
- LogHelper.debug("LegacyBridge.joinServer, Username: '%s', Access token: %s, Server ID: %s",
- username, accessToken, serverID);
+ 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) {
diff --git a/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java
index 99c3356..281bbe7 100644
--- a/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java
+++ b/Launcher/source-authlib/yggdrasil/YggdrasilMinecraftSessionService.java
@@ -1,11 +1,15 @@
package com.mojang.authlib.yggdrasil;
import java.net.InetAddress;
+import java.util.Base64;
import java.util.EnumMap;
-import java.util.Iterator;
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.mojang.authlib.AuthenticationService;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
@@ -17,6 +21,7 @@
import com.mojang.authlib.properties.PropertyMap;
import launcher.client.ClientLauncher;
import launcher.client.PlayerProfile;
+import launcher.helper.IOHelper;
import launcher.helper.LogHelper;
import launcher.helper.SecurityHelper;
import launcher.request.auth.CheckServerRequest;
@@ -69,21 +74,25 @@
// Add textures
if (!NO_TEXTURES) {
// 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));
+ Property skinURL = Iterables.getFirst(profile.getProperties().get(ClientLauncher.SKIN_URL_PROPERTY), null);
+ Property skinDigest = Iterables.getFirst(profile.getProperties().get(ClientLauncher.SKIN_DIGEST_PROPERTY), null);
+ if (skinURL != null && skinDigest != null) {
+ textures.put(Type.SKIN, new MinecraftProfileTexture(skinURL.getValue(), skinDigest.getValue()));
}
// 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));
+ Property cloakURL = Iterables.getFirst(profile.getProperties().get(ClientLauncher.CLOAK_URL_PROPERTY), null);
+ Property cloakDigest = Iterables.getFirst(profile.getProperties().get(ClientLauncher.CLOAK_DIGEST_PROPERTY), null);
+ if (cloakURL != null && cloakDigest != null) {
+ textures.put(Type.CAPE, new MinecraftProfileTexture(cloakURL.getValue(), cloakDigest.getValue()));
+ }
+
+ // Try to find missing textures in textures payload (now always true because launcher is not passing elytra skins)
+ 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());
+ }
}
}
@@ -163,4 +172,33 @@
fillTextureProperties(profile, pp);
return profile;
}
+
+ private static void getTexturesMojang(Map textures, String texturesBase64, String username) {
+ // 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();
+ } catch (Exception ignored) {
+ LogHelper.error("Could not decode textures payload, username: '%s'", username);
+ return;
+ }
+
+ // Fetch textures from textures JSON
+ for (Type type : MinecraftProfileTexture.PROFILE_TEXTURE_TYPES) {
+ if (textures.containsKey(type)) {
+ continue; // Overriden by launcher
+ }
+
+ // 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()));
+ }
+ }
+ }
+ }
}
diff --git a/compat/BungeeCord.patch b/compat/BungeeCord.patch
index c5f2cb3..897c6ba 100644
--- a/compat/BungeeCord.patch
+++ b/compat/BungeeCord.patch
@@ -3,7 +3,7 @@
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
---- bootstrap/pom.xml (revision 53cc3242e1d2786c34b2e138d233c4eeca8e3b1d)
+--- bootstrap/pom.xml (revision 16d261553c1a648ce38101bda19b7166d1ca5a41)
+++ bootstrap/pom.xml (revision )
@@ -57,7 +57,8 @@
@@ -20,14 +20,24 @@
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
---- proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java (revision 53cc3242e1d2786c34b2e138d233c4eeca8e3b1d)
+--- proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java (revision 16d261553c1a648ce38101bda19b7166d1ca5a41)
+++ proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java (revision )
-@@ -8,10 +8,13 @@
+@@ -2,6 +2,7 @@
+
+ import com.google.common.base.Charsets;
+ import com.google.common.base.Preconditions;
++import com.google.common.util.concurrent.ThreadFactoryBuilder;
+ import com.google.gson.Gson;
+ import java.math.BigInteger;
+ import java.net.InetAddress;
+@@ -9,10 +10,15 @@
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
++import java.util.concurrent.ExecutorService;
++import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.crypto.SecretKey;
@@ -36,7 +46,16 @@
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.BungeeCord;
-@@ -261,7 +264,7 @@
+@@ -103,6 +109,8 @@
+ private boolean legacy;
+ @Getter
+ private String extraDataInHandshake = "";
++ private ExecutorService loginExecutor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().
++ setNameFormat("Login Thread #%1$d").setDaemon(true).build());
+
+ @Override
+ public boolean shouldHandle(PacketWrapper packet) throws Exception
+@@ -263,7 +271,7 @@
this.handshake = handshake;
ch.setVersion( handshake.getProtocolVersion() );
@@ -45,14 +64,15 @@
// with Bungee's IP forwarding, so we detect it, and remove it from the host string, for now.
// We know FML appends \00FML\00. However, we need to also consider that other systems might
// add their own data to the end of the string. So, we just take everything from the \0 character
-@@ -402,35 +405,26 @@
+@@ -404,37 +412,27 @@
{
sha.update( bit );
}
- String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" );
-- String authURL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" + encName + "&serverId=" + encodedHash;
--
+- String preventProxy = ( ( BungeeCord.getInstance().config.isPreventProxyConnections() ) ? "&ip=" + URLEncoder.encode( getAddress().getAddress().getHostAddress(), "UTF-8" ) : "" );
+- String authURL = "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" + encName + "&serverId=" + encodedHash + preventProxy;
+
- Callback handler = new Callback()
- {
- @Override
@@ -61,9 +81,10 @@
- if ( error == null )
- {
- LoginResult obj = BungeeCord.getInstance().gson.fromJson( result, LoginResult.class );
-- if ( obj != null )
+- if ( obj != null && obj.getId() != null )
- {
- loginProfile = obj;
+- name = obj.getName();
- uniqueId = Util.getUUID( obj.getId() );
- finish();
- return;
@@ -75,7 +96,7 @@
- bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", error );
+ final String username = InitialHandler.this.getName();
+ final String serverID = new BigInteger(sha.digest()).toString(16);
-+ ch.getHandle().eventLoop().execute(() -> {
++ loginExecutor.submit(() -> {
+ try {
+ Map properties = LegacyBridge.checkServerWithProperties(username, serverID);
+ if(properties == null) { // Invalid username or serverID
@@ -103,7 +124,7 @@
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
---- bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java (revision 53cc3242e1d2786c34b2e138d233c4eeca8e3b1d)
+--- bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java (revision 16d261553c1a648ce38101bda19b7166d1ca5a41)
+++ bootstrap/src/main/java/net/md_5/bungee/Bootstrap.java (revision )
@@ -5,9 +5,9 @@
@@ -122,7 +143,7 @@
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
---- proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java (revision 53cc3242e1d2786c34b2e138d233c4eeca8e3b1d)
+--- proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java (revision 16d261553c1a648ce38101bda19b7166d1ca5a41)
+++ proxy/src/main/java/net/md_5/bungee/connection/LoginResult.java (revision )
@@ -1,5 +1,8 @@
package net.md_5.bungee.connection;
@@ -133,8 +154,8 @@
import lombok.AllArgsConstructor;
import lombok.Data;
-@@ -11,6 +14,17 @@
- private String id;
+@@ -12,6 +15,17 @@
+ private String name;
private Property[] properties;
+ public LoginResult(Map propertiesMap) {
@@ -156,7 +177,7 @@
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
---- pom.xml (revision 53cc3242e1d2786c34b2e138d233c4eeca8e3b1d)
+--- pom.xml (revision 16d261553c1a648ce38101bda19b7166d1ca5a41)
+++ pom.xml (revision )
@@ -67,8 +67,8 @@
@@ -176,7 +197,7 @@
+
+ launcher
+ clientside
-+ 13.4+
++ 15.4+
+ system
+ /full/path/to/Launcher.jar
+
diff --git a/compat/authlib/authlib-clean.jar b/compat/authlib/authlib-clean.jar
index 4f5361a..15708bb 100644
--- a/compat/authlib/authlib-clean.jar
+++ b/compat/authlib/authlib-clean.jar
Binary files differ