From dbb2441936118788203dc43a4c4582ee71e017c8 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Sun, 2 Oct 2016 07:54:16 +0200 Subject: [PATCH] Multi-session with same Minecraft account with specific permission Players with permission bungeecord.multiple_connect can have multiples connections with the same Minecraft account. To manage UUID and Name conflict, an increment value is appended to the player name, and the uuid used is the offline one. So be carefull: Spigot servers and plugins will considers 2 players from the same account like if they were 2 different MC account. diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 0f1716c0..b07d2e06 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -110,6 +110,17 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Getter private String extraDataInHandshake = ""; + @Getter + private boolean duplication = false; + + @Getter + private String realName = null; + + @Getter + private UUID realId = null; + + private String gameName = null; + @Override public boolean shouldHandle(PacketWrapper packet) throws Exception { @@ -364,6 +375,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection { Preconditions.checkState( thisState == State.USERNAME, "Not expecting USERNAME" ); this.loginRequest = loginRequest; + this.realName = loginRequest.getData(); + this.gameName = this.realName; if ( getName().contains( " " ) ) { @@ -378,9 +391,21 @@ public class InitialHandler extends PacketHandler implements PendingConnection return; } + ProxiedPlayer existingPlayer = bungee.getPlayer( getName() ); + + duplication = ( existingPlayer != null && existingPlayer.hasPermission( "bungeecord.multiple_connect" ) ); + + if ( duplication ) + { + gameName = generateDuplicatedName( realName ); + this.loginRequest.setData( gameName ); // gameName transmitted to Spigot server + } + + offlineId = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + gameName ).getBytes( Charsets.UTF_8 ) ); + // If offline mode and they are already on, don't allow connect // We can just check by UUID here as names are based on UUID - if ( !isOnlineMode() && bungee.getPlayer( getUniqueId() ) != null ) + if ( !isOnlineMode() && bungee.getPlayer( offlineId ) != null && !duplication ) { disconnect( bungee.getTranslation( "already_connected_proxy" ) ); return; @@ -435,7 +460,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection BungeeCipher encrypt = EncryptionUtil.getCipher( true, sharedKey ); ch.addBefore( PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) ); - String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" ); + String encName = URLEncoder.encode( InitialHandler.this.realName, "UTF-8" ); MessageDigest sha = MessageDigest.getInstance( "SHA-1" ); for ( byte[] bit : new byte[][] @@ -461,8 +486,10 @@ public class InitialHandler extends PacketHandler implements PendingConnection if ( obj != null && obj.getId() != null ) { loginProfile = obj; - name = obj.getName(); - uniqueId = Util.getUUID( obj.getId() ); + realName = obj.getName(); + realId = Util.getUUID( obj.getId() ); + if ( !duplication ) + uniqueId = realId; finish(); return; } @@ -470,7 +497,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection } else { disconnect( bungee.getTranslation( "mojang_fail" ) ); - bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", error ); + bungee.getLogger().log( Level.SEVERE, "Error authenticating " + realName + " with minecraft.net", error ); } } }; @@ -480,6 +507,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection private void finish() { + + if ( uniqueId == null ) + { + uniqueId = offlineId; + } + if ( isOnlineMode() ) { // Check for multiple connections @@ -510,12 +543,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection } - offlineId = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + getName() ).getBytes( Charsets.UTF_8 ) ); - if ( uniqueId == null ) - { - uniqueId = offlineId; - } - Callback complete = new Callback() { @Override @@ -615,7 +642,22 @@ public class InitialHandler extends PacketHandler implements PendingConnection @Override public String getName() { - return ( name != null ) ? name : ( loginRequest == null ) ? null : loginRequest.getData(); + return gameName; + } + + private String generateDuplicatedName(String original) + { + String newName; + int i = 0; + do + { + i++; + String strCount = Integer.toString( i ); + if ( original.length() > 16 - strCount.length() ) + original = original.substring( 0, 16 - strCount.length() ); + newName = original + i; + } while ( bungee.getPlayer( newName ) != null ); + return newName; } @Override -- 2.32.0.windows.2