diff --git a/cockatrice/src/carditem.cpp b/cockatrice/src/carditem.cpp index 53876451..fd8f3805 100644 --- a/cockatrice/src/carditem.cpp +++ b/cockatrice/src/carditem.cpp @@ -148,7 +148,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance()) return; - bool faceDown = event->modifiers().testFlag(Qt::ShiftModifier); + bool faceDown = event->modifiers().testFlag(Qt::ShiftModifier) || facedown; createDragItem((CardZone *) parentItem(), id, event->pos(), event->scenePos(), faceDown); dragItem->grabMouse(); diff --git a/cockatrice/src/client.cpp b/cockatrice/src/client.cpp index b6b71049..9eae5198 100644 --- a/cockatrice/src/client.cpp +++ b/cockatrice/src/client.cpp @@ -155,7 +155,7 @@ void Client::readLine() else if (!prefix.compare("welcome")) { emit welcomeMsgReceived(welcomemsg); setStatus(StatusConnected); - setName(PlayerName); + login(PlayerName, password); } msgbuf.clear(); } else @@ -189,9 +189,10 @@ int Client::cmd(const QString &s) return MsgId; } -void Client::connectToServer(const QString &hostname, unsigned int port, const QString &playername) +void Client::connectToServer(const QString &hostname, unsigned int port, const QString &playername, const QString &_password) { PlayerName = playername; + password = _password; socket->connectToHost(hostname, port); setStatus(StatusConnecting); } @@ -229,9 +230,9 @@ int Client::leaveGame() return cmd("leave_game"); } -int Client::setName(const QString &name) +int Client::login(const QString &name, const QString &pass) { - return cmd(QString("set_name|%1").arg(name)); + return cmd(QString("login|%1|%2").arg(name).arg(pass)); } int Client::say(const QString &s) diff --git a/cockatrice/src/client.h b/cockatrice/src/client.h index 18cae5a4..0d051cc2 100644 --- a/cockatrice/src/client.h +++ b/cockatrice/src/client.h @@ -48,6 +48,7 @@ private: ProtocolStatus status; QList msgbuf; QString PlayerName; + QString password; unsigned int MsgId; void msg(const QString &s); int cmd(const QString &s); @@ -58,14 +59,14 @@ public: ProtocolStatus getStatus() { return status; } QString peerName() const { return socket->peerName(); } - void connectToServer(const QString &hostname, unsigned int port, const QString &playername); + void connectToServer(const QString &hostname, unsigned int port, const QString &playername, const QString &password); void disconnectFromServer(); int listGames(); int listPlayers(); int createGame(const QString &name, const QString &description, const QString &password, unsigned int maxPlayers); int joinGame(const QString &name, const QString &password); int leaveGame(); - int setName(const QString &name); + int login(const QString &name, const QString &pass); int say(const QString &s); int shuffle(); int rollDice(unsigned int sides); diff --git a/cockatrice/src/dlg_connect.cpp b/cockatrice/src/dlg_connect.cpp index 90430275..52dccaaa 100644 --- a/cockatrice/src/dlg_connect.cpp +++ b/cockatrice/src/dlg_connect.cpp @@ -16,6 +16,11 @@ DlgConnect::DlgConnect(QWidget *parent) playernameEdit = new QLineEdit("Player"); playernameLabel->setBuddy(playernameEdit); + passwordLabel = new QLabel(tr("P&assword:")); + passwordEdit = new QLineEdit; + passwordLabel->setBuddy(passwordEdit); + passwordEdit->setEchoMode(QLineEdit::Password); + okButton = new QPushButton(tr("&OK")); okButton->setDefault(true); cancelButton = new QPushButton(tr("&Cancel")); @@ -27,6 +32,8 @@ DlgConnect::DlgConnect(QWidget *parent) grid->addWidget(portEdit, 1, 1); grid->addWidget(playernameLabel, 2, 0); grid->addWidget(playernameEdit, 2, 1); + grid->addWidget(passwordLabel, 3, 0); + grid->addWidget(passwordEdit, 3, 1); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); @@ -59,3 +66,8 @@ QString DlgConnect::getPlayerName() { return playernameEdit->text(); } + +QString DlgConnect::getPassword() +{ + return passwordEdit->text(); +} diff --git a/cockatrice/src/dlg_connect.h b/cockatrice/src/dlg_connect.h index 5c5b4243..00f39b6b 100644 --- a/cockatrice/src/dlg_connect.h +++ b/cockatrice/src/dlg_connect.h @@ -14,9 +14,10 @@ public: QString getHost(); int getPort(); QString getPlayerName(); + QString getPassword(); private: - QLabel *hostLabel, *portLabel, *playernameLabel; - QLineEdit *hostEdit, *portEdit, *playernameEdit; + QLabel *hostLabel, *portLabel, *playernameLabel, *passwordLabel; + QLineEdit *hostEdit, *portEdit, *playernameEdit, *passwordEdit; QPushButton *okButton, *cancelButton; }; diff --git a/cockatrice/src/game.cpp b/cockatrice/src/game.cpp index 7234609d..7127ec4f 100644 --- a/cockatrice/src/game.cpp +++ b/cockatrice/src/game.cpp @@ -68,6 +68,8 @@ Game::Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_a connect(aUntap, SIGNAL(triggered()), this, SLOT(actUntap())); aDoesntUntap = new QAction(tr("Toggle &normal untapping"), this); connect(aDoesntUntap, SIGNAL(triggered()), this, SLOT(actDoesntUntap())); + aFlip = new QAction(tr("&Flip"), this); + connect(aFlip, SIGNAL(triggered()), this, SLOT(actFlip())); aAddCounter = new QAction(tr("&Add counter"), this); connect(aAddCounter, SIGNAL(triggered()), this, SLOT(actAddCounter())); aRemoveCounter = new QAction(tr("&Remove counter"), this); @@ -81,6 +83,8 @@ Game::Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_a cardMenu->addAction(aUntap); cardMenu->addAction(aDoesntUntap); cardMenu->addSeparator(); + cardMenu->addAction(aFlip); + cardMenu->addSeparator(); cardMenu->addAction(aAddCounter); cardMenu->addAction(aRemoveCounter); cardMenu->addAction(aSetCounters); @@ -321,6 +325,16 @@ void Game::actDoesntUntap() } } +void Game::actFlip() +{ + QListIterator i(scene->selectedItems()); + while (i.hasNext()) { + CardItem *temp = (CardItem *) i.next(); + QString zone = qgraphicsitem_cast(temp->parentItem())->getName(); + client->moveCard(temp->getId(), zone, zone, temp->pos().x(), temp->pos().y(), !temp->getFaceDown()); + } +} + void Game::actAddCounter() { QListIterator i(scene->selectedItems()); diff --git a/cockatrice/src/game.h b/cockatrice/src/game.h index 2f564a2f..c1a037f0 100644 --- a/cockatrice/src/game.h +++ b/cockatrice/src/game.h @@ -15,7 +15,7 @@ class Game : public QObject { Q_OBJECT private: QMenu *actionsMenu, *cardMenu; - QAction *aTap, *aUntap, *aDoesntUntap, *aAddCounter, *aRemoveCounter, *aSetCounters, *aRearrange, + QAction *aTap, *aUntap, *aDoesntUntap, *aFlip, *aAddCounter, *aRemoveCounter, *aSetCounters, *aRearrange, *aUntapAll, *aDecLife, *aIncLife, *aSetLife, *aShuffle, *aDraw, *aDrawCards, *aRollDice, *aCreateToken; DlgStartGame *dlgStartGame; @@ -41,6 +41,7 @@ private slots: void actTap(); void actUntap(); void actDoesntUntap(); + void actFlip(); void actAddCounter(); void actRemoveCounter(); void actSetCounters(); diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 9d628028..f70abacd 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -82,7 +82,7 @@ void MainWindow::actConnect() { DlgConnect dlg(this); if (dlg.exec()) - client->connectToServer(dlg.getHost(), dlg.getPort(), dlg.getPlayerName()); + client->connectToServer(dlg.getHost(), dlg.getPort(), dlg.getPlayerName(), dlg.getPassword()); } void MainWindow::actDisconnect() diff --git a/servatrice/servertest.pro b/servatrice/servatrice.pro similarity index 58% rename from servatrice/servertest.pro rename to servatrice/servatrice.pro index 03aa811b..51a9cecd 100755 --- a/servatrice/servertest.pro +++ b/servatrice/servatrice.pro @@ -8,25 +8,25 @@ DEPENDPATH += . src INCLUDEPATH += . src CONFIG += qt thread -QT += network +QT += network sql QT -= gui # Input -HEADERS += src/testserver.h src/testservergame.h src/testserversocket.h \ +HEADERS += src/server.h src/servergame.h src/serversocket.h \ src/playerzone.h \ - src/testcard.h \ + src/card.h \ src/version.h \ src/counter.h \ - src/testrandom.h \ - src/testservergamethread.h \ + src/random.h \ + src/servergamethread.h \ src/returnmessage.h SOURCES += src/main.cpp \ - src/testserver.cpp \ - src/testservergame.cpp \ - src/testserversocket.cpp \ + src/server.cpp \ + src/servergame.cpp \ + src/serversocket.cpp \ src/playerzone.cpp \ - src/testcard.cpp \ + src/card.cpp \ src/counter.cpp \ - src/testrandom.cpp \ - src/testservergamethread.cpp \ + src/random.cpp \ + src/servergamethread.cpp \ src/returnmessage.cpp diff --git a/servatrice/src/testcard.cpp b/servatrice/src/card.cpp similarity index 91% rename from servatrice/src/testcard.cpp rename to servatrice/src/card.cpp index 48fdaea0..e3490d5e 100644 --- a/servatrice/src/testcard.cpp +++ b/servatrice/src/card.cpp @@ -17,19 +17,19 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#include "testcard.h" +#include "card.h" -TestCard::TestCard(QString _name, int _id, int _coord_x, int _coord_y) +Card::Card(QString _name, int _id, int _coord_x, int _coord_y) : id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), counters(0), tapped(false), attacking(false), facedown(false), annotation(QString()), doesntUntap(false) { } -TestCard::~TestCard() +Card::~Card() { } -void TestCard::resetState() +void Card::resetState() { setCoords(0, 0); setCounters(0); @@ -40,7 +40,7 @@ void TestCard::resetState() setDoesntUntap(false); } -bool TestCard::setAttribute(const QString &aname, const QString &avalue, bool allCards) +bool Card::setAttribute(const QString &aname, const QString &avalue, bool allCards) { if (!aname.compare("counters")) { bool ok; diff --git a/servatrice/src/testcard.h b/servatrice/src/card.h similarity index 95% rename from servatrice/src/testcard.h rename to servatrice/src/card.h index e1a0f6d3..7bcbb30e 100644 --- a/servatrice/src/testcard.h +++ b/servatrice/src/card.h @@ -17,12 +17,12 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#ifndef TESTCARD_H -#define TESTCARD_H +#ifndef CARD_H +#define CARD_H #include -class TestCard { +class Card { private: int id; int coord_x, coord_y; @@ -34,8 +34,8 @@ private: QString annotation; bool doesntUntap; public: - TestCard(QString _name, int _id, int _coord_x, int _coord_y); - ~TestCard(); + Card(QString _name, int _id, int _coord_x, int _coord_y); + ~Card(); int getId() { return id; } int getX() { return coord_x; } diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index 5a78ff90..0e1d24b4 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -20,14 +20,18 @@ #include -#include "testserver.h" +#include "server.h" int main(int argc, char *argv[]) { - QCoreApplication app(argc, argv); - - TestServer server; - server.listen(QHostAddress::Any, 4747); + QCoreApplication app(argc, argv); - return app.exec(); + Server server; + if (!server.openDatabase()) { + qCritical("Database error"); + return -1; + } + server.listen(QHostAddress::Any, 4747); + + return app.exec(); } diff --git a/servatrice/src/playerzone.cpp b/servatrice/src/playerzone.cpp index d58d26da..36a94c7f 100644 --- a/servatrice/src/playerzone.cpp +++ b/servatrice/src/playerzone.cpp @@ -18,6 +18,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "playerzone.h" +#include "random.h" +#include "card.h" PlayerZone::PlayerZone(QString _name, bool _has_coords, bool _is_public, bool _is_private, bool _id_access) : name(_name), has_coords(_has_coords), is_public(_is_public), is_private(_is_private), id_access(_id_access) @@ -30,21 +32,21 @@ PlayerZone::~PlayerZone() clear(); } -void PlayerZone::shuffle(TestRandom *rnd) +void PlayerZone::shuffle(Random *rnd) { - QList temp; + QList temp; for (int i = cards.size(); i; i--) temp.append(cards.takeAt(rnd->getNumber(0, i - 1))); cards = temp; } -TestCard *PlayerZone::getCard(int id, bool remove, int *position) +Card *PlayerZone::getCard(int id, bool remove, int *position) { if (hasIdAccess()) { - QListIterator CardIterator(cards); + QListIterator CardIterator(cards); int i = 0; while (CardIterator.hasNext()) { - TestCard *tmp = CardIterator.next(); + Card *tmp = CardIterator.next(); if (tmp->getId() == id) { if (remove) cards.removeAt(i); @@ -58,7 +60,7 @@ TestCard *PlayerZone::getCard(int id, bool remove, int *position) } else { if (id >= cards.size()) return NULL; - TestCard *tmp = cards[id]; + Card *tmp = cards[id]; if (remove) cards.removeAt(id); if (position) @@ -67,7 +69,7 @@ TestCard *PlayerZone::getCard(int id, bool remove, int *position) } } -void PlayerZone::insertCard(TestCard *card, int x, int y) +void PlayerZone::insertCard(Card *card, int x, int y) { if (hasCoords()) { card->setCoords(x, y); diff --git a/servatrice/src/playerzone.h b/servatrice/src/playerzone.h index 17214e81..d06dbe21 100644 --- a/servatrice/src/playerzone.h +++ b/servatrice/src/playerzone.h @@ -21,8 +21,10 @@ #define PLAYERZONE_H #include -#include "testcard.h" -#include "testrandom.h" +#include + +class Card; +class Random; class PlayerZone { private: @@ -40,7 +42,7 @@ public: PlayerZone(QString _name, bool _has_coords, bool _is_public, bool _is_private, bool _id_access); ~PlayerZone(); - TestCard *getCard(int id, bool remove, int *position = NULL); + Card *getCard(int id, bool remove, int *position = NULL); bool isPublic() { return is_public; } bool isPrivate() { return is_private; } @@ -48,9 +50,9 @@ public: bool hasIdAccess() { return id_access; } QString getName() { return name; } - QList cards; - void insertCard(TestCard *card, int x, int y); - void shuffle(TestRandom *rnd); + QList cards; + void insertCard(Card *card, int x, int y); + void shuffle(Random *rnd); void clear(); }; diff --git a/servatrice/src/testrandom.cpp b/servatrice/src/random.cpp similarity index 74% rename from servatrice/src/testrandom.cpp rename to servatrice/src/random.cpp index 8590154d..0d9068ae 100644 --- a/servatrice/src/testrandom.cpp +++ b/servatrice/src/random.cpp @@ -1,7 +1,7 @@ -#include "testrandom.h" +#include "random.h" #include -void TestRandom::init() +void Random::init() { if (initialized) return; @@ -11,7 +11,7 @@ void TestRandom::init() initialized = true; } -unsigned int TestRandom::getNumber(unsigned int min, unsigned int max) +unsigned int Random::getNumber(unsigned int min, unsigned int max) { int r = qrand(); return min + (unsigned int) (((double) (max + 1 - min)) * r / (RAND_MAX + 1.0)); diff --git a/servatrice/src/testrandom.h b/servatrice/src/random.h similarity index 56% rename from servatrice/src/testrandom.h rename to servatrice/src/random.h index 6ae998ba..a5e60143 100644 --- a/servatrice/src/testrandom.h +++ b/servatrice/src/random.h @@ -1,16 +1,16 @@ -#ifndef TESTRANDOM_H -#define TESTRANDOM_H +#ifndef RANDOM_H +#define RANDOM_H #include #include #include -class TestRandom : public QObject { +class Random : public QObject { Q_OBJECT private: bool initialized; public: - TestRandom(QObject *parent) : QObject(parent), initialized(false) { } + Random(QObject *parent) : QObject(parent), initialized(false) { } void init(); unsigned int getNumber(unsigned int min, unsigned int max); }; diff --git a/servatrice/src/returnmessage.cpp b/servatrice/src/returnmessage.cpp index dee88e1f..b6549365 100644 --- a/servatrice/src/returnmessage.cpp +++ b/servatrice/src/returnmessage.cpp @@ -1,25 +1,36 @@ #include "returnmessage.h" -#include "testserversocket.h" +#include "serversocket.h" void ReturnMessage::setMsgId(unsigned int _msg_id) { msg_id = _msg_id; } -bool ReturnMessage::send(const QString &args, bool success) +bool ReturnMessage::send(ReturnCode code) { - TestServerSocket *s = qobject_cast(parent()); + ServerSocket *s = qobject_cast(parent()); if (!s) return false; + bool success = (code == ReturnOk); + QString returnCodeString; + switch (code) { + case ReturnNothing: return true; + case ReturnOk: break; + case ReturnLoginNeeded: returnCodeString = "login_needed"; break; + case ReturnSyntaxError: returnCodeString = "syntax"; break; + case ReturnContextError: returnCodeString = "context"; break; + case ReturnPasswordWrong: returnCodeString = "password"; break; + case ReturnNameNotFound: returnCodeString = "name_not_found"; break; + } s->msg(QString("resp|%1|%2|%3").arg(msg_id) .arg(success ? "ok" : "err") - .arg(args)); + .arg(returnCodeString)); return success; } bool ReturnMessage::sendList(const QStringList &args) { - TestServerSocket *s = qobject_cast(parent()); + ServerSocket *s = qobject_cast(parent()); if (!s) return false; diff --git a/servatrice/src/returnmessage.h b/servatrice/src/returnmessage.h index 95714d16..f7f4f74d 100644 --- a/servatrice/src/returnmessage.h +++ b/servatrice/src/returnmessage.h @@ -1,8 +1,7 @@ #ifndef RETURNMESSAGE_H #define RETURNMESSAGE_H -#include -#include +#include class ReturnMessage : public QObject { Q_OBJECT @@ -10,11 +9,12 @@ private: unsigned int msg_id; QString cmd; public: + enum ReturnCode { ReturnNothing, ReturnOk, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong, ReturnNameNotFound }; ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { } unsigned int getMsgId() const { return msg_id; } void setMsgId(unsigned int _msg_id); void setCmd(const QString &_cmd) { cmd = _cmd; } - bool send(const QString &args = QString(), bool success = true); + bool send(ReturnCode code); bool sendList(const QStringList &args); }; diff --git a/servatrice/src/testserver.cpp b/servatrice/src/server.cpp similarity index 51% rename from servatrice/src/testserver.cpp rename to servatrice/src/server.cpp index d590100a..ecab5a55 100644 --- a/servatrice/src/testserver.cpp +++ b/servatrice/src/server.cpp @@ -17,58 +17,91 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#include "testserver.h" +#include "server.h" +#include "servergamethread.h" +#include "servergame.h" +#include "serversocket.h" +#include "counter.h" +#include -TestServer::TestServer(QObject *parent) +Server::Server(QObject *parent) : QTcpServer(parent) { } -TestServer::~TestServer() +Server::~Server() { } -void TestServer::gameCreated(TestServerGame *_game, TestServerSocket *_creator) +bool Server::openDatabase() +{ + QSqlDatabase sqldb = QSqlDatabase::addDatabase("QMYSQL"); + sqldb.setHostName("localhost"); + sqldb.setDatabaseName("cockatrice"); + sqldb.setUserName("cockatrice"); + sqldb.setPassword("45CdX6rmd"); + return sqldb.open(); +} + +void Server::gameCreated(ServerGame *_game, ServerSocket *_creator) { games << _game; _creator->moveToThread(_game->thread()); _game->addPlayer(_creator); } -void TestServer::addGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator) +void Server::addGame(const QString name, const QString description, const QString password, const int maxPlayers, ServerSocket *creator) { - TestServerGameThread *newThread = new TestServerGameThread(name, description, password, maxPlayers, creator); - connect(newThread, SIGNAL(gameCreated(TestServerGame *, TestServerSocket *)), this, SLOT(gameCreated(TestServerGame *, TestServerSocket *))); + ServerGameThread *newThread = new ServerGameThread(name, description, password, maxPlayers, creator); + connect(newThread, SIGNAL(gameCreated(ServerGame *, ServerSocket *)), this, SLOT(gameCreated(ServerGame *, ServerSocket *))); connect(newThread, SIGNAL(finished()), this, SLOT(gameClosed())); newThread->start(); } -void TestServer::incomingConnection(int socketId) +void Server::incomingConnection(int socketId) { - TestServerSocket *socket = new TestServerSocket(this); + ServerSocket *socket = new ServerSocket(this); socket->setSocketDescriptor(socketId); - connect(socket, SIGNAL(createGame(const QString, const QString, const QString, const int, TestServerSocket *)), this, SLOT(addGame(const QString, const QString, const QString, const int, TestServerSocket *))); - connect(socket, SIGNAL(joinGame(const QString, TestServerSocket *)), this, SLOT(addClientToGame(const QString, TestServerSocket *))); + connect(socket, SIGNAL(createGame(const QString, const QString, const QString, const int, ServerSocket *)), this, SLOT(addGame(const QString, const QString, const QString, const int, ServerSocket *))); + connect(socket, SIGNAL(joinGame(const QString, ServerSocket *)), this, SLOT(addClientToGame(const QString, ServerSocket *))); socket->initConnection(); } -TestServerGame *TestServer::getGame(const QString &name) +AuthenticationResult Server::checkUserPassword(const QString &user, const QString &password) { - QListIterator i(games); + QSqlQuery query; + query.prepare("select password from users where name = :name"); + query.bindValue(":name", user); + if (!query.exec()) { + qCritical(QString("Database error: %1").arg(query.lastError().text()).toLatin1()); + exit(-1); + } + if (query.next()) { + if (query.value(0).toString() == password) + return PasswordRight; + else + return PasswordWrong; + } else + return UnknownUser; +} + +ServerGame *Server::getGame(const QString &name) +{ + QListIterator i(games); while (i.hasNext()) { - TestServerGame *tmp = i.next(); + ServerGame *tmp = i.next(); if ((!tmp->name.compare(name, Qt::CaseSensitive)) && !tmp->getGameStarted()) return tmp; } return NULL; } -QList TestServer::listOpenGames() +QList Server::listOpenGames() { - QList result; - QListIterator i(games); + QList result; + QListIterator i(games); while (i.hasNext()) { - TestServerGame *tmp = i.next(); + ServerGame *tmp = i.next(); tmp->mutex->lock(); if ((!tmp->getGameStarted()) && (tmp->getPlayerCount() < tmp->maxPlayers)) @@ -78,9 +111,9 @@ QList TestServer::listOpenGames() return result; } -bool TestServer::checkGamePassword(const QString &name, const QString &password) +bool Server::checkGamePassword(const QString &name, const QString &password) { - TestServerGame *tmp; + ServerGame *tmp; if ((tmp = getGame(name))) { QMutexLocker locker(tmp->mutex); if ((!tmp->getGameStarted()) @@ -91,17 +124,17 @@ bool TestServer::checkGamePassword(const QString &name, const QString &password) return false; } -void TestServer::addClientToGame(const QString name, TestServerSocket *client) +void Server::addClientToGame(const QString name, ServerSocket *client) { - TestServerGame *tmp = getGame(name); + ServerGame *tmp = getGame(name); client->moveToThread(tmp->thread()); tmp->addPlayer(client); } -void TestServer::gameClosed() +void Server::gameClosed() { - qDebug("TestServer::gameClosed"); - TestServerGameThread *t = qobject_cast(sender()); + qDebug("Server::gameClosed"); + ServerGameThread *t = qobject_cast(sender()); games.removeAt(games.indexOf(t->getGame())); delete t; } diff --git a/servatrice/src/testserver.h b/servatrice/src/server.h similarity index 71% rename from servatrice/src/testserver.h rename to servatrice/src/server.h index 1fbe38fd..848bd17f 100644 --- a/servatrice/src/testserver.h +++ b/servatrice/src/server.h @@ -17,33 +17,36 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#ifndef TESTSERVER_H -#define TESTSERVER_H +#ifndef SERVER_H +#define SERVER_H #include -#include "testservergamethread.h" -#include "testservergame.h" -class TestServerGame; -class TestServerSocket; +class ServerGame; +class ServerSocket; +class QSqlDatabase; -class TestServer : public QTcpServer +enum AuthenticationResult { PasswordWrong = 0, PasswordRight = 1, UnknownUser = 2 }; + +class Server : public QTcpServer { Q_OBJECT private slots: - void addGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator); - void addClientToGame(const QString name, TestServerSocket *client); - void gameCreated(TestServerGame *_game, TestServerSocket *_creator); + void addGame(const QString name, const QString description, const QString password, const int maxPlayers, ServerSocket *creator); + void addClientToGame(const QString name, ServerSocket *client); + void gameCreated(ServerGame *_game, ServerSocket *_creator); void gameClosed(); public: - TestServer(QObject *parent = 0); - ~TestServer(); + Server(QObject *parent = 0); + ~Server(); + bool openDatabase(); bool checkGamePassword(const QString &name, const QString &password); - QList listOpenGames(); - TestServerGame *getGame(const QString &name); + AuthenticationResult checkUserPassword(const QString &user, const QString &password); + QList listOpenGames(); + ServerGame *getGame(const QString &name); private: void incomingConnection(int SocketId); - QList games; + QList games; }; #endif diff --git a/servatrice/src/testservergame.cpp b/servatrice/src/servergame.cpp similarity index 73% rename from servatrice/src/testservergame.cpp rename to servatrice/src/servergame.cpp index 10464a42..3e8e2e5a 100644 --- a/servatrice/src/testservergame.cpp +++ b/servatrice/src/servergame.cpp @@ -17,9 +17,11 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#include "testservergame.h" +#include "servergame.h" +#include "random.h" +#include "serversocket.h" -TestServerGame::TestServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent) +ServerGame::ServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent) : QObject(parent), name(_name), description(_description), password(_password), maxPlayers(_maxPlayers) { gameStarted = false; @@ -27,59 +29,59 @@ TestServerGame::TestServerGame(QString _name, QString _description, QString _pas rnd = NULL; } -TestServerGame::~TestServerGame() +ServerGame::~ServerGame() { if (rnd) delete rnd; delete mutex; - qDebug("TestServerGame destructor"); + qDebug("ServerGame destructor"); } -bool TestServerGame::getGameStarted() +bool ServerGame::getGameStarted() { return gameStarted; } -int TestServerGame::getPlayerCount() +int ServerGame::getPlayerCount() { QMutexLocker locker(mutex); return players.size(); } -QStringList TestServerGame::getPlayerNames() +QStringList ServerGame::getPlayerNames() { QMutexLocker locker(mutex); QStringList result; - QListIterator i(players); + QListIterator i(players); while (i.hasNext()) { - TestServerSocket *tmp = i.next(); + ServerSocket *tmp = i.next(); result << QString("%1|%2").arg(tmp->getPlayerId()).arg(tmp->PlayerName); } return result; } -TestServerSocket *TestServerGame::getPlayer(int player_id) +ServerSocket *ServerGame::getPlayer(int player_id) { - QListIterator i(players); + QListIterator i(players); while (i.hasNext()) { - TestServerSocket *tmp = i.next(); + ServerSocket *tmp = i.next(); if (tmp->getPlayerId() == player_id) return tmp; } return NULL; } -void TestServerGame::msg(const QString &s) +void ServerGame::msg(const QString &s) { QMutexLocker locker(mutex); - QListIterator i(players); + QListIterator i(players); while (i.hasNext()) i.next()->msg(s); } -void TestServerGame::broadcastEvent(const QString &cmd, TestServerSocket *player) +void ServerGame::broadcastEvent(const QString &cmd, ServerSocket *player) { if (player) msg(QString("public|%1|%2|%3").arg(player->getPlayerId()).arg(player->PlayerName).arg(cmd)); @@ -87,7 +89,7 @@ void TestServerGame::broadcastEvent(const QString &cmd, TestServerSocket *player msg(QString("public|||%1").arg(cmd)); } -void TestServerGame::startGameIfReady() +void ServerGame::startGameIfReady() { QMutexLocker locker(mutex); @@ -98,7 +100,7 @@ void TestServerGame::startGameIfReady() return; if (!rnd) { - rnd = new TestRandom(this); + rnd = new Random(this); rnd->init(); } @@ -111,12 +113,12 @@ void TestServerGame::startGameIfReady() broadcastEvent("game_start", NULL); } -void TestServerGame::addPlayer(TestServerSocket *player) +void ServerGame::addPlayer(ServerSocket *player) { QMutexLocker locker(mutex); int max = -1; - QListIterator i(players); + QListIterator i(players); while (i.hasNext()) { int tmp = i.next()->getPlayerId(); if (tmp > max) @@ -130,10 +132,10 @@ void TestServerGame::addPlayer(TestServerSocket *player) players << player; - connect(player, SIGNAL(broadcastEvent(const QString &, TestServerSocket *)), this, SLOT(broadcastEvent(const QString &, TestServerSocket *))); + connect(player, SIGNAL(broadcastEvent(const QString &, ServerSocket *)), this, SLOT(broadcastEvent(const QString &, ServerSocket *))); } -void TestServerGame::removePlayer(TestServerSocket *player) +void ServerGame::removePlayer(ServerSocket *player) { QMutexLocker locker(mutex); @@ -143,14 +145,14 @@ void TestServerGame::removePlayer(TestServerSocket *player) thread()->quit(); } -void TestServerGame::setActivePlayer(int _activePlayer) +void ServerGame::setActivePlayer(int _activePlayer) { activePlayer = _activePlayer; broadcastEvent(QString("set_active_player|%1").arg(_activePlayer), NULL); setActivePhase(0); } -void TestServerGame::setActivePhase(int _activePhase) +void ServerGame::setActivePhase(int _activePhase) { activePhase = _activePhase; broadcastEvent(QString("set_active_phase|%1").arg(_activePhase), NULL); diff --git a/servatrice/src/testservergame.h b/servatrice/src/servergame.h similarity index 77% rename from servatrice/src/testservergame.h rename to servatrice/src/servergame.h index 42a7e26e..b8c3f058 100644 --- a/servatrice/src/testservergame.h +++ b/servatrice/src/servergame.h @@ -17,41 +17,40 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#ifndef TESTSERVERGAME_H -#define TESTSERVERGAME_H +#ifndef SERVERGAME_H +#define SERVERGAME_H #include #include #include -#include "testserversocket.h" -#include "testrandom.h" -class TestServerSocket; +class ServerSocket; +class Random; -class TestServerGame : public QObject { +class ServerGame : public QObject { Q_OBJECT private: - QList players; + QList players; bool gameStarted; int activePlayer; int activePhase; public slots: - void broadcastEvent(const QString &event, TestServerSocket *player); + void broadcastEvent(const QString &event, ServerSocket *player); public: QMutex *mutex; - TestRandom *rnd; + Random *rnd; QString name; QString description; QString password; int maxPlayers; - TestServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent = 0); - ~TestServerGame(); + ServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent = 0); + ~ServerGame(); bool getGameStarted(); int getPlayerCount(); QStringList getPlayerNames(); - TestServerSocket *getPlayer(int player_id); - void addPlayer(TestServerSocket *player); - void removePlayer(TestServerSocket *player); + ServerSocket *getPlayer(int player_id); + void addPlayer(ServerSocket *player); + void removePlayer(ServerSocket *player); void startGameIfReady(); void msg(const QString &s); int getActivePlayer() { return activePlayer; } diff --git a/servatrice/src/servergamethread.cpp b/servatrice/src/servergamethread.cpp new file mode 100644 index 00000000..fb180a2b --- /dev/null +++ b/servatrice/src/servergamethread.cpp @@ -0,0 +1,21 @@ +#include "servergamethread.h" +#include "servergame.h" + +ServerGameThread::ServerGameThread(const QString _name, const QString _description, const QString _password, const int _maxPlayers, ServerSocket *_creator, QObject *parent) + : QThread(parent), name(_name), description(_description), password(_password), maxPlayers(_maxPlayers), creator(_creator), game(0) +{ + +} + +ServerGameThread::~ServerGameThread() +{ + if (game) + delete game; +} + +void ServerGameThread::run() +{ + game = new ServerGame(name, description, password, maxPlayers); + emit gameCreated(game, creator); + exec(); +} diff --git a/servatrice/src/servergamethread.h b/servatrice/src/servergamethread.h new file mode 100644 index 00000000..cd1cba23 --- /dev/null +++ b/servatrice/src/servergamethread.h @@ -0,0 +1,28 @@ +#ifndef SERVERGAMETHREAD_H +#define SERVERGAMETHREAD_H + +#include +#include + +class ServerGame; +class ServerSocket; + +class ServerGameThread : public QThread { + Q_OBJECT +signals: + void gameCreated(ServerGame *_game, ServerSocket *creator); +private: + QString name; + QString description; + QString password; + int maxPlayers; + ServerSocket *creator; + ServerGame *game; +public: + ServerGameThread(const QString _name, const QString _description, const QString _password, const int _maxPlayers, ServerSocket *_creator, QObject *parent = 0); + ~ServerGameThread(); + ServerGame *getGame() { return game; } + void run(); +}; + +#endif diff --git a/servatrice/src/serversocket.cpp b/servatrice/src/serversocket.cpp new file mode 100644 index 00000000..611a3dc4 --- /dev/null +++ b/servatrice/src/serversocket.cpp @@ -0,0 +1,690 @@ +/*************************************************************************** + * Copyright (C) 2008 by Max-Wilhelm Bruker * + * brukie@laptop * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include "server.h" +#include "serversocket.h" +#include "servergame.h" +#include "version.h" +#include "returnmessage.h" +#include "playerzone.h" +#include "counter.h" +#include "card.h" +#include "random.h" + +ServerSocket::ServerSocket(Server *_server, QObject *parent) + : QTcpSocket(parent), server(_server), game(0), authState(PasswordWrong) +{ + remsg = new ReturnMessage(this); + connect(this, SIGNAL(readyRead()), this, SLOT(readClient())); + connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater())); + connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); + setTextModeEnabled(true); + PlayerStatus = StatusNormal; +} + +ServerSocket::~ServerSocket() +{ + qDebug("ServerSocket destructor"); + if (game) + game->removePlayer(this); +} + +int ServerSocket::newCardId() +{ + return nextCardId++; +} + +void ServerSocket::setName(const QString &name) +{ + emit broadcastEvent(QString("name|%1|%2").arg(PlayerName).arg(name), this); + PlayerName = name; +} + +PlayerZone *ServerSocket::getZone(const QString &name) +{ + QListIterator ZoneIterator(zones); + while (ZoneIterator.hasNext()) { + PlayerZone *temp = ZoneIterator.next(); + if (!temp->getName().compare(name)) + return temp; + } + return NULL; +} + +Counter *ServerSocket::getCounter(const QString &name) +{ + QListIterator CounterIterator(counters); + while (CounterIterator.hasNext()) { + Counter *temp = CounterIterator.next(); + if (!temp->getName().compare(name)) + return temp; + } + return NULL; +} + +void ServerSocket::setupZones() +{ + // Delete existing zones and counters + clearZones(); + + // This may need to be customized according to the game rules. + // ------------------------------------------------------------------ + + // Create zones + PlayerZone *deck = new PlayerZone("deck", false, false, false, false); + zones << deck; + PlayerZone *sb = new PlayerZone("sb", false, false, false, false); + zones << sb; + zones << new PlayerZone("table", true, true, false, true); + zones << new PlayerZone("hand", false, false, true, true); + zones << new PlayerZone("grave", false, true, false, true); + zones << new PlayerZone("rfg", false, true, false, true); + + // Create life counter + Counter *life = new Counter("life", 20); + counters << life; + + // ------------------------------------------------------------------ + + // Assign card ids and create deck from decklist + QListIterator DeckIterator(DeckList); + int i = 0; + while (DeckIterator.hasNext()) + deck->cards.append(new Card(DeckIterator.next(), i++, 0, 0)); + deck->shuffle(game->rnd); + + QListIterator SBIterator(SideboardList); + while (SBIterator.hasNext()) + sb->cards.append(new Card(SBIterator.next(), i++, 0, 0)); + + nextCardId = i; + + PlayerStatus = StatusPlaying; + broadcastEvent(QString("setup_zones|%1|%2|%3").arg(getCounter("life")->getCount()) + .arg(deck->cards.size()) + .arg(getZone("sb")->cards.size()), this); +} + +void ServerSocket::clearZones() +{ + for (int i = 0; i < zones.size(); i++) + delete zones.at(i); + zones.clear(); + + for (int i = 0; i < counters.size(); i++) + delete counters.at(i); + counters.clear(); +} + +void ServerSocket::leaveGame() +{ + if (!game) + return; + game->removePlayer(this); + game = 0; + PlayerStatus = StatusNormal; + clearZones(); + moveToThread(server->thread()); +} + +void ServerSocket::readClient() +{ + QTextStream *stream = new QTextStream(this); + stream->setCodec("UTF-8"); + QStringList lines; + + // Before parsing, everything has to be buffered so that the stream + // can be deleted in order to avoid problems when moving the object + // to another thread while this function is still running. + for (;;) { + QString line = stream->readLine(); + if (line.isNull()) + break; + lines << line; + } + delete stream; + + QStringListIterator i(lines); + while (i.hasNext()) { + QString line = i.next(); + + qDebug(QString("<<< %1").arg(line).toLatin1()); + switch (PlayerStatus) { + case StatusNormal: + case StatusReadyStart: + case StatusPlaying: + parseCommand(line); + break; + case StatusSubmitDeck: + QString card = line; + if (!card.compare(".")) { + PlayerStatus = StatusNormal; + remsg->send(ReturnMessage::ReturnOk); + } else if (card.startsWith("SB:")) + SideboardList << card.mid(3); + else + DeckList << card; + } + } +} + +const ServerSocket::CommandProperties ServerSocket::commandList[ServerSocket::numberCommands] = { + {"login", 2, false, false, false, &ServerSocket::cmdLogin}, + {"list_games", 0, true, false, false, &ServerSocket::cmdListGames}, + {"create_game", 4, true, false, false, &ServerSocket::cmdCreateGame}, + {"join_game", 2, true, false, false, &ServerSocket::cmdJoinGame}, + {"leave_game", 0, true, true, false, &ServerSocket::cmdLeaveGame}, + {"list_players", 0, true, true, false, &ServerSocket::cmdListPlayers}, + {"say", 1, true, true, false, &ServerSocket::cmdSay}, + {"submit_deck", 0, true, true, false, &ServerSocket::cmdSubmitDeck}, + {"ready_start", 0, true, true, false, &ServerSocket::cmdReadyStart}, + {"shuffle", 0, true, true, true, &ServerSocket::cmdShuffle}, + {"draw_cards", 1, true, true, true, &ServerSocket::cmdDrawCards}, + {"move_card", 6, true, true, true, &ServerSocket::cmdMoveCard}, + {"create_token", 5, true, true, true, &ServerSocket::cmdCreateToken}, + {"set_card_attr", 4, true, true, true, &ServerSocket::cmdSetCardAttr}, + {"inc_counter", 2, true, true, true, &ServerSocket::cmdIncCounter}, + {"set_counter", 2, true, true, true, &ServerSocket::cmdSetCounter}, + {"del_counter", 1, true, true, true, &ServerSocket::cmdDelCounter}, + {"list_counters", 2, true, true, true, &ServerSocket::cmdListCounters}, + {"list_zones", 1, true, true, true, &ServerSocket::cmdListZones}, + {"dump_zone", 3, true, true, true, &ServerSocket::cmdDumpZone}, + {"roll_dice", 1, true, true, true, &ServerSocket::cmdRollDice}, + {"set_active_player", 1, true, true, true, &ServerSocket::cmdSetActivePlayer}, + {"set_active_phase", 1, true, true, true, &ServerSocket::cmdSetActivePhase} +}; + +ReturnMessage::ReturnCode ServerSocket::cmdLogin(const QStringList ¶ms) +{ + authState = server->checkUserPassword(params[0], params[1]); + if (authState == PasswordWrong) + return ReturnMessage::ReturnPasswordWrong; + PlayerName = params[0]; + + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdListGames(const QStringList ¶ms) +{ + QList gameList = server->listOpenGames(); + QListIterator gameListIterator(gameList); + QStringList result; + while (gameListIterator.hasNext()) { + ServerGame *tmp = gameListIterator.next(); + tmp->mutex->lock(); + result << QString("%1|%2|%3|%4|%5").arg(tmp->name) + .arg(tmp->description) + .arg(tmp->password == "" ? 0 : 1) + .arg(tmp->getPlayerCount()) + .arg(tmp->maxPlayers); + tmp->mutex->unlock(); + } + remsg->sendList(result); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdCreateGame(const QStringList ¶ms) +{ + QString name = params[0]; + QString description = params[1]; + QString password = params[2]; + int maxPlayers = params[3].toInt(); + if (server->getGame(name)) + return ReturnMessage::ReturnNameNotFound; + leaveGame(); + emit createGame(name, description, password, maxPlayers, this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdJoinGame(const QStringList ¶ms) +{ + QString name = params[0]; + QString password = params[1]; + if (!server->checkGamePassword(name, password)) + return ReturnMessage::ReturnPasswordWrong; + leaveGame(); + emit joinGame(name, this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdLeaveGame(const QStringList ¶ms) +{ + leaveGame(); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdListPlayers(const QStringList ¶ms) +{ + remsg->sendList(game->getPlayerNames()); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdSay(const QStringList ¶ms) +{ + emit broadcastEvent(QString("say|%1").arg(params[0]), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdSubmitDeck(const QStringList ¶ms) +{ + PlayerStatus = StatusSubmitDeck; + DeckList.clear(); + SideboardList.clear(); + return ReturnMessage::ReturnNothing; +} + +ReturnMessage::ReturnCode ServerSocket::cmdReadyStart(const QStringList ¶ms) +{ + PlayerStatus = StatusReadyStart; + emit broadcastEvent(QString("ready_start"), this); + game->startGameIfReady(); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdShuffle(const QStringList ¶ms) +{ + getZone("deck")->shuffle(game->rnd); + emit broadcastEvent("shuffle", this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdDrawCards(const QStringList ¶ms) +{ + bool ok; + int number = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + PlayerZone *deck = getZone("deck"); + PlayerZone *hand = getZone("hand"); + if (deck->cards.size() < number) + return ReturnMessage::ReturnContextError; + + for (int i = 0; i < number; ++i) { + Card *card = deck->cards.first(); + deck->cards.removeFirst(); + hand->cards.append(card); + msg(QString("private|||draw|%1|%2").arg(card->getId()).arg(card->getName())); + } + + emit broadcastEvent(QString("draw|%1").arg(number), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdMoveCard(const QStringList ¶ms) +{ + // ID Karte, Startzone, Zielzone, Koordinaten X, Y, Facedown + bool ok; + int cardid = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + PlayerZone *startzone = getZone(params[1]); + PlayerZone *targetzone = getZone(params[2]); + if ((!startzone) || (!targetzone)) + return ReturnMessage::ReturnContextError; + + int position = -1; + Card *card = startzone->getCard(cardid, true, &position); + if (!card) + return ReturnMessage::ReturnContextError; + int x = params[3].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + int y = 0; + if (targetzone->hasCoords()) { + y = params[4].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + } + bool facedown = params[5].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + + targetzone->insertCard(card, x, y); + + QString privateCardName, publicCardName; + if (facedown) + card->setId(newCardId()); + if ((!facedown && !card->getFaceDown()) + || (card->getFaceDown() && !facedown && startzone->isPublic() && targetzone->isPublic())) + publicCardName = card->getName(); + if ((!facedown && !card->getFaceDown()) + || (card->getFaceDown() && !facedown && startzone->isPublic() && targetzone->isPublic()) + || (!facedown && targetzone->isPrivate())) + privateCardName = card->getName(); + + card->setFaceDown(facedown); + msg(QString("private|||move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(card->getId()) + .arg(privateCardName) + .arg(startzone->getName()) + .arg(position) + .arg(targetzone->getName()) + .arg(x) + .arg(y) + .arg(facedown ? 1 : 0)); + if ((startzone->isPublic()) || (targetzone->isPublic())) + emit broadcastEvent(QString("move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(card->getId()) + .arg(publicCardName) + .arg(startzone->getName()) + .arg(position) + .arg(targetzone->getName()) + .arg(x) + .arg(y) + .arg(facedown ? 1 : 0), this); + else + emit broadcastEvent(QString("move_card|||%1|%2|%3|%4|%5|0").arg(startzone->getName()) + .arg(position) + .arg(targetzone->getName()) + .arg(x) + .arg(y), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdCreateToken(const QStringList ¶ms) +{ + // zone, cardname, powtough, x, y + // powtough wird erst mal ignoriert + PlayerZone *zone = getZone(params[0]); + if (!zone) + return ReturnMessage::ReturnContextError; + QString cardname = params[1]; + int x = params[3].toInt(); + int y = params[4].toInt(); + int cardid = newCardId(); + QString powtough = params[2]; + + Card *card = new Card(cardname, cardid, x, y); + zone->insertCard(card, x, y); + emit broadcastEvent(QString("create_token|%1|%2|%3|%4|%5|%6").arg(zone->getName()) + .arg(cardid) + .arg(cardname) + .arg(powtough) + .arg(x) + .arg(y), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdSetCardAttr(const QStringList ¶ms) +{ + // zone, card id, attr name, attr value + // card id = -1 => affects all cards in the specified zone + PlayerZone *zone = getZone(params[0]); + if (!zone) + return ReturnMessage::ReturnContextError; + bool ok; + int cardid = params[1].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + + if (cardid == -1) { + QListIterator CardIterator(zone->cards); + while (CardIterator.hasNext()) + if (!CardIterator.next()->setAttribute(params[2], params[3], true)) + return ReturnMessage::ReturnSyntaxError; + } else { + Card *card = zone->getCard(cardid, false); + if (!card) + return ReturnMessage::ReturnContextError; + if (!card->setAttribute(params[2], params[3], false)) + return ReturnMessage::ReturnSyntaxError; + } + emit broadcastEvent(QString("set_card_attr|%1|%2|%3|%4").arg(zone->getName()).arg(cardid).arg(params[2]).arg(params[3]), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdIncCounter(const QStringList ¶ms) +{ + Counter *c = getCounter(params[0]); + if (!c) + return ReturnMessage::ReturnContextError; + bool ok; + int delta = params[1].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + c->setCount(c->getCount() + delta); + emit broadcastEvent(QString("set_counter|%1|%2").arg(params[0]).arg(c->getCount()), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdSetCounter(const QStringList ¶ms) +{ + Counter *c = getCounter(params[0]); + bool ok; + int count = params[1].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + if (!c) { + c = new Counter(params[0], count); + counters << c; + } else + c->setCount(count); + emit broadcastEvent(QString("set_counter|%1|%2").arg(params[0]).arg(count), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdDelCounter(const QStringList ¶ms) +{ + Counter *c = getCounter(params[0]); + if (!c) + return ReturnMessage::ReturnContextError; + delete c; + counters.removeAt(counters.indexOf(c)); + emit broadcastEvent(QString("del_counter|%1").arg(params[0]), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdListCounters(const QStringList ¶ms) +{ + bool ok; + int player_id = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + ServerSocket *player = game->getPlayer(player_id); + if (!player) + return ReturnMessage::ReturnContextError; + remsg->sendList(player->listCounters()); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdListZones(const QStringList ¶ms) +{ + bool ok; + int player_id = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + ServerSocket *player = game->getPlayer(player_id); + if (!player) + return ReturnMessage::ReturnContextError; + remsg->sendList(player->listZones()); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdDumpZone(const QStringList ¶ms) +{ + bool ok; + int player_id = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + int number_cards = params[2].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + ServerSocket *player = game->getPlayer(player_id); + if (!player) + return ReturnMessage::ReturnContextError; + PlayerZone *zone = player->getZone(params[1]); + if (!zone) + return ReturnMessage::ReturnContextError; + if (!(zone->isPublic() || (player_id == PlayerId))) + return ReturnMessage::ReturnContextError; + QListIterator card_iterator(zone->cards); + QStringList result; + for (int i = 0; card_iterator.hasNext() && (i < number_cards || number_cards == 0); i++) { + Card *tmp = card_iterator.next(); + // XXX Face down cards + if (zone->hasIdAccess()) + result << QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(tmp->getId()) + .arg(tmp->getName()) + .arg(tmp->getX()) + .arg(tmp->getY()) + .arg(tmp->getCounters()) + .arg(tmp->getTapped()) + .arg(tmp->getAttacking()) + .arg(tmp->getAnnotation()); + else + result << QString("%1|%2||||||").arg(i).arg(tmp->getName()); + } + remsg->sendList(result); + emit broadcastEvent(QString("dump_zone|%1|%2|%3").arg(player_id).arg(zone->getName()).arg(number_cards), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdRollDice(const QStringList ¶ms) +{ + bool ok; + int sides = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + emit broadcastEvent(QString("roll_dice|%1|%2").arg(sides).arg(game->rnd->getNumber(1, sides)), this); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdSetActivePlayer(const QStringList ¶ms) +{ + bool ok; + int active_player = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + if (!game->getPlayer(active_player)) + return ReturnMessage::ReturnContextError; + game->setActivePlayer(active_player); + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdSetActivePhase(const QStringList ¶ms) +{ + bool ok; + int active_phase = params[0].toInt(&ok); + if (!ok) + return ReturnMessage::ReturnSyntaxError; + // XXX Überprüfung, ob die Phase existiert... + game->setActivePhase(active_phase); + return ReturnMessage::ReturnOk; +} + +bool ServerSocket::parseCommand(QString line) +{ + QStringList params = line.split("|"); + + // Extract message id + bool conv_ok; + int msgId = params.takeFirst().toInt(&conv_ok); + if (!conv_ok) { + remsg->setMsgId(0); + return remsg->send(ReturnMessage::ReturnSyntaxError); + } + remsg->setMsgId(msgId); + + if (params.empty()) { + remsg->setMsgId(0); + return remsg->send(ReturnMessage::ReturnSyntaxError); + } + + // Extract command + QString cmd = params.takeFirst(); + remsg->setCmd(cmd); + + for (int i = 0; i < numberCommands; i++) + if (commandList[i].name == cmd) { + // Check login + if (commandList[i].needsLogin && (authState == PasswordWrong)) + return remsg->send(ReturnMessage::ReturnLoginNeeded); + // Check context + if (commandList[i].needsGame && !game) + return remsg->send(ReturnMessage::ReturnContextError); + if (commandList[i].needsStartedGame && !game->getGameStarted()) + return remsg->send(ReturnMessage::ReturnContextError); + // Check parameter count + if (commandList[i].numberParams != params.size()) + return remsg->send(ReturnMessage::ReturnSyntaxError); + // Call handler function + CommandHandler handler = commandList[i].handler; + return remsg->send((this->*handler)(params)); + } + return remsg->send(ReturnMessage::ReturnSyntaxError); +} + +PlayerStatusEnum ServerSocket::getStatus() +{ + return PlayerStatus; +} + +void ServerSocket::setStatus(PlayerStatusEnum status) +{ + PlayerStatus = status; +} + +void ServerSocket::setGame(ServerGame *g) +{ + game = g; +} + +QStringList ServerSocket::listCounters() +{ + QStringList counter_list; + QListIterator i(counters); + while (i.hasNext()) { + Counter *tmp = i.next(); + counter_list << QString("%1|%2").arg(tmp->getName()).arg(tmp->getCount()); + } + return counter_list; +} + +QStringList ServerSocket::listZones() +{ + QStringList zone_list; + QListIterator i(zones); + while (i.hasNext()) { + PlayerZone *tmp = i.next(); + zone_list << QString("%1|%2|%3|%4").arg(tmp->getName()).arg(tmp->isPublic()).arg(tmp->hasCoords()).arg(tmp->cards.size()); + } + return zone_list; +} + +void ServerSocket::msg(const QString &s) +{ + qDebug(QString(">>> %1").arg(s).toLatin1()); + QTextStream stream(this); + stream.setCodec("UTF-8"); + stream << s << endl; + stream.flush(); + flush(); +} + +void ServerSocket::initConnection() +{ + msg(QString("welcome||%1").arg(VERSION_STRING)); + msg("welcome||."); +} + +void ServerSocket::catchSocketError(QAbstractSocket::SocketError socketError) +{ + qDebug(QString("socket error: %1").arg(socketError).toLatin1()); + deleteLater(); +} diff --git a/servatrice/src/testserversocket.h b/servatrice/src/serversocket.h similarity index 50% rename from servatrice/src/testserversocket.h rename to servatrice/src/serversocket.h index 73cb6f19..2fa18c0c 100644 --- a/servatrice/src/testserversocket.h +++ b/servatrice/src/serversocket.h @@ -17,37 +17,71 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#ifndef TESTSERVERSOCKET_H -#define TESTSERVERSOCKET_H +#ifndef SERVERSOCKET_H +#define SERVERSOCKET_H #include -#include "testserver.h" -#include "testservergame.h" -#include "playerzone.h" +#include "server.h" #include "returnmessage.h" -#include "counter.h" -class TestServer; -class TestServerGame; +class Server; +class ServerGame; class PlayerZone; +class Counter; enum PlayerStatusEnum { StatusNormal, StatusSubmitDeck, StatusReadyStart, StatusPlaying }; -class TestServerSocket : public QTcpSocket +class ServerSocket : public QTcpSocket { Q_OBJECT private slots: void readClient(); void catchSocketError(QAbstractSocket::SocketError socketError); signals: - void createGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator); - void joinGame(const QString name, TestServerSocket *player); - void commandReceived(QString cmd, TestServerSocket *player); - void broadcastEvent(const QString &event, TestServerSocket *player); + void createGame(const QString name, const QString description, const QString password, const int maxPlayers, ServerSocket *creator); + void joinGame(const QString name, ServerSocket *player); + void commandReceived(QString cmd, ServerSocket *player); + void broadcastEvent(const QString &event, ServerSocket *player); void startGameIfReady(); private: - TestServer *server; - TestServerGame *game; + typedef ReturnMessage::ReturnCode (ServerSocket::*CommandHandler)(const QStringList &); + struct CommandProperties { + QString name; + int numberParams; + bool needsLogin; + bool needsGame; + bool needsStartedGame; + CommandHandler handler; + }; + static const int numberCommands = 23; + static const CommandProperties commandList[numberCommands]; + + ReturnMessage::ReturnCode cmdLogin(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdListGames(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdCreateGame(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdJoinGame(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdLeaveGame(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdListPlayers(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdSay(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdSubmitDeck(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdReadyStart(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdShuffle(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdDrawCards(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdMoveCard(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdCreateToken(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdSetCardAttr(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdIncCounter(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdSetCounter(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdDelCounter(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdListCounters(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdListZones(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdDumpZone(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdRollDice(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdSetActivePlayer(const QStringList ¶ms); + ReturnMessage::ReturnCode cmdSetActivePhase(const QStringList ¶ms); + + Server *server; + ServerGame *game; QList DeckList; QList SideboardList; QList zones; @@ -63,12 +97,13 @@ private: bool parseCommand(QString line); PlayerStatusEnum PlayerStatus; ReturnMessage *remsg; + AuthenticationResult authState; public: QString PlayerName; - TestServerSocket(TestServer *_server, QObject *parent = 0); - ~TestServerSocket(); + ServerSocket(Server *_server, QObject *parent = 0); + ~ServerSocket(); void msg(const QString &s); - void setGame(TestServerGame *g); + void setGame(ServerGame *g); PlayerStatusEnum getStatus(); void setStatus(PlayerStatusEnum status); void initConnection(); diff --git a/servatrice/src/testservergamethread.cpp b/servatrice/src/testservergamethread.cpp deleted file mode 100644 index b0c1b218..00000000 --- a/servatrice/src/testservergamethread.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "testservergamethread.h" - -TestServerGameThread::TestServerGameThread(const QString _name, const QString _description, const QString _password, const int _maxPlayers, TestServerSocket *_creator, QObject *parent) - : QThread(parent), name(_name), description(_description), password(_password), maxPlayers(_maxPlayers), creator(_creator), game(0) -{ - -} - -TestServerGameThread::~TestServerGameThread() -{ - if (game) - delete game; -} - -void TestServerGameThread::run() -{ - game = new TestServerGame(name, description, password, maxPlayers); - emit gameCreated(game, creator); - exec(); -} diff --git a/servatrice/src/testservergamethread.h b/servatrice/src/testservergamethread.h deleted file mode 100644 index f1dbfe84..00000000 --- a/servatrice/src/testservergamethread.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef TESTSERVERGAMETHREAD_H -#define TESTSERVERGAMETHREAD_H - -#include -#include -#include "testservergame.h" -#include "testserversocket.h" - -class TestServerGame; -class TestServerSocket; - -class TestServerGameThread : public QThread { - Q_OBJECT -signals: - void gameCreated(TestServerGame *_game, TestServerSocket *creator); -private: - QString name; - QString description; - QString password; - int maxPlayers; - TestServerSocket *creator; - TestServerGame *game; -public: - TestServerGameThread(const QString _name, const QString _description, const QString _password, const int _maxPlayers, TestServerSocket *_creator, QObject *parent = 0); - ~TestServerGameThread(); - TestServerGame *getGame() { return game; } - void run(); -}; - -#endif diff --git a/servatrice/src/testserversocket.cpp b/servatrice/src/testserversocket.cpp deleted file mode 100644 index 80940017..00000000 --- a/servatrice/src/testserversocket.cpp +++ /dev/null @@ -1,617 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Max-Wilhelm Bruker * - * brukie@laptop * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include "testserver.h" -#include "testserversocket.h" -#include "version.h" - -TestServerSocket::TestServerSocket(TestServer *_server, QObject *parent) - : QTcpSocket(parent), server(_server) -{ - remsg = new ReturnMessage(this); - connect(this, SIGNAL(readyRead()), this, SLOT(readClient())); - connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater())); - connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); - setTextModeEnabled(true); - PlayerStatus = StatusNormal; - game = 0; -} - -TestServerSocket::~TestServerSocket() -{ - qDebug("TestServerSocket destructor"); - if (game) - game->removePlayer(this); -} - -int TestServerSocket::newCardId() -{ - return nextCardId++; -} - -void TestServerSocket::setName(const QString &name) -{ - emit broadcastEvent(QString("name|%1|%2").arg(PlayerName).arg(name), this); - PlayerName = name; -} - -PlayerZone *TestServerSocket::getZone(const QString &name) -{ - QListIterator ZoneIterator(zones); - while (ZoneIterator.hasNext()) { - PlayerZone *temp = ZoneIterator.next(); - if (!temp->getName().compare(name)) - return temp; - } - return NULL; -} - -Counter *TestServerSocket::getCounter(const QString &name) -{ - QListIterator CounterIterator(counters); - while (CounterIterator.hasNext()) { - Counter *temp = CounterIterator.next(); - if (!temp->getName().compare(name)) - return temp; - } - return NULL; -} - -void TestServerSocket::setupZones() -{ - // Delete existing zones and counters - clearZones(); - - // This may need to be customized according to the game rules. - // ------------------------------------------------------------------ - - // Create zones - PlayerZone *deck = new PlayerZone("deck", false, false, false, false); - zones << deck; - PlayerZone *sb = new PlayerZone("sb", false, false, false, false); - zones << sb; - zones << new PlayerZone("table", true, true, false, true); - zones << new PlayerZone("hand", false, false, true, true); - zones << new PlayerZone("grave", false, true, false, true); - zones << new PlayerZone("rfg", false, true, false, true); - - // Create life counter - Counter *life = new Counter("life", 20); - counters << life; - - // ------------------------------------------------------------------ - - // Assign card ids and create deck from decklist - QListIterator DeckIterator(DeckList); - int i = 0; - while (DeckIterator.hasNext()) - deck->cards.append(new TestCard(DeckIterator.next(), i++, 0, 0)); - deck->shuffle(game->rnd); - - QListIterator SBIterator(SideboardList); - while (SBIterator.hasNext()) - sb->cards.append(new TestCard(SBIterator.next(), i++, 0, 0)); - - nextCardId = i; - - PlayerStatus = StatusPlaying; - broadcastEvent(QString("setup_zones|%1|%2|%3").arg(getCounter("life")->getCount()) - .arg(deck->cards.size()) - .arg(getZone("sb")->cards.size()), this); -} - -void TestServerSocket::clearZones() -{ - for (int i = 0; i < zones.size(); i++) - delete zones.at(i); - zones.clear(); - - for (int i = 0; i < counters.size(); i++) - delete counters.at(i); - counters.clear(); -} - -void TestServerSocket::leaveGame() -{ - if (!game) - return; - game->removePlayer(this); - game = 0; - PlayerStatus = StatusNormal; - clearZones(); - moveToThread(server->thread()); -} - -void TestServerSocket::readClient() -{ - QTextStream *stream = new QTextStream(this); - stream->setCodec("UTF-8"); - QStringList lines; - - // Before parsing, everything has to be buffered so that the stream - // can be deleted in order to avoid problems when moving the object - // to another thread while this function is still running. - for (;;) { - QString line = stream->readLine(); - if (line.isNull()) - break; - lines << line; - } - delete stream; - - QStringListIterator i(lines); - while (i.hasNext()) { - QString line = i.next(); - - qDebug(QString("<<< %1").arg(line).toLatin1()); - switch (PlayerStatus) { - case StatusNormal: - case StatusReadyStart: - case StatusPlaying: - parseCommand(line); - break; - case StatusSubmitDeck: - QString card = line; - if (!card.compare(".")) { - PlayerStatus = StatusNormal; - remsg->send(); - } else if (card.startsWith("SB:")) - SideboardList << card.mid(3); - else - DeckList << card; - } - } -} - -bool TestServerSocket::parseCommand(QString line) -{ - QStringList params = line.split("|"); - - // Extract message id - bool conv_ok; - int msgId = params.takeFirst().toInt(&conv_ok); - if (!conv_ok) { - remsg->setMsgId(0); - return remsg->send("syntax", false); - } - remsg->setMsgId(msgId); - - if (params.empty()) { - remsg->setMsgId(0); - return remsg->send("syntax", false); - } - - // Extract command - QString cmd = params.takeFirst(); - remsg->setCmd(cmd); - - // parse command - - if (!cmd.compare("list_games", Qt::CaseInsensitive)) { - remsg->send(); - QList gameList = server->listOpenGames(); - QListIterator gameListIterator(gameList); - QStringList result; - while (gameListIterator.hasNext()) { - TestServerGame *tmp = gameListIterator.next(); - tmp->mutex->lock(); - result << QString("%1|%2|%3|%4|%5").arg(tmp->name) - .arg(tmp->description) - .arg(tmp->password == "" ? 0 : 1) - .arg(tmp->getPlayerCount()) - .arg(tmp->maxPlayers); - tmp->mutex->unlock(); - } - remsg->sendList(result); - } else if (!cmd.compare("create_game", Qt::CaseInsensitive)) { - if (params.size() != 4) - return remsg->send("syntax", false); - QString name = params[0]; - QString description = params[1]; - QString password = params[2]; - int maxPlayers = params[3].toInt(); - if (server->getGame(name)) - return remsg->send("name_not_found", false); - remsg->send(); - leaveGame(); - - emit createGame(name, description, password, maxPlayers, this); - } else if (!cmd.compare("join_game", Qt::CaseInsensitive)) { - if (params.size() != 2) - return remsg->send("syntax", false); - QString name = params[0]; - QString password = params[1]; - if (!server->checkGamePassword(name, password)) - return remsg->send("wrong_password", false); - remsg->send(); - leaveGame(); - - emit joinGame(name, this); - } else if (!cmd.compare("leave_game", Qt::CaseInsensitive)) { - remsg->send(); - leaveGame(); - } else if (!cmd.compare("set_name", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - remsg->send(); - setName(params[0]); - } else if (!cmd.compare("list_players", Qt::CaseInsensitive)) { - if (!game) - return remsg->send("game_state", false); - - remsg->send(); - remsg->sendList(game->getPlayerNames()); - } else if (!cmd.compare("say", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - remsg->send(); - emit broadcastEvent(QString("say|%1").arg(params[0]), this); - } else if (!cmd.compare("submit_deck", Qt::CaseInsensitive)) { - PlayerStatus = StatusSubmitDeck; - DeckList.clear(); - SideboardList.clear(); - } else if (!cmd.compare("shuffle", Qt::CaseInsensitive)) { - if (!game) - return remsg->send("game_state", false); - if (!game->getGameStarted()) - return remsg->send("game_state", false); - getZone("deck")->shuffle(game->rnd); - remsg->send(); - emit broadcastEvent("shuffle", this); - } else if (!cmd.compare("ready_start", Qt::CaseInsensitive)) { - if (!game) - return remsg->send("game_state", false); - remsg->send(); - PlayerStatus = StatusReadyStart; - emit broadcastEvent(QString("ready_start"), this); - game->startGameIfReady(); - } else if (!cmd.compare("draw_cards", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - bool ok; - int number = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - PlayerZone *deck = getZone("deck"); - PlayerZone *hand = getZone("hand"); - - if (deck->cards.size() < number) - return remsg->send("game_state", false); - remsg->send(); - - for (int i = 0; i < number; ++i) { - TestCard *card = deck->cards.first(); - deck->cards.removeFirst(); - hand->cards.append(card); - msg(QString("private|||draw|%1|%2").arg(card->getId()).arg(card->getName())); - } - - emit broadcastEvent(QString("draw|%1").arg(number), this); - } else if (!cmd.compare("move_card", Qt::CaseInsensitive)) { - // ID Karte, Startzone, Zielzone, Koordinaten X, Y, Facedown - if (params.size() != 6) - return remsg->send("syntax", false); - bool ok; - int cardid = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - PlayerZone *startzone = getZone(params[1]); - PlayerZone *targetzone = getZone(params[2]); - if ((!startzone) || (!targetzone)) - return remsg->send("game_state", false); - - int position = -1; - TestCard *card = startzone->getCard(cardid, true, &position); - if (!card) - return remsg->send("game_state", false); - int x = params[3].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - int y = 0; - if (targetzone->hasCoords()) { - y = params[4].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - } - bool facedown = params[5].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - remsg->send(); - targetzone->insertCard(card, x, y); - - QString privateCardName, publicCardName; - if (facedown) - card->setId(newCardId()); - if ((!facedown && !card->getFaceDown()) - || (card->getFaceDown() && !facedown && startzone->isPublic() && targetzone->isPublic())) - publicCardName = card->getName(); - if ((!facedown && !card->getFaceDown()) - || (card->getFaceDown() && !facedown && startzone->isPublic() && targetzone->isPublic()) - || (!facedown && targetzone->isPrivate())) - privateCardName = card->getName(); - - card->setFaceDown(facedown); - msg(QString("private|||move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(card->getId()) - .arg(privateCardName) - .arg(startzone->getName()) - .arg(position) - .arg(targetzone->getName()) - .arg(x) - .arg(y) - .arg(facedown ? 1 : 0)); - if ((startzone->isPublic()) || (targetzone->isPublic())) - emit broadcastEvent(QString("move_card|%1|%2|%3|%4|%5|%6|%7|%8").arg(card->getId()) - .arg(publicCardName) - .arg(startzone->getName()) - .arg(position) - .arg(targetzone->getName()) - .arg(x) - .arg(y) - .arg(facedown ? 1 : 0), this); - else - emit broadcastEvent(QString("move_card|||%1|%2|%3|%4|%5|0").arg(startzone->getName()) - .arg(position) - .arg(targetzone->getName()) - .arg(x) - .arg(y), this); - } else if (!cmd.compare("create_token", Qt::CaseInsensitive)) { - // zone, cardname, powtough, x, y - // powtough wird erst mal ignoriert - if (params.size() != 5) - return remsg->send("syntax", false); - PlayerZone *zone = getZone(params[0]); - if (!zone) - return remsg->send("game_state", false); - QString cardname = params[1]; - int x = params[3].toInt(); - int y = params[4].toInt(); - int cardid = newCardId(); - QString powtough = params[2]; - - remsg->send(); - TestCard *card = new TestCard(cardname, cardid, x, y); - zone->insertCard(card, x, y); - emit broadcastEvent(QString("create_token|%1|%2|%3|%4|%5|%6").arg(zone->getName()) - .arg(cardid) - .arg(cardname) - .arg(powtough) - .arg(x) - .arg(y), this); - } else if (!cmd.compare("set_card_attr", Qt::CaseInsensitive)) { - if (params.size() != 4) - return remsg->send("syntax", false); - // zone, card id, attr name, attr value - // card id = -1 => affects all cards in the specified zone - PlayerZone *zone = getZone(params[0]); - if (!zone) - return remsg->send("game_state", false); - bool ok; - int cardid = params[1].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - - if (cardid == -1) { - QListIterator CardIterator(zone->cards); - while (CardIterator.hasNext()) - if (!CardIterator.next()->setAttribute(params[2], params[3], true)) - return remsg->send("syntax", false); - } else { - TestCard *card = zone->getCard(cardid, false); - if (!card) - return remsg->send("game_state", false); - if (!card->setAttribute(params[2], params[3], false)) - return remsg->send("syntax", false); - } - remsg->send(); - emit broadcastEvent(QString("set_card_attr|%1|%2|%3|%4").arg(zone->getName()).arg(cardid).arg(params[2]).arg(params[3]), this); - } else if (!cmd.compare("inc_counter", Qt::CaseInsensitive)) { - if (params.size() != 2) - return remsg->send("syntax", false); - Counter *c = getCounter(params[0]); - if (!c) - return remsg->send("game_state", false); - bool ok; - int delta = params[1].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - remsg->send(); - c->setCount(c->getCount() + delta); - emit broadcastEvent(QString("set_counter|%1|%2").arg(params[0]).arg(c->getCount()), this); - } else if (!cmd.compare("set_counter", Qt::CaseInsensitive)) { - if (params.size() != 2) - return remsg->send("syntax", false); - Counter *c = getCounter(params[0]); - bool ok; - int count = params[1].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - if (!c) { - c = new Counter(params[0], count); - counters << c; - } else - c->setCount(count); - remsg->send(); - emit broadcastEvent(QString("set_counter|%1|%2").arg(params[0]).arg(count), this); - } else if (!cmd.compare("del_counter", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - Counter *c = getCounter(params[0]); - if (!c) - return remsg->send("game_state", false); - delete c; - counters.removeAt(counters.indexOf(c)); - remsg->send(); - emit broadcastEvent(QString("del_counter|%1").arg(params[0]), this); - } else if (!cmd.compare("list_counters", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - bool ok; - int player_id = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - TestServerSocket *player = game->getPlayer(player_id); - if (!player) - return remsg->send("game_state", false); - remsg->send(); - remsg->sendList(player->listCounters()); - } else if (!cmd.compare("list_zones", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - bool ok; - int player_id = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - TestServerSocket *player = game->getPlayer(player_id); - if (!player) - return remsg->send("game_state", false); - remsg->send(); - remsg->sendList(player->listZones()); - } else if (!cmd.compare("dump_zone", Qt::CaseInsensitive)) { - if (params.size() != 3) - return remsg->send("syntax", false); - bool ok; - int player_id = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - int number_cards = params[2].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - TestServerSocket *player = game->getPlayer(player_id); - if (!player) - return remsg->send("game_state", false); - PlayerZone *zone = player->getZone(params[1]); - if (!zone) - return remsg->send("game_state", false); - if (!(zone->isPublic() || (player_id == PlayerId))) - return remsg->send("game_state", false); - remsg->send(); - QListIterator card_iterator(zone->cards); - QStringList result; - for (int i = 0; card_iterator.hasNext() && (i < number_cards || number_cards == 0); i++) { - TestCard *tmp = card_iterator.next(); - // XXX Face down cards - if (zone->hasIdAccess()) - result << QString("%1|%2|%3|%4|%5|%6|%7|%8").arg(tmp->getId()) - .arg(tmp->getName()) - .arg(tmp->getX()) - .arg(tmp->getY()) - .arg(tmp->getCounters()) - .arg(tmp->getTapped()) - .arg(tmp->getAttacking()) - .arg(tmp->getAnnotation()); - else - result << QString("%1|%2||||||").arg(i).arg(tmp->getName()); - } - remsg->sendList(result); - emit broadcastEvent(QString("dump_zone|%1|%2|%3").arg(player_id).arg(zone->getName()).arg(number_cards), this); - } else if (!cmd.compare("roll_dice", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - bool ok; - int sides = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - remsg->send(); - emit broadcastEvent(QString("roll_dice|%1|%2").arg(sides).arg(game->rnd->getNumber(1, sides)), this); - } else if (!cmd.compare("set_active_player", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - bool ok; - int active_player = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - if (!game->getPlayer(active_player)) - return remsg->send("game_state", false); - remsg->send(); - game->setActivePlayer(active_player); - } else if (!cmd.compare("set_active_phase", Qt::CaseInsensitive)) { - if (params.size() != 1) - return remsg->send("syntax", false); - bool ok; - int active_phase = params[0].toInt(&ok); - if (!ok) - return remsg->send("syntax", false); - // XXX Überprüfung, ob die Phase existiert... - remsg->send(); - game->setActivePhase(active_phase); - } else - return remsg->send("syntax", false); - return true; -} - -PlayerStatusEnum TestServerSocket::getStatus() -{ - return PlayerStatus; -} - -void TestServerSocket::setStatus(PlayerStatusEnum status) -{ - PlayerStatus = status; -} - -void TestServerSocket::setGame(TestServerGame *g) -{ - game = g; -} - -QStringList TestServerSocket::listCounters() -{ - QStringList counter_list; - QListIterator i(counters); - while (i.hasNext()) { - Counter *tmp = i.next(); - counter_list << QString("%1|%2").arg(tmp->getName()).arg(tmp->getCount()); - } - return counter_list; -} - -QStringList TestServerSocket::listZones() -{ - QStringList zone_list; - QListIterator i(zones); - while (i.hasNext()) { - PlayerZone *tmp = i.next(); - zone_list << QString("%1|%2|%3|%4").arg(tmp->getName()).arg(tmp->isPublic()).arg(tmp->hasCoords()).arg(tmp->cards.size()); - } - return zone_list; -} - -void TestServerSocket::msg(const QString &s) -{ - qDebug(QString(">>> %1").arg(s).toLatin1()); - QTextStream stream(this); - stream.setCodec("UTF-8"); - stream << s << endl; - stream.flush(); - flush(); -} - -void TestServerSocket::initConnection() -{ - msg(QString("welcome||%1").arg(VERSION_STRING)); - msg("welcome||."); -} - -void TestServerSocket::catchSocketError(QAbstractSocket::SocketError socketError) -{ - qDebug(QString("socket error: %1").arg(socketError).toLatin1()); - deleteLater(); -} diff --git a/servatrice/src/version.h b/servatrice/src/version.h index b17ba9d0..3a2f3b43 100644 --- a/servatrice/src/version.h +++ b/servatrice/src/version.h @@ -18,4 +18,4 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -const char *VERSION_STRING = "Testserver 0.20090407"; +const char *VERSION_STRING = "Testserver 0.20090408";