mirror of
https://github.com/TuxCoding/FastLogin.git
synced 2025-08-01 11:44:44 +02:00
Set UUIDs using MethodHandles
This commit is contained in:
@@ -8,8 +8,11 @@ import com.github.games647.fastlogin.bungee.task.ForceLoginTask;
|
|||||||
import com.github.games647.fastlogin.core.RateLimiter;
|
import com.github.games647.fastlogin.core.RateLimiter;
|
||||||
import com.github.games647.fastlogin.core.StoredProfile;
|
import com.github.games647.fastlogin.core.StoredProfile;
|
||||||
import com.github.games647.fastlogin.core.shared.LoginSession;
|
import com.github.games647.fastlogin.core.shared.LoginSession;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodHandles.Lookup;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
@@ -37,6 +40,26 @@ public class ConnectListener implements Listener {
|
|||||||
|
|
||||||
private final RateLimiter rateLimiter;
|
private final RateLimiter rateLimiter;
|
||||||
|
|
||||||
|
private static final MethodHandle uniqueIdSetter;
|
||||||
|
private static final MethodHandle uniqueIdGetter;
|
||||||
|
|
||||||
|
private static final String UUID_FIELD_NAME = "uniqueId";
|
||||||
|
|
||||||
|
static {
|
||||||
|
MethodHandle setHandle = null;
|
||||||
|
MethodHandle getHandle = null;
|
||||||
|
try {
|
||||||
|
final Lookup lookup = MethodHandles.lookup();
|
||||||
|
setHandle = lookup.findSetter(InitialHandler.class, UUID_FIELD_NAME, UUID.class);
|
||||||
|
getHandle = lookup.findGetter(InitialHandler.class, UUID_FIELD_NAME, UUID.class);
|
||||||
|
} catch (ReflectiveOperationException reflectiveOperationException) {
|
||||||
|
reflectiveOperationException.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
uniqueIdSetter = setHandle;
|
||||||
|
uniqueIdGetter = getHandle;
|
||||||
|
}
|
||||||
|
|
||||||
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter) {
|
public ConnectListener(FastLoginBungee plugin, RateLimiter rateLimiter) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.rateLimiter = rateLimiter;
|
this.rateLimiter = rateLimiter;
|
||||||
@@ -81,31 +104,7 @@ public class ConnectListener implements Listener {
|
|||||||
|
|
||||||
//bungeecord will do this automatically so override it on disabled option
|
//bungeecord will do this automatically so override it on disabled option
|
||||||
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
|
if (!plugin.getCore().getConfig().get("premiumUuid", true)) {
|
||||||
try {
|
setOfflineId(connection, username);
|
||||||
final UUID oldPremiumId = connection.getUniqueId();
|
|
||||||
final UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
|
|
||||||
|
|
||||||
// BungeeCord only allows setting the UUID in PreLogin events and before requesting online mode
|
|
||||||
// However if online mode is requested, it will override previous values
|
|
||||||
// So we have to do it with reflection
|
|
||||||
Field idField = InitialHandler.class.getDeclaredField("uniqueId");
|
|
||||||
idField.setAccessible(true);
|
|
||||||
idField.set(connection, offlineUUID);
|
|
||||||
|
|
||||||
String format = "Overridden UUID from {} to {} (based of {}) on {}";
|
|
||||||
plugin.getLog().info(format, oldPremiumId, offlineUUID, username, connection);
|
|
||||||
|
|
||||||
// check if the field was actually set correctly
|
|
||||||
UUID offlineResult = (UUID) idField.get(connection);
|
|
||||||
UUID connectionResult = connection.getUniqueId();
|
|
||||||
if (!offlineUUID.equals(offlineResult)
|
|
||||||
|| !offlineUUID.equals(connectionResult)) {
|
|
||||||
throw new RuntimeException("Inconsistent UUIDs: expected " + offlineUUID
|
|
||||||
+ " got (Reflection, Connection)" + offlineResult + " and " + connection);
|
|
||||||
}
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
|
||||||
plugin.getLog().error("Failed to set offline uuid of {}", username, ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!plugin.getCore().getConfig().get("forwardSkin", true)) {
|
if (!plugin.getCore().getConfig().get("forwardSkin", true)) {
|
||||||
@@ -118,6 +117,35 @@ public class ConnectListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setOfflineId(PendingConnection connection, String username) {
|
||||||
|
try {
|
||||||
|
final UUID oldPremiumId = connection.getUniqueId();
|
||||||
|
final UUID offlineUUID = UUIDAdapter.generateOfflineId(username);
|
||||||
|
|
||||||
|
// BungeeCord only allows setting the UUID in PreLogin events and before requesting online mode
|
||||||
|
// However if online mode is requested, it will override previous values
|
||||||
|
// So we have to do it with reflection
|
||||||
|
uniqueIdSetter.invoke(connection, offlineUUID);
|
||||||
|
|
||||||
|
String format = "Overridden UUID from {} to {} (based of {}) on {}";
|
||||||
|
plugin.getLog().info(format, oldPremiumId, offlineUUID, username, connection);
|
||||||
|
|
||||||
|
// check if the field was actually set correctly
|
||||||
|
UUID offlineResult = (UUID) uniqueIdGetter.invoke(connection);
|
||||||
|
UUID connectionResult = connection.getUniqueId();
|
||||||
|
if (!offlineUUID.equals(offlineResult)
|
||||||
|
|| !offlineUUID.equals(connectionResult)) {
|
||||||
|
throw new RuntimeException("Inconsistent UUIDs: expected " + offlineUUID
|
||||||
|
+ " got (Reflection, Connection)" + offlineResult + " and " + connection);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
plugin.getLog().error("Failed to set offline uuid of {}", username, ex);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
// throw remaining exceptions like outofmemory that we shouldn't handle ourself
|
||||||
|
Throwables.throwIfUnchecked(throwable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onServerConnected(ServerConnectedEvent serverConnectedEvent) {
|
public void onServerConnected(ServerConnectedEvent serverConnectedEvent) {
|
||||||
ProxiedPlayer player = serverConnectedEvent.getPlayer();
|
ProxiedPlayer player = serverConnectedEvent.getPlayer();
|
||||||
|
Reference in New Issue
Block a user