diff --git a/cockatrice/src/gamescene.cpp b/cockatrice/src/gamescene.cpp index 4e068904..a1d3033e 100644 --- a/cockatrice/src/gamescene.cpp +++ b/cockatrice/src/gamescene.cpp @@ -52,15 +52,16 @@ void GameScene::rearrange() QPointF base; qreal sceneWidth = 0; qreal sceneHeight = 0; - Player *localPlayer = 0; + QList localPlayers; for (int i = 0; i < players.size(); ++i) if (!players[i]->getLocal()) PlayerProcessor::processPlayer(players[i], sceneWidth, sceneHeight, base, players.size() == 1); else - localPlayer = players[i]; - if (localPlayer) - PlayerProcessor::processPlayer(localPlayer, sceneWidth, sceneHeight, base, players.size() == 1); + localPlayers.append(players[i]); + + for (int i = 0; i < localPlayers.size(); ++i) + PlayerProcessor::processPlayer(localPlayers[i], sceneWidth, sceneHeight, base, players.size() == 1); playersRect = QRectF(0, 0, sceneWidth, sceneHeight); diff --git a/cockatrice/src/localclient.cpp b/cockatrice/src/localclient.cpp index e81d0e16..b42b810c 100644 --- a/cockatrice/src/localclient.cpp +++ b/cockatrice/src/localclient.cpp @@ -2,11 +2,11 @@ #include "localserverinterface.h" #include "protocol.h" -LocalClient::LocalClient(LocalServerInterface *_lsi, QObject *parent) +LocalClient::LocalClient(LocalServerInterface *_lsi, const QString &_playerName, QObject *parent) : AbstractClient(parent), lsi(_lsi) { connect(lsi, SIGNAL(itemToClient(ProtocolItem *)), this, SLOT(itemFromServer(ProtocolItem *))); - sendCommand(new Command_Login("Player", QString())); + sendCommand(new Command_Login(_playerName, QString())); } LocalClient::~LocalClient() diff --git a/cockatrice/src/localclient.h b/cockatrice/src/localclient.h index bc3ae50d..4ea8cf2b 100644 --- a/cockatrice/src/localclient.h +++ b/cockatrice/src/localclient.h @@ -10,7 +10,7 @@ class LocalClient : public AbstractClient { private: LocalServerInterface *lsi; public: - LocalClient(LocalServerInterface *_lsi, QObject *parent = 0); + LocalClient(LocalServerInterface *_lsi, const QString &_playerName, QObject *parent = 0); ~LocalClient(); void sendCommandContainer(CommandContainer *cont); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index d2c7e791..c2aa6d3c 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -1,5 +1,4 @@ #include "player.h" -#include "abstractclient.h" #include "cardzone.h" #include "playertarget.h" #include "counter.h" @@ -21,8 +20,8 @@ #include #include -Player::Player(const QString &_name, int _id, bool _local, AbstractClient *_client, TabGame *_parent) - : QObject(_parent), defaultNumberTopCards(3), lastTokenDestroy(true), name(_name), id(_id), active(false), local(_local), mirrored(false), client(_client) +Player::Player(const QString &_name, int _id, bool _local, TabGame *_parent) + : QObject(_parent), defaultNumberTopCards(3), lastTokenDestroy(true), name(_name), id(_id), active(false), local(_local), mirrored(false) { setCacheMode(DeviceCoordinateCache); @@ -977,12 +976,12 @@ void Player::rearrangeCounters() void Player::sendGameCommand(GameCommand *command) { - static_cast(parent())->sendGameCommand(command); + static_cast(parent())->sendGameCommand(command, id); } void Player::sendCommandContainer(CommandContainer *cont) { - static_cast(parent())->sendCommandContainer(cont); + static_cast(parent())->sendCommandContainer(cont, id); } void Player::cardMenuAction() diff --git a/cockatrice/src/player.h b/cockatrice/src/player.h index 48a64828..f4f3c869 100644 --- a/cockatrice/src/player.h +++ b/cockatrice/src/player.h @@ -6,7 +6,6 @@ #include #include "carditem.h" -class AbstractClient; class CardDatabase; class QMenu; class QAction; @@ -171,8 +170,7 @@ public: void clearArrows(); PlayerTarget *getPlayerTarget() const { return playerTarget; } - AbstractClient *client; - Player(const QString &_name, int _id, bool _local, AbstractClient *_client, TabGame *_parent); + Player(const QString &_name, int _id, bool _local, TabGame *_parent); ~Player(); void retranslateUi(); QMenu *getPlayerMenu() const { return playerMenu; } diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 2f32a020..dc7db9b7 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -42,32 +42,123 @@ void ReadyStartButton::setReadyStart(bool _readyStart) update(); } -TabGame::TabGame(AbstractClient *_client, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) - : Tab(), client(_client), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1) +DeckViewContainer::DeckViewContainer(AbstractClient *_client, TabGame *parent) + : QWidget(parent), client(_client) { - scene = new GameScene(this); - gameView = new GameView(scene); - gameView->hide(); - loadLocalButton = new QPushButton; loadRemoteButton = new QPushButton; readyStartButton = new ReadyStartButton; readyStartButton->setEnabled(false); + connect(loadLocalButton, SIGNAL(clicked()), this, SLOT(loadLocalDeck())); + connect(loadRemoteButton, SIGNAL(clicked()), this, SLOT(loadRemoteDeck())); + connect(readyStartButton, SIGNAL(clicked()), this, SLOT(readyStart())); + QHBoxLayout *buttonHBox = new QHBoxLayout; buttonHBox->addWidget(loadLocalButton); buttonHBox->addWidget(loadRemoteButton); buttonHBox->addWidget(readyStartButton); buttonHBox->addStretch(); deckView = new DeckView; - connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *))); + connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *))); connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged())); + QVBoxLayout *deckViewLayout = new QVBoxLayout; deckViewLayout->addLayout(buttonHBox); deckViewLayout->addWidget(deckView); - deckViewContainer = new QWidget; - deckViewContainer->setLayout(deckViewLayout); + setLayout(deckViewLayout); + + retranslateUi(); +} +void DeckViewContainer::retranslateUi() +{ + loadLocalButton->setText(tr("Load &local deck")); + loadRemoteButton->setText(tr("Load d&eck from server")); + readyStartButton->setText(tr("Ready to s&tart")); +} + +void DeckViewContainer::setButtonsVisible(bool _visible) +{ + loadLocalButton->setVisible(_visible); + loadRemoteButton->setVisible(_visible); + readyStartButton->setVisible(_visible); +} + +void DeckViewContainer::loadLocalDeck() +{ + QFileDialog dialog(this, tr("Load deck")); + QSettings settings; + dialog.setDirectory(settings.value("paths/decks").toString()); + dialog.setNameFilters(DeckList::fileNameFilters); + if (!dialog.exec()) + return; + + QString fileName = dialog.selectedFiles().at(0); + DeckList::FileFormat fmt = DeckList::getFormatFromNameFilter(dialog.selectedNameFilter()); + DeckList *deck = new DeckList; + if (!deck->loadFromFile(fileName, fmt)) { + delete deck; + // Error message + return; + } + + Command_DeckSelect *cmd = new Command_DeckSelect(static_cast(parent())->getGameId(), deck, -1); + connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(deckSelectFinished(ProtocolResponse *))); + client->sendCommand(cmd); +} + +void DeckViewContainer::loadRemoteDeck() +{ + DlgLoadRemoteDeck dlg(client); + if (dlg.exec()) { + Command_DeckSelect *cmd = new Command_DeckSelect(static_cast(parent())->getGameId(), 0, dlg.getDeckId()); + connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(deckSelectFinished(ProtocolResponse *))); + client->sendCommand(cmd); + } +} + +void DeckViewContainer::deckSelectFinished(ProtocolResponse *r) +{ + Response_DeckDownload *resp = qobject_cast(r); + if (!resp) + return; + + Deck_PictureCacher::cachePictures(resp->getDeck(), this); + deckView->setDeck(new DeckList(resp->getDeck())); + readyStartButton->setEnabled(true); +} + +void DeckViewContainer::readyStart() +{ + client->sendCommand(new Command_ReadyStart(static_cast(parent())->getGameId(), !readyStartButton->getReadyStart())); +} + +void DeckViewContainer::sideboardPlanChanged() +{ + QList newPlan = deckView->getSideboardPlan(); + client->sendCommand(new Command_SetSideboardPlan(static_cast(parent())->getGameId(), newPlan)); +} + +void DeckViewContainer::setReadyStart(bool ready) +{ + readyStartButton->setReadyStart(ready); + deckView->setLocked(ready); +} + +void DeckViewContainer::setDeck(DeckList *deck) +{ + deckView->setDeck(deck); + readyStartButton->setEnabled(true); +} + +TabGame::TabGame(QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) + : Tab(), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1) +{ + scene = new GameScene(this); + gameView = new GameView(scene); + gameView->hide(); + cardInfo = new CardInfoWidget; playerListWidget = new PlayerListWidget; playerListWidget->setFocusPolicy(Qt::NoFocus); @@ -79,10 +170,12 @@ TabGame::TabGame(AbstractClient *_client, int _gameId, const QString &_gameDescr QHBoxLayout *hLayout = new QHBoxLayout; hLayout->addWidget(sayLabel); hLayout->addWidget(sayEdit); + + deckViewContainerLayout = new QVBoxLayout; phasesToolbar = new PhasesToolbar; phasesToolbar->hide(); - connect(phasesToolbar, SIGNAL(sendGameCommand(GameCommand *)), this, SLOT(sendGameCommand(GameCommand *))); + connect(phasesToolbar, SIGNAL(sendGameCommand(GameCommand *, int)), this, SLOT(sendGameCommand(GameCommand *, int))); QVBoxLayout *verticalLayout = new QVBoxLayout; verticalLayout->addWidget(cardInfo); @@ -90,26 +183,17 @@ TabGame::TabGame(AbstractClient *_client, int _gameId, const QString &_gameDescr verticalLayout->addWidget(messageLog, 3); verticalLayout->addLayout(hLayout); - QHBoxLayout *mainLayout = new QHBoxLayout; + mainLayout = new QHBoxLayout; mainLayout->addWidget(phasesToolbar); mainLayout->addWidget(gameView, 10); - mainLayout->addWidget(deckViewContainer, 10); + mainLayout->addLayout(deckViewContainerLayout, 10); mainLayout->addLayout(verticalLayout); - if (spectator) { - if (!spectatorsCanTalk) { - sayLabel->hide(); - sayEdit->hide(); - } - loadLocalButton->hide(); - loadRemoteButton->hide(); - readyStartButton->hide(); + if (spectator && !spectatorsCanTalk) { + sayLabel->hide(); + sayEdit->hide(); } - connect(loadLocalButton, SIGNAL(clicked()), this, SLOT(loadLocalDeck())); - connect(loadRemoteButton, SIGNAL(clicked()), this, SLOT(loadRemoteDeck())); - connect(readyStartButton, SIGNAL(clicked()), this, SLOT(readyStart())); - connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(actSay())); // Menu actions @@ -147,6 +231,8 @@ TabGame::~TabGame() delete i.next().value(); players.clear(); + delete deckViewContainerLayout; + emit gameClosing(this); } @@ -163,15 +249,15 @@ void TabGame::retranslateUi() aConcede->setShortcut(tr("F2")); aLeaveGame->setText(tr("&Leave game")); - loadLocalButton->setText(tr("Load &local deck")); - loadRemoteButton->setText(tr("Load d&eck from server")); - readyStartButton->setText(tr("Ready to s&tart")); sayLabel->setText(tr("&Say:")); cardInfo->retranslateUi(); QMapIterator i(players); while (i.hasNext()) i.next().value()->retranslateUi(); + QMapIterator j(deckViewContainers); + while (j.hasNext()) + j.next().value()->retranslateUi(); scene->retranslateUi(); } @@ -181,7 +267,7 @@ void TabGame::actConcede() if (QMessageBox::question(this, tr("Concede"), tr("Are you sure you want to concede this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) return; - sendGameCommand(new Command_Concede); + sendGameCommand(new Command_Concede, getActiveLocalPlayer()->getId()); } void TabGame::actLeaveGame() @@ -189,14 +275,14 @@ void TabGame::actLeaveGame() if (QMessageBox::question(this, tr("Leave game"), tr("Are you sure you want to leave this game?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) return; - sendGameCommand(new Command_LeaveGame); + sendGameCommand(new Command_LeaveGame, getActiveLocalPlayer()->getId()); deleteLater(); } void TabGame::actSay() { if (!sayEdit->text().isEmpty()) { - sendGameCommand(new Command_Say(-1, sayEdit->text())); + sendGameCommand(new Command_Say(-1, sayEdit->text()), getActiveLocalPlayer()->getId()); sayEdit->clear(); } } @@ -206,12 +292,12 @@ void TabGame::actNextPhase() int phase = currentPhase; if (++phase >= phasesToolbar->phaseCount()) phase = 0; - sendGameCommand(new Command_SetActivePhase(-1, phase)); + sendGameCommand(new Command_SetActivePhase(-1, phase), getActiveLocalPlayer()->getId()); } void TabGame::actNextTurn() { - sendGameCommand(new Command_NextTurn); + sendGameCommand(new Command_NextTurn, getActiveLocalPlayer()->getId()); } void TabGame::actRemoveLocalArrows() @@ -224,18 +310,31 @@ void TabGame::actRemoveLocalArrows() QMapIterator arrowIterator(player->getArrows()); while (arrowIterator.hasNext()) { ArrowItem *a = arrowIterator.next().value(); - sendGameCommand(new Command_DeleteArrow(-1, a->getId())); + sendGameCommand(new Command_DeleteArrow(-1, a->getId()), getActiveLocalPlayer()->getId()); } } } Player *TabGame::addPlayer(int playerId, const QString &playerName) { - Player *newPlayer = new Player(playerName, playerId, playerId == localPlayerId, client, this); + bool local = ((clients.size() > 1) || (playerId == localPlayerId)); + Player *newPlayer = new Player(playerName, playerId, local, this); scene->addPlayer(newPlayer); connect(newPlayer, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *))); messageLog->connectToPlayer(newPlayer); + + if (local && !spectator) { + AbstractClient *client; + if (clients.size() > 1) + client = clients.at(playerId); + else + client = clients.first(); + DeckViewContainer *deckView = new DeckViewContainer(client, this); + connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *))); + deckViewContainers.insert(playerId, deckView); + deckViewContainerLayout->addWidget(deckView); + } tabMenu->insertMenu(playersSeparator, newPlayer->getPlayerMenu()); @@ -283,13 +382,19 @@ void TabGame::processGameEventContainer(GameEventContainer *cont) } } -void TabGame::sendGameCommand(GameCommand *command) +void TabGame::sendGameCommand(GameCommand *command, int playerId) { command->setGameId(gameId); + + AbstractClient *client; + if (clients.size() > 1) + client = clients.at(playerId); + else + client = clients.first(); client->sendCommand(command); } -void TabGame::sendCommandContainer(CommandContainer *cont) +void TabGame::sendCommandContainer(CommandContainer *cont, int playerId) { const QList &cmdList = cont->getCommandList(); for (int i = 0; i < cmdList.size(); ++i) { @@ -297,6 +402,12 @@ void TabGame::sendCommandContainer(CommandContainer *cont) if (cmd) cmd->setGameId(gameId); } + + AbstractClient *client; + if (clients.size() > 1) + client = clients.at(playerId); + else + client = clients.first(); client->sendCommandContainer(cont); } @@ -304,11 +415,16 @@ void TabGame::startGame() { currentPhase = -1; - readyStartButton->setReadyStart(false); - deckView->setLocked(false); + QMapIterator i(deckViewContainers); + while (i.hasNext()) { + i.next(); + i.value()->setReadyStart(false); + i.value()->hide(); + } + mainLayout->removeItem(deckViewContainerLayout); + playerListWidget->setGameStarted(true); started = true; - deckViewContainer->hide(); gameView->show(); phasesToolbar->show(); } @@ -318,12 +434,18 @@ void TabGame::stopGame() currentPhase = -1; activePlayer = -1; + QMapIterator i(deckViewContainers); + while (i.hasNext()) { + i.next(); + i.value()->show(); + } + mainLayout->insertLayout(2, deckViewContainerLayout, 10); + playerListWidget->setActivePlayer(-1); playerListWidget->setGameStarted(false); started = false; gameView->hide(); phasesToolbar->hide(); - deckViewContainer->show(); } void TabGame::eventSpectatorSay(Event_Say *event, GameEventContext * /*context*/) @@ -361,8 +483,7 @@ void TabGame::eventGameStateChanged(Event_GameStateChanged *event, GameEventCont player->processPlayerInfo(pl); if (player->getLocal() && pl->getDeck()) { Deck_PictureCacher::cachePictures(pl->getDeck(), this); - deckView->setDeck(new DeckList(pl->getDeck())); - readyStartButton->setEnabled(true); + deckViewContainers.value(player->getId())->setDeck(new DeckList(pl->getDeck())); } } } @@ -398,10 +519,8 @@ void TabGame::eventPlayerPropertiesChanged(Event_PlayerPropertiesChanged *event, if (context) switch (context->getItemId()) { case ItemId_Context_ReadyStart: { bool ready = event->getProperties()->getReadyStart(); - if (player->getLocal()) { - readyStartButton->setReadyStart(ready); - deckView->setLocked(ready); - } + if (player->getLocal()) + deckViewContainers.value(player->getId())->setReadyStart(ready); if (ready) messageLog->logReadyStart(player); else @@ -500,66 +619,11 @@ void TabGame::eventPing(Event_Ping *event, GameEventContext * /*context*/) playerListWidget->updatePing(pingList[i]->getPlayerId(), pingList[i]->getPingTime()); } -void TabGame::loadLocalDeck() -{ - QFileDialog dialog(this, tr("Load deck")); - QSettings settings; - dialog.setDirectory(settings.value("paths/decks").toString()); - dialog.setNameFilters(DeckList::fileNameFilters); - if (!dialog.exec()) - return; - - QString fileName = dialog.selectedFiles().at(0); - DeckList::FileFormat fmt = DeckList::getFormatFromNameFilter(dialog.selectedNameFilter()); - DeckList *deck = new DeckList; - if (!deck->loadFromFile(fileName, fmt)) { - delete deck; - // Error message - return; - } - - Command_DeckSelect *cmd = new Command_DeckSelect(gameId, deck, -1); - connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(deckSelectFinished(ProtocolResponse *))); - client->sendCommand(cmd); -} - -void TabGame::loadRemoteDeck() -{ - DlgLoadRemoteDeck dlg(client); - if (dlg.exec()) { - Command_DeckSelect *cmd = new Command_DeckSelect(gameId, 0, dlg.getDeckId()); - connect(cmd, SIGNAL(finished(ProtocolResponse *)), this, SLOT(deckSelectFinished(ProtocolResponse *))); - client->sendCommand(cmd); - } -} - -void TabGame::deckSelectFinished(ProtocolResponse *r) -{ - Response_DeckDownload *resp = qobject_cast(r); - if (!resp) - return; - - Deck_PictureCacher::cachePictures(resp->getDeck(), this); - deckView->setDeck(new DeckList(resp->getDeck())); - readyStartButton->setEnabled(true); -} - -void TabGame::readyStart() -{ - client->sendCommand(new Command_ReadyStart(gameId, !readyStartButton->getReadyStart())); -} - void TabGame::newCardAdded(AbstractCardItem *card) { connect(card, SIGNAL(hovered(AbstractCardItem *)), cardInfo, SLOT(setCard(AbstractCardItem *))); } -void TabGame::sideboardPlanChanged() -{ - QList newPlan = deckView->getSideboardPlan(); - client->sendCommand(new Command_SetSideboardPlan(gameId, newPlan)); -} - CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) const { Player *player = players.value(playerId, 0); diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 21fb0689..33cf86fd 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -39,6 +39,10 @@ class Player; class CardZone; class AbstractCardItem; class CardItem; +class TabGame; +class DeckList; +class QVBoxLayout; +class QHBoxLayout; class ReadyStartButton : public QPushButton { Q_OBJECT @@ -52,10 +56,33 @@ protected: void paintEvent(QPaintEvent *event); }; +class DeckViewContainer : public QWidget { + Q_OBJECT +private: + QPushButton *loadLocalButton, *loadRemoteButton; + ReadyStartButton *readyStartButton; + DeckView *deckView; + AbstractClient *client; +private slots: + void loadLocalDeck(); + void loadRemoteDeck(); + void readyStart(); + void deckSelectFinished(ProtocolResponse *r); + void sideboardPlanChanged(); +signals: + void newCardAdded(AbstractCardItem *card); +public: + DeckViewContainer(AbstractClient *_client, TabGame *parent = 0); + void retranslateUi(); + void setButtonsVisible(bool _visible); + void setReadyStart(bool ready); + void setDeck(DeckList *deck); +}; + class TabGame : public Tab { Q_OBJECT private: - AbstractClient *client; + QList clients; int gameId; QString gameDescription; int localPlayerId; @@ -68,8 +95,6 @@ private: int currentPhase; int activePlayer; - QPushButton *loadLocalButton, *loadRemoteButton; - ReadyStartButton *readyStartButton; CardInfoWidget *cardInfo; PlayerListWidget *playerListWidget; MessageLogWidget *messageLog; @@ -78,8 +103,9 @@ private: PhasesToolbar *phasesToolbar; GameScene *scene; GameView *gameView; - DeckView *deckView; - QWidget *deckViewContainer; + QMap deckViewContainers; + QVBoxLayout *deckViewContainerLayout; + QHBoxLayout *mainLayout; ZoneViewLayout *zoneLayout; QAction *playersSeparator; QMenu *playersMenu; @@ -106,12 +132,7 @@ private: signals: void gameClosing(TabGame *tab); private slots: - void loadLocalDeck(); - void loadRemoteDeck(); - void readyStart(); - void deckSelectFinished(ProtocolResponse *r); void newCardAdded(AbstractCardItem *card); - void sideboardPlanChanged(); void actConcede(); void actLeaveGame(); @@ -120,7 +141,7 @@ private slots: void actNextPhase(); void actNextTurn(); public: - TabGame(AbstractClient *_client, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); + TabGame(QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming); ~TabGame(); void retranslateUi(); const QMap &getPlayers() const { return players; } @@ -134,8 +155,8 @@ public: void processGameEventContainer(GameEventContainer *cont); public slots: - void sendGameCommand(GameCommand *command); - void sendCommandContainer(CommandContainer *cont); + void sendGameCommand(GameCommand *command, int playerId); + void sendCommandContainer(CommandContainer *cont, int playerId); }; #endif diff --git a/cockatrice/src/tab_supervisor.cpp b/cockatrice/src/tab_supervisor.cpp index a5a60e1a..c1f55891 100644 --- a/cockatrice/src/tab_supervisor.cpp +++ b/cockatrice/src/tab_supervisor.cpp @@ -68,6 +68,14 @@ void TabSupervisor::start(AbstractClient *_client) retranslateUi(); } +void TabSupervisor::startLocal(const QList &_clients) +{ + localClients = _clients; + for (int i = 0; i < localClients.size(); ++i) + connect(localClients[i], SIGNAL(gameEventContainerReceived(GameEventContainer *)), this, SLOT(processGameEventContainer(GameEventContainer *))); + connect(localClients.first(), SIGNAL(gameJoinedEventReceived(Event_GameJoined *)), this, SLOT(localGameJoined(Event_GameJoined *))); +} + void TabSupervisor::stop() { if (!client) @@ -104,13 +112,28 @@ void TabSupervisor::updatePingTime(int value, int max) void TabSupervisor::gameJoined(Event_GameJoined *event) { - TabGame *tab = new TabGame(client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + TabGame *tab = new TabGame(QList() << client, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); myAddTab(tab); gameTabs.insert(event->getGameId(), tab); setCurrentWidget(tab); } +void TabSupervisor::localGameJoined(Event_GameJoined *event) +{ + TabGame *tab = new TabGame(localClients, event->getGameId(), event->getGameDescription(), event->getPlayerId(), event->getSpectator(), event->getSpectatorsCanTalk(), event->getSpectatorsSeeEverything(), event->getResuming()); + connect(tab, SIGNAL(gameClosing(TabGame *)), this, SLOT(gameLeft(TabGame *))); + myAddTab(tab); + gameTabs.insert(event->getGameId(), tab); + setCurrentWidget(tab); + + for (int i = 1; i < localClients.size(); ++i) { + qDebug("JOINING"); + Command_JoinGame *cmd = new Command_JoinGame(event->getGameId()); + localClients[i]->sendCommand(cmd); + } +} + void TabSupervisor::gameLeft(TabGame *tab) { emit setMenu(0); diff --git a/cockatrice/src/tab_supervisor.h b/cockatrice/src/tab_supervisor.h index d36294fe..6c743abb 100644 --- a/cockatrice/src/tab_supervisor.h +++ b/cockatrice/src/tab_supervisor.h @@ -20,6 +20,7 @@ class TabSupervisor : public QTabWidget { private: QIcon *tabChangedIcon; AbstractClient *client; + QList localClients; TabServer *tabServer; TabDeckStorage *tabDeckStorage; QMap chatChannelTabs; @@ -30,6 +31,7 @@ public: ~TabSupervisor(); void retranslateUi(); void start(AbstractClient *_client); + void startLocal(const QList &_clients); void stop(); int getGameCount() const { return gameTabs.size(); } signals: @@ -38,6 +40,7 @@ private slots: void updateCurrent(int index); void updatePingTime(int value, int max); void gameJoined(Event_GameJoined *event); + void localGameJoined(Event_GameJoined *event); void gameLeft(TabGame *tab); void addChatChannelTab(const QString &channelName); void chatChannelLeft(TabChatChannel *tab); diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 1427f80e..6d1c3893 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -80,11 +80,25 @@ void MainWindow::actDisconnect() void MainWindow::actSinglePlayer() { + bool ok; + int numberPlayers = QInputDialog::getInt(this, tr("Number of players"), tr("Please enter the number of players."), 2, 1, 8, 1, &ok); + if (!ok) + return; + LocalServer *ls = new LocalServer(this); LocalServerInterface *mainLsi = ls->newConnection(); - LocalClient *mainClient = new LocalClient(mainLsi, this); - tabSupervisor->start(mainClient); + LocalClient *mainClient = new LocalClient(mainLsi, tr("Player %1").arg(1), this); + localClients.append(mainClient); + for (int i = 0; i < numberPlayers - 1; ++i) { + LocalServerInterface *slaveLsi = ls->newConnection(); + LocalClient *slaveClient = new LocalClient(slaveLsi, tr("Player %1").arg(i + 2), this); + localClients.append(slaveClient); + } + tabSupervisor->startLocal(localClients); + + Command_CreateGame *createCommand = new Command_CreateGame(QString(), QString(), numberPlayers, false, false, false, false); + mainClient->sendCommand(createCommand); } void MainWindow::actDeckEditor() diff --git a/cockatrice/src/window_main.h b/cockatrice/src/window_main.h index b81d37ab..979994e2 100644 --- a/cockatrice/src/window_main.h +++ b/cockatrice/src/window_main.h @@ -26,6 +26,7 @@ class TabSupervisor; class RemoteClient; +class LocalClient; class MainWindow : public QMainWindow { Q_OBJECT @@ -55,6 +56,7 @@ private: TabSupervisor *tabSupervisor; RemoteClient *client; + QList localClients; public: MainWindow(QWidget *parent = 0); protected: diff --git a/common/server.h b/common/server.h index 461e516b..298eda4c 100644 --- a/common/server.h +++ b/common/server.h @@ -14,6 +14,8 @@ enum AuthenticationResult { PasswordWrong = 0, PasswordRight = 1, UnknownUser = class Server : public QObject { Q_OBJECT +signals: + void pingClockTimeout(); private slots: void gameClosing(); void broadcastChannelUpdate(); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 2d4a4968..abba6e72 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -12,14 +12,11 @@ #include "server_player.h" #include "decklist.h" #include -#include Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) : QObject(parent), server(_server), authState(PasswordWrong), acceptsGameListChanges(false), lastCommandTime(QDateTime::currentDateTime()) { - pingClock = new QTimer(this); - connect(pingClock, SIGNAL(timeout()), this, SLOT(pingClockTimeout())); - pingClock->start(1000); + connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); } Server_ProtocolHandler::~Server_ProtocolHandler() @@ -332,7 +329,7 @@ ResponseCode Server_ProtocolHandler::cmdJoinGame(Command_JoinGame *cmd, CommandC Server_Game *g = server->getGame(cmd->getGameId()); if (!g) return RespNameNotFound; - + ResponseCode result = g->checkJoin(cmd->getPassword(), cmd->getSpectator()); if (result == RespOk) { Server_Player *player = g->addPlayer(this, cmd->getSpectator()); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 5a3c427c..74d1966d 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -27,6 +27,10 @@ Servatrice::Servatrice(QObject *parent) : Server(parent) { + pingClock = new QTimer(this); + connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); + pingClock->start(1000); + ProtocolItem::initializeHash(); settings = new QSettings("servatrice.ini", QSettings::IniFormat, this); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index fd1bb782..be44cde8 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -26,6 +26,7 @@ class QSqlDatabase; class QSettings; class QSqlQuery; +class QTimer; class Servatrice : public Server { @@ -44,6 +45,7 @@ public: int getMaxGameInactivityTime() const { return maxGameInactivityTime; } int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; } private: + QTimer *pingClock; QTcpServer *tcpServer; QString loginMessage; QSettings *settings;