[Breaking] Close #423 by making tab list per listener.

This commit is contained in:
md_5 2013-06-08 13:13:17 +10:00
parent b5aecd5dcc
commit b75a2b5060
13 changed files with 104 additions and 125 deletions

View File

@ -120,21 +120,6 @@ public abstract class ProxyServer
*/ */
public abstract void setConfigurationAdapter(ConfigurationAdapter adapter); public abstract void setConfigurationAdapter(ConfigurationAdapter adapter);
/**
* Get the currently in use tab list handle.
*
* @return the tab list handler
*/
public abstract TabListHandler getTabListHandler();
/**
* Set the used tab list handler, should not be changed once players have
* connected
*
* @param handler the tab list handler to set
*/
public abstract void setTabListHandler(TabListHandler handler);
/** /**
* Get the currently in use reconnect handler. * Get the currently in use reconnect handler.
* *

View File

@ -1,23 +1,29 @@
package net.md_5.bungee.api; package net.md_5.bungee.api;
import lombok.Data;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
public interface TabListHandler @Data
public abstract class TabListHandler
{ {
private final ProxiedPlayer player;
/**
* Called when this player first connects to the proxy.
*/
public void onConnect()
{
}
/** /**
* Called when a player first connects to the proxy. * Called when a player first connects to the proxy.
* *
* @param player the connecting player * @param player the connecting player
*/ */
public void onConnect(ProxiedPlayer player); public void onServerChange()
{
/** }
* Called when a player changes their connected server.
*
* @param player the player who changed servers
*/
public void onServerChange(ProxiedPlayer player);
/** /**
* Called when a players ping changes. The new ping will have not updated in * Called when a players ping changes. The new ping will have not updated in
@ -26,14 +32,18 @@ public interface TabListHandler
* @param player the player who's ping changed * @param player the player who's ping changed
* @param ping the player's new ping. * @param ping the player's new ping.
*/ */
public void onPingChange(ProxiedPlayer player, int ping); public void onPingChange(int ping)
{
}
/** /**
* Called when a player disconnects. * Called when a player disconnects.
* *
* @param player the disconnected player * @param player the disconnected player
*/ */
public void onDisconnect(ProxiedPlayer player); public void onDisconnect()
{
}
/** /**
* Called when a list update packet is sent from server to client. * Called when a list update packet is sent from server to client.
@ -44,5 +54,5 @@ public interface TabListHandler
* @param ping ping of the subject player * @param ping ping of the subject player
* @return whether to send the packet to the client * @return whether to send the packet to the client
*/ */
public boolean onListUpdate(ProxiedPlayer player, String name, boolean online, int ping); public abstract boolean onListUpdate(String name, boolean online, int ping);
} }

View File

@ -3,6 +3,7 @@ package net.md_5.bungee.api.config;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Map; import java.util.Map;
import lombok.Data; import lombok.Data;
import net.md_5.bungee.api.TabListHandler;
/** /**
* Class representing the configuration of a server listener. Used for allowing * Class representing the configuration of a server listener. Used for allowing
@ -52,4 +53,8 @@ public class ListenerInfo
* null. * null.
*/ */
private final TexturePackInfo texturePack; private final TexturePackInfo texturePack;
/**
* Class used to build tab lists for this player.
*/
private final Class<? extends TabListHandler> tabList;
} }

View File

@ -96,12 +96,6 @@ public class BungeeCord extends ProxyServer
*/ */
private final Map<String, UserConnection> connections = new CaseInsensitiveMap<>(); private final Map<String, UserConnection> connections = new CaseInsensitiveMap<>();
private final ReadWriteLock connectionLock = new ReentrantReadWriteLock(); private final ReadWriteLock connectionLock = new ReentrantReadWriteLock();
/**
* Tab list handler
*/
@Getter
@Setter
public TabListHandler tabListHandler;
/** /**
* Plugin manager. * Plugin manager.
*/ */

View File

@ -154,7 +154,7 @@ public class ServerConnector extends PacketHandler
user.unsafe().sendPacket( modLogin ); user.unsafe().sendPacket( modLogin );
} else } else
{ {
bungee.getTabListHandler().onServerChange( user ); user.getTabList().onServerChange();
Scoreboard serverScoreboard = user.getServerSentScoreboard(); Scoreboard serverScoreboard = user.getServerSentScoreboard();
for ( Objective objective : serverScoreboard.getObjectives() ) for ( Objective objective : serverScoreboard.getObjectives() )

View File

@ -21,6 +21,7 @@ import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.TabListHandler;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.config.TexturePackInfo; import net.md_5.bungee.api.config.TexturePackInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
@ -62,6 +63,8 @@ public final class UserConnection implements ProxiedPlayer
private final Collection<ServerInfo> pendingConnects = new HashSet<>(); private final Collection<ServerInfo> pendingConnects = new HashSet<>();
/*========================================================================*/ /*========================================================================*/
@Getter @Getter
private TabListHandler tabList;
@Getter
@Setter @Setter
private int sentPingId; private int sentPingId;
@Getter @Getter
@ -101,6 +104,13 @@ public final class UserConnection implements ProxiedPlayer
public void init() public void init()
{ {
this.displayName = name; this.displayName = name;
try
{
this.tabList = getPendingConnection().getListener().getTabList().getDeclaredConstructor( ProxiedPlayer.class ).newInstance( this );
} catch ( ReflectiveOperationException ex )
{
throw new RuntimeException( ex );
}
Collection<String> g = bungee.getConfigurationAdapter().getGroups( name ); Collection<String> g = bungee.getConfigurationAdapter().getGroups( name );
for ( String s : g ) for ( String s : g )
@ -125,9 +135,9 @@ public final class UserConnection implements ProxiedPlayer
{ {
Preconditions.checkNotNull( name, "displayName" ); Preconditions.checkNotNull( name, "displayName" );
Preconditions.checkArgument( name.length() <= 16, "Display name cannot be longer than 16 characters" ); Preconditions.checkArgument( name.length() <= 16, "Display name cannot be longer than 16 characters" );
bungee.getTabListHandler().onDisconnect( this ); getTabList().onDisconnect();
displayName = name; displayName = name;
bungee.getTabListHandler().onConnect( this ); getTabList().onConnect();
} }
@Override @Override

View File

@ -22,14 +22,7 @@ import net.md_5.bungee.util.CaseInsensitiveMap;
public class Configuration public class Configuration
{ {
/**
* The default tab list options available for picking.
*/
private enum DefaultTabList
{
GLOBAL, GLOBAL_PING, SERVER;
}
/** /**
* Time before users are disconnected due to no network activity. * Time before users are disconnected due to no network activity.
*/ */
@ -62,24 +55,6 @@ public class Configuration
onlineMode = adapter.getBoolean( "online_mode", onlineMode ); onlineMode = adapter.getBoolean( "online_mode", onlineMode );
playerLimit = adapter.getInt( "player_limit", playerLimit ); playerLimit = adapter.getInt( "player_limit", playerLimit );
DefaultTabList tab = DefaultTabList.valueOf( adapter.getString( "tab_list", "GLOBAL_PING" ) );
if ( tab == null )
{
tab = DefaultTabList.GLOBAL_PING;
}
switch ( tab )
{
case GLOBAL:
ProxyServer.getInstance().setTabListHandler( new Global() );
break;
case GLOBAL_PING:
ProxyServer.getInstance().setTabListHandler( new GlobalPing() );
break;
case SERVER:
ProxyServer.getInstance().setTabListHandler( new ServerUnique() );
break;
}
listeners = adapter.getListeners(); listeners = adapter.getListeners();
Preconditions.checkArgument( listeners != null && !listeners.isEmpty(), "No listeners defined." ); Preconditions.checkArgument( listeners != null && !listeners.isEmpty(), "No listeners defined." );

View File

@ -14,13 +14,18 @@ import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import lombok.RequiredArgsConstructor;
import net.md_5.bungee.Util; import net.md_5.bungee.Util;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.TabListHandler;
import net.md_5.bungee.api.config.ConfigurationAdapter; import net.md_5.bungee.api.config.ConfigurationAdapter;
import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.config.TexturePackInfo; import net.md_5.bungee.api.config.TexturePackInfo;
import net.md_5.bungee.tablist.Global;
import net.md_5.bungee.tablist.GlobalPing;
import net.md_5.bungee.tablist.ServerUnique;
import net.md_5.bungee.util.CaseInsensitiveMap; import net.md_5.bungee.util.CaseInsensitiveMap;
import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
@ -28,6 +33,16 @@ import org.yaml.snakeyaml.Yaml;
public class YamlConfig implements ConfigurationAdapter public class YamlConfig implements ConfigurationAdapter
{ {
/**
* The default tab list options available for picking.
*/
@RequiredArgsConstructor
private enum DefaultTabList
{
GLOBAL( Global.class ), GLOBAL_PING( GlobalPing.class ), SERVER( ServerUnique.class );
private final Class<? extends TabListHandler> clazz;
}
private Yaml yaml; private Yaml yaml;
private Map config; private Map config;
private final File file = new File( "config.yml" ); private final File file = new File( "config.yml" );
@ -194,7 +209,14 @@ public class YamlConfig implements ConfigurationAdapter
String textureURL = get( "texture_url", null, val ); String textureURL = get( "texture_url", null, val );
int textureSize = get( "texture_size", 16, val ); int textureSize = get( "texture_size", 16, val );
TexturePackInfo texture = ( textureURL == null ) ? null : new TexturePackInfo( textureURL, textureSize ); TexturePackInfo texture = ( textureURL == null ) ? null : new TexturePackInfo( textureURL, textureSize );
ListenerInfo info = new ListenerInfo( address, motd, maxPlayers, tabListSize, defaultServer, fallbackServer, forceDefault, forced, texture ); String tabListName = get( "tab_list", "GLOBAL_PING", val );
DefaultTabList value = DefaultTabList.valueOf( tabListName.toUpperCase() );
if ( value == null )
{
value = DefaultTabList.GLOBAL_PING;
}
ListenerInfo info = new ListenerInfo( address, motd, maxPlayers, tabListSize, defaultServer, fallbackServer, forceDefault, forced, texture, value.clazz );
ret.add( info ); ret.add( info );
} }

View File

@ -86,7 +86,7 @@ public class DownstreamBridge extends PacketHandler
public void handle(PacketC9PlayerListItem playerList) throws Exception public void handle(PacketC9PlayerListItem playerList) throws Exception
{ {
if ( !bungee.getTabListHandler().onListUpdate( con, playerList.getUsername(), playerList.isOnline(), playerList.getPing() ) ) if ( !con.getTabList().onListUpdate( playerList.getUsername(), playerList.isOnline(), playerList.getPing() ) )
{ {
throw new CancelSendSignal(); throw new CancelSendSignal();
} }
@ -161,9 +161,9 @@ public class DownstreamBridge extends PacketHandler
t.setDisplayName( team.getDisplayName() ); t.setDisplayName( team.getDisplayName() );
t.setPrefix( team.getPrefix() ); t.setPrefix( team.getPrefix() );
t.setSuffix( team.getSuffix() ); t.setSuffix( team.getSuffix() );
t.setFriendlyFire(team.isFriendlyFire() ); t.setFriendlyFire( team.isFriendlyFire() );
} }
if ( team.getPlayers()!= null ) if ( team.getPlayers() != null )
{ {
for ( String s : team.getPlayers() ) for ( String s : team.getPlayers() )
{ {

View File

@ -28,7 +28,7 @@ public class UpstreamBridge extends PacketHandler
this.con = con; this.con = con;
BungeeCord.getInstance().addConnection( con ); BungeeCord.getInstance().addConnection( con );
bungee.getTabListHandler().onConnect( con ); con.getTabList().onConnect();
con.unsafe().sendPacket( BungeeCord.getInstance().registerChannels() ); con.unsafe().sendPacket( BungeeCord.getInstance().registerChannels() );
TexturePackInfo texture = con.getPendingConnection().getListener().getTexturePack(); TexturePackInfo texture = con.getPendingConnection().getListener().getTexturePack();
@ -50,7 +50,7 @@ public class UpstreamBridge extends PacketHandler
// We lost connection to the client // We lost connection to the client
PlayerDisconnectEvent event = new PlayerDisconnectEvent( con ); PlayerDisconnectEvent event = new PlayerDisconnectEvent( con );
bungee.getPluginManager().callEvent( event ); bungee.getPluginManager().callEvent( event );
bungee.getTabListHandler().onDisconnect( con ); con.getTabList().onDisconnect();
BungeeCord.getInstance().removeConnection( con ); BungeeCord.getInstance().removeConnection( con );
if ( con.getServer() != null ) if ( con.getServer() != null )
@ -75,7 +75,7 @@ public class UpstreamBridge extends PacketHandler
if ( alive.getRandomId() == con.getSentPingId() ) if ( alive.getRandomId() == con.getSentPingId() )
{ {
int newPing = (int) ( System.currentTimeMillis() - con.getSentPingTime() ); int newPing = (int) ( System.currentTimeMillis() - con.getSentPingTime() );
bungee.getTabListHandler().onPingChange( con, newPing ); con.getTabList().onPingChange( newPing );
con.setPing( newPing ); con.setPing( newPing );
} }
} }

View File

@ -1,52 +1,49 @@
package net.md_5.bungee.tablist; package net.md_5.bungee.tablist;
import java.util.Collection;
import java.util.HashSet;
import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.TabListHandler; import net.md_5.bungee.api.TabListHandler;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem; import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem;
public class Global implements TabListHandler public class Global extends TabListHandler
{ {
private final Collection<ProxiedPlayer> sentPings = new HashSet<>(); private boolean sentPing;
public Global(ProxiedPlayer player)
{
super( player );
}
@Override @Override
public void onConnect(ProxiedPlayer player) public void onConnect()
{ {
for ( ProxiedPlayer p : ProxyServer.getInstance().getPlayers() ) for ( ProxiedPlayer p : ProxyServer.getInstance().getPlayers() )
{ {
player.unsafe().sendPacket( new PacketC9PlayerListItem( p.getDisplayName(), true, (short) p.getPing() ) ); getPlayer().unsafe().sendPacket( new PacketC9PlayerListItem( p.getDisplayName(), true, (short) p.getPing() ) );
} }
BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( player.getDisplayName(), true, (short) player.getPing() ) ); BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( getPlayer().getDisplayName(), true, (short) getPlayer().getPing() ) );
} }
@Override @Override
public void onPingChange(ProxiedPlayer player, int ping) public void onPingChange(int ping)
{ {
if ( !sentPings.contains( player ) ) if ( !sentPing )
{ {
BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( player.getDisplayName(), true, (short) player.getPing() ) ); sentPing = true;
sentPings.add( player ); BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( getPlayer().getDisplayName(), true, (short) getPlayer().getPing() ) );
} }
} }
@Override @Override
public void onDisconnect(ProxiedPlayer player) public void onDisconnect()
{ {
BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( player.getDisplayName(), false, (short) 9999 ) ); BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( getPlayer().getDisplayName(), false, (short) 9999 ) );
sentPings.remove( player );
} }
@Override @Override
public void onServerChange(ProxiedPlayer player) public boolean onListUpdate(String name, boolean online, int ping)
{
}
@Override
public boolean onListUpdate(ProxiedPlayer player, String name, boolean online, int ping)
{ {
return false; return false;
} }

View File

@ -1,7 +1,5 @@
package net.md_5.bungee.tablist; package net.md_5.bungee.tablist;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem; import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem;
@ -10,23 +8,21 @@ public class GlobalPing extends Global
{ {
private static final int PING_THRESHOLD = 20; private static final int PING_THRESHOLD = 20;
private final TObjectIntMap<ProxiedPlayer> lastPings = new TObjectIntHashMap<>(); /*========================================================================*/
private int lastPing;
@Override public GlobalPing(ProxiedPlayer player)
public void onDisconnect(ProxiedPlayer player)
{ {
lastPings.remove( player ); super( player );
super.onDisconnect( player );
} }
@Override @Override
public void onPingChange(ProxiedPlayer player, int ping) public void onPingChange(int ping)
{ {
int lastPing = lastPings.get( player );
if ( ping - PING_THRESHOLD > lastPing && ping + PING_THRESHOLD < lastPing ) if ( ping - PING_THRESHOLD > lastPing && ping + PING_THRESHOLD < lastPing )
{ {
BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( player.getDisplayName(), true, (short) ping ) ); lastPing = ping;
lastPings.put( player, ping ); BungeeCord.getInstance().broadcast( new PacketC9PlayerListItem( getPlayer().getDisplayName(), true, (short) ping ) );
} }
} }
} }

View File

@ -1,58 +1,43 @@
package net.md_5.bungee.tablist; package net.md_5.bungee.tablist;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import java.util.Collection; import java.util.Collection;
import net.md_5.bungee.UserConnection; import java.util.HashSet;
import net.md_5.bungee.api.TabListHandler; import net.md_5.bungee.api.TabListHandler;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem; import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem;
public class ServerUnique implements TabListHandler public class ServerUnique extends TabListHandler
{ {
private final Multimap<ProxiedPlayer, String> sentUsernames = Multimaps.synchronizedMultimap( HashMultimap.<ProxiedPlayer, String>create() ); private final Collection<String> usernames = new HashSet<>();
@Override public ServerUnique(ProxiedPlayer player)
public void onConnect(ProxiedPlayer player)
{ {
super( player );
} }
@Override @Override
public void onPingChange(ProxiedPlayer player, int ping) public void onServerChange()
{ {
} synchronized ( usernames )
@Override
public void onDisconnect(ProxiedPlayer player)
{
sentUsernames.removeAll( player );
}
@Override
public void onServerChange(ProxiedPlayer player)
{
Collection<String> usernames = sentUsernames.get( player );
synchronized ( sentUsernames )
{ {
for ( String username : usernames ) for ( String username : usernames )
{ {
player.unsafe().sendPacket( new PacketC9PlayerListItem( username, false, (short) 9999 ) ); getPlayer().unsafe().sendPacket( new PacketC9PlayerListItem( username, false, (short) 9999 ) );
} }
usernames.clear(); usernames.clear();
} }
} }
@Override @Override
public boolean onListUpdate(ProxiedPlayer player, String name, boolean online, int ping) public boolean onListUpdate(String name, boolean online, int ping)
{ {
if ( online ) if ( online )
{ {
sentUsernames.put( player, name ); usernames.add( name );
} else } else
{ {
sentUsernames.remove( player, name ); usernames.remove( name );
} }
return true; return true;