316 lines
7.8 KiB
C++
316 lines
7.8 KiB
C++
#include <QTimer>
|
|
#include "client.h"
|
|
|
|
Client::Client(QObject *parent)
|
|
: QObject(parent)
|
|
{
|
|
timer = new QTimer(this);
|
|
timer->setInterval(1000);
|
|
connect(timer, SIGNAL(timeout()), this, SLOT(checkTimeout()));
|
|
|
|
MsgId = 0;
|
|
status = StatusDisconnected;
|
|
socket = new QTcpSocket(this);
|
|
socket->setTextModeEnabled(true);
|
|
connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
|
|
connect(socket, SIGNAL(readyRead()), this, SLOT(readLine()));
|
|
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
|
}
|
|
|
|
Client::~Client()
|
|
{
|
|
delete socket;
|
|
}
|
|
|
|
void Client::checkTimeout()
|
|
{
|
|
QListIterator<PendingCommand *> i(PendingCommands);
|
|
while (i.hasNext()) {
|
|
PendingCommand *c = i.next();
|
|
c->incTime();
|
|
if (c->timeout()) {
|
|
disconnectFromServer();
|
|
emit serverTimeout();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Client::slotSocketError(QAbstractSocket::SocketError error)
|
|
{
|
|
emit logSocketError(socket->errorString());
|
|
disconnectFromServer();
|
|
}
|
|
|
|
void Client::slotConnected()
|
|
{
|
|
timer->start();
|
|
setStatus(StatusAwaitingWelcome);
|
|
}
|
|
|
|
void Client::readLine()
|
|
{
|
|
QString line;
|
|
for (;;) {
|
|
if (!socket->canReadLine())
|
|
break;
|
|
line = QString(socket->readLine()).trimmed();
|
|
|
|
if (line.isNull())
|
|
break;
|
|
qDebug(QString("readLine: %1").arg(line).toLatin1());
|
|
QStringList values = line.split("|");
|
|
QString prefix = values.takeFirst();
|
|
// prefix is one of {welcome, private, public, resp, list_games, list_players, list_counters, list_zones, dump_zone}
|
|
if (!(prefix.compare("private") && prefix.compare("public"))) {
|
|
ServerEventData *event = new ServerEventData(line);
|
|
if (event->getEventType() == eventPlayerId) {
|
|
QStringList data = event->getEventData();
|
|
if (data.size() != 2) {
|
|
// XXX
|
|
}
|
|
bool ok;
|
|
int id = data[0].toInt(&ok);
|
|
if (!ok) {
|
|
// XXX
|
|
}
|
|
delete event;
|
|
emit playerIdReceived(id, data[1]);
|
|
} else
|
|
emit gameEvent(event);
|
|
} else if (!prefix.compare("resp")) {
|
|
bool ok;
|
|
int msgid = values.takeFirst().toInt(&ok);
|
|
if (!ok) {
|
|
// XXX
|
|
}
|
|
|
|
if (values.empty()) {
|
|
// XXX
|
|
}
|
|
|
|
ok = !values.takeFirst().compare("ok");
|
|
|
|
// XXX
|
|
ServerErrorMessage message = msgNone;
|
|
|
|
// Update list of pending commands
|
|
QListIterator<PendingCommand *> i(PendingCommands);
|
|
bool found = false;
|
|
PendingCommand *c;
|
|
while (i.hasNext()) {
|
|
c = i.next();
|
|
if (c->getMsgId() == msgid) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (found) {
|
|
PendingCommands.removeAt(PendingCommands.indexOf(c));
|
|
delete c;
|
|
}
|
|
|
|
emit responseReceived(new ServerResponse(msgid, ok, message));
|
|
} else if (!(prefix.compare("list_games")
|
|
&& prefix.compare("list_players")
|
|
&& prefix.compare("list_counters")
|
|
&& prefix.compare("list_zones")
|
|
&& prefix.compare("dump_zone")
|
|
&& prefix.compare("welcome"))) {
|
|
int cmdid = values.takeFirst().toInt();
|
|
if (!values[0].compare(".")) {
|
|
QListIterator<QStringList> i(msgbuf);
|
|
QList<ServerGame *> gamelist;
|
|
QList<ServerPlayer *> playerlist;
|
|
QList<ServerZone *> zonelist;
|
|
QList<ServerZoneCard *> zonedump;
|
|
QStringList welcomemsg;
|
|
while (i.hasNext()) {
|
|
QStringList val = i.next();
|
|
|
|
// XXX Parametergültigkeit überprüfen
|
|
if (!prefix.compare("list_games"))
|
|
gamelist << new ServerGame(val[0], val[1], val[2].toInt(), val[3].toInt(), val[4].toInt());
|
|
else if (!prefix.compare("list_players"))
|
|
playerlist << new ServerPlayer(val[0].toInt(), val[1]);
|
|
else if (!prefix.compare("list_counters"))
|
|
{ }
|
|
else if (!prefix.compare("list_zones"))
|
|
zonelist << new ServerZone(val[0], val[1] == "1", val[2] == "1", val[3].toInt());
|
|
else if (!prefix.compare("dump_zone"))
|
|
zonedump << new ServerZoneCard(val[0].toInt(), val[1], val[2].toInt(), val[3].toInt(), val[4].toInt(), val[5] == "1", val[6]);
|
|
else if (!prefix.compare("welcome"))
|
|
welcomemsg << val[0];
|
|
}
|
|
if (!prefix.compare("list_games"))
|
|
emit gameListReceived(gamelist);
|
|
else if (!prefix.compare("list_players"))
|
|
emit playerListReceived(playerlist);
|
|
else if (!prefix.compare("list_counters"))
|
|
{ }
|
|
else if (!prefix.compare("list_zones"))
|
|
emit zoneListReceived(cmdid, zonelist);
|
|
else if (!prefix.compare("dump_zone"))
|
|
emit zoneDumpReceived(cmdid, zonedump);
|
|
else if (!prefix.compare("welcome")) {
|
|
emit welcomeMsgReceived(welcomemsg);
|
|
setStatus(StatusConnected);
|
|
setName(PlayerName);
|
|
}
|
|
msgbuf.clear();
|
|
} else
|
|
msgbuf << values;
|
|
} else {
|
|
// XXX
|
|
}
|
|
}
|
|
}
|
|
|
|
void Client::setStatus(const ProtocolStatus _status)
|
|
{
|
|
status = _status;
|
|
emit statusChanged(_status);
|
|
}
|
|
|
|
void Client::msg(const QString &s)
|
|
{
|
|
qDebug(QString("msg gibt aus: %1").arg(s).toLatin1());
|
|
QTextStream stream(socket);
|
|
stream.setCodec("UTF-8");
|
|
stream << s << endl;
|
|
stream.flush();
|
|
socket->flush();
|
|
}
|
|
|
|
int Client::cmd(const QString &s)
|
|
{
|
|
msg(QString("%1|%2").arg(++MsgId).arg(s));
|
|
PendingCommands << new PendingCommand(s, MsgId);
|
|
return MsgId;
|
|
}
|
|
|
|
void Client::connectToServer(const QString &hostname, unsigned int port, const QString &playername)
|
|
{
|
|
PlayerName = playername;
|
|
socket->connectToHost(hostname, port);
|
|
setStatus(StatusConnecting);
|
|
}
|
|
|
|
void Client::disconnectFromServer()
|
|
{
|
|
timer->stop();
|
|
PendingCommands.clear();
|
|
setStatus(StatusDisconnected);
|
|
socket->close();
|
|
}
|
|
|
|
int Client::listGames()
|
|
{
|
|
return cmd("list_games");
|
|
}
|
|
|
|
int Client::listPlayers()
|
|
{
|
|
return cmd("list_players");
|
|
}
|
|
|
|
int Client::createGame(const QString &name, const QString &description, const QString &password, unsigned int maxPlayers)
|
|
{
|
|
return cmd(QString("create_game|%1|%2|%3|%4").arg(name).arg(description).arg(password).arg(maxPlayers));
|
|
}
|
|
|
|
int Client::joinGame(const QString &name, const QString &password)
|
|
{
|
|
return cmd(QString("join_game|%1|%2").arg(name).arg(password));
|
|
}
|
|
|
|
int Client::leaveGame()
|
|
{
|
|
return cmd("leave_game");
|
|
}
|
|
|
|
int Client::setName(const QString &name)
|
|
{
|
|
return cmd(QString("set_name|%1").arg(name));
|
|
}
|
|
|
|
int Client::say(const QString &s)
|
|
{
|
|
return cmd(QString("say|%1").arg(s));
|
|
}
|
|
|
|
int Client::shuffle()
|
|
{
|
|
return cmd("shuffle");
|
|
}
|
|
|
|
int Client::rollDice(unsigned int sides)
|
|
{
|
|
return cmd(QString("roll_dice|%1").arg(sides));
|
|
}
|
|
|
|
int Client::drawCards(unsigned int number)
|
|
{
|
|
return cmd(QString("draw_cards|%1").arg(number));
|
|
}
|
|
|
|
int Client::moveCard(int cardid, const QString &startzone, const QString &targetzone, int x, int y)
|
|
{
|
|
// if startzone is public: cardid is the card's id
|
|
// else: cardid is the position of the card in the zone (e.g. deck)
|
|
return cmd(QString("move_card|%1|%2|%3|%4|%5").arg(cardid).arg(startzone).arg(targetzone).arg(x).arg(y));
|
|
}
|
|
|
|
int Client::createToken(const QString &zone, const QString &name, const QString &powtough, int x, int y)
|
|
{
|
|
return cmd(QString("create_token|%1|%2|%3|%4|%5").arg(zone).arg(name).arg(powtough).arg(x).arg(y));
|
|
}
|
|
|
|
int Client::setCardAttr(const QString &zone, int cardid, const QString &aname, const QString &avalue)
|
|
{
|
|
return cmd(QString("set_card_attr|%1|%2|%3|%4").arg(zone).arg(cardid).arg(aname).arg(avalue));
|
|
}
|
|
|
|
void Client::submitDeck(const QStringList &deck)
|
|
{
|
|
cmd("submit_deck");
|
|
QStringListIterator i(deck);
|
|
while (i.hasNext())
|
|
msg(i.next());
|
|
msg(".");
|
|
}
|
|
|
|
int Client::readyStart()
|
|
{
|
|
return cmd("ready_start");
|
|
}
|
|
|
|
int Client::incCounter(const QString &counter, int delta)
|
|
{
|
|
return cmd(QString("inc_counter|%1|%2").arg(counter).arg(delta));
|
|
}
|
|
|
|
int Client::setCounter(const QString &counter, int value)
|
|
{
|
|
return cmd(QString("set_counter|%1|%2").arg(counter).arg(value));
|
|
}
|
|
|
|
int Client::delCounter(const QString &counter)
|
|
{
|
|
return cmd(QString("del_counter|%1").arg(counter));
|
|
}
|
|
|
|
int Client::setActivePlayer(int player)
|
|
{
|
|
return cmd(QString("set_active_player|%1").arg(player));
|
|
}
|
|
|
|
int Client::setActivePhase(int phase)
|
|
{
|
|
return cmd(QString("set_active_phase|%1").arg(phase));
|
|
}
|
|
|
|
int Client::dumpZone(int player, const QString &zone, int numberCards)
|
|
{
|
|
return cmd(QString("dump_zone|%1|%2|%3").arg(player).arg(zone).arg(numberCards));
|
|
}
|