Package clueless.controller

Source Code of clueless.controller.GameController

package clueless.controller;

import java.io.IOException;
import java.net.InetAddress;
import java.util.LinkedList;
import java.util.Vector;

import javax.swing.JOptionPane;
import javax.swing.event.EventListenerList;

import clueless.controller.client.CluelessClient;
import clueless.controller.server.CluelessServer;
import clueless.events.CharacterSelectedEvent;
import clueless.events.CharacterSelectedEventListener;
import clueless.events.CharactersAvailableEvent;
import clueless.events.CharactersAvailableEventListener;
import clueless.events.CharactersRequestEvent;
import clueless.events.CharactersRequestEventListener;
import clueless.events.ClientJoinedEvent;
import clueless.events.ClientJoinedEventListener;
import clueless.events.DisconnectEvent;
import clueless.events.DisconnectEventListener;
import clueless.events.DisproveCardEvent;
import clueless.events.DisproveCardEventListener;
import clueless.events.EndTurnEvent;
import clueless.events.EndTurnEventListener;
import clueless.events.MakeAccusationEvent;
import clueless.events.MakeAccusationEventListener;
import clueless.events.MakeMoveEvent;
import clueless.events.MakeMoveEventListener;
import clueless.events.MakeSuggestionEvent;
import clueless.events.MakeSuggestionEventListener;
import clueless.events.MessageEvent;
import clueless.events.MessageEventListener;
import clueless.events.ServerClientInfoEvent;
import clueless.events.ServerClientInfoEventListener;
import clueless.events.SuggestionDisprovedNeedFeedBackEvent;
import clueless.events.SuggestionDisprovedNeedFeedBackEventListener;
import clueless.events.TextStatusEvent;
import clueless.events.TextStatusEventListener;
import clueless.messaging.AccusationMessage;
import clueless.messaging.AvailableMoveMessage;
import clueless.messaging.CurrentLocationMessage;
import clueless.messaging.DisconnectMessage;
import clueless.messaging.DrawPawnsMessage;
import clueless.messaging.EndGameMessage;
import clueless.messaging.EndTurnMessage;
import clueless.messaging.GameInitializationMessage;
import clueless.messaging.CurrentLocationRequestMessage;
import clueless.messaging.GetMoveMessage;
import clueless.messaging.MoveMessage;
import clueless.messaging.SendClientPlayerMessage;
import clueless.messaging.ShowTextStatusMessage;
import clueless.messaging.SuggestionDisprovedCardMessage;
import clueless.messaging.SuggestionDisprovedMessage;
import clueless.messaging.SuggestionDisprovedNeedFeedBackMessage;
import clueless.messaging.SuggestionMessage;
import clueless.messaging.CharactersAvailableMessage;
import clueless.messaging.CharactersRequestMessage;
import clueless.messaging.CharacterSelectedMessage;
import clueless.messaging.TakeCharacterMessage;
import clueless.messaging.TextStatusMessage;
import clueless.model.AbstractModel;
import clueless.model.CaseFile;
import clueless.model.Character.CharacterName;
import clueless.model.Game;
import clueless.model.Hallway;
import clueless.model.Hallway.HallwayName;
import clueless.model.Location;
import clueless.model.Location.LocationType;
import clueless.model.Player;
import clueless.model.decks.Card;
import clueless.model.decks.CharacterCard;
import clueless.model.decks.CharacterDeck;
import clueless.model.decks.LocationCard;
import clueless.model.decks.LocationDeck;
import clueless.model.decks.WeaponCard;
import clueless.model.decks.WeaponDeck;
import clueless.model.Theory;
import clueless.view.AbstractView;
import clueless.view.BoardView;
import clueless.view.MainGameView;
import clueless.view.PlayerSetup;
import clueless.view.WaitForClientsView;

/**
* GameController
*
* Class responsible for interfacing between the
* game views and model. Handles Server behavior
* and events.
*
* @author T
*/
public class GameController implements   ServerClientInfoEventListener,
                    MessageEventListener,
                    CharacterSelectedEventListener,
                    MakeAccusationEventListener,
                    MakeSuggestionEventListener,
                    MakeMoveEventListener,
                    ClientJoinedEventListener,
                    CharactersRequestEventListener,
                    EndTurnEventListener,
                    TextStatusEventListener,
                    DisproveCardEventListener,
                    SuggestionDisprovedNeedFeedBackEventListener,
                    DisconnectEventListener{
 
  /** The list of all registered Models. */
  private Vector<AbstractModel> registeredModels = null;

  /** The list of all registered Views. */
  private Vector<AbstractView> registeredViews = null;

  /** The list of all event listeners. */
  private EventListenerList  eventListeners = null;

  /** Handle to the main View for this instance of Clueless. */
  MainGameView mainView = null;

  /** Handle to the server - this field is only non-null when this is the host/server. */
  CluelessServer server = null;

  /** Handle to this client instance */
  CluelessClient client = null;

  /** True if this is a server implementation, false otherwise. */
  boolean isServer = false;

  /** Game model, non-null when this is host */
  Game game = null;

  /** Player whose turn it is currently */
  private Player currentPlayer = null;
 
  /** The character names of all players whose names have been selected */
  private Vector<CharacterName> characterNames = new Vector<CharacterName>();
 
  /** The number of player required to start the game. */
  private int numPlayers = 0;

  /**
   * Public constructor.
   */
  public GameController(){
    registeredModels = new Vector<AbstractModel>();
    registeredViews  = new Vector<AbstractView>();
    eventListeners   = new EventListenerList();
    this.addServerClientInfoEventListener(this);
    this.addCharacterSelectedEventListener(this);
    this.addMakeAccusationEventListener(this);
    this.addMakeSuggestionEventListener(this);
    this.addClientJoinedEventListener(this);
    this.addCharactersRequestEventListener(this);
    this.addMessageEventListener(this);
    this.addEndTurnEventListener(this);
    this.addDisproveCardEventListener(this);
    this.addMakeMoveEventListener(this);
    this.addTextStatusEventListener(this);
    mainView = new MainGameView(this);
    mainView.gameSetup();


    //mainView.initialView();
  }

  /**
   * Sets the currentPlayer object to a reference to the next player in the game
   * @return Next player
   */
  public Player getNextPlayer()
  {
    //To keep track of whose turn it is / move to next
    currentPlayer = game.getPlayers().get(((game.getPlayers().indexOf(currentPlayer)+1)%game.getNumberOfPlayers()));
    return currentPlayer;
  }

  /**
   * Looks at next player in vector without modifying game's currentPlayer
   * might be useful for suggestions?
   * @param player - player who is before the return value
   * @return player - player who is after the parameter
   */
  public Player peekNextPlayer(Player player)
  {
    return game.getPlayers().get(((game.getPlayers().indexOf(player)+1)%game.getNumberOfPlayers())-1);
  }

  /**
   * Returns current player whose turn it is
   * @return current player whose turn it is
   */
  public Player getCurrentPlayer()
  {
    if(isServer)
    {
      if(currentPlayer == null)
        return game.getPlayers().firstElement();
      return currentPlayer;
    }
    else
      return client.getPlayer();
  }
 
  /**
   * Returns Player at a given Vector Index
   * Required for initial Client matching with premade Players
   * @param index
   * @return Player at index
   */
  public Player getPlayerAtIndex(int index){   
    return game.getPlayers().elementAt(index);
  }

  /**
   * Sets number of players entered by host and deals cards to them pre-emptively
   * @param playerCount Number of players before starting game
   */
  public void setNumberOfPlayers(int playerCount)
  {
    //Once number of players is known, instantiate them so they have UUIDs
    for(int i=0; i<playerCount; i++)
    {
      game.joinGame(new Player(this));
    }
    //initialize currentPlayer object
    currentPlayer = game.getPlayers().get(0);
    //then deal their cards
    game.dealCards();
  }

  public void addModel(AbstractModel model){
    if(!registeredModels.contains(model)){
      registeredModels.add(model);
    }
  }

  public void removeModel(AbstractModel model){
    registeredModels.remove(model);

    // TODO - remove all associated listeners
  }

  public void addView(AbstractView view){ 
    if(!registeredViews.contains(view)){
      registeredViews.add(view);
    }
  }
  public void removeView(AbstractView view){
    registeredViews.remove(view);

    // TODO - remove all associated listeners
  }

  /**
   * Adds a listener for the ServerClientInfo event.
   * @param listener - the event listener
   */
  public synchronized void addServerClientInfoEventListener(ServerClientInfoEventListener listener){
    eventListeners.add(ServerClientInfoEventListener.class, listener);
  }

  /**
   * Removes a listener for the ServerClientInfo event from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeServerClientInfoEventListener(ServerClientInfoEventListener listener){
    eventListeners.remove(ServerClientInfoEventListener.class, listener);
  }

  /**
   * Fires an event of type ServerClientInfo for all listeners.
   * @param event - the ServerClientInfoEvent
   */
  public synchronized void fireServerClientInfoEvent(ServerClientInfoEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==ServerClientInfoEventListener.class){
        ((ServerClientInfoEventListener)listeners[i+1]).handleServerClientInfoEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the CharacterSelectedEvent.
   * @param listener - the event listener
   */
  public synchronized void addCharacterSelectedEventListener(CharacterSelectedEventListener listener){
    eventListeners.add(CharacterSelectedEventListener.class, listener);
  }

  /**
   * Removes a listener for the CharacterSelectedEvent from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeCharacterSelectedEventListener(CharacterSelectedEventListener listener){
    eventListeners.remove(CharacterSelectedEventListener.class, listener);
  }

  /**
   * Fires an event of type CharacterSelected for all listeners.
   * @param event - the CharacterSelectedEvent
   */
  public synchronized void fireCharacterSelectedEvent(CharacterSelectedEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==CharacterSelectedEventListener.class){
        ((CharacterSelectedEventListener)listeners[i+1]).handleCharacterSelectedEvent(event);
      }
    }
  }
 
  /**
   * Adds a listener for the MakeMove event.
   * @param listener - the event listener
   */
  public synchronized void addMakeMoveEventListener(MakeMoveEventListener listener){
    eventListeners.add(MakeMoveEventListener.class, listener);
  }

  /**
   * Removes a listener for the MakeMove event from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeMakeMoveEventListener(MakeMoveEventListener listener){
    eventListeners.remove(MakeMoveEventListener.class, listener);
  }

  /**
   * Fires an event of type MakeMove for all listeners.
   * @param event - the MakeMoveEvent
   */
  public synchronized void fireMakeMoveEvent(MakeMoveEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==MakeMoveEventListener.class){
        ((MakeMoveEventListener)listeners[i+1]).handleMakeMoveEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the MessageEvent event to the controller's list.
   * @param listener - the event listener
   */
  public synchronized void addMessageEventListener(MessageEventListener listener){
    eventListeners.add(MessageEventListener.class, listener);
  }

  /**
   * Removes a listener for the MessageEvent event from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeMessageEventListener(MessageEventListener listener){
    eventListeners.remove(MessageEventListener.class, listener);
  }

  /**
   * Fires an event of type MessageEvent for all listeners
   * @param event - the MessageEvent
   */
  public synchronized void fireMessageEvent(MessageEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==MessageEventListener.class){
        ((MessageEventListener)listeners[i+1]).handleMessageEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the MakeAccusation event.
   * @param listener - the event listener
   */
  public synchronized void addMakeAccusationEventListener(MakeAccusationEventListener listener){
    eventListeners.add(MakeAccusationEventListener.class, listener);
  }

  /**
   * Removes a listener for the MakeAccusationEvent from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeMakeAccusationEventListener(MakeAccusationEventListener listener){
    eventListeners.remove(MakeAccusationEventListener.class, listener);
  }

  /**
   * Fires an event of type MakeAccusationEvent for all listeners.
   * @param event - the ServerClientInfoEvent
   */
  public synchronized void fireMakeAccusationEvent(MakeAccusationEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==MakeAccusationEventListener.class){
        ((MakeAccusationEventListener)listeners[i+1]).handleMakeAccusationEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the MakeSuggestion event.
   * @param listener - the event listener
   */
  public synchronized void addMakeSuggestionEventListener(MakeSuggestionEventListener listener){
    eventListeners.add(MakeSuggestionEventListener.class, listener);
  }

  /**
   * Removes a listener for the MakeSuggestionEvent from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeMakeSuggestionEventListener(MakeSuggestionEventListener listener){
    eventListeners.remove(MakeSuggestionEventListener.class, listener);
  }

  /**
   * Fires an event of type MakeSuggestionEvent for all listeners.
   * @param event - the ServerClientInfoEvent
   */
  public synchronized void fireMakeSuggestionEvent(MakeSuggestionEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==MakeSuggestionEventListener.class){
        ((MakeSuggestionEventListener)listeners[i+1]).handleMakeSuggestionEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the ClientJoined event.
   * @param listener - the event listener
   */
  public synchronized void addClientJoinedEventListener(ClientJoinedEventListener listener){
    eventListeners.add(ClientJoinedEventListener.class, listener);
  }

  /**
   * Removes a listener for the ClientJoined from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeaddClientJoinedEventListener(ClientJoinedEventListener listener){
    eventListeners.remove(ClientJoinedEventListener.class, listener);
  }

  /**
   * Fires an event of type ClientJoinedEvent for all listeners.
   * @param event - the ServerClientInfoEvent
   */
  public synchronized void fireClientJoinedEvent(ClientJoinedEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==ClientJoinedEventListener.class){
        ((ClientJoinedEventListener)listeners[i+1]).handleClientJoinedEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the TextStatusEvent event.
   * @param listener - the event listener
   */
  public synchronized void addTextStatusEventListener(TextStatusEventListener listener){
    eventListeners.add(TextStatusEventListener.class, listener);
  }

  /**
   * Removes a listener for the TextStatusEvent from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeTextStatusEventListener(TextStatusEventListener listener){
    eventListeners.remove(TextStatusEventListener.class, listener);
  }

  /**
   * Fires an event of type TextStatusEvent for all listeners.
   * @param event - the ServerClientInfoEvent
   */
  public synchronized void fireTextStatusEvent(TextStatusEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==TextStatusEventListener.class){
        ((TextStatusEventListener)listeners[i+1]).handleTextStatusEvent(event);
      }
    }
  }


  /**
   * Adds a listener for the CharactersAvailableEvent event.
   * @param listener - the event listener
   */
  public synchronized void addCharactersAvailableEventListener(CharactersAvailableEventListener listener){
    eventListeners.add(CharactersAvailableEventListener.class, listener);
  }

  /**
   * Removes a listener for the TextStatusEvent from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeCharactersAvailableEventListener(CharactersAvailableEventListener listener){
    eventListeners.remove(CharactersAvailableEventListener.class, listener);
  }

  /**
   * Fires an event of type TextStatusEvent for all listeners.
   * @param event - the ServerClientInfoEvent
   */
  public synchronized void fireCharactersAvailableEvent(CharactersAvailableEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==CharactersAvailableEventListener.class){
        ((CharactersAvailableEventListener)listeners[i+1]).handleCharactersAvailableEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the CharactersRequestEvent event.
   * @param listener - the event listener
   */
  public synchronized void addCharactersRequestEventListener(CharactersRequestEventListener listener){
    eventListeners.add(CharactersRequestEventListener.class, listener);
  }

  /**
   * Removes a listener for the CharactersRequestEventListener from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeCharacterRequestEventListener(CharactersRequestEventListener listener){
    eventListeners.remove(CharactersRequestEventListener.class, listener);
  }

  /**
   * Fires an event of type CharactersRequestEventListener for all listeners.
   * @param event - the CharactersRequestEventListener
   */
  public synchronized void fireCharactersRequestEvent(CharactersRequestEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==CharactersRequestEventListener.class){
        ((CharactersRequestEventListener)listeners[i+1]).handleCharactersRequestEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the DisproveCardEventListener event.
   * @param listener - the event listener
   */
  public synchronized void addDisproveCardEventListener(DisproveCardEventListener listener){
    eventListeners.add(DisproveCardEventListener.class, listener);
  }

  /**
   * Removes a listener for the DisproveCardEventListener from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeDisproveCardEventListener(DisproveCardEventListener listener){
    eventListeners.remove(DisproveCardEventListener.class, listener);
  }

  /**
   * Fires an event of type DisproveCardEventListener for all listeners.
   * @param event - the DisproveCardEventListener
   */
  public synchronized void fireDisproveCardEvent(DisproveCardEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==DisproveCardEventListener.class){
        ((DisproveCardEventListener)listeners[i+1]).handleDisproveCardEvent(event);
      }
    }
  }
 
  /**
   * Adds a listener for the SuggestionDisprovedNeedFeedBackEvent event.
   * @param listener - the event listener
   */
  public synchronized void addSuggestionDisprovedNeedFeedBackEventListener(SuggestionDisprovedNeedFeedBackEventListener listener){
    eventListeners.add(SuggestionDisprovedNeedFeedBackEventListener.class, listener);
  }
 
  /**
   * Removes a listener for the SuggestionDisprovedNeedFeedBackEventListener from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeSuggestionDisprovedNeedFeedBackEventListener(SuggestionDisprovedNeedFeedBackEventListener listener){
    eventListeners.remove(SuggestionDisprovedNeedFeedBackEventListener.class, listener);
  }

  /**
   * Fires an event of type SuggestionDisprovedNeedFeedBackEventListener for all listeners.
   * @param event - the SuggestionDisprovedNeedFeedBackEventListener
   */
  public synchronized void fireSuggestionDisprovedNeedFeedBackEvent(SuggestionDisprovedNeedFeedBackEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==SuggestionDisprovedNeedFeedBackEventListener.class){
        ((SuggestionDisprovedNeedFeedBackEventListener)listeners[i+1]).handleSuggestionDisprovedNeedFeedBackEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the EndTurnEvent.
   * @param listener - the event listener
   */
  public synchronized void addEndTurnEventListener(EndTurnEventListener listener){
    eventListeners.add(EndTurnEventListener.class, listener);
  }

  /**
   * Removes a listener for the EndTurnEvent from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeEndTurnEventListener(EndTurnEventListener listener){
    eventListeners.remove(EndTurnEventListener.class, listener);
  }

  /**
   * Fires an event of type EndTurn for all listeners.
   * @param event - the EndTurnEvent
   */
  public synchronized void fireEndTurnEvent(EndTurnEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==EndTurnEventListener.class){
        ((EndTurnEventListener)listeners[i+1]).handleEndTurnEvent(event);
      }
    }
  }

  /**
   * Adds a listener for the DisconnectEvent event.
   * @param listener - the event listener
   */
  public synchronized void addDisconnectEvent(DisconnectEventListener listener){
    eventListeners.add(DisconnectEventListener.class, listener);
  }
 
  /**
   * Removes a listener for the SuggestionDisprovedNeedFeedBackEventListener from the controller's list.
   * @param listener - the event listener
   */
  public synchronized void removeDisconnectEventListener(DisconnectEventListener listener){
    eventListeners.remove(DisconnectEventListener.class, listener);
  }

  /**
   * Fires an event of type SuggestionDisprovedNeedFeedBackEventListener for all listeners.
   * @param event - the SuggestionDisprovedNeedFeedBackEventListener
   */
  public synchronized void fireDisconnectEvent(DisconnectEvent event){
    Object[] listeners = eventListeners.getListenerList();
    for(int i=0; i<listeners.length; i+=2){
      if(listeners[i]==DisconnectEventListener.class){
        ((DisconnectEventListener)listeners[i+1]).handleDisconnectEvent(event);
      }
    }
  }
 
 
  /**
   * Compares the theory to see if it matches the case file.
   * @param theory - theory to be tested against case file.
   * @return - Whether or not the theory was correct.
   */
  public boolean testTheory(Theory theory){
    if(game!=null && theory != null)
      return game.getCaseFile().isCorrectTheory(theory);
    return false;
  }

  /**
   * @throws Exception
   *
   */
  public void dealCards(CharacterDeck characterDeck, WeaponDeck weaponDeck, LocationDeck roomDeck) throws Exception
  {

    Card nextCardDealt = null;
    int currentPlayer = 0;

    //Loop until we find a deck that still has cards
    while(weaponDeck.hasNextCard() || characterDeck.hasNextCard() || roomDeck.hasNextCard())
    {
      //Pick a random deck

      int randomDeck = (int) (Math.random()*3);
     
      switch(randomDeck)
      {
      case 0: nextCardDealt = weaponDeck.getNextCard();
      break;
      case 1: nextCardDealt = characterDeck.getNextCard();
      break;
      case 2: nextCardDealt = roomDeck.getNextCard();
      break;
      }
      if(nextCardDealt != null)
      {
        //Add it to the current players hand
        this.game.getPlayers().get(currentPlayer%this.game.getNumberOfPlayers()).dealCard(nextCardDealt);
        currentPlayer++;
        nextCardDealt = null;
      }
     
    }
   
  }


  /**
   * Connects the client and (if applicable) the server.
   * @param isServer   - true if this is the host (server), false if just a client.
   * @param ipAddress - the InetAddress for the IP.
   * @param port     - the port number to bind to.
   * @return true upon completion.
   */
  private boolean connect(boolean isServer, InetAddress ipAddress, int port, int numPlayers) {
    this.isServer = isServer;
    this.numPlayers = numPlayers;
    if(isServer){
      server = new CluelessServer(this, port, numPlayers);
      server.start();

      //Create and register Game model
      game = new Game(this);

      /** Display connection status window &
       *  Start Pre-Game actions when all players are connected
       */
      //this.setNumberOfPlayers(numPlayers);
      WaitForClientsView waitView = new WaitForClientsView(this, numPlayers);
      //TODO: Once host has set number of players expected, generate players
      //and deal the cards
      if(this.numPlayersConnected() == 0)
        this.setNumberOfPlayers(numPlayers);
    }
    try {
      client = new CluelessClient(this, ipAddress, port);
      client.setName("Server");
    } catch (IOException e) {
      e.printStackTrace();
    }


    return true;
  }


  /**
   * Disconnects client comms and (if applicable), the server.
   * @return true if disconnect completes.
   */
  public boolean disconnect() {
    if( server != null){
      server.disconnect();
    }
    if(client != null){
      client.disconnect();
    }
    return true;
  }


  public int numPlayersConnected() {
    return server.getNumClients();
  }


  @Override
  public void handleServerClientInfoEvent(ServerClientInfoEvent event) {
    if(this.connect(event.isServer(), event.getIpAddress(), event.getPort(), event.getNumPlayers())){

      // We are connected. Start setting up the GameBoard.
      // mainView = new MainGameView(this);   
      PlayerSetup playerSetup = new PlayerSetup(this);
       
    }
  }

  @Override
  public void handleMessageEvent(MessageEvent event) {
    //System.out.println("Message from " + event.getSource() + " : " + event.getMessage());
    if(event.getMessage() instanceof GameInitializationMessage){
      GameInitializationMessage gameInit = (GameInitializationMessage)event.getMessage();
      return;
    }else if(event.getMessage() instanceof CurrentLocationRequestMessage){
      Vector<Location> spaces = this.game.getSpaces();
      CurrentLocationRequestMessage msg = ((CurrentLocationRequestMessage)event.getMessage());
      if(isServer)
      {
        for(Location space : spaces)
        {
          if(space.getPlayer() != null && space.getPlayer().getUUID().equals(currentPlayer.getUUID())){
            server.send(currentPlayer, new CurrentLocationMessage(space));
          }
        }
      }
    }else if(event.getMessage() instanceof CurrentLocationMessage){
      CurrentLocationMessage msg = ((CurrentLocationMessage)event.getMessage());
      mainView.showSuggestionView(msg.getLocation());
    } else if(event.getMessage() instanceof GetMoveMessage){
      if(isServer){
        GetMoveMessage msg = (GetMoveMessage) event.getMessage();
        for(Location space : game.getSpaces()){
          if(space.getCharacterName() == msg.getCharacterName()){
            server.sendAll(new MoveMessage(msg.getCharacterName(), msg.getNewLocation(), space));
            return;
          }
        }
      }
    } else if(event.getMessage() instanceof DrawPawnsMessage){
      if(isServer){
        ShowTextStatusMessage txt = new ShowTextStatusMessage("Game is beginning. ");
        server.sendAll(txt);
       
        DrawPawnsMessage msg = (DrawPawnsMessage) event.getMessage();
        for(CharacterName name : msg.getNames()){
          HallwayName hallway = BoardView.getDefaultHall(name);
          for(Location space : game.getSpaces()){
            if(space.getLocationType()==LocationType.HALLWAY_TYPE){
              if(((Hallway)space).getHallwayName() == hallway){
                space.setCharacterName(name);
                break;
              }
            }
          }
        }
      }
    }else if(event.getMessage() instanceof SendClientPlayerMessage) {
      client.setPlayer(((SendClientPlayerMessage) event.getMessage()).getPlayer());
      return;
    }else if(event.getMessage() instanceof CharactersAvailableMessage) {
      fireCharactersAvailableEvent(new CharactersAvailableEvent(this,
          ((CharactersAvailableMessage) event.getMessage()).getNames()));
      return;
    }else if(event.getMessage() instanceof CharactersRequestMessage) {
      fireCharactersRequestEvent(new CharactersRequestEvent(this));
      return;
    }else if(event.getMessage() instanceof TakeCharacterMessage) {
      if (isServer){
        //TODO: Make setPlayerCharacter return boolean for success (non duplicate)
        TakeCharacterMessage msg = (TakeCharacterMessage)event.getMessage();
        game.setPlayerCharacter(msg.getPlayer(), msg.getCharacterName());
        server.sendAll(new CharactersAvailableMessage(game));
        characterNames.add(msg.getCharacterName());
        if(characterNames.size() == this.numPlayers){
          // All of the players have selected their characters.
          // Tell everyone to draw their board and determine who goes first.
          server.sendAll(new DrawPawnsMessage(characterNames));
         
          Player firstPlayer = null;
          for(Player player : game.getPlayers()){
            if(player.getCharacter()== CharacterName.MISS_SCARLET){
              // Miss scarlet always goes first according to Clue rules.
              firstPlayer = player;
            }
          }
          if(firstPlayer == null){
            // Miss Scarlet is not in play so just choose someone to go first.
            firstPlayer = game.getPlayers().get(0);
          }
          currentPlayer = firstPlayer;
          this.fireTextStatusEvent(new TextStatusEvent(this, "Player "+ firstPlayer.getCharacter().toString() + " will go first. "));
         
          // Game on - start first turn.
          HallwayName hallwy = BoardView.getDefaultHall(currentPlayer.getCharacter());
          Hallway currHallwy = null;
          for(Location space : game.getSpaces()){
            if(space.getLocationType() == LocationType.HALLWAY_TYPE){
              if(((Hallway)space).getHallwayName() == hallwy){
                currHallwy = (Hallway)space;
              }
            }
          }
          server.send(currentPlayer, new AvailableMoveMessage(game.getValidMoves(currHallwy), currentPlayer.getCharacter()));
        }
      }
    }else if(event.getMessage() instanceof EndTurnMessage){
      if(isServer){
        //Move to the next player when we receive this message
        this.getNextPlayer();
        //TODO: Send available move message?  This still needs to be tested
        for(Location location : game.getSpaces()){
          Player player = location.getPlayer();
          if(player != null){
            if(player.getUUID().equals(currentPlayer.getUUID())){
              server.send(currentPlayer, new AvailableMoveMessage(game.getValidMoves(location), currentPlayer.getCharacter()));
              fireTextStatusEvent(new TextStatusEvent(this, "It is now " + currentPlayer.getCharacter() + "'s turn."))
            }
          }
        }
      }
      return;
    }else if(event.getMessage() instanceof TextStatusMessage && !(event.getMessage() instanceof ShowTextStatusMessage)){
      //Text status message sent from server
      ShowTextStatusMessage msg = new ShowTextStatusMessage(((TextStatusMessage) event.getMessage()).getMessageText());
      if(isServer)
      {
        server.sendAll(msg);
      }
    }else if(event.getMessage() instanceof CharacterSelectedMessage) {
      fireCharacterSelectedEvent(new CharacterSelectedEvent(this,
          ((CharacterSelectedMessage) event.getMessage()).getCharacter()));
      return;
    }else if(event.getMessage() instanceof AccusationMessage){
      AccusationMessage msg = ((AccusationMessage)event.getMessage());
      this.fireMakeAccusationEvent(new MakeAccusationEvent(event, msg.getTheory()));
      return;
    }else if(event.getMessage() instanceof SuggestionMessage){
      SuggestionMessage msg = ((SuggestionMessage)event.getMessage());
      this.fireMakeSuggestionEvent(new MakeSuggestionEvent(event, msg.getTheory()));
      return;
    }else if (event.getMessage() instanceof SuggestionDisprovedMessage)
    {
     
    }else if(event.getMessage() instanceof SuggestionDisprovedNeedFeedBackMessage){
      this.fireSuggestionDisprovedNeedFeedBackEvent(new SuggestionDisprovedNeedFeedBackEvent(this, ((SuggestionDisprovedNeedFeedBackMessage)event.getMessage()).getSuggestion(), ((SuggestionDisprovedNeedFeedBackMessage)event.getMessage()).getCards()));
    }else if(event.getMessage() instanceof SuggestionDisprovedCardMessage){
      if(isServer && !(client.getPlayer().getUUID().equals(currentPlayer.getUUID())))
      {
        //Forward the message onto the client
        server.send(currentPlayer, event.getMessage());
        //fireDisproveCardEvent(new DisproveCardEvent(this, ((SuggestionDisprovedCardMessage)event.getMessage()).getDisprovedCard()));
      }
      //Show a message box indicating what card was disproved
      String card = "";
      if(((SuggestionDisprovedCardMessage)event.getMessage()).getDisprovedCard() instanceof WeaponCard)
        card = ((WeaponCard)((SuggestionDisprovedCardMessage)event.getMessage()).getDisprovedCard()).getWeaponType().toString();
      else if(((SuggestionDisprovedCardMessage)event.getMessage()).getDisprovedCard() instanceof LocationCard)
        card = ((LocationCard)((SuggestionDisprovedCardMessage)event.getMessage()).getDisprovedCard()).getLocationName().toString();
      else if (((SuggestionDisprovedCardMessage)event.getMessage()).getDisprovedCard() instanceof CharacterCard)
        card = ((CharacterCard)((SuggestionDisprovedCardMessage)event.getMessage()).getDisprovedCard()).getCharacterName().toString();
     
      JOptionPane.showMessageDialog(null,  card + " has been disproven.");
    }else if(event.getMessage() instanceof EndGameMessage){
      EndGameMessage msg = (EndGameMessage) event.getMessage();
      JOptionPane.showMessageDialog(null, "Game Over!  " + msg.getWinner().getCharacter().toString() + " has solved the case!");
      mainView.quitGame();
      client.disconnect();
      if(isServer)
      {
        server.disconnect();
      }
     
    }else if(event.getMessage() instanceof DisconnectMessage){
      // Notify all players that someone quit
    }
  }


  @Override
  public void handleCharacterSelectedEvent(CharacterSelectedEvent event) {   
  client.send(new TakeCharacterMessage(client.getPlayer(), event.getName()));
    mainView.initialView()
  }

  @Override
  public void handleMakeAccusationEvent(MakeAccusationEvent event) {
    Theory theory = event.getTheory();

    //If fired by main game view, show the accusation view
    if(theory == null)
    {
      mainView.showAccusationView();
    }
    else //otherwise, fired by AccusationView and it contains an actual theory
    {
      //if host, pass message to clients indicating the suggestion being made, and whether it was correct
      if(isServer)
      {
        this.fireTextStatusEvent(new TextStatusEvent(this, theory.getTheoryText()));
        //check if theory is correct
        boolean isTheoryCorrect = testTheory(theory);
        if(isTheoryCorrect){
          this.fireTextStatusEvent(new TextStatusEvent(this, "Case Solved!"));
          //System.out.println("Case Solved!");
          // Do something like end game?
          server.sendAll(new EndGameMessage(currentPlayer));
        }
        else
        {
          this.fireTextStatusEvent(new TextStatusEvent(this, "Theory was incorrect."));
        }
         
        //AccusationMessage accusationMsg = new AccusationMessage(theory);
        //this.server.sendAll(accusationMsg);
        //this.getNextPlayer();
        //TODO:  handle if it is correct -- ending game etc.
      }
      else
      {
        client.send(new AccusationMessage(theory));
        this.fireEndTurnEvent(new EndTurnEvent(this));
        //client.send(new EndTurnMessage());
      }
    }
  }

  @Override
  public void handleMakeSuggestionEvent(MakeSuggestionEvent event) {
    /*if server, pass message to clients indicating the suggestion being made,
     *so they may respond
     *If fired by main game view, show the suggestion view and pass
     *the player's current location
     */
    Theory theory = event.getTheory();
    if(theory == null)
    {
      //TODO: Need to get current player location
      //Ask server for current player location
      CurrentLocationRequestMessage msg = new CurrentLocationRequestMessage();
      msg.setPlayer(client.getPlayer());
      client.send(msg);
    }
    else //otherwise, fired by SuggestionView and it contains an actual theory
    {
      this.fireTextStatusEvent(new TextStatusEvent(this, theory.getTheoryText()));
      if(isServer)
      {
        //Inject player as theorist if null
        if(theory.getTheorist() == null)
          theory = new Theory(Theory.Type.SUGGESTION, theory.getWeapon(), theory.getCharacter(), theory.getLocation(), this.currentPlayer); //this.client.getPlayer());
       

        //TODO:  Shouldn't this only check the immediately next player, unless they have none of the cards in question?
       
        for(Player player : this.game.getPlayers())
        {
          if(!player.equals(currentPlayer))
          {
            Vector<Card> hand = player.getHand();
            LinkedList<Card> invalidCards = new LinkedList<Card>();
            for(Card card : hand){
              switch(card.getCardType()){
              case WEAPON_CARD:
                if(theory.getWeapon().getWeaponType().equals(((WeaponCard)card).getWeaponType())){
                  invalidCards.add(card);
                }
                break;
              case CHARACTER_CARD:
                if(theory.getCharacter().getCharacterName().equals(((CharacterCard)card).getCharacterName())){
                  invalidCards.add(card);
                }
                break;
              case LOCATION_CARD:
                if(theory.getLocation().getRoomName().equals(((LocationCard)card).getLocationName())){
                  invalidCards.add(card);
                }
                break;
              }
             
            }
            if(invalidCards != null){
              if(invalidCards.size()==1) {
                // This player has one of the suggestion cards, notify the suggester AND let everyone else know at least one card in the suggestion is wrong.
                server.send(theory.getTheorist(), new SuggestionDisprovedCardMessage(player, invalidCards.get(0)));
                server.sendAll(new SuggestionDisprovedMessage(player, theory));
                return;
              } else if(invalidCards.size()>1) {
                // This player has more than one card - we need them to decide which one to show the suggester.
                this.fireSuggestionDisprovedNeedFeedBackEvent(new SuggestionDisprovedNeedFeedBackEvent(this, theory, invalidCards));
                server.sendAll(new SuggestionDisprovedMessage(player, theory));
                server.send(player, new SuggestionDisprovedNeedFeedBackMessage(theory, invalidCards));
                return; //If we hit 1 result, it moves to the next player's turn. Not all cards in the suggestion get proved.
              }
              fireTextStatusEvent(new TextStatusEvent(this, "Theory disproven."));
            }
          }
        }
      }
      else
      {
        client.send(new SuggestionMessage(theory));
        this.fireEndTurnEvent(new EndTurnEvent(this));
        //client.send(new EndTurnMessage());
      }
//      else
//      {
//
//        theory = new Theory(Theory.Type.SUGGESTION, theory.getWeapon(), theory.getCharacter(), theory.getLocation(), this.client.getPlayer());
//        SuggestionMessage msg = new SuggestionMessage(theory);
//        client.send(msg);
//      }
     
    }
  }

  @Override
  public void handleClientJoinedEvent(ClientJoinedEvent event)
  {
    if(isServer)
    { 

      //Game already instantiated and cards already dealt so we can assign players that
      event.getClient().setPlayer(this.game.getPlayers().get(server.getNumClients()-1));
      if(game.getNumberOfPlayers()==server.getNumClients())
      {
        this.fireTextStatusEvent(new TextStatusEvent(this, "Last player joined."));
        //Once number of clients connect = number of players in the game,
        //send game init message which includes hands
        for(Player player : this.game.getPlayers())
        {
          server.send(player, new GameInitializationMessage(player.getHand(), (player.getUUID().equals(this.getCurrentPlayer()))));
          //server.getClientThread(player)
          //server.send(player, new SendClientPlayerMessage(player));
          //System.out.println("playerSent: " + player.getCharacter());
        }
      }
      else
      {
        //TODO: update clients on how many more players we're waiting on
        String gameStatusText = "There are currently " + server.getNumClients() + " players connected.  Waiting for " + (this.game.getNumberOfPlayers()-server.getNumClients()) + " more players to join.";
        this.fireTextStatusEvent(new TextStatusEvent(this, gameStatusText));
      }
    }



  }

  @Override
  public void handleCharactersRequestEvent(CharactersRequestEvent event) {

    /** Send message to all listening clients with Vector of names */
    if(isServer)
    {
      server.sendAll(new CharactersAvailableMessage(game));
    }

    /** If this is not the server, send request message to server */
    if(!isServer){
      client.send(new CharactersRequestMessage());
    }
  }

  @Override
  public void handleEndTurnEvent(EndTurnEvent event) {
    /**Send message to server indicating players turn is over */
    if(isServer)
    {
      //server.send(currentPlayer, new EndTurnMessage());
      this.fireTextStatusEvent(new TextStatusEvent(this, currentPlayer.getCharacter() + "'s turn is over."));
    }
    client.send(new EndTurnMessage());
   
  }

  @Override
  public void handleTextStatusEvent(TextStatusEvent event) {
    TextStatusMessage msg = new TextStatusMessage(event.getStatusMessage());
    //System.out.println("player: " + client.getPlayer().getUUID());
    msg.setPlayer(client.getPlayer());
    client.send(msg);

  }

  @Override
  public void handleSuggestionDisprovedNeedFeedBackEvent(SuggestionDisprovedNeedFeedBackEvent event) {
    // TODO Auto-generated method stub
   
  }

  @Override
  public void handleDisproveCardEvent(DisproveCardEvent event) {
    //Send disproved card to current player who had made the suggestion
    if(isServer)
    {
      //server.send(currentPlayer, new SuggestionDisprovedCardMessage(currentPlayer, ((DisproveCardEvent)event).getDisprovedCard()));
    }

    //Otherwise let the server know
    client.send(new SuggestionDisprovedCardMessage(client.getPlayer(), ((DisproveCardEvent)event).getDisprovedCard()));
  }

  @Override
  public void handleMakeMoveEvent(MakeMoveEvent event) {
    // The client being controlled by this controller has chosen to make a move
    client.send(new GetMoveMessage(event.getCharacterName(), event.getNewLocation()));
  }

  @Override
  public void handleDisconnectEvent(DisconnectEvent event) {
    // The client being controlled by this controller has chosen to quit
    client.send(new DisconnectMessage());
   
  }
}
TOP

Related Classes of clueless.controller.GameController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.