/*
** j###t ########## #### ####
** j###t ########## #### ####
** j###T "###L J###"
** ######P' ########## #########
** ######k, ########## T######T
** ####~###L ####
** #### q###L ########## .#####
** #### \###L ########## #####"
**
** $Id$
**
** Class History
**
** Date Name Description
** ---------|------------|-----------------------------------------------
** 30Sep98 subtle created
**
*/
package key;
import key.collections.*;
import java.util.Enumeration;
import java.io.*;
import java.util.StringTokenizer;
import key.util.Trie;
/**
* LightWeight Player Group - a collection of players
*/
public class LWPlayerGroup implements PlayerGroup
{
transient Collection players;
public LWPlayerGroup()
{
}
public void setCollection( Collection c )
{
players = c;
}
/**
* Add this player to the list of players
*
* @param p the player to add to the list
* @exception NonUniqueKeyException if there is already a player in with this name
* @exception BadKeyException if this players name is malformed somehow
*/
public void linkPlayer( Player p ) throws NonUniqueKeyException,BadKeyException
{
if( !players.contains( p ) )
{
players.link( p );
}
else
throw new UnexpectedResult( "adding player " + p.getName() + " to scape when he's already in it" );
}
/**
* Take this player out of the list of players
*
* @param p the player to remove from the list
* @exception NoSuchElementException if the player is not in the list
* @exception BadKeyException if the players name is malformed somehow
*/
public void unlinkPlayer( Player p ) throws NonUniqueKeyException,java.util.NoSuchElementException,BadKeyException
{
players.unlink( p );
}
/**
* Returns the player matched, or, possibly, an instance of
* a Trie object that contains all the matching players.
* <p>
* A null is returned if no matches were found at all. The
* match string is searched until the end of the string or
* a non-alphabetical character is found.
* <p>
* If you specify a comma seperated list of players, a scape
* containing the players will be returned. Such a scape can
* also contain errors when individual multiple matches are
* caught
*
* @param match the start or whole string to match from
* @return A player object, referring to the sole match, or a Trie
*/
public final Object getPlayer( Player p, String match )
{
//System.out.println( "players is " + players.getClass().getName() + " on " + getClass().getName() );
StringTokenizer st = new StringTokenizer( match, ",", false );
return( getPlayer( p, st ) );
}
public final Object getPlayer( String match )
{
return( players.get( match ) );
}
protected final Object getPlayer( Player p, StringTokenizer st )
{
Object single;
if( st.hasMoreTokens() )
{
single = players.get( st.nextToken() );
if( st.hasMoreTokens() )
{ // more than one player
try
{
LWPlayerGroup group = new LWPlayerGroup();
// the use of this makes the reference persistant -
// it can survive the deletion and login/logout
// of players fairly easily.
group.players = new ReferencingProxyCollection( new NoKeyCollection() );
do
{
if( single instanceof Player )
{
group.linkPlayer( (Player)single );
}
else if( single instanceof Trie )
{
// look for a prefer
for( Enumeration e = ((Trie)single).elements(); e.hasMoreElements(); )
{
Player o = (Player) e.nextElement();
if( p.getPrefer().containsPlayer( o ) )
group.linkPlayer( o );
}
}
single = players.get( st.nextToken() );
} while( st.hasMoreTokens() );
if( single instanceof Player )
{
group.linkPlayer( (Player)single );
}
else
; // in the future, link to a seperate linked
// linked list explicitly for multiple matches
return( group );
}
catch( BadKeyException e )
{
throw new UnexpectedResult( e.toString() + " occurred when creating temporary sub-group" );
}
catch( NonUniqueKeyException e )
{
throw new UnexpectedResult( e.toString() + " occurred when creating temporary sub-group" );
}
}
else
{
return( single );
}
}
else
return( null );
}
public final Enumeration players()
{
return( players.elements() );
}
public final boolean containsPlayer( Player p )
{
return( players.contains( p ) );
}
public final String allNames()
{
String all[] = new String[numberPlayers()];
int upto=0;
for( Enumeration e = players(); e.hasMoreElements(); )
all[upto++] = (String) ((Player)e.nextElement()).getName();
return( Grammar.enumerate( all ) );
}
/**
* All the names, except substitute 'you' for player p
*/
public final String allNames( Player p )
{
String all[] = new String[numberPlayers()];
int upto=0;
for( Enumeration e = players(); e.hasMoreElements(); )
{
Player t = (Player) e.nextElement();
if( t == p )
all[upto++] = "you";
else
all[upto++] = (String) t.getName();
}
return( Grammar.enumerate( all ) );
}
// META: this one is deprecated
public final int numberPlayers()
{
return( players.count() );
}
public final int getNumberPlayers()
{
return( players.count() );
}
// this method replaced by allNames
public String getAllNames() { return( allNames() ); }
/**
* A general way of saying that the people in
* this scape should be notified of the
* supplied Effect.
*/
public void splash( Effect t, SuppressionList s )
{
for( Enumeration e = players(); e.hasMoreElements(); )
splashToPlayer( ((Player)e.nextElement()), t, s );
}
protected final void splashToPlayer( Player p, Effect t, SuppressionList sl )
{
try
{
p.splash( t, sl );
}
catch( Exception e )
{
Log.error( " during splashToPlayer( " + p.getName() + " )" , e );
}
}
/**
* Sends the splash to everyone except the listed
* atom
*/
public void splashExcept( Effect t, Splashable except, SuppressionList sl )
{
for( Enumeration e = players(); e.hasMoreElements(); )
{
Player s = (Player)e.nextElement();
if( except instanceof Scape )
{
if( !((Scape)except).containsPlayer( s ) )
splashToPlayer( s, t, sl );
}
else
{
if( s != except )
splashToPlayer( s, t, sl );
}
}
}
/**
* Sends the splash to everyone except the listed
* atoms
*/
public void splashExcept( Effect t, Splashable[] except, SuppressionList sl )
{
for( Enumeration e = players(); e.hasMoreElements(); )
{
Atom s = (Atom)e.nextElement();
boolean match;
match=true;
for( int i = 0; i < except.length; i++ )
{
if( s == except[i] )
{
match = false;
break;
}
}
if( match )
s.splash( t, sl );
}
}
}