File indexing completed on 2024-12-01 06:50:28
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"