File indexing completed on 2024-12-08 09:47:03

0001 // Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com>
0002 //
0003 // This library is free software; you can redistribute it and/or
0004 // modify it under the terms of the GNU Lesser General Public
0005 // License version 2.1 as published by the Free Software Foundation.
0006 //
0007 // This library is distributed in the hope that it will be useful,
0008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
0009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0010 // Lesser General Public License for more details.
0011 //
0012 // You should have received a copy of the GNU Lesser General Public License
0013 // along with this library; see the file COPYING.LIB.  If not, write to
0014 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0015 // Boston, MA 02110-1301, USA.
0016 
0017 #include <iostream>
0018 
0019 #include <qtextcodec.h>
0020 #include <QTimer>
0021 #include <QTcpSocket>
0022 #include <QHostAddress>
0023 
0024 #include <klocalizedstring.h>
0025 
0026 #include <atlantic_core.h>
0027 #include <auction.h>
0028 #include <card.h>
0029 #include <configoption.h>
0030 #include <estate.h>
0031 #include <estategroup.h>
0032 #include <game.h>
0033 #include <player.h>
0034 #include <trade.h>
0035 
0036 #include "atlantik_network.h"
0037 
0038 #include <libatlantikclient_debug.h>
0039 
0040 AtlantikNetwork::AtlantikNetwork(AtlanticCore *atlanticCore)
0041     : QObject()
0042     , m_atlanticCore(atlanticCore)
0043     , m_monopdsocket(nullptr)
0044     , m_playerId(-1)
0045 {
0046     reset();
0047 }
0048 
0049 AtlantikNetwork::~AtlantikNetwork(void)
0050 {
0051     disconnect();
0052 }
0053 
0054 void AtlantikNetwork::disconnect()
0055 {
0056     if (m_monopdsocket) {
0057         m_monopdstream.setDevice(nullptr);
0058         m_monopdsocket->close();
0059         delete m_monopdsocket;
0060         m_monopdsocket = nullptr;
0061     }
0062 }
0063 
0064 void AtlantikNetwork::reset()
0065 {
0066     disconnect();
0067     m_monopdsocket = new QTcpSocket(this);
0068     m_monopdsocket->setSocketOption(QAbstractSocket::LowDelayOption, true);
0069 
0070     connect(m_monopdsocket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), this, SLOT(slotConnectionFailed(QAbstractSocket::SocketError)));
0071     connect(m_monopdsocket, SIGNAL(connected()), this, SLOT(slotConnectionSuccess()));
0072     connect(m_monopdsocket, SIGNAL(hostFound()), this, SLOT(slotLookupFinished()));
0073     connect(m_monopdsocket, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
0074 }
0075 
0076 QString AtlantikNetwork::host() const
0077 {
0078     return isConnected()
0079       ? m_monopdsocket->peerAddress().toString()
0080       : QString();
0081 }
0082 
0083 int AtlantikNetwork::port() const
0084 {
0085     return isConnected()
0086       ? m_monopdsocket->peerPort()
0087       : -1;
0088 }
0089 
0090 bool AtlantikNetwork::isConnected() const
0091 {
0092     return m_monopdsocket && m_monopdsocket->state() == QAbstractSocket::ConnectedState;
0093 }
0094 
0095 void AtlantikNetwork::slotwriteData(const QString &msg)
0096 {
0097     Q_EMIT networkEvent(msg, ET_NetOut);
0098 
0099 }
0100 
0101 void AtlantikNetwork::slotRead()
0102 {
0103     if (!m_monopdstream.device())
0104         return;
0105 
0106     const QString line = m_monopdstream.readLine();
0107     if (!line.isNull())
0108     {
0109         
0110         processMsg(line);
0111         
0112         // There might be more data; Do we really need this?
0113         QTimer::singleShot(0, this, SLOT(slotRead()));
0114     }
0115     else
0116     {
0117         // Maximum message size. Messages won't get bigger than 32k anyway, so
0118         // if we didn't receive a newline by now, we probably won't anyway.
0119         if (m_monopdsocket->bytesAvailable() > (1024 * 32))
0120             m_monopdsocket->flush();
0121     }
0122 }
0123 
0124 
0125 
0126 void AtlantikNetwork::serverConnect(const QString &host, int port)
0127 {
0128     Q_EMIT msgStatus(i18n("Connecting to %1:%2...", host, QString::number(port)), ET_NetGeneric);
0129     m_host = host;
0130     m_port = port;
0131     m_monopdsocket->connectToHost(host, port);
0132 }
0133 
0134 void AtlantikNetwork::slotLookupFinished()
0135 {
0136     Q_EMIT msgStatus(i18n("Server host name lookup finished..."), ET_NetGeneric);
0137 }
0138 
0139 void AtlantikNetwork::slotConnectionSuccess()
0140 {
0141     Q_EMIT msgStatus(i18n("Connected to %1:%2.", m_host, QString::number(m_port)), ET_NetConnected);
0142     m_monopdstream.setDevice(m_monopdsocket);
0143     connect(m_monopdsocket, SIGNAL(readyRead()), this, SLOT(slotRead()));
0144 
0145     Q_EMIT connectionSuccess();
0146 }
0147 
0148 void AtlantikNetwork::slotConnectionFailed(QAbstractSocket::SocketError error)
0149 {
0150     Q_EMIT connectionFailed(error);
0151     Q_EMIT msgStatus(i18n("Connection failed! Error code: %1", error), ET_NetError);
0152 }
0153 
0154 void AtlantikNetwork::slotDisconnected()
0155 {
0156     Q_EMIT msgStatus(i18n("Disconnected from %1:%2.", m_host, QString::number(m_port)), ET_NetGeneric);
0157     Q_EMIT disconnected();
0158 }
0159 
0160 void AtlantikNetwork::writeData(const QString &data) {
0161 
0162     Q_EMIT networkEvent(data, ET_NetOut);
0163     //data.append("\n");
0164     m_monopdstream << data << '\n';
0165     m_monopdstream.flush();
0166     qCDebug(LIBATLANTIKCLIENT_LOG) << "writing data:" << data;
0167 
0168 }
0169 
0170 //Atlantik-specific stuff follows here
0171 //Perhaps it is better to separate this out in another class
0172 
0173 void AtlantikNetwork::rollDice()
0174 {
0175         writeData(QStringLiteral(".r"));
0176 }
0177 
0178 void AtlantikNetwork::buyEstate()
0179 {
0180         writeData(QStringLiteral(".eb"));
0181 }
0182 
0183 void AtlantikNetwork::auctionEstate()
0184 {
0185         writeData(QStringLiteral(".ea"));
0186 }
0187 
0188 void AtlantikNetwork::startGame()
0189 {
0190         writeData(QStringLiteral(".gs"));
0191 }
0192 
0193 void AtlantikNetwork::reconnect(const QString &cookie)
0194 {
0195         writeData(QStringLiteral(".R") + cookie);
0196 }
0197 
0198 void AtlantikNetwork::leaveGame()
0199 {
0200         writeData(QStringLiteral(".gx"));
0201 }
0202 
0203 void AtlantikNetwork::endTurn()
0204 {
0205         writeData(QStringLiteral(".E"));
0206 }
0207 
0208 void AtlantikNetwork::setName(const QString &name)
0209 {
0210         // Almost deprecated, will be replaced by libmonopdprotocol
0211         writeData(QStringLiteral(".n%1").arg(name));
0212         qCDebug(LIBATLANTIKCLIENT_LOG) << "set name to:" << name;
0213 }
0214 
0215 void AtlantikNetwork::tokenConfirmation(Estate *estate)
0216 {
0217         writeData(QStringLiteral(".t%1").arg(estate ? estate->id() : -1));
0218 }
0219 
0220 void AtlantikNetwork::estateToggleMortgage(Estate *estate)
0221 {
0222         writeData(QStringLiteral(".em%1").arg(estate ? estate->id() : -1));
0223 }
0224 
0225 void AtlantikNetwork::estateHouseBuy(Estate *estate)
0226 {
0227         writeData(QStringLiteral(".hb%1").arg(estate ? estate->id() : -1));
0228 }
0229 
0230 void AtlantikNetwork::estateHouseSell(Estate *estate)
0231 {
0232         writeData(QStringLiteral(".hs%1").arg(estate ? estate->id() : -1));
0233 }
0234 
0235 void AtlantikNetwork::estateSell(Estate *estate)
0236 {
0237         writeData(QStringLiteral(".es%1").arg(estate ? estate->id() : -1));
0238 }
0239 
0240 void AtlantikNetwork::newGame(const QString &gameType)
0241 {
0242         writeData(QStringLiteral(".gn%1").arg(gameType));
0243 }
0244 
0245 void AtlantikNetwork::joinGame(int gameId)
0246 {
0247         writeData(QStringLiteral(".gj%1").arg(gameId));
0248         qCDebug(LIBATLANTIKCLIENT_LOG) << "joining game" << gameId;
0249 }
0250 
0251 void AtlantikNetwork::watchGame(int gameId)
0252 {
0253         writeData(QStringLiteral(".gS%1").arg(gameId));
0254         qCDebug(LIBATLANTIKCLIENT_LOG) << "watching game" << gameId;
0255 }
0256 
0257 void AtlantikNetwork::cmdChat(const QString &msg)
0258 {
0259         writeData(msg);
0260 }
0261 
0262 void AtlantikNetwork::newTrade(Player *player)
0263 {
0264         writeData(QStringLiteral(".Tn%1").arg(player ? player->id() : -1));
0265 }
0266 
0267 void AtlantikNetwork::kickPlayer(Player *player)
0268 {
0269         writeData(QStringLiteral(".gk%1").arg(player ? player->id() : -1));
0270 }
0271 
0272 void AtlantikNetwork::tradeUpdateEstate(Trade *trade, Estate *estate, Player *player)
0273 {
0274         writeData(QStringLiteral(".Te%1:%2:%3").arg(trade ? trade->tradeId() : -1).arg(estate ? estate->id() : -1).arg(player ? player->id() : -1));
0275 }
0276 
0277 void AtlantikNetwork::tradeUpdateMoney(Trade *trade, unsigned int money, Player *pFrom, Player *pTo)
0278 {
0279         writeData(QStringLiteral(".Tm%1:%2:%3:%4").arg(trade ? trade->tradeId() : -1).arg(pFrom ? pFrom->id() : -1).arg(pTo ? pTo->id() : -1).arg(money));
0280 }
0281 
0282 void AtlantikNetwork::tradeUpdateCard(Trade *trade, Card *card, Player *pTo)
0283 {
0284         writeData(QStringLiteral(".Tc%1:%2:%3").arg(trade ? trade->tradeId() : -1).arg(card ? card->cardId() : -1).arg(pTo ? pTo->id() : -1));
0285 }
0286 
0287 void AtlantikNetwork::tradeReject(Trade *trade)
0288 {
0289         writeData(QStringLiteral(".Tr%1").arg(trade ? trade->tradeId() : -1));
0290 }
0291 
0292 void AtlantikNetwork::tradeAccept(Trade *trade)
0293 {
0294         writeData(QStringLiteral(".Ta%1:%2").arg(trade ? trade->tradeId() : -1).arg(trade ? trade->revision() : -1));
0295 }
0296 
0297 void AtlantikNetwork::auctionBid(Auction *auction, int amount)
0298 {
0299         writeData(QStringLiteral(".ab%1:%2").arg(auction ? auction->auctionId() : -1).arg(amount));
0300 }
0301 
0302 void AtlantikNetwork::setImage(const QString &name)
0303 {
0304         writeData(QStringLiteral(".pi%1").arg(name));
0305 }
0306 
0307 void AtlantikNetwork::jailPay()
0308 {
0309         writeData(QStringLiteral(".jp"));
0310 }
0311 
0312 void AtlantikNetwork::jailRoll()
0313 {
0314         writeData(QStringLiteral(".jr"));
0315 }
0316 
0317 void AtlantikNetwork::jailCard()
0318 {
0319         writeData(QStringLiteral(".jc"));
0320 }
0321 
0322 void AtlantikNetwork::changeOption(int configId, const QString &value)
0323 {
0324         writeData(QStringLiteral(".gc%1:%2").arg(configId).arg(value));
0325 }
0326 
0327 
0328 void AtlantikNetwork::processMsg(const QString &msg) {
0329     Q_EMIT networkEvent(msg, ET_NetIn);
0330     qCDebug(LIBATLANTIKCLIENT_LOG) << msg;
0331     QDomDocument dom;
0332     dom.setContent(msg);
0333     QDomElement e = dom.documentElement();
0334     if (e.tagName() != QLatin1String("monopd")) {
0335         // Invalid data, request full update from server
0336         writeData(QStringLiteral(".f"));
0337         return;
0338     }
0339     QDomNode n = e.firstChild();
0340     processNode(n);
0341     if (LIBATLANTIKCLIENT_LOG().isDebugEnabled())
0342         m_atlanticCore->printDebug();
0343 }
0344 
0345 void AtlantikNetwork::processNode(QDomNode n) {
0346     QDomAttr a;
0347 
0348     for ( ; !n.isNull() ; n = n.nextSibling() ) {
0349         QDomElement e = n.toElement();
0350         if(!e.isNull()) {
0351             if (e.tagName() == QLatin1String("server")) {
0352                 a = e.attributeNode(QStringLiteral("version"));
0353                 if ( !a.isNull() )
0354                     m_serverVersion = a.value();
0355                     qCDebug(LIBATLANTIKCLIENT_LOG) << "receivedHandshake";
0356                 Q_EMIT receivedHandshake();
0357             } else if (e.tagName() == QLatin1String("msg")) {
0358                 a = e.attributeNode(QStringLiteral("type"));
0359                 if (!a.isNull()) {
0360                     if (a.value() == QLatin1String("error"))
0361                         Q_EMIT msgError(e.attributeNode(QStringLiteral("value")).value());
0362                     else if (a.value() == QLatin1String("info"))
0363                         Q_EMIT msgInfo(e.attributeNode(QStringLiteral("value")).value());
0364                     else if (a.value() == QLatin1String("chat"))
0365                         Q_EMIT msgChat(e.attributeNode(QStringLiteral("author")).value(), e.attributeNode(QStringLiteral("value")).value());
0366                 }
0367             } else if (e.tagName() == QLatin1String("display")) {
0368                 Estate *estate = nullptr;
0369                 bool hasEstateId = false;
0370 
0371                 a = e.attributeNode(QStringLiteral("estateid"));
0372                 if (!a.isNull()) {
0373                     estate = m_atlanticCore->findEstate(a.value().toInt());
0374                     hasEstateId = true;
0375                 }
0376                 if (hasEstateId) {
0377                     Q_EMIT displayDetails(e.attributeNode(QStringLiteral("text")).value(), e.attributeNode(QStringLiteral("cleartext")).value().toInt(), e.attributeNode(QStringLiteral("clearbuttons")).value().toInt(), estate);
0378                 } else {
0379                     Q_EMIT displayText(e.attributeNode(QStringLiteral("text")).value(), e.attributeNode(QStringLiteral("cleartext")).value().toInt(), e.attributeNode(QStringLiteral("clearbuttons")).value().toInt());
0380                 }
0381 
0382                     bool hasButtons = false;
0383                     for( QDomNode nButtons = n.firstChild() ; !nButtons.isNull() ; nButtons = nButtons.nextSibling() ) {
0384                         QDomElement eButton = nButtons.toElement();
0385                         if (!eButton.isNull() && eButton.tagName() == QLatin1String("button")) {
0386                             Q_EMIT addCommandButton(eButton.attributeNode(QStringLiteral("command")).value(), eButton.attributeNode(QStringLiteral("caption")).value(), eButton.attributeNode(QStringLiteral("enabled")).value().toInt());
0387                             hasButtons = true;
0388                         }
0389                     }
0390 
0391                     if (!hasButtons)
0392                         Q_EMIT addCloseButton();
0393             } else if (e.tagName() == QLatin1String("client")) {
0394                 a = e.attributeNode(QStringLiteral("playerid"));
0395                 if (!a.isNull())
0396                     m_playerId = a.value().toInt();
0397 
0398                 a = e.attributeNode(QStringLiteral("cookie"));
0399                 if (!a.isNull())
0400                     Q_EMIT clientCookie(a.value());
0401             } else if (e.tagName() == QLatin1String("configupdate")) {
0402                 Game *game = nullptr;
0403                 a = e.attributeNode(QStringLiteral("gameid"));
0404                 if (!a.isNull()) {
0405                     int gameId = a.value().toInt();
0406                     game = m_atlanticCore->findGame(gameId);
0407                 }
0408 
0409                 a = e.attributeNode(QStringLiteral("configid"));
0410                 if (!a.isNull() && game) {
0411                     int configId = a.value().toInt();
0412                     ConfigOption *configOption = game->findConfigOption(configId);
0413                     bool created = false;
0414                     if (!configOption) {
0415                         configOption = new ConfigOption(configId);
0416                         created = true;
0417                     }
0418 
0419                     a = e.attributeNode(QStringLiteral("name"));
0420                     if (configOption && !a.isNull())
0421                         configOption->setName(a.value());
0422 
0423                     a = e.attributeNode(QStringLiteral("description"));
0424                     if (configOption && !a.isNull())
0425                         configOption->setDescription(a.value());
0426 
0427                     a = e.attributeNode(QStringLiteral("edit"));
0428                     if (configOption && !a.isNull())
0429                         configOption->setEdit(a.value().toInt());
0430 
0431                     a = e.attributeNode(QStringLiteral("type"));
0432                     if (configOption && !a.isNull())
0433                         configOption->setType(a.value());
0434 
0435                     a = e.attributeNode(QStringLiteral("value"));
0436                     if (configOption && !a.isNull())
0437                         configOption->setValue(a.value());
0438 
0439                     configOption->update();
0440                     if (created)
0441                         game->addConfigOption(configOption);
0442                 }
0443             } else if (e.tagName() == QLatin1String("deletegame")) {
0444                 a = e.attributeNode(QStringLiteral("gameid"));
0445                 if (!a.isNull()) {
0446                     int gameId = a.value().toInt();
0447 
0448                     Game *game = m_atlanticCore->findGame(gameId);
0449                     if (game)
0450                         m_atlanticCore->removeGame(game);
0451                 }
0452             } else if (e.tagName() == QLatin1String("gameupdate")) {
0453                 int gameId = -1;
0454 
0455                 a = e.attributeNode(QStringLiteral("gameid"));
0456                 if (!a.isNull()) {
0457                     gameId = a.value().toInt();
0458 
0459                     Player *playerSelf = m_atlanticCore->playerSelf();
0460                     if ( playerSelf && playerSelf->game() )
0461                         qCDebug(LIBATLANTIKCLIENT_LOG) << "gameupdate for" << gameId << "with playerSelf in game" << playerSelf->game()->id();
0462                     else
0463                         qCDebug(LIBATLANTIKCLIENT_LOG) << "gameupdate for" << gameId;
0464 
0465 
0466                     Game *game = nullptr;
0467                     if (gameId == -1) {
0468                         a = e.attributeNode(QStringLiteral("gametype"));
0469                         if ( !a.isNull() && !(game = m_atlanticCore->findGame(a.value())) )
0470                             game = m_atlanticCore->newGame(gameId, a.value());
0471                     } else if (!(game = m_atlanticCore->findGame(gameId)))
0472                         game = m_atlanticCore->newGame(gameId);
0473 
0474                     a = e.attributeNode(QStringLiteral("canbejoined"));
0475                     if (game && !a.isNull())
0476                         game->setCanBeJoined(a.value().toInt());
0477 
0478                     a = e.attributeNode(QStringLiteral("canbewatched"));
0479                     if (game && !a.isNull())
0480                         game->setCanBeWatched(a.value().toInt());
0481 
0482                     a = e.attributeNode(QStringLiteral("description"));
0483                     if (game && !a.isNull())
0484                         game->setDescription(a.value());
0485 
0486                     a = e.attributeNode(QStringLiteral("name"));
0487                     if (game && !a.isNull())
0488                         game->setName(a.value());
0489 
0490                     a = e.attributeNode(QStringLiteral("players"));
0491                     if (game && !a.isNull())
0492                         game->setPlayers(a.value().toInt());
0493 
0494                     a = e.attributeNode(QStringLiteral("master"));
0495                     if (game && !a.isNull()) {
0496                         // Ensure setMaster succeeds by creating player if necessary
0497                         Player *player = m_atlanticCore->findPlayer( a.value().toInt() );
0498                         if ( !player )
0499                             player = m_atlanticCore->newPlayer( a.value().toInt() );
0500                         game->setMaster( player );
0501                     }
0502 
0503                     QString status = e.attributeNode(QStringLiteral("status")).value();
0504                     if ( m_serverVersion.left(4) == QLatin1String("0.9.") || (playerSelf && playerSelf->game() == game) ) {
0505                         if (status == QLatin1String("config"))
0506                             Q_EMIT gameConfig();
0507                         else if (status == QLatin1String("init"))
0508                             Q_EMIT gameInit();
0509                         else if (status == QLatin1String("run"))
0510                             Q_EMIT gameRun();
0511                         else if (status == QLatin1String("end"))
0512                             Q_EMIT gameEnd();
0513                     }
0514 
0515                     if (game)
0516                         game->update();
0517                 }
0518             } else if (e.tagName() == QLatin1String("deleteplayer")) {
0519                 a = e.attributeNode(QStringLiteral("playerid"));
0520                 if (!a.isNull()) {
0521                     int playerId = a.value().toInt();
0522 
0523                     Player *player = m_atlanticCore->findPlayer(playerId);
0524                     if (player) {
0525                         m_playerLocationMap.remove(player);
0526                         m_atlanticCore->removePlayer(player);
0527                     }
0528                 }
0529             } else if (e.tagName() == QLatin1String("playerupdate")) {
0530                 int playerId = -1;
0531 
0532                 a = e.attributeNode(QStringLiteral("playerid"));
0533                 if (!a.isNull()) {
0534                     playerId = a.value().toInt();
0535 
0536                     Player *player;
0537                     if (!(player = m_atlanticCore->findPlayer(playerId)))
0538                         player = m_atlanticCore->newPlayer( playerId, (m_playerId == playerId) );
0539                     else if (m_playerId == playerId)
0540                         m_atlanticCore->setPlayerSelf(player);
0541 
0542                     // Update player name
0543                     a = e.attributeNode(QStringLiteral("name"));
0544                     if (player && !a.isNull())
0545                         player->setName(a.value());
0546 
0547                     // Update player game
0548                     a = e.attributeNode(QStringLiteral("game"));
0549                     if (player && !a.isNull()) {
0550                         int gameId = a.value().toInt();
0551                         if (gameId == -1)
0552                             player->setGame( nullptr );
0553                         else {
0554                             // Ensure setGame succeeds by creating game if necessary
0555                             Game *game = m_atlanticCore->findGame(a.value().toInt());
0556                             if (!game)
0557                                 game = m_atlanticCore->newGame(a.value().toInt()); //
0558                             player->setGame( game );
0559                         }
0560                     }
0561 
0562                     // Update player host
0563                     a = e.attributeNode(QStringLiteral("host"));
0564                     if (player && !a.isNull())
0565                         player->setHost(a.value());
0566 
0567                     // Update player image/token
0568                     a = e.attributeNode(QStringLiteral("image"));
0569                     if (player && !a.isNull())
0570                         player->setImage(a.value());
0571 
0572                     // Update player money
0573                     a = e.attributeNode(QStringLiteral("money"));
0574                     if (player && !a.isNull())
0575                         player->setMoney(a.value().toInt());
0576 
0577                     a = e.attributeNode(QStringLiteral("bankrupt"));
0578                     if (player && !a.isNull())
0579                         player->setBankrupt(a.value().toInt());
0580 
0581                     a = e.attributeNode(QStringLiteral("hasdebt"));
0582                     if (player && !a.isNull())
0583                         player->setHasDebt(a.value().toInt());
0584 
0585                     a = e.attributeNode(QStringLiteral("hasturn"));
0586                     if (player && !a.isNull())
0587                         player->setHasTurn(a.value().toInt());
0588 
0589                     // Update whether player can roll
0590                     a = e.attributeNode(QStringLiteral("can_roll"));
0591                     if (player && !a.isNull())
0592                         player->setCanRoll(a.value().toInt());
0593 
0594                     // Update whether player can buy
0595                     a = e.attributeNode(QStringLiteral("can_buyestate"));
0596                     if (player && !a.isNull())
0597                         player->setCanBuy(a.value().toInt());
0598 
0599                     // Update whether player can auction
0600                     a = e.attributeNode(QStringLiteral("canauction"));
0601                     if (player && !a.isNull())
0602                         player->setCanAuction(a.value().toInt());
0603 
0604                     // Update whether player can use a card
0605                     a = e.attributeNode(QStringLiteral("canusecard"));
0606                     if (player && !a.isNull())
0607                         player->setCanUseCard(a.value().toInt());
0608 
0609                     // Update whether player is jailed
0610                     a = e.attributeNode(QStringLiteral("jailed"));
0611                     if (player && !a.isNull()) {
0612                         player->setInJail(a.value().toInt());
0613                         // TODO: emit signal with player ptr so board can setText and display something
0614                     }
0615 
0616                     // Update whether player is a spectator
0617                     a = e.attributeNode(QStringLiteral("spectator"));
0618                     if (player && !a.isNull())
0619                         player->setSpectator(a.value().toInt());
0620 
0621                     // Update player location
0622                     a = e.attributeNode(QStringLiteral("location"));
0623                     if (!a.isNull()) {
0624                         m_playerLocationMap.insert(player, a.value().toInt());
0625 
0626                         bool directMove = false;
0627 
0628                         Estate *estate = m_atlanticCore->findEstate(a.value().toInt());
0629 
0630                         a = e.attributeNode(QStringLiteral("directmove"));
0631                         if (!a.isNull())
0632                             directMove = a.value().toInt();
0633 
0634                         if (player && estate) {
0635                             if (directMove)
0636                                 player->setLocation(estate);
0637                             else
0638                                 player->setDestination(estate);
0639                         }
0640                     }
0641 
0642                     if (player)
0643                         player->update();
0644                 }
0645             } else if (e.tagName() == QLatin1String("estategroupupdate")) {
0646                 a = e.attributeNode(QStringLiteral("groupid"));
0647                 if (!a.isNull()) {
0648                     int groupId = a.value().toInt();
0649 
0650                     EstateGroup *estateGroup = nullptr;
0651                     bool b_newEstateGroup = false;
0652 
0653                     if (!(estateGroup = m_atlanticCore->findEstateGroup(groupId))) {
0654                         // Create EstateGroup object
0655                         estateGroup = m_atlanticCore->newEstateGroup(a.value().toInt());
0656                         b_newEstateGroup = true;
0657                     }
0658 
0659                     a = e.attributeNode(QStringLiteral("name"));
0660                     if (estateGroup && !a.isNull())
0661                         estateGroup->setName(a.value());
0662 
0663                     // Emit signal so GUI implementations can create view(s)
0664                     // TODO:  port to atlanticcore and create view there
0665                     if (estateGroup) {
0666                         if (b_newEstateGroup)
0667                             Q_EMIT newEstateGroup(estateGroup);
0668                         estateGroup->update();
0669                     }
0670                 }
0671             } else if (e.tagName() == QLatin1String("estateupdate")) {
0672                 int estateId = -1;
0673 
0674                 a = e.attributeNode(QStringLiteral("estateid"));
0675                 if (!a.isNull()) {
0676                     estateId = a.value().toInt();
0677 
0678                     Estate *estate = nullptr;
0679                     bool b_newEstate = false;
0680 
0681                     // FIXME: allow any estateId, GUI should not use it to determin its geometry
0682                     if (estateId >= 0 && estateId < 100 && !(estate = m_atlanticCore->findEstate(a.value().toInt()))) {
0683                         // Create estate object
0684                         estate = m_atlanticCore->newEstate(estateId);
0685                         b_newEstate = true;
0686 
0687                         QObject::connect(estate, SIGNAL(estateToggleMortgage(Estate *)), this, SLOT(estateToggleMortgage(Estate *)));
0688                         QObject::connect(estate, SIGNAL(estateHouseBuy(Estate *)), this, SLOT(estateHouseBuy(Estate *)));
0689                         QObject::connect(estate, SIGNAL(estateHouseSell(Estate *)), this, SLOT(estateHouseSell(Estate *)));
0690                         QObject::connect(estate, SIGNAL(estateSell(Estate *)), this, SLOT(estateSell(Estate *)));
0691                         QObject::connect(estate, SIGNAL(newTrade(Player *)), this, SLOT(newTrade(Player *)));
0692 
0693                         // Players without estate should get one
0694                         foreach (Player *player, m_atlanticCore->players())
0695                             if (m_playerLocationMap.value(player) == estate->id())
0696                                 player->setLocation(estate);
0697                     }
0698 
0699                     a = e.attributeNode(QStringLiteral("name"));
0700                     if (estate && !a.isNull())
0701                         estate->setName(a.value());
0702 
0703                     a = e.attributeNode(QStringLiteral("color"));
0704                     if (estate && !a.isNull() && !a.value().isEmpty())
0705                         estate->setColor(a.value());
0706 
0707                     a = e.attributeNode(QStringLiteral("bgcolor"));
0708                     if (estate && !a.isNull())
0709                         estate->setBgColor(a.value());
0710 
0711                     a = e.attributeNode(QStringLiteral("owner"));
0712                     Player *player = m_atlanticCore->findPlayer(a.value().toInt());
0713                     if (estate && !a.isNull())
0714                         estate->setOwner(player);
0715 
0716                     a = e.attributeNode(QStringLiteral("houses"));
0717                     if (estate && !a.isNull())
0718                         estate->setHouses(a.value().toInt());
0719 
0720                     a = e.attributeNode(QStringLiteral("mortgaged"));
0721                     if (estate && !a.isNull())
0722                         estate->setIsMortgaged(a.value().toInt());
0723 
0724                     a = e.attributeNode(QStringLiteral("group"));
0725                     if (!a.isNull()) {
0726                         EstateGroup *estateGroup = m_atlanticCore->findEstateGroup(a.value().toInt());
0727                         if (estate)
0728                             estate->setEstateGroup(estateGroup);
0729                     }
0730 
0731                     a = e.attributeNode(QStringLiteral("can_toggle_mortgage"));
0732                     if (estate && !a.isNull())
0733                         estate->setCanToggleMortgage(a.value().toInt());
0734 
0735                     a = e.attributeNode(QStringLiteral("can_be_owned"));
0736                     if (estate && !a.isNull())
0737                         estate->setCanBeOwned(a.value().toInt());
0738 
0739                     a = e.attributeNode(QStringLiteral("can_buy_houses"));
0740                     if (estate && !a.isNull())
0741                         estate->setCanBuyHouses(a.value().toInt());
0742 
0743                     a = e.attributeNode(QStringLiteral("can_sell_houses"));
0744                     if (estate && !a.isNull())
0745                         estate->setCanSellHouses(a.value().toInt());
0746 
0747                     a = e.attributeNode(QStringLiteral("price"));
0748                     if (estate && !a.isNull())
0749                         estate->setPrice(a.value().toInt());
0750 
0751                     a = e.attributeNode(QStringLiteral("houseprice"));
0752                     if (estate && !a.isNull())
0753                         estate->setHousePrice(a.value().toInt());
0754 
0755                     a = e.attributeNode(QStringLiteral("sellhouseprice"));
0756                     if (estate && !a.isNull())
0757                         estate->setHouseSellPrice(a.value().toInt());
0758 
0759                     a = e.attributeNode(QStringLiteral("mortgageprice"));
0760                     if (estate && !a.isNull())
0761                         estate->setMortgagePrice(a.value().toInt());
0762 
0763                     a = e.attributeNode(QStringLiteral("unmortgageprice"));
0764                     if (estate && !a.isNull())
0765                         estate->setUnmortgagePrice(a.value().toInt());
0766 
0767                     a = e.attributeNode(QStringLiteral("money"));
0768                     if (estate && !a.isNull())
0769                         estate->setMoney(a.value().toInt());
0770 
0771                     a = e.attributeNode(QStringLiteral("icon"));
0772                     if (estate && !a.isNull())
0773                         estate->setIcon(a.value());
0774 
0775                     // Emit signal so GUI implementations can create view(s)
0776                     // TODO:  port to atlanticcore and create view there
0777                     if (estate) {
0778                         if (b_newEstate)
0779                             Q_EMIT newEstate(estate);
0780                         estate->update();
0781                     }
0782                 }
0783             } else if (e.tagName() == QLatin1String("tradeupdate")) {
0784                 a = e.attributeNode(QStringLiteral("tradeid"));
0785                 if (!a.isNull()) {
0786                     int tradeId = a.value().toInt();
0787 
0788                     Trade *trade = m_atlanticCore->findTrade(tradeId);
0789                     if (!trade) {
0790                         // Create trade object
0791                         trade = m_atlanticCore->newTrade(tradeId);
0792 
0793                         QObject::connect(trade, SIGNAL(updateEstate(Trade *, Estate *, Player *)), this, SLOT(tradeUpdateEstate(Trade *, Estate *, Player *)));
0794                         QObject::connect(trade, SIGNAL(updateMoney(Trade *, unsigned int, Player *, Player *)), this, SLOT(tradeUpdateMoney(Trade *, unsigned int, Player *, Player *)));
0795                         QObject::connect(trade, SIGNAL(updateCard(Trade *, Card *, Player *)), this, SLOT(tradeUpdateCard(Trade *, Card *, Player *)));
0796                         QObject::connect(trade, SIGNAL(reject(Trade *)), this, SLOT(tradeReject(Trade *)));
0797                         QObject::connect(trade, SIGNAL(accept(Trade *)), this, SLOT(tradeAccept(Trade *)));
0798                     }
0799 
0800                     a = e.attributeNode(QStringLiteral("revision"));
0801                     if (trade && !a.isNull())
0802                         trade->setRevision(a.value().toInt());
0803 
0804                     QString type = e.attributeNode(QStringLiteral("type")).value();
0805                     if (type == QLatin1String("new")) {
0806                         // TODO: trade->setActor
0807                         // Player *player = m_atlanticCore->findPlayer(e.attributeNode(QStringLiteral("actor")).value().toInt());
0808                         // if (trade && player)
0809                         //      trade->setActor(player);
0810 
0811                         QDomNode n_player = n.firstChild();
0812                         while(!n_player.isNull()) {
0813                             QDomElement e_player = n_player.toElement();
0814                             if (!e_player.isNull() && e_player.tagName() == QLatin1String("tradeplayer")) {
0815                                 Player *player = m_atlanticCore->findPlayer(e_player.attributeNode(QStringLiteral("playerid")).value().toInt());
0816                                 if (trade && player) {
0817                                     trade->addPlayer(player);
0818                                     QObject::connect(m_atlanticCore, SIGNAL(removePlayer(Player *)), trade, SLOT(removePlayer(Player *)));
0819                                 }
0820                             }
0821                             n_player = n_player.nextSibling();
0822                         }
0823                     } else if (type == QLatin1String("accepted") && trade)
0824                         Q_EMIT msgTradeUpdateAccepted(trade);
0825                     else if (type == QLatin1String("completed") && trade) {
0826                         m_atlanticCore->removeTrade(trade);
0827                         trade = nullptr;
0828                     } else if (type == QLatin1String("rejected")) {
0829                         Player *player = m_atlanticCore->findPlayer(e.attributeNode(QStringLiteral("actor")).value().toInt());
0830                         if (trade)
0831                             trade->reject(player);
0832                         if ( player && player == m_atlanticCore->playerSelf() ) {
0833                             m_atlanticCore->removeTrade(trade);
0834                             trade = nullptr;
0835                         }
0836                     } else {
0837                         // No type specified, edit is implied.
0838 
0839                         QDomNode n_child = n.firstChild();
0840                         while(!n_child.isNull()) {
0841                             QDomElement e_child = n_child.toElement();
0842                             if (!e_child.isNull()) {
0843                                 if (e_child.tagName() == QLatin1String("tradeplayer")) {
0844                                     a = e_child.attributeNode(QStringLiteral("playerid"));
0845                                     if (!a.isNull()) {
0846                                         Player *player = m_atlanticCore->findPlayer(a.value().toInt());
0847 
0848                                         a = e_child.attributeNode(QStringLiteral("accept"));
0849                                         if (trade && player && !a.isNull())
0850                                             trade->updateAccept(player, (bool)(a.value().toInt()));
0851                                     }
0852                                 } else if (e_child.tagName() == QLatin1String("tradeestate")) {
0853                                     a = e_child.attributeNode(QStringLiteral("estateid"));
0854                                     if (!a.isNull()) {
0855                                         Estate *estate = m_atlanticCore->findEstate(a.value().toInt());
0856                                         a = e_child.attributeNode(QStringLiteral("targetplayer"));
0857                                         if (!a.isNull()) {
0858                                             Player *player = m_atlanticCore->findPlayer(a.value().toInt());
0859                                             // Allow NULL player, it will remove the component
0860                                             if (trade && estate)
0861                                                 trade->updateEstate(estate, player);
0862                                         }
0863                                     }
0864                                 } else if (e_child.tagName() == QLatin1String("trademoney")) {
0865                                     Player *pFrom = nullptr, *pTo = nullptr;
0866 
0867                                     a = e_child.attributeNode(QStringLiteral("playerfrom"));
0868                                     if (!a.isNull())
0869                                         pFrom = m_atlanticCore->findPlayer(a.value().toInt());
0870 
0871                                     a = e_child.attributeNode(QStringLiteral("playerto"));
0872                                     if (!a.isNull())
0873                                         pTo = m_atlanticCore->findPlayer(a.value().toInt());
0874 
0875                                     a = e_child.attributeNode(QStringLiteral("money"));
0876                                     qCDebug(LIBATLANTIKCLIENT_LOG) << "tradeupdatemoney" << (pFrom ? "1" : "0") << (pTo ? "1" : "0") << (a.isNull() ? "0" : "1");
0877                                     if (trade && pFrom && pTo && !a.isNull())
0878                                         trade->updateMoney(a.value().toInt(), pFrom, pTo);
0879                                 } else if (e_child.tagName() == QLatin1String("tradecard")) {
0880                                     a = e_child.attributeNode(QStringLiteral("cardid"));
0881                                     if (!a.isNull()) {
0882                                         Card *card = m_atlanticCore->findCard(a.value().toInt());
0883                                         a = e_child.attributeNode(QStringLiteral("targetplayer"));
0884                                         if (!a.isNull()) {
0885                                             Player *player = m_atlanticCore->findPlayer(a.value().toInt());
0886                                             // Allow NULL player, it will remove the component
0887                                             if (trade && card)
0888                                                 trade->updateCard(card, player);
0889                                         }
0890                                     }
0891                                 }
0892                             }
0893                             n_child = n_child.nextSibling();
0894                         }
0895                     }
0896 
0897                     if (trade)
0898                         trade->update();
0899                 }
0900             } else if (e.tagName() == QLatin1String("auctionupdate")) {
0901                 a = e.attributeNode(QStringLiteral("auctionid"));
0902                 if (!a.isNull()) {
0903                     int auctionId = a.value().toInt();
0904 
0905                     Auction *auction = m_atlanticCore->findAuction(auctionId);
0906                     bool b_newAuction = false;
0907                     if (!auction) {
0908                         // Create auction object
0909                         auction = m_atlanticCore->newAuction(auctionId, m_atlanticCore->findEstate(e.attributeNode(QStringLiteral("estateid")).value().toInt()));
0910 
0911                         QObject::connect(auction, SIGNAL(bid(Auction *, int)), this, SLOT(auctionBid(Auction *, int)));
0912 
0913                         b_newAuction = true;
0914                     }
0915 
0916                     a = e.attributeNode(QStringLiteral("highbidder"));
0917                     if (!a.isNull()) {
0918                         Player *player = m_atlanticCore->findPlayer(e.attributeNode(QStringLiteral("highbidder")).value().toInt());
0919                         a = e.attributeNode(QStringLiteral("highbid"));
0920                         if (auction && !a.isNull())
0921                             auction->newBid(player, a.value().toInt());
0922                     }
0923 
0924                     a = e.attributeNode(QStringLiteral("status"));
0925                     if (auction && !a.isNull()) {
0926                         int status = a.value().toInt();
0927                         auction->setStatus(status);
0928 
0929                         // TODO: find a good way to visually represent "sold!"
0930                         if (status == 3) {
0931                             m_atlanticCore->delAuction(auction);
0932                             auction = nullptr;
0933                         }
0934                     }
0935 
0936                     // Emit signal so GUI implementations can create view(s)
0937                     // TODO:  port to atlanticcore and create view there
0938                     if (auction) {
0939                         if (b_newAuction)
0940                             Q_EMIT newAuction(auction);
0941                         auction->update();
0942                     }
0943                 }
0944             } else if (e.tagName() == QLatin1String("cardupdate")) {
0945                 a = e.attributeNode(QStringLiteral("cardid"));
0946                 if (!a.isNull()) {
0947                     int cardId = a.value().toInt();
0948 
0949                     Card *card;
0950                     if (!(card = m_atlanticCore->findCard(cardId)))
0951                         card = m_atlanticCore->newCard(cardId);
0952 
0953                     // Update card owner
0954                     a = e.attributeNode(QStringLiteral("owner"));
0955                     if (!a.isNull()) {
0956                         Player *player = m_atlanticCore->findPlayer(a.value().toInt());
0957                         card->setOwner(player);
0958                     }
0959 
0960                     // Update card title
0961                     a = e.attributeNode(QStringLiteral("title"));
0962                     if (!a.isNull())
0963                         card->setTitle(a.value());
0964 
0965                     if (card)
0966                         card->update();
0967                 }
0968             } else
0969                 qCDebug(LIBATLANTIKCLIENT_LOG) << "ignored TAG:" << e.tagName();
0970         }
0971         // TODO: remove permanently?
0972         // QDomNode node = n.firstChild();
0973         // processNode(node);
0974     }
0975 }
0976 
0977 #include "moc_atlantik_network.cpp"