/**
* Copyright (C) 2002-2012 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.control;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import net.sf.freecol.FreeCol;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.common.model.FreeColGameObject;
import net.sf.freecol.common.model.FreeColObject;
import net.sf.freecol.common.model.Game;
import net.sf.freecol.common.model.Nation;
import net.sf.freecol.common.model.NationOptions.NationState;
import net.sf.freecol.common.model.NationType;
import net.sf.freecol.common.model.Player;
import net.sf.freecol.common.networking.ChatMessage;
import net.sf.freecol.common.networking.Connection;
import net.sf.freecol.common.option.MapGeneratorOptions;
import net.sf.freecol.common.option.OptionGroup;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Handles the network messages that arrives before the game starts.
*/
public final class PreGameInputHandler extends InputHandler {
private static final Logger logger = Logger.getLogger(PreGameInputHandler.class.getName());
/**
* The constructor to use.
*
* @param freeColClient The main controller.
*/
public PreGameInputHandler(FreeColClient freeColClient, GUI gui) {
super(freeColClient, gui);
}
/**
* Deals with incoming messages that have just been received.
*
* @param connection The <code>Connection</code> the message was
* received on.
* @param element The root <code>Element</code> of the message.
* @return The reply.
*/
public synchronized Element handle(Connection connection,
Element element) {
String type = (element == null) ? "(null)" : element.getTagName();
return ("addPlayer".equals(type))
? addPlayer(element)
: ("chat".equals(type))
? chat(element)
: ("disconnect".equals(type))
? disconnect(element)
: ("error".equals(type))
? error(element)
: ("logout".equals(type))
? logout(element)
: ("multiple".equals(type))
? multiple(connection, element)
: ("playerReady".equals(type))
? playerReady(element)
: ("removePlayer".equals(type))
? removePlayer(element)
: ("setAvailable".equals(type))
? setAvailable(element)
: ("startGame".equals(type))
? startGame(element)
: ("updateGame".equals(type))
? updateGame(element)
: ("updateGameOptions".equals(type))
? updateGameOptions(element)
: ("updateMapGeneratorOptions".equals(type))
? updateMapGeneratorOptions(element)
: ("updateNation".equals(type))
? updateNation(element)
: ("updateNationType".equals(type))
? updateNationType(element)
: unknown(element);
}
/**
* Handles an "addPlayer"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element addPlayer(Element element) {
Game game = getFreeColClient().getGame();
Element playerElement = (Element)element
.getElementsByTagName(Player.getXMLElementTagName()).item(0);
String id = playerElement.getAttribute(FreeColObject.ID_ATTRIBUTE);
FreeColGameObject fcgo = game.getFreeColGameObject(id);
if (fcgo == null) {
game.addPlayer(new Player(game, playerElement));
} else {
fcgo.readFromXMLElement(playerElement);
}
gui.refreshPlayersTable();
return null;
}
/**
* Handles a "chat"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element chat(Element element) {
Game game = getGame();
ChatMessage chatMessage = new ChatMessage(game, element);
gui.displayChatMessage(chatMessage.getPlayer(game),
chatMessage.getMessage(),
chatMessage.isPrivate());
return null;
}
/**
* Handles an "error"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element error(Element element) {
if (element.hasAttribute("messageID")) {
gui.errorMessage(element.getAttribute("messageID"),
element.getAttribute("message"));
} else {
gui.errorMessage(null, element.getAttribute("message"));
}
return null;
}
/**
* Handles an "logout"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element logout(Element element) {
Game game = getFreeColClient().getGame();
String playerID = element.getAttribute("player");
String reason = element.getAttribute("reason");
if (reason != null && !"".equals(reason)) {
logger.info("Client logging out: " + reason);
}
Player player = game.getFreeColGameObject(playerID, Player.class);
game.removePlayer(player);
gui.refreshPlayersTable();
return null;
}
/**
* Handle all the children of this element.
*
* @param connection The <code>Connection</code> the element arrived on.
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return The result of handling the last <code>Element</code>.
*/
public Element multiple(Connection connection, Element element) {
NodeList nodes = element.getChildNodes();
Element reply = null;
for (int i = 0; i < nodes.getLength(); i++) {
reply = handle(connection, (Element)nodes.item(i));
}
return reply;
}
/**
* Handles a "playerReady"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element playerReady(Element element) {
Game game = getFreeColClient().getGame();
Player player = game
.getFreeColGameObject(element.getAttribute("player"), Player.class);
boolean ready = Boolean.valueOf(element.getAttribute("value"))
.booleanValue();
player.setReady(ready);
gui.refreshPlayersTable();
return null;
}
/**
* Handles a "removePlayer"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element removePlayer(Element element) {
Game game = getFreeColClient().getGame();
Element playerElement = (Element)element
.getElementsByTagName(Player.getXMLElementTagName()).item(0);
Player player = new Player(game, playerElement);
getFreeColClient().getGame().removePlayer(player);
gui.refreshPlayersTable();
return null;
}
/**
* Handles a "setAvailable"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element setAvailable(Element element) {
Nation nation = getGame().getSpecification()
.getNation(element.getAttribute("nation"));
NationState state = Enum.valueOf(NationState.class,
element.getAttribute("state"));
getFreeColClient().getGame().getNationOptions()
.setNationState(nation, state);
gui.refreshPlayersTable();
return null;
}
/**
* Handles an "startGame"-message.
*
* Wait until map is received from server, sometimes this
* message arrives when map is still null. Wait in other
* thread in order not to block and it can receive the map.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element startGame(Element element) {
new Thread(FreeCol.CLIENT_THREAD + "Starting game") {
@Override
public void run() {
while (getFreeColClient().getGame().getMap() == null) {
try {
Thread.sleep(200);
} catch (Exception ex) {}
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
getFreeColClient().getPreGameController()
.startGame();
}
});
}
}.start();
return null;
}
/**
* Handles an "updateGame"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element updateGame(Element element) {
NodeList children = element.getChildNodes();
if (children.getLength() == 1) {
getFreeColClient().getGame()
.readFromXMLElement((Element)children.item(0));
} else {
logger.warning("Child node expected: " + element.getTagName());
}
return null;
}
/**
* Handles an "updateGameOptions"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element updateGameOptions(Element element) {
Game game = getFreeColClient().getGame();
Element mgoElement = (Element)element
.getElementsByTagName("gameOptions").item(0);
OptionGroup gameOptions = game.getSpecification()
.getOptionGroup("gameOptions");
gameOptions.readFromXMLElement(mgoElement);
gui.updateGameOptions();
return null;
}
/**
* Handles an "updateMapGeneratorOptions"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element updateMapGeneratorOptions(Element element) {
Element mgoElement = (Element)element
.getElementsByTagName(MapGeneratorOptions.getXMLElementTagName())
.item(0);
getFreeColClient().getGame().getMapGeneratorOptions()
.readFromXMLElement(mgoElement);
gui.updateMapGeneratorOptions();
return null;
}
/**
* Handles an "updateNation"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element updateNation(Element element) {
Game game = getFreeColClient().getGame();
Player player = game
.getFreeColGameObject(element.getAttribute("player"), Player.class);
Nation nation = getGame().getSpecification()
.getNation(element.getAttribute("value"));
player.setNation(nation);
gui.refreshPlayersTable();
return null;
}
/**
* Handles an "updateNationType"-message.
*
* @param element The element (root element in a DOM-parsed XML tree) that
* holds all the information.
* @return Null.
*/
private Element updateNationType(Element element) {
Game game = getFreeColClient().getGame();
Player player = game
.getFreeColGameObject(element.getAttribute("player"), Player.class);
NationType nationType = getGame().getSpecification()
.getNationType(element.getAttribute("value"));
player.setNationType(nationType);
gui.refreshPlayersTable();
return null;
}
}