|
|
|
@@ -1,13 +1,13 @@
|
|
|
|
|
package net.md_5.bungee;
|
|
|
|
|
|
|
|
|
|
import gnu.trove.set.hash.THashSet;
|
|
|
|
|
import io.netty.channel.Channel;
|
|
|
|
|
import java.net.InetSocketAddress;
|
|
|
|
|
import java.net.Socket;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Queue;
|
|
|
|
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
|
|
|
import lombok.Getter;
|
|
|
|
@@ -20,12 +20,15 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
|
|
|
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
|
|
|
|
import net.md_5.bungee.api.event.ServerConnectEvent;
|
|
|
|
|
import net.md_5.bungee.connection.DownstreamBridge;
|
|
|
|
|
import net.md_5.bungee.connection.UpstreamBridge;
|
|
|
|
|
import net.md_5.bungee.packet.*;
|
|
|
|
|
|
|
|
|
|
public final class UserConnection extends GenericConnection implements ProxiedPlayer
|
|
|
|
|
public final class UserConnection implements ProxiedPlayer
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public final Packet2Handshake handshake;
|
|
|
|
|
private final ProxyServer bungee;
|
|
|
|
|
private final Channel ch;
|
|
|
|
|
final Packet1Login forgeLogin;
|
|
|
|
|
final List<PacketFAPluginMessage> loginMessages;
|
|
|
|
|
public Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>();
|
|
|
|
@@ -36,7 +39,6 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
|
|
|
|
|
// reconnect stuff
|
|
|
|
|
private int clientEntityId;
|
|
|
|
|
private int serverEntityId;
|
|
|
|
|
private volatile boolean reconnecting;
|
|
|
|
|
// ping stuff
|
|
|
|
|
public int trackingPingId;
|
|
|
|
|
public long pingTime;
|
|
|
|
@@ -44,12 +46,9 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
|
|
|
|
|
@Setter
|
|
|
|
|
private int ping = 1000;
|
|
|
|
|
// Permissions
|
|
|
|
|
private final Collection<String> groups = new HashSet<>();
|
|
|
|
|
private final Map<String, Boolean> permissions = new HashMap<>();
|
|
|
|
|
private final Collection<String> playerGroups = new HashSet<>();
|
|
|
|
|
private final THashSet<String> permissions = new THashSet<>();
|
|
|
|
|
private final Object permMutex = new Object();
|
|
|
|
|
// Hack for connect timings
|
|
|
|
|
private ServerInfo nextServer;
|
|
|
|
|
private volatile boolean clientConnected = true;
|
|
|
|
|
|
|
|
|
|
public UserConnection(Socket socket, PendingConnection pendingConnection, PacketStream stream, Packet2Handshake handshake, Packet1Login forgeLogin, List<PacketFAPluginMessage> loginMessages)
|
|
|
|
|
{
|
|
|
|
@@ -97,86 +96,76 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
|
|
|
|
|
target = event.getTarget(); // Update in case the event changed target
|
|
|
|
|
|
|
|
|
|
ProxyServer.getInstance().getTabListHandler().onServerChange( this );
|
|
|
|
|
try
|
|
|
|
|
|
|
|
|
|
reconnecting = true;
|
|
|
|
|
|
|
|
|
|
if ( server != null )
|
|
|
|
|
{
|
|
|
|
|
reconnecting = true;
|
|
|
|
|
|
|
|
|
|
if ( server != null )
|
|
|
|
|
{
|
|
|
|
|
stream.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
|
|
|
|
|
stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ServerConnection newServer = ServerConnector.connect( this, target, true );
|
|
|
|
|
if ( server == null )
|
|
|
|
|
{
|
|
|
|
|
// Once again, first connection
|
|
|
|
|
clientEntityId = newServer.loginPacket.entityId;
|
|
|
|
|
serverEntityId = newServer.loginPacket.entityId;
|
|
|
|
|
// Set tab list size
|
|
|
|
|
Packet1Login s = newServer.loginPacket;
|
|
|
|
|
Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() );
|
|
|
|
|
stream.write( login );
|
|
|
|
|
stream.write( BungeeCord.getInstance().registerChannels() );
|
|
|
|
|
|
|
|
|
|
upBridge = new UpstreamBridge();
|
|
|
|
|
upBridge.start();
|
|
|
|
|
} else
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
downBridge.interrupt();
|
|
|
|
|
downBridge.join();
|
|
|
|
|
} catch ( InterruptedException ie )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server.disconnect( "Quitting" );
|
|
|
|
|
server.getInfo().removePlayer( this );
|
|
|
|
|
|
|
|
|
|
Packet1Login login = newServer.loginPacket;
|
|
|
|
|
serverEntityId = login.entityId;
|
|
|
|
|
stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reconnect process has finished, lets get the player moving again
|
|
|
|
|
reconnecting = false;
|
|
|
|
|
|
|
|
|
|
// Add to new
|
|
|
|
|
target.addPlayer( this );
|
|
|
|
|
|
|
|
|
|
// Start the bridges and move on
|
|
|
|
|
server = newServer;
|
|
|
|
|
downBridge = new DownstreamBridge();
|
|
|
|
|
downBridge.start();
|
|
|
|
|
} catch ( KickException ex )
|
|
|
|
|
{
|
|
|
|
|
disconnect( ex.getMessage() );
|
|
|
|
|
} catch ( Exception ex )
|
|
|
|
|
{
|
|
|
|
|
disconnect( "Could not connect to server - " + Util.exception( ex ) );
|
|
|
|
|
stream.write( new Packet9Respawn( (byte) 1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
|
|
|
|
|
stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ServerConnection newServer = ServerConnector.connect( this, target, true );
|
|
|
|
|
if ( server == null )
|
|
|
|
|
{
|
|
|
|
|
// Once again, first connection
|
|
|
|
|
clientEntityId = newServer.loginPacket.entityId;
|
|
|
|
|
serverEntityId = newServer.loginPacket.entityId;
|
|
|
|
|
// Set tab list size
|
|
|
|
|
Packet1Login s = newServer.loginPacket;
|
|
|
|
|
Packet1Login login = new Packet1Login( s.entityId, s.levelType, s.gameMode, (byte) s.dimension, s.difficulty, s.unused, (byte) pendingConnection.getListener().getTabListSize() );
|
|
|
|
|
stream.write( login );
|
|
|
|
|
stream.write( BungeeCord.getInstance().registerChannels() );
|
|
|
|
|
|
|
|
|
|
upBridge = new UpstreamBridge();
|
|
|
|
|
upBridge.start();
|
|
|
|
|
} else
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
downBridge.interrupt();
|
|
|
|
|
downBridge.join();
|
|
|
|
|
} catch ( InterruptedException ie )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server.disconnect( "Quitting" );
|
|
|
|
|
server.getInfo().removePlayer( this );
|
|
|
|
|
|
|
|
|
|
Packet1Login login = newServer.loginPacket;
|
|
|
|
|
serverEntityId = login.entityId;
|
|
|
|
|
stream.write( new Packet9Respawn( login.dimension, login.difficulty, login.gameMode, (short) 256, login.levelType ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reconnect process has finished, lets get the player moving again
|
|
|
|
|
reconnecting = false;
|
|
|
|
|
|
|
|
|
|
// Add to new
|
|
|
|
|
target.addPlayer( this );
|
|
|
|
|
|
|
|
|
|
// Start the bridges and move on
|
|
|
|
|
server = newServer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public synchronized void disconnect(String reason)
|
|
|
|
|
{
|
|
|
|
|
if ( clientConnected )
|
|
|
|
|
if ( ch.isActive() )
|
|
|
|
|
{
|
|
|
|
|
PlayerDisconnectEvent event = new PlayerDisconnectEvent( this );
|
|
|
|
|
ProxyServer.getInstance().getPluginManager().callEvent( event );
|
|
|
|
|
ProxyServer.getInstance().getTabListHandler().onDisconnect( this );
|
|
|
|
|
ProxyServer.getInstance().getPlayers().remove( this );
|
|
|
|
|
bungee.getPluginManager().callEvent( event );
|
|
|
|
|
bungee.getTabListHandler().onDisconnect( this );
|
|
|
|
|
bungee.getPlayers().remove( this );
|
|
|
|
|
|
|
|
|
|
ch.write( new PacketFFKick( reason ) );
|
|
|
|
|
ch.close();
|
|
|
|
|
|
|
|
|
|
super.disconnect( reason );
|
|
|
|
|
if ( server != null )
|
|
|
|
|
{
|
|
|
|
|
server.getInfo().removePlayer( this );
|
|
|
|
|
server.disconnect( "Quitting" );
|
|
|
|
|
ProxyServer.getInstance().getReconnectHandler().setServer( this );
|
|
|
|
|
bungee.getReconnectHandler().setServer( this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clientConnected = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -189,20 +178,20 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
|
|
|
|
|
@Override
|
|
|
|
|
public void sendData(String channel, byte[] data)
|
|
|
|
|
{
|
|
|
|
|
server.packetQueue.add( new PacketFAPluginMessage( channel, data ) );
|
|
|
|
|
ch.write( new PacketFAPluginMessage( channel, data ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public InetSocketAddress getAddress()
|
|
|
|
|
{
|
|
|
|
|
return (InetSocketAddress) socket.getRemoteSocketAddress();
|
|
|
|
|
return (InetSocketAddress) ch.remoteAddress();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Synchronized("permMutex")
|
|
|
|
|
public Collection<String> getGroups()
|
|
|
|
|
{
|
|
|
|
|
return Collections.unmodifiableCollection( groups );
|
|
|
|
|
return Collections.unmodifiableCollection( playerGroups );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@@ -211,8 +200,8 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
|
|
|
|
|
{
|
|
|
|
|
for ( String group : groups )
|
|
|
|
|
{
|
|
|
|
|
this.groups.add( group );
|
|
|
|
|
for ( String permission : ProxyServer.getInstance().getConfigurationAdapter().getPermissions( group ) )
|
|
|
|
|
playerGroups.add( group );
|
|
|
|
|
for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) )
|
|
|
|
|
{
|
|
|
|
|
setPermission( permission, true );
|
|
|
|
|
}
|
|
|
|
@@ -225,8 +214,8 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
|
|
|
|
|
{
|
|
|
|
|
for ( String group : groups )
|
|
|
|
|
{
|
|
|
|
|
this.groups.remove( group );
|
|
|
|
|
for ( String permission : ProxyServer.getInstance().getConfigurationAdapter().getPermissions( group ) )
|
|
|
|
|
playerGroups.remove( group );
|
|
|
|
|
for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) )
|
|
|
|
|
{
|
|
|
|
|
setPermission( permission, false );
|
|
|
|
|
}
|
|
|
|
@@ -237,14 +226,19 @@ public final class UserConnection extends GenericConnection implements ProxiedPl
|
|
|
|
|
@Synchronized("permMutex")
|
|
|
|
|
public boolean hasPermission(String permission)
|
|
|
|
|
{
|
|
|
|
|
Boolean val = permissions.get( permission );
|
|
|
|
|
return ( val == null ) ? false : val;
|
|
|
|
|
return permissions.contains( permission );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@Synchronized("permMutex")
|
|
|
|
|
public void setPermission(String permission, boolean value)
|
|
|
|
|
{
|
|
|
|
|
permissions.put( permission, value );
|
|
|
|
|
if ( value )
|
|
|
|
|
{
|
|
|
|
|
permissions.add( permission );
|
|
|
|
|
} else
|
|
|
|
|
{
|
|
|
|
|
permissions.remove( permission );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|