minor improvements

This commit is contained in:
Max-Wilhelm Bruker 2009-04-08 21:49:16 +02:00
parent a429a4a004
commit 792a400a3d
30 changed files with 1022 additions and 829 deletions

View file

@ -148,7 +148,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance()) if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance())
return; 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); createDragItem((CardZone *) parentItem(), id, event->pos(), event->scenePos(), faceDown);
dragItem->grabMouse(); dragItem->grabMouse();

View file

@ -155,7 +155,7 @@ void Client::readLine()
else if (!prefix.compare("welcome")) { else if (!prefix.compare("welcome")) {
emit welcomeMsgReceived(welcomemsg); emit welcomeMsgReceived(welcomemsg);
setStatus(StatusConnected); setStatus(StatusConnected);
setName(PlayerName); login(PlayerName, password);
} }
msgbuf.clear(); msgbuf.clear();
} else } else
@ -189,9 +189,10 @@ int Client::cmd(const QString &s)
return MsgId; 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; PlayerName = playername;
password = _password;
socket->connectToHost(hostname, port); socket->connectToHost(hostname, port);
setStatus(StatusConnecting); setStatus(StatusConnecting);
} }
@ -229,9 +230,9 @@ int Client::leaveGame()
return cmd("leave_game"); 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) int Client::say(const QString &s)

View file

@ -48,6 +48,7 @@ private:
ProtocolStatus status; ProtocolStatus status;
QList<QStringList> msgbuf; QList<QStringList> msgbuf;
QString PlayerName; QString PlayerName;
QString password;
unsigned int MsgId; unsigned int MsgId;
void msg(const QString &s); void msg(const QString &s);
int cmd(const QString &s); int cmd(const QString &s);
@ -58,14 +59,14 @@ public:
ProtocolStatus getStatus() { return status; } ProtocolStatus getStatus() { return status; }
QString peerName() const { return socket->peerName(); } 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(); void disconnectFromServer();
int listGames(); int listGames();
int listPlayers(); int listPlayers();
int createGame(const QString &name, const QString &description, const QString &password, unsigned int maxPlayers); int createGame(const QString &name, const QString &description, const QString &password, unsigned int maxPlayers);
int joinGame(const QString &name, const QString &password); int joinGame(const QString &name, const QString &password);
int leaveGame(); int leaveGame();
int setName(const QString &name); int login(const QString &name, const QString &pass);
int say(const QString &s); int say(const QString &s);
int shuffle(); int shuffle();
int rollDice(unsigned int sides); int rollDice(unsigned int sides);

View file

@ -16,6 +16,11 @@ DlgConnect::DlgConnect(QWidget *parent)
playernameEdit = new QLineEdit("Player"); playernameEdit = new QLineEdit("Player");
playernameLabel->setBuddy(playernameEdit); 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 = new QPushButton(tr("&OK"));
okButton->setDefault(true); okButton->setDefault(true);
cancelButton = new QPushButton(tr("&Cancel")); cancelButton = new QPushButton(tr("&Cancel"));
@ -27,6 +32,8 @@ DlgConnect::DlgConnect(QWidget *parent)
grid->addWidget(portEdit, 1, 1); grid->addWidget(portEdit, 1, 1);
grid->addWidget(playernameLabel, 2, 0); grid->addWidget(playernameLabel, 2, 0);
grid->addWidget(playernameEdit, 2, 1); grid->addWidget(playernameEdit, 2, 1);
grid->addWidget(passwordLabel, 3, 0);
grid->addWidget(passwordEdit, 3, 1);
QHBoxLayout *buttonLayout = new QHBoxLayout; QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch(); buttonLayout->addStretch();
@ -59,3 +66,8 @@ QString DlgConnect::getPlayerName()
{ {
return playernameEdit->text(); return playernameEdit->text();
} }
QString DlgConnect::getPassword()
{
return passwordEdit->text();
}

View file

@ -14,9 +14,10 @@ public:
QString getHost(); QString getHost();
int getPort(); int getPort();
QString getPlayerName(); QString getPlayerName();
QString getPassword();
private: private:
QLabel *hostLabel, *portLabel, *playernameLabel; QLabel *hostLabel, *portLabel, *playernameLabel, *passwordLabel;
QLineEdit *hostEdit, *portEdit, *playernameEdit; QLineEdit *hostEdit, *portEdit, *playernameEdit, *passwordEdit;
QPushButton *okButton, *cancelButton; QPushButton *okButton, *cancelButton;
}; };

View file

@ -68,6 +68,8 @@ Game::Game(CardDatabase *_db, Client *_client, QGraphicsScene *_scene, QMenu *_a
connect(aUntap, SIGNAL(triggered()), this, SLOT(actUntap())); connect(aUntap, SIGNAL(triggered()), this, SLOT(actUntap()));
aDoesntUntap = new QAction(tr("Toggle &normal untapping"), this); aDoesntUntap = new QAction(tr("Toggle &normal untapping"), this);
connect(aDoesntUntap, SIGNAL(triggered()), this, SLOT(actDoesntUntap())); 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); aAddCounter = new QAction(tr("&Add counter"), this);
connect(aAddCounter, SIGNAL(triggered()), this, SLOT(actAddCounter())); connect(aAddCounter, SIGNAL(triggered()), this, SLOT(actAddCounter()));
aRemoveCounter = new QAction(tr("&Remove counter"), this); 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(aUntap);
cardMenu->addAction(aDoesntUntap); cardMenu->addAction(aDoesntUntap);
cardMenu->addSeparator(); cardMenu->addSeparator();
cardMenu->addAction(aFlip);
cardMenu->addSeparator();
cardMenu->addAction(aAddCounter); cardMenu->addAction(aAddCounter);
cardMenu->addAction(aRemoveCounter); cardMenu->addAction(aRemoveCounter);
cardMenu->addAction(aSetCounters); cardMenu->addAction(aSetCounters);
@ -321,6 +325,16 @@ void Game::actDoesntUntap()
} }
} }
void Game::actFlip()
{
QListIterator<QGraphicsItem *> i(scene->selectedItems());
while (i.hasNext()) {
CardItem *temp = (CardItem *) i.next();
QString zone = qgraphicsitem_cast<CardZone *>(temp->parentItem())->getName();
client->moveCard(temp->getId(), zone, zone, temp->pos().x(), temp->pos().y(), !temp->getFaceDown());
}
}
void Game::actAddCounter() void Game::actAddCounter()
{ {
QListIterator<QGraphicsItem *> i(scene->selectedItems()); QListIterator<QGraphicsItem *> i(scene->selectedItems());

View file

@ -15,7 +15,7 @@ class Game : public QObject {
Q_OBJECT Q_OBJECT
private: private:
QMenu *actionsMenu, *cardMenu; 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; *aUntapAll, *aDecLife, *aIncLife, *aSetLife, *aShuffle, *aDraw, *aDrawCards, *aRollDice, *aCreateToken;
DlgStartGame *dlgStartGame; DlgStartGame *dlgStartGame;
@ -41,6 +41,7 @@ private slots:
void actTap(); void actTap();
void actUntap(); void actUntap();
void actDoesntUntap(); void actDoesntUntap();
void actFlip();
void actAddCounter(); void actAddCounter();
void actRemoveCounter(); void actRemoveCounter();
void actSetCounters(); void actSetCounters();

View file

@ -82,7 +82,7 @@ void MainWindow::actConnect()
{ {
DlgConnect dlg(this); DlgConnect dlg(this);
if (dlg.exec()) if (dlg.exec())
client->connectToServer(dlg.getHost(), dlg.getPort(), dlg.getPlayerName()); client->connectToServer(dlg.getHost(), dlg.getPort(), dlg.getPlayerName(), dlg.getPassword());
} }
void MainWindow::actDisconnect() void MainWindow::actDisconnect()

View file

@ -8,25 +8,25 @@ DEPENDPATH += . src
INCLUDEPATH += . src INCLUDEPATH += . src
CONFIG += qt thread CONFIG += qt thread
QT += network QT += network sql
QT -= gui QT -= gui
# Input # 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/playerzone.h \
src/testcard.h \ src/card.h \
src/version.h \ src/version.h \
src/counter.h \ src/counter.h \
src/testrandom.h \ src/random.h \
src/testservergamethread.h \ src/servergamethread.h \
src/returnmessage.h src/returnmessage.h
SOURCES += src/main.cpp \ SOURCES += src/main.cpp \
src/testserver.cpp \ src/server.cpp \
src/testservergame.cpp \ src/servergame.cpp \
src/testserversocket.cpp \ src/serversocket.cpp \
src/playerzone.cpp \ src/playerzone.cpp \
src/testcard.cpp \ src/card.cpp \
src/counter.cpp \ src/counter.cpp \
src/testrandom.cpp \ src/random.cpp \
src/testservergamethread.cpp \ src/servergamethread.cpp \
src/returnmessage.cpp src/returnmessage.cpp

View file

@ -17,19 +17,19 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 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) : 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); setCoords(0, 0);
setCounters(0); setCounters(0);
@ -40,7 +40,7 @@ void TestCard::resetState()
setDoesntUntap(false); 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")) { if (!aname.compare("counters")) {
bool ok; bool ok;

View file

@ -17,12 +17,12 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef TESTCARD_H #ifndef CARD_H
#define TESTCARD_H #define CARD_H
#include <QString> #include <QString>
class TestCard { class Card {
private: private:
int id; int id;
int coord_x, coord_y; int coord_x, coord_y;
@ -34,8 +34,8 @@ private:
QString annotation; QString annotation;
bool doesntUntap; bool doesntUntap;
public: public:
TestCard(QString _name, int _id, int _coord_x, int _coord_y); Card(QString _name, int _id, int _coord_x, int _coord_y);
~TestCard(); ~Card();
int getId() { return id; } int getId() { return id; }
int getX() { return coord_x; } int getX() { return coord_x; }

View file

@ -20,14 +20,18 @@
#include <QCoreApplication> #include <QCoreApplication>
#include "testserver.h" #include "server.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);
TestServer server;
server.listen(QHostAddress::Any, 4747);
return app.exec(); Server server;
if (!server.openDatabase()) {
qCritical("Database error");
return -1;
}
server.listen(QHostAddress::Any, 4747);
return app.exec();
} }

View file

@ -18,6 +18,8 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#include "playerzone.h" #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) 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) : 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(); clear();
} }
void PlayerZone::shuffle(TestRandom *rnd) void PlayerZone::shuffle(Random *rnd)
{ {
QList<TestCard *> temp; QList<Card *> temp;
for (int i = cards.size(); i; i--) for (int i = cards.size(); i; i--)
temp.append(cards.takeAt(rnd->getNumber(0, i - 1))); temp.append(cards.takeAt(rnd->getNumber(0, i - 1)));
cards = temp; cards = temp;
} }
TestCard *PlayerZone::getCard(int id, bool remove, int *position) Card *PlayerZone::getCard(int id, bool remove, int *position)
{ {
if (hasIdAccess()) { if (hasIdAccess()) {
QListIterator<TestCard *> CardIterator(cards); QListIterator<Card *> CardIterator(cards);
int i = 0; int i = 0;
while (CardIterator.hasNext()) { while (CardIterator.hasNext()) {
TestCard *tmp = CardIterator.next(); Card *tmp = CardIterator.next();
if (tmp->getId() == id) { if (tmp->getId() == id) {
if (remove) if (remove)
cards.removeAt(i); cards.removeAt(i);
@ -58,7 +60,7 @@ TestCard *PlayerZone::getCard(int id, bool remove, int *position)
} else { } else {
if (id >= cards.size()) if (id >= cards.size())
return NULL; return NULL;
TestCard *tmp = cards[id]; Card *tmp = cards[id];
if (remove) if (remove)
cards.removeAt(id); cards.removeAt(id);
if (position) 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()) { if (hasCoords()) {
card->setCoords(x, y); card->setCoords(x, y);

View file

@ -21,8 +21,10 @@
#define PLAYERZONE_H #define PLAYERZONE_H
#include <QList> #include <QList>
#include "testcard.h" #include <QString>
#include "testrandom.h"
class Card;
class Random;
class PlayerZone { class PlayerZone {
private: private:
@ -40,7 +42,7 @@ public:
PlayerZone(QString _name, bool _has_coords, bool _is_public, bool _is_private, bool _id_access); PlayerZone(QString _name, bool _has_coords, bool _is_public, bool _is_private, bool _id_access);
~PlayerZone(); ~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 isPublic() { return is_public; }
bool isPrivate() { return is_private; } bool isPrivate() { return is_private; }
@ -48,9 +50,9 @@ public:
bool hasIdAccess() { return id_access; } bool hasIdAccess() { return id_access; }
QString getName() { return name; } QString getName() { return name; }
QList<TestCard *> cards; QList<Card *> cards;
void insertCard(TestCard *card, int x, int y); void insertCard(Card *card, int x, int y);
void shuffle(TestRandom *rnd); void shuffle(Random *rnd);
void clear(); void clear();
}; };

View file

@ -1,7 +1,7 @@
#include "testrandom.h" #include "random.h"
#include <QThread> #include <QThread>
void TestRandom::init() void Random::init()
{ {
if (initialized) if (initialized)
return; return;
@ -11,7 +11,7 @@ void TestRandom::init()
initialized = true; 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(); int r = qrand();
return min + (unsigned int) (((double) (max + 1 - min)) * r / (RAND_MAX + 1.0)); return min + (unsigned int) (((double) (max + 1 - min)) * r / (RAND_MAX + 1.0));

View file

@ -1,16 +1,16 @@
#ifndef TESTRANDOM_H #ifndef RANDOM_H
#define TESTRANDOM_H #define RANDOM_H
#include <QObject> #include <QObject>
#include <QDateTime> #include <QDateTime>
#include <stdlib.h> #include <stdlib.h>
class TestRandom : public QObject { class Random : public QObject {
Q_OBJECT Q_OBJECT
private: private:
bool initialized; bool initialized;
public: public:
TestRandom(QObject *parent) : QObject(parent), initialized(false) { } Random(QObject *parent) : QObject(parent), initialized(false) { }
void init(); void init();
unsigned int getNumber(unsigned int min, unsigned int max); unsigned int getNumber(unsigned int min, unsigned int max);
}; };

View file

@ -1,25 +1,36 @@
#include "returnmessage.h" #include "returnmessage.h"
#include "testserversocket.h" #include "serversocket.h"
void ReturnMessage::setMsgId(unsigned int _msg_id) void ReturnMessage::setMsgId(unsigned int _msg_id)
{ {
msg_id = _msg_id; msg_id = _msg_id;
} }
bool ReturnMessage::send(const QString &args, bool success) bool ReturnMessage::send(ReturnCode code)
{ {
TestServerSocket *s = qobject_cast<TestServerSocket *>(parent()); ServerSocket *s = qobject_cast<ServerSocket *>(parent());
if (!s) if (!s)
return false; 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) s->msg(QString("resp|%1|%2|%3").arg(msg_id)
.arg(success ? "ok" : "err") .arg(success ? "ok" : "err")
.arg(args)); .arg(returnCodeString));
return success; return success;
} }
bool ReturnMessage::sendList(const QStringList &args) bool ReturnMessage::sendList(const QStringList &args)
{ {
TestServerSocket *s = qobject_cast<TestServerSocket *>(parent()); ServerSocket *s = qobject_cast<ServerSocket *>(parent());
if (!s) if (!s)
return false; return false;

View file

@ -1,8 +1,7 @@
#ifndef RETURNMESSAGE_H #ifndef RETURNMESSAGE_H
#define RETURNMESSAGE_H #define RETURNMESSAGE_H
#include <QString> #include <QStringList>
#include <QObject>
class ReturnMessage : public QObject { class ReturnMessage : public QObject {
Q_OBJECT Q_OBJECT
@ -10,11 +9,12 @@ private:
unsigned int msg_id; unsigned int msg_id;
QString cmd; QString cmd;
public: public:
enum ReturnCode { ReturnNothing, ReturnOk, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong, ReturnNameNotFound };
ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { } ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { }
unsigned int getMsgId() const { return msg_id; } unsigned int getMsgId() const { return msg_id; }
void setMsgId(unsigned int _msg_id); void setMsgId(unsigned int _msg_id);
void setCmd(const QString &_cmd) { cmd = _cmd; } 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); bool sendList(const QStringList &args);
}; };

View file

@ -17,58 +17,91 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 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 <QtSql>
TestServer::TestServer(QObject *parent) Server::Server(QObject *parent)
: QTcpServer(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; games << _game;
_creator->moveToThread(_game->thread()); _creator->moveToThread(_game->thread());
_game->addPlayer(_creator); _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); ServerGameThread *newThread = new ServerGameThread(name, description, password, maxPlayers, creator);
connect(newThread, SIGNAL(gameCreated(TestServerGame *, TestServerSocket *)), this, SLOT(gameCreated(TestServerGame *, TestServerSocket *))); connect(newThread, SIGNAL(gameCreated(ServerGame *, ServerSocket *)), this, SLOT(gameCreated(ServerGame *, ServerSocket *)));
connect(newThread, SIGNAL(finished()), this, SLOT(gameClosed())); connect(newThread, SIGNAL(finished()), this, SLOT(gameClosed()));
newThread->start(); 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); 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(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, TestServerSocket *)), this, SLOT(addClientToGame(const QString, TestServerSocket *))); connect(socket, SIGNAL(joinGame(const QString, ServerSocket *)), this, SLOT(addClientToGame(const QString, ServerSocket *)));
socket->initConnection(); socket->initConnection();
} }
TestServerGame *TestServer::getGame(const QString &name) AuthenticationResult Server::checkUserPassword(const QString &user, const QString &password)
{ {
QListIterator<TestServerGame *> 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<ServerGame *> i(games);
while (i.hasNext()) { while (i.hasNext()) {
TestServerGame *tmp = i.next(); ServerGame *tmp = i.next();
if ((!tmp->name.compare(name, Qt::CaseSensitive)) && !tmp->getGameStarted()) if ((!tmp->name.compare(name, Qt::CaseSensitive)) && !tmp->getGameStarted())
return tmp; return tmp;
} }
return NULL; return NULL;
} }
QList<TestServerGame *> TestServer::listOpenGames() QList<ServerGame *> Server::listOpenGames()
{ {
QList<TestServerGame *> result; QList<ServerGame *> result;
QListIterator<TestServerGame *> i(games); QListIterator<ServerGame *> i(games);
while (i.hasNext()) { while (i.hasNext()) {
TestServerGame *tmp = i.next(); ServerGame *tmp = i.next();
tmp->mutex->lock(); tmp->mutex->lock();
if ((!tmp->getGameStarted()) if ((!tmp->getGameStarted())
&& (tmp->getPlayerCount() < tmp->maxPlayers)) && (tmp->getPlayerCount() < tmp->maxPlayers))
@ -78,9 +111,9 @@ QList<TestServerGame *> TestServer::listOpenGames()
return result; 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))) { if ((tmp = getGame(name))) {
QMutexLocker locker(tmp->mutex); QMutexLocker locker(tmp->mutex);
if ((!tmp->getGameStarted()) if ((!tmp->getGameStarted())
@ -91,17 +124,17 @@ bool TestServer::checkGamePassword(const QString &name, const QString &password)
return false; 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()); client->moveToThread(tmp->thread());
tmp->addPlayer(client); tmp->addPlayer(client);
} }
void TestServer::gameClosed() void Server::gameClosed()
{ {
qDebug("TestServer::gameClosed"); qDebug("Server::gameClosed");
TestServerGameThread *t = qobject_cast<TestServerGameThread *>(sender()); ServerGameThread *t = qobject_cast<ServerGameThread *>(sender());
games.removeAt(games.indexOf(t->getGame())); games.removeAt(games.indexOf(t->getGame()));
delete t; delete t;
} }

View file

@ -17,33 +17,36 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef TESTSERVER_H #ifndef SERVER_H
#define TESTSERVER_H #define SERVER_H
#include <QTcpServer> #include <QTcpServer>
#include "testservergamethread.h"
#include "testservergame.h"
class TestServerGame; class ServerGame;
class TestServerSocket; class ServerSocket;
class QSqlDatabase;
class TestServer : public QTcpServer enum AuthenticationResult { PasswordWrong = 0, PasswordRight = 1, UnknownUser = 2 };
class Server : public QTcpServer
{ {
Q_OBJECT Q_OBJECT
private slots: private slots:
void addGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator); void addGame(const QString name, const QString description, const QString password, const int maxPlayers, ServerSocket *creator);
void addClientToGame(const QString name, TestServerSocket *client); void addClientToGame(const QString name, ServerSocket *client);
void gameCreated(TestServerGame *_game, TestServerSocket *_creator); void gameCreated(ServerGame *_game, ServerSocket *_creator);
void gameClosed(); void gameClosed();
public: public:
TestServer(QObject *parent = 0); Server(QObject *parent = 0);
~TestServer(); ~Server();
bool openDatabase();
bool checkGamePassword(const QString &name, const QString &password); bool checkGamePassword(const QString &name, const QString &password);
QList<TestServerGame *> listOpenGames(); AuthenticationResult checkUserPassword(const QString &user, const QString &password);
TestServerGame *getGame(const QString &name); QList<ServerGame *> listOpenGames();
ServerGame *getGame(const QString &name);
private: private:
void incomingConnection(int SocketId); void incomingConnection(int SocketId);
QList<TestServerGame *> games; QList<ServerGame *> games;
}; };
#endif #endif

View file

@ -17,9 +17,11 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 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) : QObject(parent), name(_name), description(_description), password(_password), maxPlayers(_maxPlayers)
{ {
gameStarted = false; gameStarted = false;
@ -27,59 +29,59 @@ TestServerGame::TestServerGame(QString _name, QString _description, QString _pas
rnd = NULL; rnd = NULL;
} }
TestServerGame::~TestServerGame() ServerGame::~ServerGame()
{ {
if (rnd) if (rnd)
delete rnd; delete rnd;
delete mutex; delete mutex;
qDebug("TestServerGame destructor"); qDebug("ServerGame destructor");
} }
bool TestServerGame::getGameStarted() bool ServerGame::getGameStarted()
{ {
return gameStarted; return gameStarted;
} }
int TestServerGame::getPlayerCount() int ServerGame::getPlayerCount()
{ {
QMutexLocker locker(mutex); QMutexLocker locker(mutex);
return players.size(); return players.size();
} }
QStringList TestServerGame::getPlayerNames() QStringList ServerGame::getPlayerNames()
{ {
QMutexLocker locker(mutex); QMutexLocker locker(mutex);
QStringList result; QStringList result;
QListIterator<TestServerSocket *> i(players); QListIterator<ServerSocket *> i(players);
while (i.hasNext()) { while (i.hasNext()) {
TestServerSocket *tmp = i.next(); ServerSocket *tmp = i.next();
result << QString("%1|%2").arg(tmp->getPlayerId()).arg(tmp->PlayerName); result << QString("%1|%2").arg(tmp->getPlayerId()).arg(tmp->PlayerName);
} }
return result; return result;
} }
TestServerSocket *TestServerGame::getPlayer(int player_id) ServerSocket *ServerGame::getPlayer(int player_id)
{ {
QListIterator<TestServerSocket *> i(players); QListIterator<ServerSocket *> i(players);
while (i.hasNext()) { while (i.hasNext()) {
TestServerSocket *tmp = i.next(); ServerSocket *tmp = i.next();
if (tmp->getPlayerId() == player_id) if (tmp->getPlayerId() == player_id)
return tmp; return tmp;
} }
return NULL; return NULL;
} }
void TestServerGame::msg(const QString &s) void ServerGame::msg(const QString &s)
{ {
QMutexLocker locker(mutex); QMutexLocker locker(mutex);
QListIterator<TestServerSocket *> i(players); QListIterator<ServerSocket *> i(players);
while (i.hasNext()) while (i.hasNext())
i.next()->msg(s); i.next()->msg(s);
} }
void TestServerGame::broadcastEvent(const QString &cmd, TestServerSocket *player) void ServerGame::broadcastEvent(const QString &cmd, ServerSocket *player)
{ {
if (player) if (player)
msg(QString("public|%1|%2|%3").arg(player->getPlayerId()).arg(player->PlayerName).arg(cmd)); 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)); msg(QString("public|||%1").arg(cmd));
} }
void TestServerGame::startGameIfReady() void ServerGame::startGameIfReady()
{ {
QMutexLocker locker(mutex); QMutexLocker locker(mutex);
@ -98,7 +100,7 @@ void TestServerGame::startGameIfReady()
return; return;
if (!rnd) { if (!rnd) {
rnd = new TestRandom(this); rnd = new Random(this);
rnd->init(); rnd->init();
} }
@ -111,12 +113,12 @@ void TestServerGame::startGameIfReady()
broadcastEvent("game_start", NULL); broadcastEvent("game_start", NULL);
} }
void TestServerGame::addPlayer(TestServerSocket *player) void ServerGame::addPlayer(ServerSocket *player)
{ {
QMutexLocker locker(mutex); QMutexLocker locker(mutex);
int max = -1; int max = -1;
QListIterator<TestServerSocket *> i(players); QListIterator<ServerSocket *> i(players);
while (i.hasNext()) { while (i.hasNext()) {
int tmp = i.next()->getPlayerId(); int tmp = i.next()->getPlayerId();
if (tmp > max) if (tmp > max)
@ -130,10 +132,10 @@ void TestServerGame::addPlayer(TestServerSocket *player)
players << 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); QMutexLocker locker(mutex);
@ -143,14 +145,14 @@ void TestServerGame::removePlayer(TestServerSocket *player)
thread()->quit(); thread()->quit();
} }
void TestServerGame::setActivePlayer(int _activePlayer) void ServerGame::setActivePlayer(int _activePlayer)
{ {
activePlayer = _activePlayer; activePlayer = _activePlayer;
broadcastEvent(QString("set_active_player|%1").arg(_activePlayer), NULL); broadcastEvent(QString("set_active_player|%1").arg(_activePlayer), NULL);
setActivePhase(0); setActivePhase(0);
} }
void TestServerGame::setActivePhase(int _activePhase) void ServerGame::setActivePhase(int _activePhase)
{ {
activePhase = _activePhase; activePhase = _activePhase;
broadcastEvent(QString("set_active_phase|%1").arg(_activePhase), NULL); broadcastEvent(QString("set_active_phase|%1").arg(_activePhase), NULL);

View file

@ -17,41 +17,40 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef TESTSERVERGAME_H #ifndef SERVERGAME_H
#define TESTSERVERGAME_H #define SERVERGAME_H
#include <QThread> #include <QThread>
#include <QMutex> #include <QMutex>
#include <QStringList> #include <QStringList>
#include "testserversocket.h"
#include "testrandom.h"
class TestServerSocket; class ServerSocket;
class Random;
class TestServerGame : public QObject { class ServerGame : public QObject {
Q_OBJECT Q_OBJECT
private: private:
QList<TestServerSocket *> players; QList<ServerSocket *> players;
bool gameStarted; bool gameStarted;
int activePlayer; int activePlayer;
int activePhase; int activePhase;
public slots: public slots:
void broadcastEvent(const QString &event, TestServerSocket *player); void broadcastEvent(const QString &event, ServerSocket *player);
public: public:
QMutex *mutex; QMutex *mutex;
TestRandom *rnd; Random *rnd;
QString name; QString name;
QString description; QString description;
QString password; QString password;
int maxPlayers; int maxPlayers;
TestServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent = 0); ServerGame(QString _name, QString _description, QString _password, int _maxPlayers, QObject *parent = 0);
~TestServerGame(); ~ServerGame();
bool getGameStarted(); bool getGameStarted();
int getPlayerCount(); int getPlayerCount();
QStringList getPlayerNames(); QStringList getPlayerNames();
TestServerSocket *getPlayer(int player_id); ServerSocket *getPlayer(int player_id);
void addPlayer(TestServerSocket *player); void addPlayer(ServerSocket *player);
void removePlayer(TestServerSocket *player); void removePlayer(ServerSocket *player);
void startGameIfReady(); void startGameIfReady();
void msg(const QString &s); void msg(const QString &s);
int getActivePlayer() { return activePlayer; } int getActivePlayer() { return activePlayer; }

View file

@ -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();
}

View file

@ -0,0 +1,28 @@
#ifndef SERVERGAMETHREAD_H
#define SERVERGAMETHREAD_H
#include <QThread>
#include <QMutex>
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

View file

@ -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 <QStringList>
#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<PlayerZone *> 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<Counter *> 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<QString> DeckIterator(DeckList);
int i = 0;
while (DeckIterator.hasNext())
deck->cards.append(new Card(DeckIterator.next(), i++, 0, 0));
deck->shuffle(game->rnd);
QListIterator<QString> 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 &params)
{
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 &params)
{
QList<ServerGame *> gameList = server->listOpenGames();
QListIterator<ServerGame *> 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 &params)
{
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 &params)
{
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 &params)
{
leaveGame();
return ReturnMessage::ReturnOk;
}
ReturnMessage::ReturnCode ServerSocket::cmdListPlayers(const QStringList &params)
{
remsg->sendList(game->getPlayerNames());
return ReturnMessage::ReturnOk;
}
ReturnMessage::ReturnCode ServerSocket::cmdSay(const QStringList &params)
{
emit broadcastEvent(QString("say|%1").arg(params[0]), this);
return ReturnMessage::ReturnOk;
}
ReturnMessage::ReturnCode ServerSocket::cmdSubmitDeck(const QStringList &params)
{
PlayerStatus = StatusSubmitDeck;
DeckList.clear();
SideboardList.clear();
return ReturnMessage::ReturnNothing;
}
ReturnMessage::ReturnCode ServerSocket::cmdReadyStart(const QStringList &params)
{
PlayerStatus = StatusReadyStart;
emit broadcastEvent(QString("ready_start"), this);
game->startGameIfReady();
return ReturnMessage::ReturnOk;
}
ReturnMessage::ReturnCode ServerSocket::cmdShuffle(const QStringList &params)
{
getZone("deck")->shuffle(game->rnd);
emit broadcastEvent("shuffle", this);
return ReturnMessage::ReturnOk;
}
ReturnMessage::ReturnCode ServerSocket::cmdDrawCards(const QStringList &params)
{
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 &params)
{
// 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 &params)
{
// 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 &params)
{
// 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<Card *> 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 &params)
{
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 &params)
{
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 &params)
{
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 &params)
{
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 &params)
{
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 &params)
{
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 *> 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 &params)
{
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 &params)
{
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 &params)
{
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<Counter *> 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<PlayerZone *> 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();
}

View file

@ -17,37 +17,71 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef TESTSERVERSOCKET_H #ifndef SERVERSOCKET_H
#define TESTSERVERSOCKET_H #define SERVERSOCKET_H
#include <QTcpSocket> #include <QTcpSocket>
#include "testserver.h" #include "server.h"
#include "testservergame.h"
#include "playerzone.h"
#include "returnmessage.h" #include "returnmessage.h"
#include "counter.h"
class TestServer; class Server;
class TestServerGame; class ServerGame;
class PlayerZone; class PlayerZone;
class Counter;
enum PlayerStatusEnum { StatusNormal, StatusSubmitDeck, StatusReadyStart, StatusPlaying }; enum PlayerStatusEnum { StatusNormal, StatusSubmitDeck, StatusReadyStart, StatusPlaying };
class TestServerSocket : public QTcpSocket class ServerSocket : public QTcpSocket
{ {
Q_OBJECT Q_OBJECT
private slots: private slots:
void readClient(); void readClient();
void catchSocketError(QAbstractSocket::SocketError socketError); void catchSocketError(QAbstractSocket::SocketError socketError);
signals: signals:
void createGame(const QString name, const QString description, const QString password, const int maxPlayers, TestServerSocket *creator); void createGame(const QString name, const QString description, const QString password, const int maxPlayers, ServerSocket *creator);
void joinGame(const QString name, TestServerSocket *player); void joinGame(const QString name, ServerSocket *player);
void commandReceived(QString cmd, TestServerSocket *player); void commandReceived(QString cmd, ServerSocket *player);
void broadcastEvent(const QString &event, TestServerSocket *player); void broadcastEvent(const QString &event, ServerSocket *player);
void startGameIfReady(); void startGameIfReady();
private: private:
TestServer *server; typedef ReturnMessage::ReturnCode (ServerSocket::*CommandHandler)(const QStringList &);
TestServerGame *game; 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 &params);
ReturnMessage::ReturnCode cmdListGames(const QStringList &params);
ReturnMessage::ReturnCode cmdCreateGame(const QStringList &params);
ReturnMessage::ReturnCode cmdJoinGame(const QStringList &params);
ReturnMessage::ReturnCode cmdLeaveGame(const QStringList &params);
ReturnMessage::ReturnCode cmdListPlayers(const QStringList &params);
ReturnMessage::ReturnCode cmdSay(const QStringList &params);
ReturnMessage::ReturnCode cmdSubmitDeck(const QStringList &params);
ReturnMessage::ReturnCode cmdReadyStart(const QStringList &params);
ReturnMessage::ReturnCode cmdShuffle(const QStringList &params);
ReturnMessage::ReturnCode cmdDrawCards(const QStringList &params);
ReturnMessage::ReturnCode cmdMoveCard(const QStringList &params);
ReturnMessage::ReturnCode cmdCreateToken(const QStringList &params);
ReturnMessage::ReturnCode cmdSetCardAttr(const QStringList &params);
ReturnMessage::ReturnCode cmdIncCounter(const QStringList &params);
ReturnMessage::ReturnCode cmdSetCounter(const QStringList &params);
ReturnMessage::ReturnCode cmdDelCounter(const QStringList &params);
ReturnMessage::ReturnCode cmdListCounters(const QStringList &params);
ReturnMessage::ReturnCode cmdListZones(const QStringList &params);
ReturnMessage::ReturnCode cmdDumpZone(const QStringList &params);
ReturnMessage::ReturnCode cmdRollDice(const QStringList &params);
ReturnMessage::ReturnCode cmdSetActivePlayer(const QStringList &params);
ReturnMessage::ReturnCode cmdSetActivePhase(const QStringList &params);
Server *server;
ServerGame *game;
QList<QString> DeckList; QList<QString> DeckList;
QList<QString> SideboardList; QList<QString> SideboardList;
QList<PlayerZone *> zones; QList<PlayerZone *> zones;
@ -63,12 +97,13 @@ private:
bool parseCommand(QString line); bool parseCommand(QString line);
PlayerStatusEnum PlayerStatus; PlayerStatusEnum PlayerStatus;
ReturnMessage *remsg; ReturnMessage *remsg;
AuthenticationResult authState;
public: public:
QString PlayerName; QString PlayerName;
TestServerSocket(TestServer *_server, QObject *parent = 0); ServerSocket(Server *_server, QObject *parent = 0);
~TestServerSocket(); ~ServerSocket();
void msg(const QString &s); void msg(const QString &s);
void setGame(TestServerGame *g); void setGame(ServerGame *g);
PlayerStatusEnum getStatus(); PlayerStatusEnum getStatus();
void setStatus(PlayerStatusEnum status); void setStatus(PlayerStatusEnum status);
void initConnection(); void initConnection();

View file

@ -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();
}

View file

@ -1,30 +0,0 @@
#ifndef TESTSERVERGAMETHREAD_H
#define TESTSERVERGAMETHREAD_H
#include <QThread>
#include <QMutex>
#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

View file

@ -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 <QStringList>
#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<PlayerZone *> 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<Counter *> 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<QString> DeckIterator(DeckList);
int i = 0;
while (DeckIterator.hasNext())
deck->cards.append(new TestCard(DeckIterator.next(), i++, 0, 0));
deck->shuffle(game->rnd);
QListIterator<QString> 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<TestServerGame *> gameList = server->listOpenGames();
QListIterator<TestServerGame *> 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<TestCard *> 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<TestCard *> 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<Counter *> 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<PlayerZone *> 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();
}

View file

@ -18,4 +18,4 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
const char *VERSION_STRING = "Testserver 0.20090407"; const char *VERSION_STRING = "Testserver 0.20090408";