package com.hypefiend.javagamebook.games.Gridgame; import javax.swing.JDialog; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import com.hypefiend.javagamebook.games.Gridgame.GridGUI; import com.hypefiend.javagamebook.client.GameClient; import com.hypefiend.javagamebook.common.GameEvent; import com.hypefiend.javagamebook.common.GameEventDefault; import org.apache.log4j.BasicConfigurator; /** * Encapsulates a network connection between the GridGame client instance and the server. * * @author William Tracy */ public class NetworkConnection { private GridClient client; private NetworkEventListener listener; private GridGUI myView; private JOptionPane playerSelector; private JDialog playerDialog; private JList playerList; private final static String[] kAloneMsg = {"No other players online."}; static { BasicConfigurator.configure(); } /** * Handles network events. */ private class NetworkHandler implements Runnable { public void run() { try { // Proccess all events while (client.hasEvent()) { GameEvent event = (GameEventDefault)client.getEvent(); // React based on event type switch (event.getType()) { case(GameEventDefault.S_DISCONNECT): listener.disconnected(event.getMessage()); break; case(GameEventDefault.S_GAME_OVER): listener.gameOver(event.getMessage()); break; case(GameEventDefault.S_GET_PLAYERS): if (event.getMessage()==null) { playerList.setListData(kAloneMsg); } else { playerList.setListData(event.getMessage().split("\n")); } break; case(GameEventDefault.S_JOIN_GAME_ACK_FAIL): listener.joinGameFailed(event.getMessage()); break; case(GameEventDefault.S_JOIN_GAME_ACK_OK): listener.joinGameSucceeded(event.getMessage()); break; case(GameEventDefault.S_LOGIN_ACK_FAIL): listener.loginFailed(event.getMessage()); break; case(GameEventDefault.S_LOGIN_ACK_OK): listener.loginSucceeded(event.getMessage()); break; case(GameEventDefault.S_MOVE_ACK_FAIL): listener.moveFailed(event.getMessage()); break; case(GameEventDefault.S_MOVE_ACK_OK): listener.moveSucceeded(event.getMessage()); break; case(GameEventDefault.S_ROUND_COMPLETE): listener.roundCompleted(event.getMessage()); break; case(GameEventDefault.SB_CHAT_MSG): listener.chatReceived( "<" + event.getPlayerId() + "> " + event.getMessage()); break; case(GameEventDefault.SB_LOGIN): client.sendEvent(new GameEventDefault(GameEventDefault.C_GET_PLAYERS)); break; case(GameEventDefault.SB_LOGOUT): client.sendEvent(new GameEventDefault(GameEventDefault.C_GET_PLAYERS)); break; case(GameEventDefault.C_MOVE): listener.opponentMoved(event.getMessage()); break; default: JOptionPane.showMessageDialog( myView, event.getMessage(), "Unknown message from server", JOptionPane.ERROR_MESSAGE); } } } catch (InterruptedException e) { // break out of loop and move on e.printStackTrace(); } } } protected NetworkConnection(GridGUI view, NetworkEventListener listen) { client = new GridClient(new NetworkHandler()); myView = view; listener = listen; playerList = new JList(); playerList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); playerSelector = new JOptionPane( new JScrollPane(playerList), JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); playerDialog = playerSelector.createDialog(view, "Select an opponent"); } /** * Find a server and establish a connection with it. */ protected void connect() { // prompt for username String username = JOptionPane.showInputDialog( myView, "Pick a user name:", System.getProperty("user.name")); // prompt for server String server = JOptionPane.showInputDialog(myView, "Pick a host:", "localhost"); client.init(new String[]{server, username}); client.start(); } /** * Select an opponent from the players logged into the server. */ public void requestOpponent() { playerDialog.setVisible(true); // If no player was selected if (playerList.getSelectedValue() == null) { JOptionPane.showMessageDialog( myView, "No opponent was selected.", "Warning", JOptionPane.WARNING_MESSAGE); } // If a player was selected else if ((Integer)playerSelector.getValue() == JOptionPane.OK_OPTION) { client.sendEvent( new GameEventDefault( GameEventDefault.C_JOIN_GAME, (String)playerList.getSelectedValue())); } } /** * Announce that a game has been completed. * * @param message the notification to send to the other player. */ public void endGame(String message) { client.sendEvent(new GameEventDefault(GameEventDefault.S_GAME_OVER, message)); } /** * Fires off a chat message to all players connected to a server. * * @param message whatever you want to say */ public void sendChat(String message) { client.sendEvent(new GameEventDefault(GameEventDefault.C_CHAT_MSG, message)); } /** * Send a move. * * @param move the move encoded as a string */ public void sendMove(String move) { client.sendEvent(new GameEventDefault(GameEventDefault.C_MOVE, move)); } /** * Terminate a game prematurely. * * @param message the notification to send to the other player */ public void quit(String message) { client.sendEvent(new GameEventDefault(GameEventDefault.C_QUIT_GAME, message)); } /** * Disconnect from the server. * * @param message a goodbye message */ public void logout(String message) { client.sendEvent(new GameEventDefault(GameEventDefault.C_LOGOUT, message)); } /** * Confirm that the other player's move has been successfully completed. * * @param message feedback about the result of the move. */ public void acknowledgeMove(String message) { client.sendEvent(new GameEventDefault(GameEventDefault.S_MOVE_ACK_OK, message)); } /** * Inform the opponent that the last move was illegal. * * @param message the reason for denying the move */ public void denyMove(String message) { client.sendEvent(new GameEventDefault(GameEventDefault.S_MOVE_ACK_FAIL, message)); } } /** * An adapter that allows GridGames to talk to the server. */ class GridClient extends GameClient { private Runnable handler; public GridClient(Runnable handler) { super(); this.handler = handler; } public boolean hasEvent() { return inQueue.size() > 0; } public GameEvent getEvent() throws InterruptedException { return inQueue.deQueue(); } public void sendEvent(GameEvent e) { outQueue.enQueue(e); } protected void processIncomingEvents() { SwingUtilities.invokeLater(handler); } public String getGameName() { return "Grid"; } /** * factory method to create GameEvents */ public GameEvent createGameEvent() { return new GameEventDefault(); } /** * factory method to create login GameEvents */ public GameEvent createLoginEvent() { return new GameEventDefault(GameEventDefault.C_LOGIN); } /** * factory method to create disconnect GameEvents */ public GameEvent createDisconnectEvent(String reason) { return new GameEventDefault(GameEventDefault.S_DISCONNECT, reason); } }