package pdp.scrabble.ihm.action.impl;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JTextField;
import pdp.scrabble.Game;
import pdp.scrabble.game.GameEnvironment;
import pdp.scrabble.game.Letter;
import pdp.scrabble.game.Player;
import pdp.scrabble.game.exception.BoardWrongWordPlace;
import pdp.scrabble.game.Rack;
import pdp.scrabble.ihm.MainFrame;
import pdp.scrabble.ihm.PlayerPanel;
import pdp.scrabble.ihm.MainFrame_old;
import pdp.scrabble.ihm.MultiplayerConnectDialog;
import pdp.scrabble.ihm.MultiplayerPanel;
import pdp.scrabble.ihm.action.MultiplayerAction;
import pdp.scrabble.multiplayer.Client;
import pdp.scrabble.multiplayer.Server;
import pdp.scrabble.multiplayer.impl.ClientImpl;
import pdp.scrabble.utility.Display;
import static pdp.scrabble.Language.getGameLang;
import static pdp.scrabble.Factory.FACTORY;
/** Handle multiplayer button actions.
*/
public class MultiplayerActionImpl implements MultiplayerAction {
/** Main frame reference. */
private MainFrame mainFrame = null;
/** Multiplayer panel reference. */
private MultiplayerPanel panel = null;
/** Server reference. */
private Server server = null;
/** Client reference. */
private Client client = null;
/** Player which handle panel. */
private Player player = null;
/** Game reference. */
private GameEnvironment game = null;
/** Flag which indicate if the player owns the server. */
private boolean serverCreator = false;
/** Turn Reference. */
private boolean isMyTurn = true;
/** Create a new MultiplayerAction.
* @param mainFrame main frame reference.
* @param game game reference.
* @param multiplayerPanel multiplayer panel reference.
*/
public MultiplayerActionImpl(MainFrame mainFrame, GameEnvironment game, MultiplayerPanel multiplayerPanel) {
this.mainFrame = mainFrame;
this.game = game;
this.panel = multiplayerPanel;
}
public void create() {
this.mainFrame.setEnabled(false);
// Initialise dialog
final JDialog dialog = new JDialog();
dialog.setTitle(getGameLang("Server creation"));
dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
dialog.setResizable(false);
dialog.setLayout(new GridLayout(0, 2));
dialog.setMinimumSize(new Dimension(250, 90));
// Fields
final JTextField sname = new JTextField("localhost");
final JTextField sport = new JTextField("1099");
dialog.add(sname);
dialog.add(sport);
// Done button
JButton button = new JButton(getGameLang("Done"));
dialog.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String port = sport.getText();
String host = sname.getText();
if (host.equalsIgnoreCase("")) {
Display.error("Server",
"Please enter an @IP or 'localhost' !");
return;
}
if (port.equalsIgnoreCase("")) {
Display.error("Server", "Please enter a port !");
return;
}
try {
try {
createServer(host, port);
}
catch (NotBoundException ex) {
Display.error("Connection", "Error during connection !");
}
catch (MalformedURLException ex) {
Display.error("Connection", "Bad URL !");
}
catch (UnknownHostException ex) {
Display.error("Connection", "IP error !");
}
}
catch (RemoteException ex) {
Display.error("Connection", "Cannot connect !");
}
dialog.dispose();
terminate();
}
});
//Cancel button
JButton cancelButton = new JButton(getGameLang("Cancel"));
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.dispose();
terminate();
}
});
dialog.add(cancelButton);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
/** Create a new server, ready for client connection.
* @param host server name.
* @param port server port.
* @throws RemoteException Remote exception.
* @throws NotBoundException Not bound exception.
* @throws MalformedURLException Malformed URL exception.
*/
private void createServer(String host, String port)
throws RemoteException, NotBoundException, MalformedURLException, UnknownHostException {
// Server creation
this.server = FACTORY.createServer(Integer.parseInt(port), this.game.getLanguage());
// Player which handle the server is also a client to its server
this.client = FACTORY.createClient(this.mainFrame, this.player.getName());
// Check connection
Server result = this.client.connect(
this.mainFrame, host, port, this.player.getName(),
this.game.getLanguage());
if (result == null) {
Display.error("Server Unreachable", "Connection error");
}
InetAddress Ip = InetAddress.getLocalHost();
Display.information("IP Server", "IP adress server is :", Ip.getHostAddress());
// Update buttons panel
this.panel.getButton("Create").setEnabled(false);
this.panel.getButton("Connect").setEnabled(false);
this.panel.getButton("Disconnect").setEnabled(true);
this.panel.getButton("Ready").setEnabled(true);
this.mainFrame.getMenubar().getItem("New Game").setEnabled(false);
this.mainFrame.getMenubar().getItem("Load Game").setEnabled(false);
this.mainFrame.getMenubar().getItem("Replay").setEnabled(false);
this.mainFrame.getMenubar().getItem("Load Game").setEnabled(false);
this.mainFrame.getMenubar().getItem("Game Options").setEnabled(false);
this.mainFrame.getMenubar().getItem("Save Game").setEnabled(false);
this.serverCreator = true;
}
public void connect() {
MultiplayerConnectDialog dialog =
new MultiplayerConnectDialog(this.mainFrame, this);
dialog.create();
}
public boolean connectTo(String host, String port)
throws RemoteException, NotBoundException, MalformedURLException {
// Create client
this.client = FACTORY.createClient(this.mainFrame, this.player.getName());
// Connect to server
this.server = this.client.connect(this.mainFrame, host, port,
this.player.getName(), this.game.getLanguage());
// Check existence
if (this.server == null) {
Display.error("Connection error", "Server not found");
return false;
}
if (!this.client.isOpen()) {
Display.error("Server", "Server already running or full !");
return false;
}
if (this.client.existName(this.player.getName())) {
Display.error("Username", "Player name already used !");
return false;
}
this.player.setId(this.server.getSizePlayers() - 1);
this.client.setIdClient(this.server.getSizePlayers() - 1);
// Update buttons
this.panel.getButton("Create").setEnabled(false);
this.panel.getButton("Connect").setEnabled(false);
this.panel.getButton("Disconnect").setEnabled(true);
this.panel.getButton("Ready").setEnabled(true);
this.mainFrame.getMenubar().getItem("New Game").setEnabled(false);
this.mainFrame.getMenubar().getItem("Load Game").setEnabled(false);
this.mainFrame.getMenubar().getItem("Replay").setEnabled(false);
this.mainFrame.getMenubar().getItem("Load Game").setEnabled(false);
this.mainFrame.getMenubar().getItem("Game Options").setEnabled(false);
this.mainFrame.getMenubar().getItem("Save Game").setEnabled(false);
return true;
}
public void disconnect() throws RemoteException, MalformedURLException {
this.panel.getButton("Create").setEnabled(true);
this.panel.getButton("Connect").setEnabled(true);
this.panel.getButton("Disconnect").setEnabled(false);
this.panel.getButton("Ready").setEnabled(false);
try {
this.client.disconnect(this.serverCreator);
}
catch (RemoteException ex) {
Display.error("Server", "Error while disconnecting !");
}
this.server = null;
this.panel.clearTable();
this.game.reset();
//List<Letter> list = player.getLetters();
this.player.getRack().clear();
//list.clear();
this.panel.repaint();
this.mainFrame.getMenubar().getItem("New Game").setEnabled(true);
this.mainFrame.getMenubar().getItem("Load Game").setEnabled(true);
this.mainFrame.getMenubar().getItem("Replay").setEnabled(true);
this.mainFrame.getMenubar().getItem("Load Game").setEnabled(true);
this.mainFrame.getMenubar().getItem("Game Options").setEnabled(true);
this.mainFrame.getMenubar().getItem("Save Game").setEnabled(true);
// Terminate connection
if (this.client != null) {
Display.error("Client", "Exited from server !");
}
}
public void readyGameMulti() throws RemoteException {
this.panel.getButton("Ready").setText(getGameLang("Wait"));
this.panel.getButton("Ready").setEnabled(false);
this.server.setPlayertable(
this.player.getID(), null, getGameLang("Ready"), -1);
// Send to server player ready state, launchGame when they are all ready
this.server.sendReadyMulti(this.player.getID());
}
public void launchGameMulti() throws RemoteException, InterruptedException {
final PlayerPanel ppanel = this.mainFrame.getPlayerPanel();
this.panel.getButton("Ready").setText(getGameLang("Launched"));
ppanel.getButton("Help").setEnabled(true);
ppanel.getButton("Game Over").setEnabled(true);
ppanel.getButton("Reset").setEnabled(true);
ppanel.getScorePanel().setVisible(false);
this.game.board().setDictionary(this.game.dictionary());
if (this.client != null) {
this.game.board().addObserver((ClientImpl) this.client);
}
for (int i = 0; i < Rack.MAX_RACK_LETTERS; i++) {
this.player.getRack().addLetter(this.server.pickLetter());
}
// If server creator, start playing or wait for turn
if (this.serverCreator) {
this.server.setPlayertable(
this.player.getID(), null, getGameLang("Playing"), -1);
this.isMyTurn = true;
}
else {
this.server.setPlayertable(
this.player.getID(), null, getGameLang("Thinking"), -1);
this.isMyTurn = false;
ppanel.lock();
}
this.mainFrame.setPlayerPanelPlayer(this.player);
ppanel.getButton("Game Over").addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (mainFrame.getGameSelection() == 2) {
try {
mainFrame.getMultiplayerPanel().getAction().disconnect();
}
catch (RemoteException ex) {
Display.error("Server", "Error while disconnecting !");
}
catch (MalformedURLException ex) {
Display.error("Server", "Error while disconnecting !");
}
}
}
});
// Change turn when pick
ppanel.getButton("Validate").addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (mainFrame.getGameSelection() == 2) {
try {
try {
player.validate();
player.endTurn(true);
}
catch (BoardWrongWordPlace ex) {
Display.error(
"Multiplayer", "This word doesn't exists !");
return;
}
int len = Rack.MAX_RACK_LETTERS - player.getRack().getLetters().length();
for (int i = 0; i < len; i++) {
Letter letter = server.pickLetter();
if (letter != null) {
player.getRack().addLetter(letter);
}
}
ppanel.getButton("Validate").setEnabled(false);
ppanel.getButton("Cancel").setEnabled(false);
ppanel.getButton("Reset").setEnabled(false);
ppanel.getButton("Game Over").setEnabled(true);
panel.endTurn();
server.setPlayertable(player.getID(), player.getName(),
null, player.getScore());
}
catch (RemoteException ex) {
Display.error(
"Multiplayer", "Error while changing player turn !");
}
}
}
});
ppanel.getButton("Reset").addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (mainFrame.getGameSelection() == 2) {
List<Integer> selectedLetters = ppanel.action().getLettersToReset();
Iterator<Integer> itr = selectedLetters.iterator();
while (itr.hasNext()) {
int letterToReset = itr.next();
Letter letter = player.getRack().getLetter(letterToReset);
if (letter != null) {
try {
Letter let = server.exchangeLetter(letter);
player.getRack().changeLetter(letterToReset, let);
}
catch (RemoteException ex) {
Display.error("Reset", "Error while reseting letter.");
}
}
}
ppanel.action().clearLettersToReset();
}
}
});
this.panel.repaint();
}
public void sendMessage(String message) {
try {
this.client.sendMessage(this.player.getName(), message);
}
catch (RemoteException ex) {
Display.error("Send", "Error while sending message.");
}
}
public void changeTurnMulti() {
this.mainFrame.getPlayerPanel().lock();
this.isMyTurn = false;
}
public void setPlayer(Player player) {
this.player = player;
}
public Player player() {
return this.player;
}
public Server server() {
return this.server;
}
/** Give hand to main frame. */
private void terminate() {
this.mainFrame.setEnabled(true);
this.mainFrame.requestFocus();
}
public void sendStatServer(int turn, String name, int points, String words) {
try {
this.server.sendStats(turn, name, points, words);
}
catch (RemoteException ex) {
Display.error("Stats", "Error while sending Stats.");
}
}
public boolean isMyTurn() {
return this.isMyTurn;
}
public void setMyTurn() {
this.isMyTurn = true;
}
}