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());
}
}