import java.io.*; import java.net.*; import java.util.*; import java.util.concurrent.*; public class FortSrv { public final int majversion = 0; public final int minversion = 0; public final int microversion = 1; public final int ALLPLAYERS = -1; private String servername; private int serverport; private int numplayers; private boolean allowwatchers; private boolean quit; private Vector observers; private LinkedBlockingQueue[] messagequeues; private Vector carddeck; private TurnManager tm = null; public String getVersion() { return String.valueOf( majversion ) + "." + String.valueOf( minversion ) + "." + String.valueOf( microversion ); } public String getName() { return servername; } public String getPlayerName( int i ) { return tm.getPlayerName( i ); } public int getPlayerIndex( String name ) { return tm.getPlayerIndex( name ); } public boolean playerExists( int idx ) { return tm.playerExists( idx ); } public boolean sendMessage( FMessage msg ) { if (msg.broadcast) { for (Player p : observers) { p.sendMessage( msg ); } } else { if (tm.playerExists( msg.playerto )) { try { (tm.getPlayer( msg.playerto )).sendMessage( msg ); } catch (ArrayIndexOutOfBoundsException e) { // Probably a synchronization error. Not serious enough to warrant coding for. System.out.println( "Message failed sending to " + msg.playerto + "." ); return false; } } else { System.out.println( "Player " + msg.playerto + " not connected." ); return false; } } return true; } public void done() { quit = true; } public String serverInfo() { return "Fortresses server '" + getName() + "' version " + getVersion(); } public String protocolHelp( String topic ) { return Help.protocolHelp( topic ); } private void shuffleDistricts() { Random r = new Random(); int n = carddeck.size(); if (n > 0) { Vector newdeck = new Vector( n ); while (n > 0) { newdeck.add( carddeck.remove( r.nextInt( n ) ) ); n--; } carddeck = newdeck; } } private void initializeDistricts( String filename ) { BufferedReader cards; String instr; carddeck = new Vector(); try { cards = new BufferedReader( new FileReader( filename ) ); while ((instr = cards.readLine()) != null) { if (! (instr.startsWith( "#" ) || instr.trim().equals( "" ))) { carddeck.add( new District( instr ) ); } } cards.close(); System.out.println( carddeck.size() + " district cards initialized." ); } catch (IOException e) { System.out.println( "Error reading district file: " + e.getMessage() ); } shuffleDistricts(); } public District drawDistrict() throws EmptyDeckException { if (carddeck.isEmpty()) { throw new EmptyDeckException(); } return carddeck.remove( 0 ); } public Vector drawDistricts( int num ) throws EmptyDeckException { Vector drawpile = new Vector( num ); for (int i = 0; i < num; i++) { drawpile.add( drawDistrict() ); } return drawpile; } public void discardDistrict( District d ) { carddeck.add( d ); } public FortSrv( String name, int port, int nplayers, boolean watchers ) { servername = name; serverport = port; numplayers = nplayers; allowwatchers = watchers; int playercount = 0; ConnectionServer cs; observers = new Vector(); initializeDistricts( "districts.dat" ); tm = new TurnManager( observers, numplayers ); tm.start(); try { cs = new ConnectionServer( port ); System.out.println( "Setting up game '" + name + "' on Fortresses server with " + nplayers + " players running on port " + port + ".\n" + "Waiting for players to connect..." ); quit = false; while (!quit) { Player p = new Player( cs.newConnection(), this, ++playercount, drawDistricts( 4 ) ); p.start(); observers.add( p ); } cs.close(); } catch (IOException e) { System.out.println( "Cannot start server.\nReason: " + e.getMessage() ); } catch (SecurityException e) { System.out.println( "Cannot start server.\nReason: " + e.getMessage() ); } catch (EmptyDeckException e) { System.out.println( "Ran out of district cards.\nPlease check 'districts.dat' to ensure enough cards are defined." ); } } public String playerFlags( int player ) { return tm.playerFlags( player ); } public String playerStatus( int player ) { if (tm.playerExists( player )) { try { return "Player index: " + player + "\n" + (tm.getPlayer( player )).getStatus(); } catch (ArrayIndexOutOfBoundsException e) { return "Player " + player + " not connected."; } } else { return "Player " + player + " not connected."; } } public int getIndex( Player p ) { return tm.getIndex( p ); } }