Clang-format (#3028)

* 1/3 Add .clang-format file and travis compilation check

* 2/3 Run clang-format

* 3/3 Fix compilation problems due to include reordering

* 3bis/3 AfterControlStatement: false
This commit is contained in:
ctrlaltca 2018-01-27 10:41:32 +01:00 committed by GitHub
parent 8dbdd24c8e
commit b29bd9e070
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
272 changed files with 13378 additions and 9535 deletions

View file

@ -1,8 +1,8 @@
#include <QFile>
#include <QTextStream>
#include "decklist.h"
#include <QCryptographicHash>
#include <QDebug>
#include "decklist.h"
#include <QFile>
#include <QTextStream>
SideboardPlan::SideboardPlan(const QString &_name, const QList<MoveCard_ToZone> &_moveList)
: name(_name), moveList(_moveList)
@ -50,8 +50,7 @@ void SideboardPlan::write(QXmlStreamWriter *xml)
{
xml->writeStartElement("sideboard_plan");
xml->writeTextElement("name", name);
for (auto &i : moveList)
{
for (auto &i : moveList) {
xml->writeStartElement("move_card_to_zone");
xml->writeTextElement("card_name", QString::fromStdString(i.card_name()));
xml->writeTextElement("start_zone", QString::fromStdString(i.start_zone()));
@ -63,35 +62,28 @@ void SideboardPlan::write(QXmlStreamWriter *xml)
AbstractDecklistNode::AbstractDecklistNode(InnerDecklistNode *_parent) : parent(_parent), sortMethod(Default)
{
if (parent)
{
if (parent) {
parent->append(this);
}
}
int AbstractDecklistNode::depth() const
{
if (parent)
{
if (parent) {
return parent->depth() + 1;
}
else
{
} else {
return 0;
}
}
InnerDecklistNode::InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent) : AbstractDecklistNode(_parent), name(other->getName())
InnerDecklistNode::InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent)
: AbstractDecklistNode(_parent), name(other->getName())
{
for (int i = 0; i < other->size(); ++i)
{
for (int i = 0; i < other->size(); ++i) {
auto *inner = dynamic_cast<InnerDecklistNode *>(other->at(i));
if (inner)
{
if (inner) {
new InnerDecklistNode(inner, this);
}
else
{
} else {
new DecklistCardNode(dynamic_cast<DecklistCardNode *>(other->at(i)), this);
}
}
@ -104,20 +96,13 @@ InnerDecklistNode::~InnerDecklistNode()
QString InnerDecklistNode::visibleNameFromName(const QString &_name)
{
if (_name == DECK_ZONE_MAIN)
{
if (_name == DECK_ZONE_MAIN) {
return QObject::tr("Maindeck");
}
else if (_name == DECK_ZONE_SIDE)
{
} else if (_name == DECK_ZONE_SIDE) {
return QObject::tr("Sideboard");
}
else if (_name == DECK_ZONE_TOKENS)
{
} else if (_name == DECK_ZONE_TOKENS) {
return QObject::tr("Tokens");
}
else
{
} else {
return _name;
}
}
@ -125,8 +110,7 @@ QString InnerDecklistNode::visibleNameFromName(const QString &_name)
void InnerDecklistNode::setSortMethod(DeckSortMethod method)
{
sortMethod = method;
for (int i = 0; i < size(); i++)
{
for (int i = 0; i < size(); i++) {
at(i)->setSortMethod(method);
}
}
@ -143,17 +127,15 @@ void InnerDecklistNode::clearTree()
clear();
}
DecklistCardNode::DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), name(other->getName()), number(other->getNumber())
DecklistCardNode::DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent)
: AbstractDecklistCardNode(_parent), name(other->getName()), number(other->getNumber())
{
}
AbstractDecklistNode *InnerDecklistNode::findChild(const QString &name)
{
for (int i = 0; i < size(); i++)
{
if (at(i)->getName() == name)
{
for (int i = 0; i < size(); i++) {
if (at(i)->getName() == name) {
return at(i);
}
}
@ -168,20 +150,14 @@ int InnerDecklistNode::height() const
int InnerDecklistNode::recursiveCount(bool countTotalCards) const
{
int result = 0;
for (int i = 0; i < size(); i++)
{
for (int i = 0; i < size(); i++) {
auto *node = dynamic_cast<InnerDecklistNode *>(at(i));
if (node)
{
if (node) {
result += node->recursiveCount(countTotalCards);
}
else if (countTotalCards)
{
} else if (countTotalCards) {
result += dynamic_cast<AbstractDecklistCardNode *>(at(i))->getNumber();
}
else
{
} else {
result++;
}
}
@ -190,8 +166,7 @@ int InnerDecklistNode::recursiveCount(bool countTotalCards) const
bool InnerDecklistNode::compare(AbstractDecklistNode *other) const
{
switch (sortMethod)
{
switch (sortMethod) {
case ByNumber:
return compareNumber(other);
case ByName:
@ -216,20 +191,16 @@ bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const
bool InnerDecklistNode::compareName(AbstractDecklistNode *other) const
{
auto *other2 = dynamic_cast<InnerDecklistNode *>(other);
if (other2)
{
if (other2) {
return (getName() > other2->getName());
}
else
{
} else {
return false;
}
}
bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const
{
switch (sortMethod)
{
switch (sortMethod) {
case ByNumber:
return compareNumber(other);
case ByName:
@ -242,14 +213,11 @@ bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const
bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const
{
auto *other2 = dynamic_cast<AbstractDecklistCardNode *>(other);
if (other2)
{
if (other2) {
int n1 = getNumber();
int n2 = other2->getNumber();
return (n1 != n2) ? (n1 > n2) : compareName(other);
}
else
{
} else {
return true;
}
}
@ -257,21 +225,22 @@ bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const
bool AbstractDecklistCardNode::compareName(AbstractDecklistNode *other) const
{
auto *other2 = dynamic_cast<AbstractDecklistCardNode *>(other);
if (other2)
{
if (other2) {
return (getName() > other2->getName());
}
else
{
} else {
return true;
}
}
class InnerDecklistNode::compareFunctor {
class InnerDecklistNode::compareFunctor
{
private:
Qt::SortOrder order;
public:
explicit compareFunctor(Qt::SortOrder _order) : order(_order) { }
explicit compareFunctor(Qt::SortOrder _order) : order(_order)
{
}
inline bool operator()(QPair<int, AbstractDecklistNode *> a, QPair<int, AbstractDecklistNode *> b) const
{
return (order == Qt::AscendingOrder) ^ (a.second->compare(b.second));
@ -288,7 +257,9 @@ bool InnerDecklistNode::readElement(QXmlStreamReader *xml)
InnerDecklistNode *newZone = new InnerDecklistNode(xml->attributes().value("name").toString(), this);
newZone->readElement(xml);
} else if (childName == "card") {
DecklistCardNode *newCard = new DecklistCardNode(xml->attributes().value("name").toString(), xml->attributes().value("number").toString().toInt(), this);
DecklistCardNode *newCard =
new DecklistCardNode(xml->attributes().value("name").toString(),
xml->attributes().value("number").toString().toInt(), this);
newCard->readElement(xml);
}
} else if (xml->isEndElement() && (childName == "zone"))
@ -323,12 +294,12 @@ void AbstractDecklistCardNode::writeElement(QXmlStreamWriter *xml)
xml->writeAttribute("name", getName());
}
QVector<QPair<int, int> > InnerDecklistNode::sort(Qt::SortOrder order)
QVector<QPair<int, int>> InnerDecklistNode::sort(Qt::SortOrder order)
{
QVector<QPair<int, int> > result(size());
QVector<QPair<int, int>> result(size());
// Initialize temporary list with contents of current list
QVector<QPair<int, AbstractDecklistNode *> > tempList(size());
QVector<QPair<int, AbstractDecklistNode *>> tempList(size());
for (int i = size() - 1; i >= 0; --i) {
tempList[i].first = i;
tempList[i].second = at(i);
@ -355,13 +326,13 @@ DeckList::DeckList()
}
// TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator
DeckList::DeckList(const DeckList &other) : QObject(), name(other.name), comments(other.comments), deckHash(other.deckHash)
DeckList::DeckList(const DeckList &other)
: QObject(), name(other.name), comments(other.comments), deckHash(other.deckHash)
{
root = new InnerDecklistNode(other.getRoot());
QMapIterator<QString, SideboardPlan *> spIterator(other.getSideboardPlans());
while (spIterator.hasNext())
{
while (spIterator.hasNext()) {
spIterator.next();
sideboardPlans.insert(spIterator.key(), new SideboardPlan(spIterator.key(), spIterator.value()->getMoveList()));
}
@ -511,8 +482,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
bool priorEntryIsBlank = true, isAtBeginning = true;
int blankLines = 0;
while (!in.atEnd())
{
while (!in.atEnd()) {
QString line = in.readLine().simplified().toLower();
/*
@ -522,18 +492,14 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
* This will also concise multiple blank lines in a row to just one blank
* Ex: ("Card1", "Card2", "", "", "", "Card3") => ("Card1", "Card2", "", "Card3")
*/
if (line.isEmpty())
{
if (priorEntryIsBlank || isAtBeginning)
{
if (line.isEmpty()) {
if (priorEntryIsBlank || isAtBeginning) {
continue;
}
priorEntryIsBlank = true;
blankLines++;
}
else
{
} else {
isAtBeginning = false;
priorEntryIsBlank = false;
}
@ -547,32 +513,27 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
* NOTE: Any duplicates were taken care of above, so there can be
* at most one blank line at the very end
*/
if (!inputs.empty() && inputs.last().isEmpty())
{
if (!inputs.empty() && inputs.last().isEmpty()) {
blankLines--;
inputs.erase(inputs.end() - 1);
}
// If "Sideboard" line appears in inputs, then blank lines mean nothing
if (inputs.contains("sideboard"))
{
if (inputs.contains("sideboard")) {
blankLines = 2;
}
bool inSideboard = false, titleFound = false, isSideboard;
int okRows = 0;
foreach(QString line, inputs)
{
foreach (QString line, inputs) {
// This is a comment line, ignore it
if (line.startsWith("//"))
{
if (line.startsWith("//")) {
if (!titleFound) // Set the title to the first comment
{
name = line.mid(2).trimmed();
titleFound = true;
}
else if (okRows == 0) // We haven't processed any cards yet
} else if (okRows == 0) // We haven't processed any cards yet
{
comments += line.mid(2).trimmed() + "\n";
}
@ -584,22 +545,19 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
// Then we assume it means to start the sideboard section of the paste.
// If we have the word "Sideboard" appear on any line, then that will
// also indicate the start of the sideboard.
if ((line.isEmpty() && blankLines == 1) || line.startsWith("sideboard"))
{
if ((line.isEmpty() && blankLines == 1) || line.startsWith("sideboard")) {
inSideboard = true;
continue; // The line isn't actually a card
}
isSideboard = inSideboard;
if (line.startsWith("sb:"))
{
if (line.startsWith("sb:")) {
line = line.mid(3).trimmed();
isSideboard = true;
}
if (line.trimmed().isEmpty())
{
if (line.trimmed().isEmpty()) {
continue; // The line was " " instead of "\n"
}
@ -618,16 +576,12 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
int i = line.indexOf(' ');
int cardNameStart = i + 1;
if (i > 0)
{
if (i > 0) {
// If the count ends with an 'x', ignore it. For example,
// "4x Storm Crow" will count 4 correctly.
if (line.at(i-1) == 'x')
{
if (line.at(i - 1) == 'x') {
i--;
}
else if (! line.at(i-1).isDigit())
{
} else if (!line.at(i - 1).isDigit()) {
// If the user inputs "Quicksilver Elemental" then it will work as 1x of that card
cardNameStart = 0;
}
@ -636,14 +590,12 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
bool ok;
int number = line.left(i).toInt(&ok);
if (!ok)
{
if (!ok) {
number = 1; // If input is "cardName" assume it's "1x cardName"
}
QString cardName = line.mid(cardNameStart);
// Common differences between Cockatrice's card names
// and what's commonly used in decklists
rx.setPattern("");
@ -658,8 +610,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
// 'R&D' or 'R & D'.
// Qt regexes don't support lookbehind so we capture and replace instead.
rx.setPattern("([^A-Z])\\s*&\\s*");
if (rx.indexIn(cardName) != -1)
{
if (rx.indexIn(cardName) != -1) {
cardName.replace(rx, QString("%1 // ").arg(rx.cap(1)));
}
@ -682,13 +633,11 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
return (okRows > 0);
}
InnerDecklistNode * DeckList::getZoneObjFromName(const QString zoneName)
InnerDecklistNode *DeckList::getZoneObjFromName(const QString zoneName)
{
for (int i = 0; i < root->size(); i++)
{
for (int i = 0; i < root->size(); i++) {
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
if (node->getName() == zoneName)
{
if (node->getName() == zoneName) {
return node;
}
}
@ -702,37 +651,32 @@ bool DeckList::loadFromFile_Plain(QIODevice *device)
return loadFromStream_Plain(in);
}
struct WriteToStream {
struct WriteToStream
{
QTextStream &stream;
bool prefixSideboardCards;
bool slashTappedOutSplitCards;
WriteToStream(QTextStream &_stream, bool _prefixSideboardCards, bool _slashTappedOutSplitCards): stream(_stream), prefixSideboardCards(_prefixSideboardCards), slashTappedOutSplitCards(_slashTappedOutSplitCards) {}
WriteToStream(QTextStream &_stream, bool _prefixSideboardCards, bool _slashTappedOutSplitCards)
: stream(_stream), prefixSideboardCards(_prefixSideboardCards),
slashTappedOutSplitCards(_slashTappedOutSplitCards)
{
}
void operator()(
const InnerDecklistNode *node,
const DecklistCardNode *card
) {
if (prefixSideboardCards && node->getName() == DECK_ZONE_SIDE) {
stream << "SB: ";
}
if (!slashTappedOutSplitCards) {
stream << QString("%1 %2\n").arg(
card->getNumber()
).arg(
card->getName()
);
} else {
stream << QString("%1 %2\n").arg(
card->getNumber()
).arg(
card->getName().replace("//", "/")
);
}
void operator()(const InnerDecklistNode *node, const DecklistCardNode *card)
{
if (prefixSideboardCards && node->getName() == DECK_ZONE_SIDE) {
stream << "SB: ";
}
if (!slashTappedOutSplitCards) {
stream << QString("%1 %2\n").arg(card->getNumber()).arg(card->getName());
} else {
stream << QString("%1 %2\n").arg(card->getNumber()).arg(card->getName().replace("//", "/"));
}
}
};
bool DeckList::saveToStream_Plain(QTextStream &out, bool prefixSideboardCards, bool slashTappedOutSplitCards)
bool DeckList::saveToStream_Plain(QTextStream &out, bool prefixSideboardCards, bool slashTappedOutSplitCards)
{
WriteToStream writeToStream(out, prefixSideboardCards, slashTappedOutSplitCards);
forEachCard(writeToStream);
@ -764,16 +708,12 @@ void DeckList::cleanList()
void DeckList::getCardListHelper(InnerDecklistNode *item, QSet<QString> &result) const
{
for (int i = 0; i < item->size(); ++i)
{
for (int i = 0; i < item->size(); ++i) {
auto *node = dynamic_cast<DecklistCardNode *>(item->at(i));
if (node)
{
if (node) {
result.insert(node->getName());
}
else
{
} else {
getCardListHelper(dynamic_cast<InnerDecklistNode *>(item->at(i)), result);
}
}
@ -789,16 +729,13 @@ QStringList DeckList::getCardList() const
int DeckList::getSideboardSize() const
{
int size = 0;
for (int i = 0; i < root->size(); ++i)
{
for (int i = 0; i < root->size(); ++i) {
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
if (node->getName() != DECK_ZONE_SIDE)
{
if (node->getName() != DECK_ZONE_SIDE) {
continue;
}
for (int j = 0; j < node->size(); j++)
{
for (int j = 0; j < node->size(); j++) {
auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
size += card->getNumber();
}
@ -809,8 +746,7 @@ int DeckList::getSideboardSize() const
DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zoneName)
{
auto *zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
if (zoneNode == nullptr)
{
if (zoneNode == nullptr) {
zoneNode = new InnerDecklistNode(zoneName, root);
}
@ -822,45 +758,36 @@ DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zone
bool DeckList::deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode)
{
if (node == root)
{
if (node == root) {
return true;
}
bool updateHash = false;
if (rootNode == nullptr)
{
if (rootNode == nullptr) {
rootNode = root;
updateHash = true;
}
int index = rootNode->indexOf(node);
if (index != -1)
{
if (index != -1) {
delete rootNode->takeAt(index);
if (rootNode->empty())
{
if (rootNode->empty()) {
deleteNode(rootNode, rootNode->getParent());
}
if (updateHash)
{
if (updateHash) {
updateDeckHash();
}
return true;
}
for (int i = 0; i < rootNode->size(); i++)
{
for (int i = 0; i < rootNode->size(); i++) {
auto *inner = dynamic_cast<InnerDecklistNode *>(rootNode->at(i));
if (inner)
{
if (deleteNode(node, inner))
{
if (updateHash)
{
if (inner) {
if (deleteNode(node, inner)) {
if (updateHash) {
updateDeckHash();
}
@ -879,22 +806,18 @@ void DeckList::updateDeckHash()
QSet<QString> hashZones, optionalZones;
hashZones << DECK_ZONE_MAIN << DECK_ZONE_SIDE; // Zones in deck to be included in hashing process
optionalZones << DECK_ZONE_TOKENS; // Optional zones in deck not included in hashing process
optionalZones << DECK_ZONE_TOKENS; // Optional zones in deck not included in hashing process
for (int i = 0; i < root->size(); i++)
{
for (int i = 0; i < root->size(); i++) {
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++)
{
for (int j = 0; j < node->size(); j++) {
if (hashZones.contains(node->getName())) // Mainboard or Sideboard
{
auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
for (int k = 0; k < card->getNumber(); ++k)
{
for (int k = 0; k < card->getNumber(); ++k) {
cardList.append((node->getName() == DECK_ZONE_SIDE ? "SB:" : "") + card->getName().toLower());
}
}
else if (!optionalZones.contains(node->getName())) // Not a valid zone -> cheater?
} else if (!optionalZones.contains(node->getName())) // Not a valid zone -> cheater?
{
isValidDeckList = false; // Deck is invalid
}
@ -902,11 +825,10 @@ void DeckList::updateDeckHash()
}
cardList.sort();
QByteArray deckHashArray = QCryptographicHash::hash(cardList.join(";").toUtf8(), QCryptographicHash::Sha1);
quint64 number = (((quint64) (unsigned char) deckHashArray[0]) << 32)
+ (((quint64) (unsigned char) deckHashArray[1]) << 24)
+ (((quint64) (unsigned char) deckHashArray[2] << 16))
+ (((quint64) (unsigned char) deckHashArray[3]) << 8)
+ (quint64) (unsigned char) deckHashArray[4];
quint64 number = (((quint64)(unsigned char)deckHashArray[0]) << 32) +
(((quint64)(unsigned char)deckHashArray[1]) << 24) +
(((quint64)(unsigned char)deckHashArray[2] << 16)) +
(((quint64)(unsigned char)deckHashArray[3]) << 8) + (quint64)(unsigned char)deckHashArray[4];
deckHash = (isValidDeckList) ? QString::number(number, 32).rightJustified(8, '0') : "INVALID";
emit deckHashChanged();

View file

@ -2,12 +2,12 @@
#define DECKLIST_H
#include <QList>
#include <QVector>
#include <QPair>
#include <QObject>
#include <QStringList>
#include <QSet>
#include <QMap>
#include <QObject>
#include <QPair>
#include <QSet>
#include <QStringList>
#include <QVector>
// Required on Mac. Forward declaration doesn't work. Don't ask why.
#include <QtCore/QXmlStreamReader>
@ -27,181 +27,255 @@ class InnerDecklistNode;
class SideboardPlan
{
private:
QString name;
QList<MoveCard_ToZone> moveList;
private:
QString name;
QList<MoveCard_ToZone> moveList;
public:
explicit SideboardPlan(const QString &_name = QString(), const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
public:
explicit SideboardPlan(const QString &_name = QString(),
const QList<MoveCard_ToZone> &_moveList = QList<MoveCard_ToZone>());
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
QString getName() const { return name; }
const QList<MoveCard_ToZone> &getMoveList() const { return moveList; }
void setMoveList(const QList<MoveCard_ToZone> &_moveList);
QString getName() const
{
return name;
}
const QList<MoveCard_ToZone> &getMoveList() const
{
return moveList;
}
void setMoveList(const QList<MoveCard_ToZone> &_moveList);
};
enum DeckSortMethod { ByNumber, ByName, Default };
enum DeckSortMethod
{
ByNumber,
ByName,
Default
};
class AbstractDecklistNode
{
protected:
InnerDecklistNode *parent;
DeckSortMethod sortMethod;
protected:
InnerDecklistNode *parent;
DeckSortMethod sortMethod;
public:
explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr);
virtual ~AbstractDecklistNode() = default;
virtual void setSortMethod(DeckSortMethod method) { sortMethod = method; }
virtual QString getName() const = 0;
InnerDecklistNode *getParent() const { return parent; }
int depth() const;
virtual int height() const = 0;
virtual bool compare(AbstractDecklistNode *other) const = 0;
public:
explicit AbstractDecklistNode(InnerDecklistNode *_parent = nullptr);
virtual ~AbstractDecklistNode() = default;
virtual void setSortMethod(DeckSortMethod method)
{
sortMethod = method;
}
virtual QString getName() const = 0;
InnerDecklistNode *getParent() const
{
return parent;
}
int depth() const;
virtual int height() const = 0;
virtual bool compare(AbstractDecklistNode *other) const = 0;
virtual bool readElement(QXmlStreamReader *xml) = 0;
virtual void writeElement(QXmlStreamWriter *xml) = 0;
virtual bool readElement(QXmlStreamReader *xml) = 0;
virtual void writeElement(QXmlStreamWriter *xml) = 0;
};
class InnerDecklistNode : public AbstractDecklistNode, public QList<AbstractDecklistNode *>
{
private:
QString name;
class compareFunctor;
private:
QString name;
class compareFunctor;
public:
explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent), name(std::move(_name)) { }
explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr);
~InnerDecklistNode() override;
void setSortMethod(DeckSortMethod method) override;
QString getName() const override { return name; }
void setName(const QString &_name) { name = _name; }
static QString visibleNameFromName(const QString &_name);
virtual QString getVisibleName() const;
void clearTree();
AbstractDecklistNode *findChild(const QString &name);
int height() const override;
int recursiveCount(bool countTotalCards = false) const;
bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
QVector<QPair<int, int> > sort(Qt::SortOrder order = Qt::AscendingOrder);
public:
explicit InnerDecklistNode(QString _name = QString(), InnerDecklistNode *_parent = nullptr)
: AbstractDecklistNode(_parent), name(std::move(_name))
{
}
explicit InnerDecklistNode(InnerDecklistNode *other, InnerDecklistNode *_parent = nullptr);
~InnerDecklistNode() override;
void setSortMethod(DeckSortMethod method) override;
QString getName() const override
{
return name;
}
void setName(const QString &_name)
{
name = _name;
}
static QString visibleNameFromName(const QString &_name);
virtual QString getVisibleName() const;
void clearTree();
AbstractDecklistNode *findChild(const QString &name);
int height() const override;
int recursiveCount(bool countTotalCards = false) const;
bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
QVector<QPair<int, int>> sort(Qt::SortOrder order = Qt::AscendingOrder);
bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml) override;
bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml) override;
};
class AbstractDecklistCardNode : public AbstractDecklistNode
{
public:
explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent) { }
virtual int getNumber() const = 0;
virtual void setNumber(int _number) = 0;
QString getName() const override = 0;
virtual void setName(const QString &_name) = 0;
int height() const override { return 0; }
bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
public:
explicit AbstractDecklistCardNode(InnerDecklistNode *_parent = nullptr) : AbstractDecklistNode(_parent)
{
}
virtual int getNumber() const = 0;
virtual void setNumber(int _number) = 0;
QString getName() const override = 0;
virtual void setName(const QString &_name) = 0;
int height() const override
{
return 0;
}
bool compare(AbstractDecklistNode *other) const override;
bool compareNumber(AbstractDecklistNode *other) const;
bool compareName(AbstractDecklistNode *other) const;
bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml) override;
bool readElement(QXmlStreamReader *xml) override;
void writeElement(QXmlStreamWriter *xml) override;
};
class DecklistCardNode : public AbstractDecklistCardNode
{
private:
QString name;
int number;
public:
explicit DecklistCardNode(QString _name = QString(), int _number = 1, InnerDecklistNode *_parent = nullptr) : AbstractDecklistCardNode(_parent), name(std::move(_name)), number(_number) { }
explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
int getNumber() const override { return number; }
void setNumber(int _number) override { number = _number; }
QString getName() const override { return name; }
void setName(const QString &_name) override { name = _name; }
private:
QString name;
int number;
public:
explicit DecklistCardNode(QString _name = QString(), int _number = 1, InnerDecklistNode *_parent = nullptr)
: AbstractDecklistCardNode(_parent), name(std::move(_name)), number(_number)
{
}
explicit DecklistCardNode(DecklistCardNode *other, InnerDecklistNode *_parent);
int getNumber() const override
{
return number;
}
void setNumber(int _number) override
{
number = _number;
}
QString getName() const override
{
return name;
}
void setName(const QString &_name) override
{
name = _name;
}
};
class DeckList : public QObject
{
Q_OBJECT
private:
QString name, comments;
QString deckHash;
QMap<QString, SideboardPlan *> sideboardPlans;
InnerDecklistNode *root;
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
InnerDecklistNode *getZoneObjFromName(QString zoneName);
private:
QString name, comments;
QString deckHash;
QMap<QString, SideboardPlan *> sideboardPlans;
InnerDecklistNode *root;
void getCardListHelper(InnerDecklistNode *node, QSet<QString> &result) const;
InnerDecklistNode *getZoneObjFromName(QString zoneName);
protected:
virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName) { return currentZoneName; };
virtual QString getCompleteCardName(const QString cardName) const { return cardName; };
protected:
virtual QString getCardZoneFromName(const QString /*cardName*/, QString currentZoneName)
{
return currentZoneName;
};
virtual QString getCompleteCardName(const QString cardName) const
{
return cardName;
};
signals:
void deckHashChanged();
signals:
void deckHashChanged();
public slots:
void setName(const QString &_name = QString()) { name = _name; }
void setComments(const QString &_comments = QString()) { comments = _comments; }
public slots:
void setName(const QString &_name = QString())
{
name = _name;
}
void setComments(const QString &_comments = QString())
{
comments = _comments;
}
public:
explicit DeckList();
DeckList(const DeckList &other);
explicit DeckList(const QString &nativeString);
~DeckList() override;
QString getName() const { return name; }
QString getComments() const { return comments; }
QList<MoveCard_ToZone> getCurrentSideboardPlan();
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
const QMap<QString, SideboardPlan *> &getSideboardPlans() const { return sideboardPlans; }
public:
explicit DeckList();
DeckList(const DeckList &other);
explicit DeckList(const QString &nativeString);
~DeckList() override;
QString getName() const
{
return name;
}
QString getComments() const
{
return comments;
}
QList<MoveCard_ToZone> getCurrentSideboardPlan();
void setCurrentSideboardPlan(const QList<MoveCard_ToZone> &plan);
const QMap<QString, SideboardPlan *> &getSideboardPlans() const
{
return sideboardPlans;
}
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
bool loadFromXml(QXmlStreamReader *xml);
bool loadFromString_Native(const QString &nativeString);
QString writeToString_Native();
bool loadFromFile_Native(QIODevice *device);
bool saveToFile_Native(QIODevice *device);
bool loadFromStream_Plain(QTextStream &stream);
bool loadFromFile_Plain(QIODevice *device);
bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards);
bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards=true, bool slashTappedOutSplitCards=false);
QString writeToString_Plain(bool prefixSideboardCards=true, bool slashTappedOutSplitCards=false);
bool readElement(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
bool loadFromXml(QXmlStreamReader *xml);
bool loadFromString_Native(const QString &nativeString);
QString writeToString_Native();
bool loadFromFile_Native(QIODevice *device);
bool saveToFile_Native(QIODevice *device);
bool loadFromStream_Plain(QTextStream &stream);
bool loadFromFile_Plain(QIODevice *device);
bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards);
bool saveToFile_Plain(QIODevice *device, bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false);
QString writeToString_Plain(bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false);
void cleanList();
bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); }
QStringList getCardList() const;
void cleanList();
bool isEmpty() const
{
return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty();
}
QStringList getCardList() const;
int getSideboardSize() const;
int getSideboardSize() const;
QString getDeckHash() const { return deckHash; }
void updateDeckHash();
QString getDeckHash() const
{
return deckHash;
}
void updateDeckHash();
InnerDecklistNode *getRoot() const { return root; }
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr);
InnerDecklistNode *getRoot() const
{
return root;
}
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = nullptr);
/**
* Calls a given function object for each card in the deck. It must
* take a InnerDecklistNode* as its first argument and a
* DecklistCardNode* as its second.
*/
template <typename Callback>
void forEachCard(Callback &callback) const {
// Support for this is only possible if the internal structure
// doesn't get more complicated.
for (int i = 0; i < root->size(); i++) {
const InnerDecklistNode *node =
dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) {
const DecklistCardNode *card =
dynamic_cast<DecklistCardNode *>(
node->at(j)
);
callback(node, card);
}
/**
* Calls a given function object for each card in the deck. It must
* take a InnerDecklistNode* as its first argument and a
* DecklistCardNode* as its second.
*/
template <typename Callback> void forEachCard(Callback &callback) const
{
// Support for this is only possible if the internal structure
// doesn't get more complicated.
for (int i = 0; i < root->size(); i++) {
const InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) {
const DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j));
callback(node, card);
}
}
}
};
#endif

View file

@ -1,18 +1,19 @@
#include "featureset.h"
#include <QMap>
#include <QDebug>
#include <QMap>
FeatureSet::FeatureSet()
{
}
QMap<QString, bool> FeatureSet::getDefaultFeatureList() {
QMap<QString, bool> FeatureSet::getDefaultFeatureList()
{
initalizeFeatureList(featureList);
return featureList;
}
void FeatureSet::initalizeFeatureList(QMap<QString, bool> &featureList) {
void FeatureSet::initalizeFeatureList(QMap<QString, bool> &featureList)
{
featureList.insert("client_id", false);
featureList.insert("client_ver", false);
featureList.insert("feature_set", false);
@ -24,22 +25,28 @@ void FeatureSet::initalizeFeatureList(QMap<QString, bool> &featureList) {
featureList.insert("forgot_password", false);
}
void FeatureSet::enableRequiredFeature(QMap<QString, bool> &featureList, QString featureName){
void FeatureSet::enableRequiredFeature(QMap<QString, bool> &featureList, QString featureName)
{
if (featureList.contains(featureName))
featureList.insert(featureName,true);
featureList.insert(featureName, true);
}
void FeatureSet::disableRequiredFeature(QMap<QString, bool> &featureList, QString featureName){
void FeatureSet::disableRequiredFeature(QMap<QString, bool> &featureList, QString featureName)
{
if (featureList.contains(featureName))
featureList.insert(featureName,false);
featureList.insert(featureName, false);
}
QMap<QString, bool> FeatureSet::addFeature(QMap<QString, bool> &featureList, QString featureName, bool isFeatureRequired){
featureList.insert(featureName,isFeatureRequired);
QMap<QString, bool>
FeatureSet::addFeature(QMap<QString, bool> &featureList, QString featureName, bool isFeatureRequired)
{
featureList.insert(featureName, isFeatureRequired);
return featureList;
}
QMap<QString, bool> FeatureSet::identifyMissingFeatures(QMap<QString, bool> suppliedFeatures, QMap<QString, bool> requiredFeatures){
QMap<QString, bool> FeatureSet::identifyMissingFeatures(QMap<QString, bool> suppliedFeatures,
QMap<QString, bool> requiredFeatures)
{
QMap<QString, bool> missingList;
QMap<QString, bool>::iterator i;
for (i = requiredFeatures.begin(); i != requiredFeatures.end(); ++i) {
@ -50,11 +57,12 @@ QMap<QString, bool> FeatureSet::identifyMissingFeatures(QMap<QString, bool> supp
return missingList;
}
bool FeatureSet::isRequiredFeaturesMissing(QMap<QString, bool> suppliedFeatures, QMap<QString, bool> requiredFeatures) {
bool FeatureSet::isRequiredFeaturesMissing(QMap<QString, bool> suppliedFeatures, QMap<QString, bool> requiredFeatures)
{
QMap<QString, bool>::iterator i;
for (i = requiredFeatures.begin(); i != requiredFeatures.end(); ++i) {
if (i.value() && suppliedFeatures.contains(i.key())) {
return true;
return true;
}
}
return false;

View file

@ -14,11 +14,12 @@ public:
void enableRequiredFeature(QMap<QString, bool> &featureList, QString featureName);
void disableRequiredFeature(QMap<QString, bool> &featureList, QString featureName);
QMap<QString, bool> addFeature(QMap<QString, bool> &featureList, QString featureName, bool isFeatureRequired);
QMap<QString, bool> identifyMissingFeatures(QMap<QString, bool> featureListToCheck, QMap<QString, bool> featureListToCompareTo);
QMap<QString, bool> identifyMissingFeatures(QMap<QString, bool> featureListToCheck,
QMap<QString, bool> featureListToCompareTo);
bool isRequiredFeaturesMissing(QMap<QString, bool> featureListToCheck, QMap<QString, bool> featureListToCompareTo);
private:
QMap<QString, bool> featureList;
};
#endif // FEEATURESET_H

View file

@ -1,10 +1,10 @@
#include "get_pb_extension.h"
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
int getPbExtension(const ::google::protobuf::Message &message)
{
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList;
std::vector<const ::google::protobuf::FieldDescriptor *> fieldList;
message.GetReflection()->ListFields(message, &fieldList);
for (unsigned int j = 0; j < fieldList.size(); ++j)
if (fieldList[j]->is_extension())

View file

@ -1,11 +1,13 @@
#ifndef GET_PB_EXTENSION_H
#define GET_PB_EXTENSION_H
namespace google {
namespace protobuf {
class Message;
}
namespace google
{
namespace protobuf
{
class Message;
}
} // namespace google
int getPbExtension(const ::google::protobuf::Message &message);

View file

@ -1,7 +1,6 @@
#include "rng_abstract.h"
#include <QDebug>
QVector<int> RNG_Abstract::makeNumbersVector(int n, int min, int max)
{
const int bins = max - min + 1;
@ -21,10 +20,10 @@ double RNG_Abstract::testRandom(const QVector<int> &numbers) const
int n = 0;
for (int i = 0; i < numbers.size(); ++i)
n += numbers[i];
double expected = (double) n / (double) numbers.size();
double expected = (double)n / (double)numbers.size();
double chisq = 0;
for (int i = 0; i < numbers.size(); ++i)
chisq += ((double) numbers[i] - expected) * ((double) numbers[i] - expected) / expected;
chisq += ((double)numbers[i] - expected) * ((double)numbers[i] - expected) / expected;
return chisq;
}

View file

@ -4,10 +4,13 @@
#include <QObject>
#include <QVector>
class RNG_Abstract : public QObject {
class RNG_Abstract : public QObject
{
Q_OBJECT
public:
RNG_Abstract(QObject *parent = 0) : QObject(parent) { }
RNG_Abstract(QObject *parent = 0) : QObject(parent)
{
}
virtual unsigned int rand(int min, int max) = 0;
QVector<int> makeNumbersVector(int n, int min, int max);
double testRandom(const QVector<int> &numbers) const;

View file

@ -10,8 +10,7 @@
#define UINT64_MAX (~(uint64_t)0)
#endif
RNG_SFMT::RNG_SFMT(QObject *parent)
: RNG_Abstract(parent)
RNG_SFMT::RNG_SFMT(QObject *parent) : RNG_Abstract(parent)
{
// initialize the random number generator with a 32bit integer seed (timestamp)
sfmt_init_gen_rand(&sfmt, QDateTime::currentDateTime().toTime_t());
@ -26,33 +25,33 @@ RNG_SFMT::RNG_SFMT(QObject *parent)
* It is only necessary that the upper bound is larger or equal to the lower bound - with the exception
* that someone wants something like rand() % -foo.
*/
unsigned int RNG_SFMT::rand(int min, int max) {
/* If min is negative, it would be possible to calculate
* cdf(0, max - min) + min
* There has been no use for negative random numbers with rand() though, so it's treated as error.
*/
if(min < 0) {
throw std::invalid_argument(
QString("Invalid bounds for RNG: Got min " +
QString::number(min) + " < 0!\n").toStdString());
// at this point, the method exits. No return value is needed, because
// basically the exception itself is returned.
}
unsigned int RNG_SFMT::rand(int min, int max)
{
/* If min is negative, it would be possible to calculate
* cdf(0, max - min) + min
* There has been no use for negative random numbers with rand() though, so it's treated as error.
*/
if (min < 0) {
throw std::invalid_argument(
QString("Invalid bounds for RNG: Got min " + QString::number(min) + " < 0!\n").toStdString());
// at this point, the method exits. No return value is needed, because
// basically the exception itself is returned.
}
// For complete fairness and equal timing, this should be a roll, but let's skip it anyway
if(min == max)
return max;
// For complete fairness and equal timing, this should be a roll, but let's skip it anyway
if (min == max)
return max;
// This is actually not used in Cockatrice:
// Someone wants rand() % -foo, so we compute -rand(0, +foo)
// This is the only time where min > max is (sort of) legal.
// Not handling this will cause the application to crash.
if(min == 0 && max < 0) {
return -cdf(0, -max);
}
// This is actually not used in Cockatrice:
// Someone wants rand() % -foo, so we compute -rand(0, +foo)
// This is the only time where min > max is (sort of) legal.
// Not handling this will cause the application to crash.
if (min == 0 && max < 0) {
return -cdf(0, -max);
}
// No special cases are left, except !(min > max) which is caught in the cdf itself.
return cdf(min, max);
// No special cases are left, except !(min > max) which is caught in the cdf itself.
return cdf(min, max);
}
/**
@ -89,9 +88,9 @@ unsigned int RNG_SFMT::rand(int min, int max) {
* This can be compared to an ideal six sided die that is rolled until only sides
* 1-5 show up, while 6 represents something that you don't want. So you basically roll
* a five sided die.
*
*
* Note: If you replace the SFMT RNG with some other rand() function in the future,
* then you _need_ to change the UINT64_MAX constant to the largest possible random
* then you _need_ to change the UINT64_MAX constant to the largest possible random
* number which can be created by the new rand() function. This value is often defined
* in a RAND_MAX constant.
* Otherwise you will probably skew the outcome of the rand() method or worsen the
@ -100,11 +99,10 @@ unsigned int RNG_SFMT::rand(int min, int max) {
unsigned int RNG_SFMT::cdf(unsigned int min, unsigned int max)
{
// This all makes no sense if min > max, which should never happen.
if(min > max) {
throw std::invalid_argument(
QString("Invalid bounds for RNG: min > max! Values were: min = " +
QString::number(min) + ", max = " +
QString::number(max)).toStdString());
if (min > max) {
throw std::invalid_argument(QString("Invalid bounds for RNG: min > max! Values were: min = " +
QString::number(min) + ", max = " + QString::number(max))
.toStdString());
// at this point, the method exits. No return value is needed, because
// basically the exception itself is returned.
}
@ -132,5 +130,5 @@ unsigned int RNG_SFMT::cdf(unsigned int min, unsigned int max)
// Now determine the bucket containing the SFMT() random number and after adding
// the lower bound, a random number from [min, max] can be returned.
return (unsigned int) (rand / buckets + min);
return (unsigned int)(rand / buckets + min);
}

View file

@ -1,10 +1,10 @@
#ifndef RNG_SFMT_H
#define RNG_SFMT_H
#include <climits>
#include <QMutex>
#include "sfmt/SFMT.h"
#include "rng_abstract.h"
#include "sfmt/SFMT.h"
#include <QMutex>
#include <climits>
/**
* This class encapsulates a state of the art PRNG and can be used
@ -25,17 +25,18 @@
* Edition Volume 2 / Seminumerical Algorithms".
*/
class RNG_SFMT : public RNG_Abstract {
class RNG_SFMT : public RNG_Abstract
{
Q_OBJECT
private:
QMutex mutex;
sfmt_t sfmt;
// The discrete cumulative distribution function for the RNG
unsigned int cdf(unsigned int min, unsigned int max);
public:
RNG_SFMT(QObject *parent = 0);
unsigned int rand(int min, int max);
};
#endif

View file

@ -18,27 +18,26 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "server.h"
#include "server_game.h"
#include "server_player.h"
#include "server_counter.h"
#include "server_room.h"
#include "server_protocolhandler.h"
#include "server_remoteuserinterface.h"
#include "server_metatypes.h"
#include "server_database_interface.h"
#include "featureset.h"
#include "pb/event_connection_closed.pb.h"
#include "pb/event_list_rooms.pb.h"
#include "pb/event_user_joined.pb.h"
#include "pb/event_user_left.pb.h"
#include "pb/event_list_rooms.pb.h"
#include "pb/session_event.pb.h"
#include "pb/event_connection_closed.pb.h"
#include "pb/isl_message.pb.h"
#include "featureset.h"
#include "pb/session_event.pb.h"
#include "server_counter.h"
#include "server_database_interface.h"
#include "server_game.h"
#include "server_metatypes.h"
#include "server_player.h"
#include "server_protocolhandler.h"
#include "server_remoteuserinterface.h"
#include "server_room.h"
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QThread>
Server::Server(QObject *parent)
: QObject(parent), nextLocalGameId(0), tcpUserCount(0), webSocketUserCount(0)
Server::Server(QObject *parent) : QObject(parent), nextLocalGameId(0), tcpUserCount(0), webSocketUserCount(0)
{
qRegisterMetaType<ServerInfo_Ban>("ServerInfo_Ban");
qRegisterMetaType<ServerInfo_Game>("ServerInfo_Game");
@ -50,7 +49,8 @@ Server::Server(QObject *parent)
qRegisterMetaType<IslMessage>("IslMessage");
qRegisterMetaType<Command_JoinGame>("Command_JoinGame");
connect(this, SIGNAL(sigSendIslMessage(IslMessage, int)), this, SLOT(doSendIslMessage(IslMessage, int)), Qt::QueuedConnection);
connect(this, SIGNAL(sigSendIslMessage(IslMessage, int)), this, SLOT(doSendIslMessage(IslMessage, int)),
Qt::QueuedConnection);
}
Server::~Server()
@ -78,15 +78,24 @@ Server_DatabaseInterface *Server::getDatabaseInterface() const
return databaseInterfaces.value(QThread::currentThread());
}
AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reasonStr, int &secondsLeft, QString &clientid, QString &clientVersion, QString & /* connectionType */)
AuthenticationResult Server::loginUser(Server_ProtocolHandler *session,
QString &name,
const QString &password,
QString &reasonStr,
int &secondsLeft,
QString &clientid,
QString &clientVersion,
QString & /* connectionType */)
{
if (name.size() > 35)
name = name.left(35);
Server_DatabaseInterface *databaseInterface = getDatabaseInterface();
AuthenticationResult authState = databaseInterface->checkUserPassword(session, name, password, clientid, reasonStr, secondsLeft);
if (authState == NotLoggedIn || authState == UserIsBanned || authState == UsernameInvalid || authState == UserIsInactive)
AuthenticationResult authState =
databaseInterface->checkUserPassword(session, name, password, clientid, reasonStr, secondsLeft);
if (authState == NotLoggedIn || authState == UserIsBanned || authState == UsernameInvalid ||
authState == UserIsInactive)
return authState;
ServerInfo_User data = databaseInterface->getUserData(name, true);
@ -108,7 +117,9 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
users.value(name)->prepareDestroy();
} else {
qDebug() << "Active session and sessions table inconsistent, please validate session table information for user " << name;
qDebug() << "Active session and sessions table inconsistent, please validate session table information "
"for user "
<< name;
}
}
@ -123,7 +134,8 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
QString tempName = name;
int i = 0;
while (users.contains(tempName) || databaseInterface->activeUserExists(tempName) || databaseInterface->userSessionExists(tempName))
while (users.contains(tempName) || databaseInterface->activeUserExists(tempName) ||
databaseInterface->userSessionExists(tempName))
tempName = name + "_" + QString::number(++i);
name = tempName;
data.set_name(name.toStdString());
@ -134,7 +146,8 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
users.insert(name, session);
qDebug() << "Server::loginUser:" << session << "name=" << name;
data.set_session_id(databaseInterface->startSession(name, session->getAddress(), clientid, session->getConnectionType()));
data.set_session_id(
databaseInterface->startSession(name, session->getAddress(), clientid, session->getConnectionType()));
databaseInterface->unlockSessionTables();
usersBySessionId.insert(data.session_id(), session);
@ -153,12 +166,11 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
event.mutable_user_info()->CopyFrom(session->copyUserInfo(true, true, true));
locker.unlock();
if (clientid.isEmpty()){
if (clientid.isEmpty()) {
// client id is empty, either out dated client or client has been modified
if (getClientIDRequiredEnabled())
return ClientIdRequired;
}
else {
} else {
// update users database table with client id
databaseInterface->updateUsersClientID(name, clientid);
}
@ -214,7 +226,7 @@ void Server::addClient(Server_ProtocolHandler *client)
void Server::removeClient(Server_ProtocolHandler *client)
{
if (client->getConnectionType() == "tcp")
tcpUserCount--;
@ -244,7 +256,8 @@ void Server::removeClient(Server_ProtocolHandler *client)
qDebug() << "closed session id:" << sessionId;
}
}
qDebug() << "Server::removeClient: removed" << (void *) client << ";" << clients.size() << "clients; " << users.size() << "users left";
qDebug() << "Server::removeClient: removed" << (void *)client << ";" << clients.size() << "clients; "
<< users.size() << "users left";
}
QList<QString> Server::getOnlineModeratorList()
@ -254,11 +267,9 @@ QList<QString> Server::getOnlineModeratorList()
for (int i = 0; i < clients.size(); ++i) {
ServerInfo_User *data = clients[i]->getUserInfo();
//TODO: this line should be updated in the event there is any type of new user level created
// TODO: this line should be updated in the event there is any type of new user level created
if (data &&
(data->user_level() & ServerInfo_User::IsModerator ||
data->user_level() & ServerInfo_User::IsAdmin)
)
(data->user_level() & ServerInfo_User::IsModerator || data->user_level() & ServerInfo_User::IsAdmin))
results << QString::fromStdString(data->name()).simplified();
}
return results;
@ -297,8 +308,8 @@ void Server::externalUserLeft(const QString &userName)
externalUsersBySessionId.remove(user->getUserInfo()->session_id());
clientsLock.unlock();
QMap<int, QPair<int, int> > userGames(user->getGames());
QMapIterator<int, QPair<int, int> > userGamesIterator(userGames);
QMap<int, QPair<int, int>> userGames(user->getGames());
QMapIterator<int, QPair<int, int>> userGamesIterator(userGames);
roomsLock.lockForRead();
while (userGamesIterator.hasNext()) {
userGamesIterator.next();
@ -372,7 +383,8 @@ void Server::externalRoomSay(int roomId, const QString &userName, const QString
}
room->say(userName, message, false);
getDatabaseInterface()->logMessage(0, userName, "ISL", message, Server_DatabaseInterface::MessageTargetIslRoom, room->getId(), room->getName());
getDatabaseInterface()->logMessage(0, userName, "ISL", message, Server_DatabaseInterface::MessageTargetIslRoom,
room->getId(), room->getName());
}
void Server::externalRoomGameListChanged(int roomId, const ServerInfo_Game &gameInfo)
@ -388,7 +400,11 @@ void Server::externalRoomGameListChanged(int roomId, const ServerInfo_Game &game
room->updateExternalGameList(gameInfo);
}
void Server::externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cmdId, int roomId, int serverId, qint64 sessionId)
void Server::externalJoinGameCommandReceived(const Command_JoinGame &cmd,
int cmdId,
int roomId,
int serverId,
qint64 sessionId)
{
// This function is always called from the main thread via signal/slot.
@ -419,7 +435,10 @@ void Server::externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cm
}
}
void Server::externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId)
void Server::externalGameCommandContainerReceived(const CommandContainer &cont,
int playerId,
int serverId,
qint64 sessionId)
{
// This function is always called from the main thread via signal/slot.
@ -528,7 +547,8 @@ void Server::addRoom(Server_Room *newRoom)
QWriteLocker locker(&roomsLock);
qDebug() << "Adding room: ID=" << newRoom->getId() << "name=" << newRoom->getName();
rooms.insert(newRoom->getId(), newRoom);
connect(newRoom, SIGNAL(roomInfoChanged(ServerInfo_Room)), this, SLOT(broadcastRoomUpdate(const ServerInfo_Room &)), Qt::QueuedConnection);
connect(newRoom, SIGNAL(roomInfoChanged(ServerInfo_Room)), this, SLOT(broadcastRoomUpdate(const ServerInfo_Room &)),
Qt::QueuedConnection);
}
int Server::getUsersCount() const

View file

@ -1,18 +1,18 @@
#ifndef SERVER_H
#define SERVER_H
#include <QObject>
#include <QStringList>
#include "pb/commands.pb.h"
#include "pb/serverinfo_ban.pb.h"
#include "pb/serverinfo_chat_message.pb.h"
#include "pb/serverinfo_user.pb.h"
#include "pb/serverinfo_warning.pb.h"
#include "server_player_reference.h"
#include <QMap>
#include <QMultiMap>
#include <QMutex>
#include <QObject>
#include <QReadWriteLock>
#include "pb/commands.pb.h"
#include "pb/serverinfo_user.pb.h"
#include "pb/serverinfo_ban.pb.h"
#include "pb/serverinfo_warning.pb.h"
#include "pb/serverinfo_chat_message.pb.h"
#include "server_player_reference.h"
#include <QStringList>
class Server_DatabaseInterface;
class Server_Game;
@ -31,7 +31,18 @@ class GameEventContainer;
class CommandContainer;
class Command_JoinGame;
enum AuthenticationResult { NotLoggedIn, PasswordRight, UnknownUser, WouldOverwriteOldSession, UserIsBanned, UsernameInvalid, RegistrationRequired, UserIsInactive, ClientIdRequired };
enum AuthenticationResult
{
NotLoggedIn,
PasswordRight,
UnknownUser,
WouldOverwriteOldSession,
UserIsBanned,
UsernameInvalid,
RegistrationRequired,
UserIsInactive,
ClientIdRequired
};
class Server : public QObject
{
@ -42,45 +53,132 @@ signals:
void endSession(qint64 sessionId);
private slots:
void broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl = false);
public:
mutable QReadWriteLock clientsLock, roomsLock; // locking order: roomsLock before clientsLock
Server(QObject *parent = 0);
~Server();
AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reason, int &secondsLeft, QString &clientid, QString &clientVersion, QString &connectionType);
AuthenticationResult loginUser(Server_ProtocolHandler *session,
QString &name,
const QString &password,
QString &reason,
int &secondsLeft,
QString &clientid,
QString &clientVersion,
QString &connectionType);
const QMap<int, Server_Room *> &getRooms() { return rooms; }
const QMap<int, Server_Room *> &getRooms()
{
return rooms;
}
Server_AbstractUserInterface *findUser(const QString &userName) const;
const QMap<QString, Server_ProtocolHandler *> &getUsers() const { return users; }
const QMap<qint64, Server_ProtocolHandler *> &getUsersBySessionId() const { return usersBySessionId; }
virtual QMap<QString, bool> getServerRequiredFeatureList() const { return QMap<QString, bool>(); }
const QMap<QString, Server_ProtocolHandler *> &getUsers() const
{
return users;
}
const QMap<qint64, Server_ProtocolHandler *> &getUsersBySessionId() const
{
return usersBySessionId;
}
virtual QMap<QString, bool> getServerRequiredFeatureList() const
{
return QMap<QString, bool>();
}
void addClient(Server_ProtocolHandler *player);
void removeClient(Server_ProtocolHandler *player);
QList<QString> getOnlineModeratorList();
virtual QString getLoginMessage() const { return QString(); }
virtual QString getRequiredFeatures() const { return QString(); }
virtual bool permitUnregisteredUsers() const { return true; }
virtual bool getGameShouldPing() const { return false; }
virtual bool getClientIDRequiredEnabled() const { return false; }
virtual bool getRegOnlyServerEnabled() const { return false; }
virtual bool getMaxUserLimitEnabled() const { return false; }
virtual bool getEnableLogQuery() const { return false; }
virtual bool getStoreReplaysEnabled() const { return true; }
virtual int getIdleClientTimeout() const { return 0; }
virtual int getClientKeepAlive() const { return 0; }
virtual int getMaxGameInactivityTime() const { return 9999999; }
virtual int getMaxPlayerInactivityTime() const { return 9999999; }
virtual int getMessageCountingInterval() const { return 0; }
virtual int getMaxMessageCountPerInterval() const { return 0; }
virtual int getMaxMessageSizePerInterval() const { return 0; }
virtual int getMaxGamesPerUser() const { return 0; }
virtual int getCommandCountingInterval() const { return 0; }
virtual int getMaxCommandCountPerInterval() const { return 0; }
virtual int getMaxUserTotal() const { return 9999999; }
virtual int getServerID() const { return 0; }
virtual QString getLoginMessage() const
{
return QString();
}
virtual QString getRequiredFeatures() const
{
return QString();
}
virtual bool permitUnregisteredUsers() const
{
return true;
}
virtual bool getGameShouldPing() const
{
return false;
}
virtual bool getClientIDRequiredEnabled() const
{
return false;
}
virtual bool getRegOnlyServerEnabled() const
{
return false;
}
virtual bool getMaxUserLimitEnabled() const
{
return false;
}
virtual bool getEnableLogQuery() const
{
return false;
}
virtual bool getStoreReplaysEnabled() const
{
return true;
}
virtual int getIdleClientTimeout() const
{
return 0;
}
virtual int getClientKeepAlive() const
{
return 0;
}
virtual int getMaxGameInactivityTime() const
{
return 9999999;
}
virtual int getMaxPlayerInactivityTime() const
{
return 9999999;
}
virtual int getMessageCountingInterval() const
{
return 0;
}
virtual int getMaxMessageCountPerInterval() const
{
return 0;
}
virtual int getMaxMessageSizePerInterval() const
{
return 0;
}
virtual int getMaxGamesPerUser() const
{
return 0;
}
virtual int getCommandCountingInterval() const
{
return 0;
}
virtual int getMaxCommandCountPerInterval() const
{
return 0;
}
virtual int getMaxUserTotal() const
{
return 9999999;
}
virtual int getServerID() const
{
return 0;
}
Server_DatabaseInterface *getDatabaseInterface() const;
int getNextLocalGameId() { QMutexLocker locker(&nextLocalGameIdMutex); return ++nextLocalGameId; }
int getNextLocalGameId()
{
QMutexLocker locker(&nextLocalGameIdMutex);
return ++nextLocalGameId;
}
void sendIsl_Response(const Response &item, int serverId = -1, qint64 sessionId = -1);
void sendIsl_SessionEvent(const SessionEvent &item, int serverId = -1, qint64 sessionId = -1);
@ -91,15 +189,25 @@ public:
void addExternalUser(const ServerInfo_User &userInfo);
void removeExternalUser(const QString &userName);
const QMap<QString, Server_AbstractUserInterface *> &getExternalUsers() const { return externalUsers; }
const QMap<QString, Server_AbstractUserInterface *> &getExternalUsers() const
{
return externalUsers;
}
void addPersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
void removePersistentPlayer(const QString &userName, int roomId, int gameId, int playerId);
QList<PlayerReference> getPersistentPlayerReferences(const QString &userName) const;
int getUsersCount() const;
int getGamesCount() const;
int getTCPUserCount() const { return tcpUserCount; }
int getWebSocketUserCount() const { return webSocketUserCount; }
int getTCPUserCount() const
{
return tcpUserCount;
}
int getWebSocketUserCount() const
{
return webSocketUserCount;
}
private:
QMultiMap<QString, PlayerReference> persistentPlayers;
mutable QReadWriteLock persistentPlayersLock;
@ -113,12 +221,17 @@ protected slots:
void externalRoomUserLeft(int roomId, const QString &userName);
void externalRoomSay(int roomId, const QString &userName, const QString &message);
void externalRoomGameListChanged(int roomId, const ServerInfo_Game &gameInfo);
void externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cmdId, int roomId, int serverId, qint64 sessionId);
void externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId);
void
externalJoinGameCommandReceived(const Command_JoinGame &cmd, int cmdId, int roomId, int serverId, qint64 sessionId);
void
externalGameCommandContainerReceived(const CommandContainer &cont, int playerId, int serverId, qint64 sessionId);
void externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId);
void externalResponseReceived(const Response &resp, qint64 sessionId);
virtual void doSendIslMessage(const IslMessage & /* msg */, int /* serverId */) { }
virtual void doSendIslMessage(const IslMessage & /* msg */, int /* serverId */)
{
}
protected:
void prepareDestroy();
void setDatabaseInterface(Server_DatabaseInterface *_databaseInterface);

View file

@ -1,52 +1,67 @@
#include <QList>
#include <QPair>
#include <QDebug>
#include "server_abstractuserinterface.h"
#include "server_game.h"
#include "server_response_containers.h"
#include "server_player_reference.h"
#include "server.h"
#include "server_room.h"
#include "server_game.h"
#include "server_player.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_game_state_changed.pb.h"
#include "server.h"
#include "server_game.h"
#include "server_player.h"
#include "server_player_reference.h"
#include "server_response_containers.h"
#include "server_room.h"
#include <QDebug>
#include <QList>
#include <QPair>
#include <google/protobuf/descriptor.h>
void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item)
void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type,
const ::google::protobuf::Message &item)
{
switch (type) {
case ServerMessage::RESPONSE: sendProtocolItem(static_cast<const Response &>(item)); break;
case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast<const SessionEvent &>(item)); break;
case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast<const GameEventContainer &>(item)); break;
case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast<const RoomEvent &>(item)); break;
case ServerMessage::RESPONSE:
sendProtocolItem(static_cast<const Response &>(item));
break;
case ServerMessage::SESSION_EVENT:
sendProtocolItem(static_cast<const SessionEvent &>(item));
break;
case ServerMessage::GAME_EVENT_CONTAINER:
sendProtocolItem(static_cast<const GameEventContainer &>(item));
break;
case ServerMessage::ROOM_EVENT:
sendProtocolItem(static_cast<const RoomEvent &>(item));
break;
}
}
SessionEvent *Server_AbstractUserInterface::prepareSessionEvent(const ::google::protobuf::Message &sessionEvent)
{
SessionEvent *event = new SessionEvent;
event->GetReflection()->MutableMessage(event, sessionEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(sessionEvent);
event->GetReflection()
->MutableMessage(event, sessionEvent.GetDescriptor()->FindExtensionByName("ext"))
->CopyFrom(sessionEvent);
return event;
}
void Server_AbstractUserInterface::sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode)
void Server_AbstractUserInterface::sendResponseContainer(const ResponseContainer &responseContainer,
Response::ResponseCode responseCode)
{
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &preResponseQueue = responseContainer.getPreResponseQueue();
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *>> &preResponseQueue =
responseContainer.getPreResponseQueue();
for (int i = 0; i < preResponseQueue.size(); ++i)
sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second);
if (responseCode != Response::RespNothing) {
Response response;
response.set_cmd_id(responseContainer.getCmdId());
response.set_response_code(responseCode);
::google::protobuf::Message *responseExtension = responseContainer.getResponseExtension();
if (responseExtension)
response.GetReflection()->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(*responseExtension);
response.GetReflection()
->MutableMessage(&response, responseExtension->GetDescriptor()->FindExtensionByName("ext"))
->CopyFrom(*responseExtension);
sendProtocolItem(response);
}
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue();
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *>> &postResponseQueue =
responseContainer.getPostResponseQueue();
for (int i = 0; i < postResponseQueue.size(); ++i)
sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second);
}
@ -54,7 +69,7 @@ void Server_AbstractUserInterface::sendResponseContainer(const ResponseContainer
void Server_AbstractUserInterface::playerRemovedFromGame(Server_Game *game)
{
qDebug() << "Server_AbstractUserInterface::playerRemovedFromGame(): gameId =" << game->getGameId();
QMutexLocker locker(&gameListMutex);
games.remove(game->getGameId());
}
@ -62,36 +77,37 @@ void Server_AbstractUserInterface::playerRemovedFromGame(Server_Game *game)
void Server_AbstractUserInterface::playerAddedToGame(int gameId, int roomId, int playerId)
{
qDebug() << "Server_AbstractUserInterface::playerAddedToGame(): gameId =" << gameId;
QMutexLocker locker(&gameListMutex);
games.insert(gameId, QPair<int, int>(roomId, playerId));
}
void Server_AbstractUserInterface::joinPersistentGames(ResponseContainer &rc)
{
QList<PlayerReference> gamesToJoin = server->getPersistentPlayerReferences(QString::fromStdString(userInfo->name()));
QList<PlayerReference> gamesToJoin =
server->getPersistentPlayerReferences(QString::fromStdString(userInfo->name()));
server->roomsLock.lockForRead();
for (int i = 0; i < gamesToJoin.size(); ++i) {
const PlayerReference &pr = gamesToJoin.at(i);
Server_Room *room = server->getRooms().value(pr.getRoomId());
if (!room)
continue;
QReadLocker roomGamesLocker(&room->gamesLock);
Server_Game *game = room->getGames().value(pr.getGameId());
if (!game)
continue;
QMutexLocker gameLocker(&game->gameMutex);
Server_Player *player = game->getPlayers().value(pr.getPlayerId());
if (!player)
continue;
player->setUserInterface(this);
playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId());
game->createGameJoinedEvent(player, rc, true);
}
server->roomsLock.unlock();

View file

@ -1,12 +1,12 @@
#ifndef SERVER_ABSTRACTUSERINTERFACE
#define SERVER_ABSTRACTUSERINTERFACE
#include <QMutex>
#include <QMap>
#include <QPair>
#include "serverinfo_user_container.h"
#include "pb/server_message.pb.h"
#include "pb/response.pb.h"
#include "pb/server_message.pb.h"
#include "serverinfo_user_container.h"
#include <QMap>
#include <QMutex>
#include <QPair>
class SessionEvent;
class GameEventContainer;
@ -16,31 +16,44 @@ class ResponseContainer;
class Server;
class Server_Game;
class Server_AbstractUserInterface : public ServerInfo_User_Container {
class Server_AbstractUserInterface : public ServerInfo_User_Container
{
private:
mutable QMutex gameListMutex;
QMap<int, QPair<int, int> > games; // gameId -> (roomId, playerId)
QMap<int, QPair<int, int>> games; // gameId -> (roomId, playerId)
protected:
Server *server;
public:
Server_AbstractUserInterface(Server *_server) : server(_server) { }
Server_AbstractUserInterface(Server *_server, const ServerInfo_User_Container &other) : ServerInfo_User_Container(other), server(_server) { }
virtual ~Server_AbstractUserInterface() { }
Server_AbstractUserInterface(Server *_server) : server(_server)
{
}
Server_AbstractUserInterface(Server *_server, const ServerInfo_User_Container &other)
: ServerInfo_User_Container(other), server(_server)
{
}
virtual ~Server_AbstractUserInterface()
{
}
virtual int getLastCommandTime() const = 0;
void playerRemovedFromGame(Server_Game *game);
void playerAddedToGame(int gameId, int roomId, int playerId);
void joinPersistentGames(ResponseContainer &rc);
QMap<int, QPair<int, int> > getGames() const { QMutexLocker locker(&gameListMutex); return games; }
QMap<int, QPair<int, int>> getGames() const
{
QMutexLocker locker(&gameListMutex);
return games;
}
virtual void sendProtocolItem(const Response &item) = 0;
virtual void sendProtocolItem(const SessionEvent &item) = 0;
virtual void sendProtocolItem(const GameEventContainer &item) = 0;
virtual void sendProtocolItem(const RoomEvent &item) = 0;
void sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item);
static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent);
void sendResponseContainer(const ResponseContainer &responseContainer, Response::ResponseCode responseCode);
};

View file

@ -1,14 +1,11 @@
#include "server_arrow.h"
#include "server_player.h"
#include "pb/serverinfo_arrow.pb.h"
#include "server_card.h"
#include "server_cardzone.h"
#include "pb/serverinfo_arrow.pb.h"
#include "server_player.h"
Server_Arrow::Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor)
: id(_id),
startCard(_startCard),
targetItem(_targetItem),
arrowColor(_arrowColor)
: id(_id), startCard(_startCard), targetItem(_targetItem), arrowColor(_arrowColor)
{
}

View file

@ -7,19 +7,33 @@ class Server_Card;
class Server_ArrowTarget;
class ServerInfo_Arrow;
class Server_Arrow {
class Server_Arrow
{
private:
int id;
Server_Card *startCard;
Server_ArrowTarget *targetItem;
color arrowColor;
public:
Server_Arrow(int _id, Server_Card *_startCard, Server_ArrowTarget *_targetItem, const color &_arrowColor);
int getId() const { return id; }
Server_Card *getStartCard() const { return startCard; }
Server_ArrowTarget *getTargetItem() const { return targetItem; }
const color &getColor() const { return arrowColor; }
int getId() const
{
return id;
}
Server_Card *getStartCard() const
{
return startCard;
}
Server_ArrowTarget *getTargetItem() const
{
return targetItem;
}
const color &getColor() const
{
return arrowColor;
}
void getInfo(ServerInfo_Arrow *info);
};

View file

@ -3,7 +3,8 @@
#include <QObject>
class Server_ArrowTarget : public QObject {
class Server_ArrowTarget : public QObject
{
Q_OBJECT
};

View file

@ -18,12 +18,14 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "server_card.h"
#include "pb/serverinfo_card.pb.h"
#include "server_cardzone.h"
#include "server_player.h"
#include "pb/serverinfo_card.pb.h"
Server_Card::Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone)
: zone(_zone), id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), tapped(false), attacking(false), facedown(false), color(QString()), power(-1), toughness(-1), annotation(QString()), destroyOnZoneChange(false), doesntUntap(false), parentCard(0)
: zone(_zone), id(_id), coord_x(_coord_x), coord_y(_coord_y), name(_name), tapped(false), attacking(false),
facedown(false), color(QString()), power(-1), toughness(-1), annotation(QString()), destroyOnZoneChange(false),
doesntUntap(false), parentCard(0)
{
}
@ -32,7 +34,7 @@ Server_Card::~Server_Card()
// setParentCard(0) leads to the item being removed from our list, so we can't iterate properly
while (!attachedCards.isEmpty())
attachedCards.first()->setParentCard(0);
if (parentCard)
parentCard->removeAttachedCard(this);
}
@ -57,12 +59,24 @@ QString Server_Card::setAttribute(CardAttribute attribute, const QString &avalue
setTapped(value);
break;
}
case AttrAttacking: setAttacking(avalue == "1"); break;
case AttrFaceDown: setFaceDown(avalue == "1"); break;
case AttrColor: setColor(avalue); break;
case AttrPT: setPT(avalue); return getPT();
case AttrAnnotation: setAnnotation(avalue); break;
case AttrDoesntUntap: setDoesntUntap(avalue == "1"); break;
case AttrAttacking:
setAttacking(avalue == "1");
break;
case AttrFaceDown:
setFaceDown(avalue == "1");
break;
case AttrColor:
setColor(avalue);
break;
case AttrPT:
setPT(avalue);
return getPT();
case AttrAnnotation:
setAnnotation(avalue);
break;
case AttrDoesntUntap:
setDoesntUntap(avalue == "1");
break;
}
return avalue;
}
@ -121,14 +135,13 @@ void Server_Card::setParentCard(Server_Card *_parentCard)
void Server_Card::getInfo(ServerInfo_Card *info)
{
QString displayedName = facedown ? QString() : name;
info->set_id(id);
info->set_name(displayedName.toStdString());
info->set_x(coord_x);
info->set_y(coord_y);
QString ptStr = getPT();
if (facedown)
{
if (facedown) {
info->set_face_down(true);
ptStr = getPT();
}
@ -145,7 +158,7 @@ void Server_Card::getInfo(ServerInfo_Card *info)
info->set_destroy_on_zone_change(true);
if (doesntUntap)
info->set_doesnt_untap(true);
QMapIterator<int, int> cardCounterIterator(counters);
while (cardCounterIterator.hasNext()) {
cardCounterIterator.next();

View file

@ -20,15 +20,16 @@
#ifndef SERVER_CARD_H
#define SERVER_CARD_H
#include "server_arrowtarget.h"
#include "pb/card_attributes.pb.h"
#include <QString>
#include "server_arrowtarget.h"
#include <QMap>
#include <QString>
class Server_CardZone;
class ServerInfo_Card;
class Server_Card : public Server_ArrowTarget {
class Server_Card : public Server_ArrowTarget
{
Q_OBJECT
private:
Server_CardZone *zone;
@ -44,52 +45,141 @@ private:
QString annotation;
bool destroyOnZoneChange;
bool doesntUntap;
Server_Card *parentCard;
QList<Server_Card *> attachedCards;
public:
Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone = 0);
~Server_Card();
Server_CardZone *getZone() const { return zone; }
void setZone(Server_CardZone *_zone) { zone = _zone; }
int getId() const { return id; }
int getX() const { return coord_x; }
int getY() const { return coord_y; }
QString getName() const { return name; }
const QMap<int, int> &getCounters() const { return counters; }
int getCounter(int id) const { return counters.value(id, 0); }
bool getTapped() const { return tapped; }
bool getAttacking() const { return attacking; }
bool getFaceDown() const { return facedown; }
QString getColor() const { return color; }
QString getPT() const;
QString getAnnotation() const { return annotation; }
bool getDoesntUntap() const { return doesntUntap; }
bool getDestroyOnZoneChange() const { return destroyOnZoneChange; }
Server_Card *getParentCard() const { return parentCard; }
const QList<Server_Card *> &getAttachedCards() const { return attachedCards; }
void setId(int _id) { id = _id; }
void setCoords(int x, int y) { coord_x = x; coord_y = y; }
void setName(const QString &_name) { name = _name; }
Server_CardZone *getZone() const
{
return zone;
}
void setZone(Server_CardZone *_zone)
{
zone = _zone;
}
int getId() const
{
return id;
}
int getX() const
{
return coord_x;
}
int getY() const
{
return coord_y;
}
QString getName() const
{
return name;
}
const QMap<int, int> &getCounters() const
{
return counters;
}
int getCounter(int id) const
{
return counters.value(id, 0);
}
bool getTapped() const
{
return tapped;
}
bool getAttacking() const
{
return attacking;
}
bool getFaceDown() const
{
return facedown;
}
QString getColor() const
{
return color;
}
QString getPT() const;
QString getAnnotation() const
{
return annotation;
}
bool getDoesntUntap() const
{
return doesntUntap;
}
bool getDestroyOnZoneChange() const
{
return destroyOnZoneChange;
}
Server_Card *getParentCard() const
{
return parentCard;
}
const QList<Server_Card *> &getAttachedCards() const
{
return attachedCards;
}
void setId(int _id)
{
id = _id;
}
void setCoords(int x, int y)
{
coord_x = x;
coord_y = y;
}
void setName(const QString &_name)
{
name = _name;
}
void setCounter(int id, int value);
void setTapped(bool _tapped) { tapped = _tapped; }
void setAttacking(bool _attacking) { attacking = _attacking; }
void setFaceDown(bool _facedown) { facedown = _facedown; }
void setColor(const QString &_color) { color = _color; }
void setTapped(bool _tapped)
{
tapped = _tapped;
}
void setAttacking(bool _attacking)
{
attacking = _attacking;
}
void setFaceDown(bool _facedown)
{
facedown = _facedown;
}
void setColor(const QString &_color)
{
color = _color;
}
void setPT(const QString &_pt);
void setAnnotation(const QString &_annotation) { annotation = _annotation; }
void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; }
void setDoesntUntap(bool _doesntUntap) { doesntUntap = _doesntUntap; }
void setAnnotation(const QString &_annotation)
{
annotation = _annotation;
}
void setDestroyOnZoneChange(bool _destroy)
{
destroyOnZoneChange = _destroy;
}
void setDoesntUntap(bool _doesntUntap)
{
doesntUntap = _doesntUntap;
}
void setParentCard(Server_Card *_parentCard);
void addAttachedCard(Server_Card *card) { attachedCards.append(card); }
void removeAttachedCard(Server_Card *card) { attachedCards.removeAt(attachedCards.indexOf(card)); }
void addAttachedCard(Server_Card *card)
{
attachedCards.append(card);
}
void removeAttachedCard(Server_Card *card)
{
attachedCards.removeAt(attachedCards.indexOf(card));
}
void resetState();
QString setAttribute(CardAttribute attribute, const QString &avalue, bool allCards);
void getInfo(ServerInfo_Card *info);
};

View file

@ -18,20 +18,19 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "server_cardzone.h"
#include "pb/command_move_card.pb.h"
#include "rng_abstract.h"
#include "server_card.h"
#include "server_player.h"
#include "rng_abstract.h"
#include <QSet>
#include <QDebug>
#include "pb/command_move_card.pb.h"
#include <QSet>
Server_CardZone::Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type)
: player(_player),
name(_name),
has_coords(_has_coords),
type(_type),
cardsBeingLookedAt(0),
alwaysRevealTopCard(false)
Server_CardZone::Server_CardZone(Server_Player *_player,
const QString &_name,
bool _has_coords,
ServerInfo_Zone::ZoneType _type)
: player(_player), name(_name), has_coords(_has_coords), type(_type), cardsBeingLookedAt(0),
alwaysRevealTopCard(false)
{
}
@ -44,33 +43,35 @@ Server_CardZone::~Server_CardZone()
void Server_CardZone::shuffle()
{
// Size 0 or 1 decks are sorted
if (cards.size() < 2) return;
for (int i = cards.size() - 1; i > 0; i--){
if (cards.size() < 2)
return;
for (int i = cards.size() - 1; i > 0; i--) {
int j = rng->rand(0, i);
cards.swap(j,i);
cards.swap(j, i);
}
playersWithWritePermission.clear();
}
void Server_CardZone::removeCardFromCoordMap(Server_Card *card, int oldX, int oldY)
{
if (oldX < 0)
return;
const int baseX = (oldX / 3) * 3;
QMap<int, Server_Card *> &coordMap = coordinateMap[oldY];
if (coordMap.contains(baseX) && coordMap.contains(baseX + 1) && coordMap.contains(baseX + 2))
// If the removal of this card has opened up a previously full pile...
freePilesMap[oldY].insert(coordMap.value(baseX)->getName(), baseX);
coordMap.remove(oldX);
if (!(coordMap.contains(baseX) && coordMap.value(baseX)->getName() == card->getName()) && !(coordMap.contains(baseX + 1) && coordMap.value(baseX + 1)->getName() == card->getName()) && !(coordMap.contains(baseX + 2) && coordMap.value(baseX + 2)->getName() == card->getName()))
if (!(coordMap.contains(baseX) && coordMap.value(baseX)->getName() == card->getName()) &&
!(coordMap.contains(baseX + 1) && coordMap.value(baseX + 1)->getName() == card->getName()) &&
!(coordMap.contains(baseX + 2) && coordMap.value(baseX + 2)->getName() == card->getName()))
// If this card was the last one with this name...
freePilesMap[oldY].remove(card->getName(), baseX);
if (!coordMap.contains(baseX) && !coordMap.contains(baseX + 1) && !coordMap.contains(baseX + 2)) {
// If the removal of this card has freed a whole pile, i.e. it was the last card in it...
if (baseX < freeSpaceMap[oldY])
@ -82,7 +83,7 @@ void Server_CardZone::insertCardIntoCoordMap(Server_Card *card, int x, int y)
{
if (x < 0)
return;
coordinateMap[y].insert(x, card);
if (!(x % 3)) {
if (!card->getFaceDown() && !freePilesMap[y].contains(card->getName(), x) && card->getAttachedCards().isEmpty())
@ -91,7 +92,8 @@ void Server_CardZone::insertCardIntoCoordMap(Server_Card *card, int x, int y)
int nextFreeX = x;
do {
nextFreeX += 3;
} while (coordinateMap[y].contains(nextFreeX) || coordinateMap[y].contains(nextFreeX + 1) || coordinateMap[y].contains(nextFreeX + 2));
} while (coordinateMap[y].contains(nextFreeX) || coordinateMap[y].contains(nextFreeX + 1) ||
coordinateMap[y].contains(nextFreeX + 2));
freeSpaceMap[y] = nextFreeX;
}
} else if (!((x - 2) % 3)) {
@ -107,7 +109,7 @@ int Server_CardZone::removeCard(Server_Card *card)
if (has_coords)
removeCardFromCoordMap(card, card->getX(), card->getY());
card->setZone(0);
return index;
}
@ -147,10 +149,8 @@ int Server_CardZone::getFreeGridColumn(int x, int y, const QString &cardName, bo
if (x == -1) {
if (!dontStackSameName && freePilesMap[y].contains(cardName)) {
x = (freePilesMap[y].value(cardName) / 3) * 3;
if(coordMap.contains(x) &&
(coordMap[x]->getFaceDown() ||
!coordMap[x]->getAttachedCards().isEmpty())) {
if (coordMap.contains(x) && (coordMap[x]->getFaceDown() || !coordMap[x]->getAttachedCards().isEmpty())) {
// don't pile up on: 1. facedown cards 2. cards with attached cards
} else if (!coordMap.contains(x))
return x;
@ -181,7 +181,7 @@ int Server_CardZone::getFreeGridColumn(int x, int y, const QString &cardName, bo
return resultX;
}
return freeSpaceMap[y];
}
@ -189,7 +189,7 @@ bool Server_CardZone::isColumnStacked(int x, int y) const
{
if (!has_coords)
return false;
return coordinateMap[y].contains((x / 3) * 3 + 1);
}
@ -197,7 +197,7 @@ bool Server_CardZone::isColumnEmpty(int x, int y) const
{
if (!has_coords)
return true;
return !coordinateMap[y].contains((x / 3) * 3);
}
@ -213,17 +213,17 @@ void Server_CardZone::fixFreeSpaces(GameEventStorage &ges)
{
if (!has_coords)
return;
QSet<QPair<int, int> > placesToLook;
QSet<QPair<int, int>> placesToLook;
for (int i = 0; i < cards.size(); ++i)
placesToLook.insert(QPair<int, int>((cards[i]->getX() / 3) * 3, cards[i]->getY()));
QSetIterator<QPair<int, int> > placeIterator(placesToLook);
QSetIterator<QPair<int, int>> placeIterator(placesToLook);
while (placeIterator.hasNext()) {
const QPair<int, int> &foo = placeIterator.next();
int baseX = foo.first;
int y = foo.second;
if (!coordinateMap[y].contains(baseX)) {
if (coordinateMap[y].contains(baseX + 1))
moveCardInRow(ges, coordinateMap[y].value(baseX + 1), baseX, y);
@ -242,7 +242,7 @@ void Server_CardZone::updateCardCoordinates(Server_Card *card, int oldX, int old
{
if (!has_coords)
return;
if (oldX != -1)
removeCardFromCoordMap(card, oldX, oldY);
insertCardIntoCoordMap(card, card->getX(), card->getY());
@ -287,10 +287,8 @@ void Server_CardZone::getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAs
info->set_with_coords(has_coords);
info->set_card_count(cards.size());
info->set_always_reveal_top_card(alwaysRevealTopCard);
if (
(((playerWhosAsking == player) || omniscient) && (type != ServerInfo_Zone::HiddenZone))
|| ((playerWhosAsking != player) && (type == ServerInfo_Zone::PublicZone))
) {
if ((((playerWhosAsking == player) || omniscient) && (type != ServerInfo_Zone::HiddenZone)) ||
((playerWhosAsking != player) && (type == ServerInfo_Zone::PublicZone))) {
QListIterator<Server_Card *> cardIterator(cards);
while (cardIterator.hasNext())
cardIterator.next()->getInfo(info->add_card_list());

View file

@ -20,18 +20,19 @@
#ifndef SERVER_CARDZONE_H
#define SERVER_CARDZONE_H
#include "pb/serverinfo_zone.pb.h"
#include <QList>
#include <QString>
#include <QMap>
#include <QSet>
#include "pb/serverinfo_zone.pb.h"
#include <QString>
class Server_Card;
class Server_Player;
class Server_Game;
class GameEventStorage;
class Server_CardZone {
class Server_CardZone
{
private:
Server_Player *player;
QString name;
@ -41,27 +42,49 @@ private:
QSet<int> playersWithWritePermission;
bool alwaysRevealTopCard;
QList<Server_Card *> cards;
QMap<int, QMap<int, Server_Card *> > coordinateMap; // y -> (x -> card)
QMap<int, QMultiMap<QString, int> > freePilesMap; // y -> (cardName -> x)
QMap<int, int> freeSpaceMap; // y -> x
QMap<int, QMap<int, Server_Card *>> coordinateMap; // y -> (x -> card)
QMap<int, QMultiMap<QString, int>> freePilesMap; // y -> (cardName -> x)
QMap<int, int> freeSpaceMap; // y -> x
void removeCardFromCoordMap(Server_Card *card, int oldX, int oldY);
void insertCardIntoCoordMap(Server_Card *card, int x, int y);
public:
Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type);
~Server_CardZone();
const QList<Server_Card *> &getCards() const { return cards; }
const QList<Server_Card *> &getCards() const
{
return cards;
}
int removeCard(Server_Card *card);
Server_Card *getCard(int id, int *position = NULL, bool remove = false);
int getCardsBeingLookedAt() const { return cardsBeingLookedAt; }
void setCardsBeingLookedAt(int _cardsBeingLookedAt) { cardsBeingLookedAt = _cardsBeingLookedAt; }
bool hasCoords() const { return has_coords; }
ServerInfo_Zone::ZoneType getType() const { return type; }
QString getName() const { return name; }
Server_Player *getPlayer() const { return player; }
int getCardsBeingLookedAt() const
{
return cardsBeingLookedAt;
}
void setCardsBeingLookedAt(int _cardsBeingLookedAt)
{
cardsBeingLookedAt = _cardsBeingLookedAt;
}
bool hasCoords() const
{
return has_coords;
}
ServerInfo_Zone::ZoneType getType() const
{
return type;
}
QString getName() const
{
return name;
}
Server_Player *getPlayer() const
{
return player;
}
void getInfo(ServerInfo_Zone *info, Server_Player *playerWhosAsking, bool omniscient);
int getFreeGridColumn(int x, int y, const QString &cardName, bool dontStackSameName) const;
bool isColumnEmpty(int x, int y) const;
bool isColumnStacked(int x, int y) const;
@ -72,9 +95,18 @@ public:
void shuffle();
void clear();
void addWritePermission(int playerId);
const QSet<int> &getPlayersWithWritePermission() const { return playersWithWritePermission; }
bool getAlwaysRevealTopCard() const { return alwaysRevealTopCard; }
void setAlwaysRevealTopCard(bool _alwaysRevealTopCard) { alwaysRevealTopCard = _alwaysRevealTopCard; }
const QSet<int> &getPlayersWithWritePermission() const
{
return playersWithWritePermission;
}
bool getAlwaysRevealTopCard() const
{
return alwaysRevealTopCard;
}
void setAlwaysRevealTopCard(bool _alwaysRevealTopCard)
{
alwaysRevealTopCard = _alwaysRevealTopCard;
}
};
#endif

View file

@ -2,11 +2,7 @@
#include "pb/serverinfo_counter.pb.h"
Server_Counter::Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count)
: id(_id),
name(_name),
counterColor(_counterColor),
radius(_radius),
count(_count)
: id(_id), name(_name), counterColor(_counterColor), radius(_radius), count(_count)
{
}

View file

@ -20,28 +20,50 @@
#ifndef SERVER_COUNTER_H
#define SERVER_COUNTER_H
#include <QString>
#include "pb/color.pb.h"
#include <QString>
class ServerInfo_Counter;
class Server_Counter {
class Server_Counter
{
protected:
int id;
QString name;
color counterColor;
int radius;
int count;
public:
Server_Counter(int _id, const QString &_name, const color &_counterColor, int _radius, int _count = 0);
~Server_Counter() { }
int getId() const { return id; }
QString getName() const { return name; }
const color &getColor() const { return counterColor; }
int getRadius() const { return radius; }
int getCount() const { return count; }
void setCount(int _count) { count = _count; }
~Server_Counter()
{
}
int getId() const
{
return id;
}
QString getName() const
{
return name;
}
const color &getColor() const
{
return counterColor;
}
int getRadius() const
{
return radius;
}
int getCount() const
{
return count;
}
void setCount(int _count)
{
count = _count;
}
void getInfo(ServerInfo_Counter *info);
};

View file

@ -1,53 +1,162 @@
#ifndef SERVER_DATABASE_INTERFACE_H
#define SERVER_DATABASE_INTERFACE_H
#include <QObject>
#include "server.h"
#include <QObject>
class Server_DatabaseInterface : public QObject {
class Server_DatabaseInterface : public QObject
{
Q_OBJECT
public:
Server_DatabaseInterface(QObject *parent = 0)
: QObject(parent) { }
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, const QString &clientId, QString &reasonStr, int &secondsLeft) = 0;
virtual bool checkUserIsBanned(const QString & /* ipAddress */, const QString & /* userName */, const QString & /* clientId */, QString & /* banReason */, int & /* banSecondsRemaining */) { return false; }
virtual bool activeUserExists(const QString & /* user */) { return false; }
virtual bool userExists(const QString & /* user */) { return false; }
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
virtual bool isInBuddyList(const QString & /* whoseList */, const QString & /* who */) { return false; }
virtual bool isInIgnoreList(const QString & /* whoseList */, const QString & /* who */) { return false; }
Server_DatabaseInterface(QObject *parent = 0) : QObject(parent)
{
}
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler,
const QString &user,
const QString &password,
const QString &clientId,
QString &reasonStr,
int &secondsLeft) = 0;
virtual bool checkUserIsBanned(const QString & /* ipAddress */,
const QString & /* userName */,
const QString & /* clientId */,
QString & /* banReason */,
int & /* banSecondsRemaining */)
{
return false;
}
virtual bool activeUserExists(const QString & /* user */)
{
return false;
}
virtual bool userExists(const QString & /* user */)
{
return false;
}
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString & /* name */)
{
return QMap<QString, ServerInfo_User>();
}
virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString & /* name */)
{
return QMap<QString, ServerInfo_User>();
}
virtual bool isInBuddyList(const QString & /* whoseList */, const QString & /* who */)
{
return false;
}
virtual bool isInIgnoreList(const QString & /* whoseList */, const QString & /* who */)
{
return false;
}
virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0;
virtual void storeGameInformation(const QString & /* roomName */, const QStringList & /* roomGameTypes */, const ServerInfo_Game & /* gameInfo */, const QSet<QString> & /* allPlayersEver */, const QSet<QString> & /* allSpectatorsEver */, const QList<GameReplay *> & /* replayList */) { }
virtual DeckList *getDeckFromDatabase(int /* deckId */, int /* userId */) { return 0; }
virtual bool removeForgotPassword(const QString & /* user */) { return false; }
virtual qint64 startSession(const QString & /* userName */, const QString & /* address */, const QString & /* clientId */, const QString & /* connectionType */) { return 0; }
virtual bool usernameIsValid(const QString & /*userName */, QString & /* error */) { return true; };
virtual void storeGameInformation(const QString & /* roomName */,
const QStringList & /* roomGameTypes */,
const ServerInfo_Game & /* gameInfo */,
const QSet<QString> & /* allPlayersEver */,
const QSet<QString> & /* allSpectatorsEver */,
const QList<GameReplay *> & /* replayList */)
{
}
virtual DeckList *getDeckFromDatabase(int /* deckId */, int /* userId */)
{
return 0;
}
virtual bool removeForgotPassword(const QString & /* user */)
{
return false;
}
virtual qint64 startSession(const QString & /* userName */,
const QString & /* address */,
const QString & /* clientId */,
const QString & /* connectionType */)
{
return 0;
}
virtual bool usernameIsValid(const QString & /*userName */, QString & /* error */)
{
return true;
};
public slots:
virtual void endSession(qint64 /* sessionId */ ) { }
virtual void endSession(qint64 /* sessionId */)
{
}
public:
virtual int getNextGameId() = 0;
virtual int getNextReplayId() = 0;
virtual int getActiveUserCount(QString connectionType = QString()) = 0;
virtual void clearSessionTables() { }
virtual void lockSessionTables() { }
virtual void unlockSessionTables() { }
virtual bool userSessionExists(const QString & /* userName */) { return false; }
virtual bool getRequireRegistration() { return false; }
virtual bool registerUser(const QString & /* userName */, const QString & /* realName */, ServerInfo_User_Gender const & /* gender */, const QString & /* password */, const QString & /* emailAddress */, const QString & /* country */, bool /* active = false */) { return false; }
virtual bool activateUser(const QString & /* userName */, const QString & /* token */) { return false; }
virtual void updateUsersClientID(const QString & /* userName */, const QString & /* userClientID */) { }
virtual void updateUsersLastLoginData(const QString & /* userName */, const QString & /* clientVersion */) { }
virtual void clearSessionTables()
{
}
virtual void lockSessionTables()
{
}
virtual void unlockSessionTables()
{
}
virtual bool userSessionExists(const QString & /* userName */)
{
return false;
}
enum LogMessage_TargetType { MessageTargetRoom, MessageTargetGame, MessageTargetChat, MessageTargetIslRoom };
virtual void logMessage(const int /* senderId */, const QString & /* senderName */, const QString & /* senderIp */, const QString & /* logMessage */, LogMessage_TargetType /* targetType */, const int /* targetId */, const QString & /* targetName */) { };
virtual bool getRequireRegistration()
{
return false;
}
virtual bool registerUser(const QString & /* userName */,
const QString & /* realName */,
ServerInfo_User_Gender const & /* gender */,
const QString & /* password */,
const QString & /* emailAddress */,
const QString & /* country */,
bool /* active = false */)
{
return false;
}
virtual bool activateUser(const QString & /* userName */, const QString & /* token */)
{
return false;
}
virtual void updateUsersClientID(const QString & /* userName */, const QString & /* userClientID */)
{
}
virtual void updateUsersLastLoginData(const QString & /* userName */, const QString & /* clientVersion */)
{
}
enum LogMessage_TargetType
{
MessageTargetRoom,
MessageTargetGame,
MessageTargetChat,
MessageTargetIslRoom
};
virtual void logMessage(const int /* senderId */,
const QString & /* senderName */,
const QString & /* senderIp */,
const QString & /* logMessage */,
LogMessage_TargetType /* targetType */,
const int /* targetId */,
const QString & /* targetName */){};
bool checkUserIsBanned(Server_ProtocolHandler *session, QString &banReason, int &banSecondsRemaining);
virtual int checkNumberOfUserAccounts(const QString & /* email */) { return 0; };
virtual bool changeUserPassword(const QString & /* user */, const QString & /* oldPassword */, const QString & /* newPassword */, const bool & /* force */) { return false; };
virtual QChar getGenderChar(ServerInfo_User_Gender const & /* gender */) { return QChar('u'); };
virtual int checkNumberOfUserAccounts(const QString & /* email */)
{
return 0;
};
virtual bool changeUserPassword(const QString & /* user */,
const QString & /* oldPassword */,
const QString & /* newPassword */,
const bool & /* force */)
{
return false;
};
virtual QChar getGenderChar(ServerInfo_User_Gender const & /* gender */)
{
return QChar('u');
};
};
#endif

View file

@ -17,62 +17,56 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "server.h"
#include "server_room.h"
#include "server_game.h"
#include "server_player.h"
#include "server_protocolhandler.h"
#include "decklist.h"
#include "pb/context_connection_state_changed.pb.h"
#include "pb/context_ping_changed.pb.h"
#include "pb/event_delete_arrow.pb.h"
#include "pb/event_game_closed.pb.h"
#include "pb/event_game_host_changed.pb.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_game_state_changed.pb.h"
#include "pb/event_join.pb.h"
#include "pb/event_kicked.pb.h"
#include "pb/event_leave.pb.h"
#include "pb/event_player_properties_changed.pb.h"
#include "pb/event_replay_added.pb.h"
#include "pb/event_set_active_phase.pb.h"
#include "pb/event_set_active_player.pb.h"
#include "pb/game_replay.pb.h"
#include "pb/serverinfo_playerping.pb.h"
#include "server.h"
#include "server_arrow.h"
#include "server_card.h"
#include "server_cardzone.h"
#include "server_database_interface.h"
#include "decklist.h"
#include "pb/context_connection_state_changed.pb.h"
#include "pb/context_ping_changed.pb.h"
#include "pb/event_player_properties_changed.pb.h"
#include "pb/event_game_closed.pb.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_game_host_changed.pb.h"
#include "pb/event_game_state_changed.pb.h"
#include "pb/event_kicked.pb.h"
#include "pb/event_join.pb.h"
#include "pb/event_leave.pb.h"
#include "pb/event_delete_arrow.pb.h"
#include "pb/event_set_active_player.pb.h"
#include "pb/event_set_active_phase.pb.h"
#include "pb/serverinfo_playerping.pb.h"
#include "pb/game_replay.pb.h"
#include "pb/event_replay_added.pb.h"
#include <google/protobuf/descriptor.h>
#include <QTimer>
#include "server_player.h"
#include "server_protocolhandler.h"
#include "server_room.h"
#include <QDebug>
#include <QTimer>
#include <google/protobuf/descriptor.h>
Server_Game::Server_Game(const ServerInfo_User &_creatorInfo, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room)
: QObject(),
room(_room),
nextPlayerId(0),
hostId(0),
creatorInfo(new ServerInfo_User(_creatorInfo)),
gameStarted(false),
gameClosed(false),
gameId(_gameId),
password(_password),
maxPlayers(_maxPlayers),
gameTypes(_gameTypes),
activePlayer(-1),
activePhase(-1),
onlyBuddies(_onlyBuddies),
onlyRegistered(_onlyRegistered),
spectatorsAllowed(_spectatorsAllowed),
spectatorsNeedPassword(_spectatorsNeedPassword),
spectatorsCanTalk(_spectatorsCanTalk),
spectatorsSeeEverything(_spectatorsSeeEverything),
inactivityCounter(0),
startTimeOfThisGame(0),
secondsElapsed(0),
firstGameStarted(false),
startTime(QDateTime::currentDateTime()),
gameMutex(QMutex::Recursive)
Server_Game::Server_Game(const ServerInfo_User &_creatorInfo,
int _gameId,
const QString &_description,
const QString &_password,
int _maxPlayers,
const QList<int> &_gameTypes,
bool _onlyBuddies,
bool _onlyRegistered,
bool _spectatorsAllowed,
bool _spectatorsNeedPassword,
bool _spectatorsCanTalk,
bool _spectatorsSeeEverything,
Server_Room *_room)
: QObject(), room(_room), nextPlayerId(0), hostId(0), creatorInfo(new ServerInfo_User(_creatorInfo)),
gameStarted(false), gameClosed(false), gameId(_gameId), password(_password), maxPlayers(_maxPlayers),
gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies),
onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed),
spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk),
spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), startTimeOfThisGame(0),
secondsElapsed(0), firstGameStarted(false), startTime(QDateTime::currentDateTime()), gameMutex(QMutex::Recursive)
{
currentReplay = new GameReplay;
currentReplay->set_replay_id(room->getServer()->getDatabaseInterface()->getNextReplayId());
@ -154,14 +148,14 @@ void Server_Game::storeGameInformation()
while (allUsersIterator.hasNext()) {
Server_AbstractUserInterface *userHandler = server->findUser(allUsersIterator.next());
if (userHandler && server->getStoreReplaysEnabled())
userHandler->sendProtocolItem(*sessionEvent);
userHandler->sendProtocolItem(*sessionEvent);
}
server->clientsLock.unlock();
delete sessionEvent;
if (server->getStoreReplaysEnabled())
server->getDatabaseInterface()->storeGameInformation(room->getName(), gameTypes, gameInfo, allPlayersEver, allSpectatorsEver, replayList);
server->getDatabaseInterface()->storeGameInformation(room->getName(), gameTypes, gameInfo, allPlayersEver,
allSpectatorsEver, replayList);
}
void Server_Game::pingClockTimeout()
@ -193,7 +187,8 @@ void Server_Game::pingClockTimeout()
if ((newPingTime != -1) && !player->getSpectator())
allPlayersInactive = false;
if ((abs(oldPingTime - newPingTime) > 1) || ((newPingTime == -1) && (oldPingTime != -1)) || ((newPingTime != -1) && (oldPingTime == -1))) {
if ((abs(oldPingTime - newPingTime) > 1) || ((newPingTime == -1) && (oldPingTime != -1)) ||
((newPingTime != -1) && (oldPingTime == -1))) {
player->setPingTime(newPingTime);
Event_PlayerPropertiesChanged event;
@ -235,7 +230,10 @@ int Server_Game::getSpectatorCount() const
return result;
}
void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo)
void Server_Game::createGameStateChangedEvent(Event_GameStateChanged *event,
Server_Player *playerWhosAsking,
bool omniscient,
bool withUserInfo)
{
event->set_seconds_elapsed(secondsElapsed);
if (gameStarted) {
@ -262,8 +260,9 @@ void Server_Game::sendGameStateToPlayers()
currentReplay->add_event_list()->CopyFrom(*replayCont);
delete replayCont;
// If spectators are not omniscient, we need an additional createGameStateChangedEvent call, otherwise we can use the data we used for the replay.
// All spectators are equal, so we don't need to make a createGameStateChangedEvent call for each one.
// If spectators are not omniscient, we need an additional createGameStateChangedEvent call, otherwise we can use
// the data we used for the replay. All spectators are equal, so we don't need to make a createGameStateChangedEvent
// call for each one.
Event_GameStateChanged spectatorEvent;
if (spectatorsSeeEverything)
spectatorEvent = omniscientEvent;
@ -391,7 +390,8 @@ void Server_Game::stopGameIfFinished()
emit gameInfoChanged(gameInfo);
}
Response::ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions)
Response::ResponseCode
Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions)
{
Server_DatabaseInterface *databaseInterface = room->getServer()->getDatabaseInterface();
{
@ -406,9 +406,11 @@ Response::ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QStri
if (!(user->user_level() & ServerInfo_User::IsRegistered) && onlyRegistered)
return Response::RespUserLevelTooLow;
if (onlyBuddies && (user->name() != creatorInfo->name()))
if (!databaseInterface->isInBuddyList(QString::fromStdString(creatorInfo->name()), QString::fromStdString(user->name())))
if (!databaseInterface->isInBuddyList(QString::fromStdString(creatorInfo->name()),
QString::fromStdString(user->name())))
return Response::RespOnlyBuddies;
if (databaseInterface->isInIgnoreList(QString::fromStdString(creatorInfo->name()), QString::fromStdString(user->name())))
if (databaseInterface->isInIgnoreList(QString::fromStdString(creatorInfo->name()),
QString::fromStdString(user->name())))
return Response::RespInIgnoreList;
if (spectator) {
if (!spectatorsAllowed)
@ -432,11 +434,15 @@ bool Server_Game::containsUser(const QString &userName) const
return false;
}
void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, ResponseContainer &rc, bool spectator, bool broadcastUpdate)
void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface,
ResponseContainer &rc,
bool spectator,
bool broadcastUpdate)
{
QMutexLocker locker(&gameMutex);
Server_Player *newPlayer = new Server_Player(this, nextPlayerId++, userInterface->copyUserInfo(true, true, true), spectator, userInterface);
Server_Player *newPlayer = new Server_Player(this, nextPlayerId++, userInterface->copyUserInfo(true, true, true),
spectator, userInterface);
newPlayer->moveToThread(thread());
Event_Join joinEvent;
@ -473,7 +479,8 @@ void Server_Game::addPlayer(Server_AbstractUserInterface *userInterface, Respons
void Server_Game::removePlayer(Server_Player *player, Event_Leave::LeaveReason reason)
{
room->getServer()->removePersistentPlayer(QString::fromStdString(player->getUserInfo()->name()), room->getId(), gameId, player->getPlayerId());
room->getServer()->removePersistentPlayer(QString::fromStdString(player->getUserInfo()->name()), room->getId(),
gameId, player->getPlayerId());
players.remove(player->getPlayerId());
GameEventStorage ges;
@ -675,12 +682,15 @@ void Server_Game::createGameJoinedEvent(Server_Player *player, ResponseContainer
QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext())
playerIterator.next().value()->getInfo(event2.add_player_list(), player, player->getSpectator() && spectatorsSeeEverything, true);
playerIterator.next().value()->getInfo(event2.add_player_list(), player,
player->getSpectator() && spectatorsSeeEverything, true);
rc.enqueuePostResponseItem(ServerMessage::GAME_EVENT_CONTAINER, prepareGameEvent(event2, -1));
}
void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients, int privatePlayerId)
void Server_Game::sendGameEventContainer(GameEventContainer *cont,
GameEventStorageItem::EventRecipients recipients,
int privatePlayerId)
{
QMutexLocker locker(&gameMutex);
@ -688,8 +698,10 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStor
QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext()) {
Server_Player *p = playerIterator.next().value();
const bool playerPrivate = (p->getPlayerId() == privatePlayerId) || (p->getSpectator() && spectatorsSeeEverything);
if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) || (recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate))
const bool playerPrivate =
(p->getPlayerId() == privatePlayerId) || (p->getSpectator() && spectatorsSeeEverything);
if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) ||
(recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate))
p->sendGameEvent(*cont);
}
if (recipients.testFlag(GameEventStorageItem::SendToPrivate)) {
@ -701,7 +713,8 @@ void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStor
delete cont;
}
GameEventContainer *Server_Game::prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context)
GameEventContainer *
Server_Game::prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context)
{
GameEventContainer *cont = new GameEventContainer;
cont->set_game_id(gameId);
@ -710,7 +723,9 @@ GameEventContainer *Server_Game::prepareGameEvent(const ::google::protobuf::Mess
GameEvent *event = cont->add_event_list();
if (playerId != -1)
event->set_player_id(playerId);
event->GetReflection()->MutableMessage(event, gameEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(gameEvent);
event->GetReflection()
->MutableMessage(event, gameEvent.GetDescriptor()->FindExtensionByName("ext"))
->CopyFrom(gameEvent);
return cont;
}

View file

@ -20,16 +20,16 @@
#ifndef SERVERGAME_H
#define SERVERGAME_H
#include <QStringList>
#include <QObject>
#include <QMutex>
#include <QSet>
#include <QDateTime>
#include <QMap>
#include "server_response_containers.h"
#include "pb/event_leave.pb.h"
#include "pb/response.pb.h"
#include "pb/serverinfo_game.pb.h"
#include "pb/event_leave.pb.h"
#include "server_response_containers.h"
#include <QDateTime>
#include <QMap>
#include <QMutex>
#include <QObject>
#include <QSet>
#include <QStringList>
class QTimer;
class GameEventContainer;
@ -42,7 +42,8 @@ class ServerInfo_Game;
class Server_AbstractUserInterface;
class Event_GameStateChanged;
class Server_Game : public QObject {
class Server_Game : public QObject
{
Q_OBJECT
private:
Server_Room *room;
@ -71,8 +72,11 @@ private:
QTimer *pingClock;
QList<GameReplay *> replayList;
GameReplay *currentReplay;
void createGameStateChangedEvent(Event_GameStateChanged *event, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
void createGameStateChangedEvent(Event_GameStateChanged *event,
Server_Player *playerWhosAsking,
bool omniscient,
bool withUserInfo);
void sendGameStateToPlayers();
void storeGameInformation();
signals:
@ -81,48 +85,117 @@ signals:
private slots:
void pingClockTimeout();
void doStartGameIfReady();
public:
mutable QMutex gameMutex;
Server_Game(const ServerInfo_User &_creatorInfo, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent);
Server_Game(const ServerInfo_User &_creatorInfo,
int _gameId,
const QString &_description,
const QString &_password,
int _maxPlayers,
const QList<int> &_gameTypes,
bool _onlyBuddies,
bool _onlyRegistered,
bool _spectatorsAllowed,
bool _spectatorsNeedPassword,
bool _spectatorsCanTalk,
bool _spectatorsSeeEverything,
Server_Room *parent);
~Server_Game();
Server_Room *getRoom() const { return room; }
Server_Room *getRoom() const
{
return room;
}
void getInfo(ServerInfo_Game &result) const;
int getHostId() const { return hostId; }
ServerInfo_User *getCreatorInfo() const { return creatorInfo; }
bool getGameStarted() const { return gameStarted; }
int getHostId() const
{
return hostId;
}
ServerInfo_User *getCreatorInfo() const
{
return creatorInfo;
}
bool getGameStarted() const
{
return gameStarted;
}
int getPlayerCount() const;
int getSpectatorCount() const;
const QMap<int, Server_Player *> &getPlayers() const { return players; }
int getGameId() const { return gameId; }
QString getDescription() const { return description; }
QString getPassword() const { return password; }
int getMaxPlayers() const { return maxPlayers; }
bool getSpectatorsAllowed() const { return spectatorsAllowed; }
bool getSpectatorsNeedPassword() const { return spectatorsNeedPassword; }
bool getSpectatorsCanTalk() const { return spectatorsCanTalk; }
bool getSpectatorsSeeEverything() const { return spectatorsSeeEverything; }
Response::ResponseCode checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions);
const QMap<int, Server_Player *> &getPlayers() const
{
return players;
}
int getGameId() const
{
return gameId;
}
QString getDescription() const
{
return description;
}
QString getPassword() const
{
return password;
}
int getMaxPlayers() const
{
return maxPlayers;
}
bool getSpectatorsAllowed() const
{
return spectatorsAllowed;
}
bool getSpectatorsNeedPassword() const
{
return spectatorsNeedPassword;
}
bool getSpectatorsCanTalk() const
{
return spectatorsCanTalk;
}
bool getSpectatorsSeeEverything() const
{
return spectatorsSeeEverything;
}
Response::ResponseCode
checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions);
bool containsUser(const QString &userName) const;
void addPlayer(Server_AbstractUserInterface *userInterface, ResponseContainer &rc, bool spectator, bool broadcastUpdate = true);
void addPlayer(Server_AbstractUserInterface *userInterface,
ResponseContainer &rc,
bool spectator,
bool broadcastUpdate = true);
void removePlayer(Server_Player *player, Event_Leave::LeaveReason reason);
void removeArrowsRelatedToPlayer(GameEventStorage &ges, Server_Player *player);
void unattachCards(GameEventStorage &ges, Server_Player *player);
bool kickPlayer(int playerId);
void startGameIfReady();
void stopGameIfFinished();
int getActivePlayer() const { return activePlayer; }
int getActivePhase() const { return activePhase; }
int getActivePlayer() const
{
return activePlayer;
}
int getActivePhase() const
{
return activePhase;
}
void setActivePlayer(int _activePlayer);
void setActivePhase(int _activePhase);
void nextTurn();
int getSecondsElapsed() const { return secondsElapsed; }
int getSecondsElapsed() const
{
return secondsElapsed;
}
void createGameJoinedEvent(Server_Player *player, ResponseContainer &rc, bool resuming);
GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0);
GameEventContainer *
prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0);
GameEventContext prepareGameEventContext(const ::google::protobuf::Message &gameEventContext);
void sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int privatePlayerId = -1);
void sendGameEventContainer(GameEventContainer *cont,
GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate |
GameEventStorageItem::SendToOthers,
int privatePlayerId = -1);
};
#endif

View file

@ -3,15 +3,15 @@
#include <QMetaType>
#include "pb/serverinfo_ban.pb.h"
#include "pb/serverinfo_user.pb.h"
#include "pb/serverinfo_room.pb.h"
#include "pb/serverinfo_game.pb.h"
#include "pb/commands.pb.h"
#include "pb/response.pb.h"
#include "pb/game_event_container.pb.h"
#include "pb/isl_message.pb.h"
#include "pb/response.pb.h"
#include "pb/room_commands.pb.h"
#include "pb/serverinfo_ban.pb.h"
#include "pb/serverinfo_game.pb.h"
#include "pb/serverinfo_room.pb.h"
#include "pb/serverinfo_user.pb.h"
Q_DECLARE_METATYPE(ServerInfo_Ban)
Q_DECLARE_METATYPE(ServerInfo_User)

File diff suppressed because it is too large Load diff

View file

@ -3,13 +3,13 @@
#include "server_arrowtarget.h"
#include "serverinfo_user_container.h"
#include <QString>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QString>
#include "pb/response.pb.h"
#include "pb/card_attributes.pb.h"
#include "pb/response.pb.h"
class DeckList;
class Server_Game;
@ -61,7 +61,8 @@ class Command_DeckSelect;
class Command_SetSideboardLock;
class Command_ChangeZoneProperties;
class Server_Player : public Server_ArrowTarget, public ServerInfo_User_Container {
class Server_Player : public Server_ArrowTarget, public ServerInfo_User_Container
{
Q_OBJECT
private:
class MoveCardCompareFunctor;
@ -80,56 +81,121 @@ private:
bool readyStart;
bool conceded;
bool sideboardLocked;
public:
mutable QMutex playerMutex;
Server_Player(Server_Game *_game, int _playerId, const ServerInfo_User &_userInfo, bool _spectator, Server_AbstractUserInterface *_handler);
Server_Player(Server_Game *_game,
int _playerId,
const ServerInfo_User &_userInfo,
bool _spectator,
Server_AbstractUserInterface *_handler);
~Server_Player();
void prepareDestroy();
Server_AbstractUserInterface *getUserInterface() const { return userInterface; }
Server_AbstractUserInterface *getUserInterface() const
{
return userInterface;
}
void setUserInterface(Server_AbstractUserInterface *_userInterface);
void disconnectClient();
void setPlayerId(int _id) { playerId = _id; }
bool getReadyStart() const { return readyStart; }
void setReadyStart(bool _readyStart) { readyStart = _readyStart; }
int getPlayerId() const { return playerId; }
bool getSpectator() const { return spectator; }
bool getConceded() const { return conceded; }
void setConceded(bool _conceded) { conceded = _conceded; }
DeckList *getDeck() const { return deck; }
Server_Game *getGame() const { return game; }
const QMap<QString, Server_CardZone *> &getZones() const { return zones; }
const QMap<int, Server_Counter *> &getCounters() const { return counters; }
const QMap<int, Server_Arrow *> &getArrows() const { return arrows; }
int getPingTime() const { return pingTime; }
void setPingTime(int _pingTime) { pingTime = _pingTime; }
void setPlayerId(int _id)
{
playerId = _id;
}
bool getReadyStart() const
{
return readyStart;
}
void setReadyStart(bool _readyStart)
{
readyStart = _readyStart;
}
int getPlayerId() const
{
return playerId;
}
bool getSpectator() const
{
return spectator;
}
bool getConceded() const
{
return conceded;
}
void setConceded(bool _conceded)
{
conceded = _conceded;
}
DeckList *getDeck() const
{
return deck;
}
Server_Game *getGame() const
{
return game;
}
const QMap<QString, Server_CardZone *> &getZones() const
{
return zones;
}
const QMap<int, Server_Counter *> &getCounters() const
{
return counters;
}
const QMap<int, Server_Arrow *> &getArrows() const
{
return arrows;
}
int getPingTime() const
{
return pingTime;
}
void setPingTime(int _pingTime)
{
pingTime = _pingTime;
}
void getProperties(ServerInfo_PlayerProperties &result, bool withUserInfo);
int newCardId();
int newCounterId() const;
int newArrowId() const;
void addZone(Server_CardZone *zone);
void addArrow(Server_Arrow *arrow);
bool deleteArrow(int arrowId);
void addCounter(Server_Counter *counter);
void clearZones();
void setupZones();
Response::ResponseCode drawCards(GameEventStorage &ges, int number);
Response::ResponseCode moveCard(GameEventStorage &ges, Server_CardZone *startzone, const QList<const CardToMove *> &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces = true, bool undoingDraw = false);
Response::ResponseCode moveCard(GameEventStorage &ges,
Server_CardZone *startzone,
const QList<const CardToMove *> &_cards,
Server_CardZone *targetzone,
int x,
int y,
bool fixFreeSpaces = true,
bool undoingDraw = false);
void unattachCard(GameEventStorage &ges, Server_Card *card);
Response::ResponseCode setCardAttrHelper(GameEventStorage &ges, int targetPlayerId, const QString &zone, int cardId, CardAttribute attribute, const QString &attrValue);
Response::ResponseCode setCardAttrHelper(GameEventStorage &ges,
int targetPlayerId,
const QString &zone,
int cardId,
CardAttribute attribute,
const QString &attrValue);
Response::ResponseCode cmdLeaveGame(const Command_LeaveGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdKickFromGame(const Command_KickFromGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdKickFromGame(const Command_KickFromGame &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdConcede(const Command_Concede &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdReadyStart(const Command_ReadyStart &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeckSelect(const Command_DeckSelect &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetSideboardLock(const Command_SetSideboardLock &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdSetSideboardPlan(const Command_SetSideboardPlan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdSetSideboardLock(const Command_SetSideboardLock &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdGameSay(const Command_GameSay &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdShuffle(const Command_Shuffle &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMulligan(const Command_Mulligan &cmd, ResponseContainer &rc, GameEventStorage &ges);
@ -143,22 +209,28 @@ public:
Response::ResponseCode cmdCreateArrow(const Command_CreateArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDeleteArrow(const Command_DeleteArrow &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCardAttr(const Command_SetCardAttr &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdSetCardCounter(const Command_SetCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdIncCardCounter(const Command_IncCardCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdIncCounter(const Command_IncCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdCreateCounter(const Command_CreateCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetCounter(const Command_SetCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDelCounter(const Command_DelCounter &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdNextTurn(const Command_NextTurn &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdSetActivePhase(const Command_SetActivePhase &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdSetActivePhase(const Command_SetActivePhase &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdDumpZone(const Command_DumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdStopDumpZone(const Command_StopDumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdStopDumpZone(const Command_StopDumpZone &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRevealCards(const Command_RevealCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode
cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode processGameCommand(const GameCommand &command, ResponseContainer &rc, GameEventStorage &ges);
void sendGameEvent(const GameEventContainer &event);
void getInfo(ServerInfo_Player *info, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo);
};

View file

@ -1,17 +1,33 @@
#ifndef SERVER_PLAYER_REFERENCE_H
#define SERVER_PLAYER_REFERENCE_H
class PlayerReference {
class PlayerReference
{
private:
int roomId;
int gameId;
int playerId;
public:
PlayerReference(int _roomId, int _gameId, int _playerId) : roomId(_roomId), gameId(_gameId), playerId(_playerId) { }
int getRoomId() const { return roomId; }
int getGameId() const { return gameId; }
int getPlayerId() const { return playerId; }
bool operator==(const PlayerReference &other) { return ((roomId == other.roomId) && (gameId == other.gameId) && (playerId == other.playerId)); }
PlayerReference(int _roomId, int _gameId, int _playerId) : roomId(_roomId), gameId(_gameId), playerId(_playerId)
{
}
int getRoomId() const
{
return roomId;
}
int getGameId() const
{
return gameId;
}
int getPlayerId() const
{
return playerId;
}
bool operator==(const PlayerReference &other)
{
return ((roomId == other.roomId) && (gameId == other.gameId) && (playerId == other.playerId));
}
};
#endif

View file

@ -1,43 +1,36 @@
#include <QDebug>
#include <QDateTime>
#include <math.h>
#include "server_protocolhandler.h"
#include "server_database_interface.h"
#include "server_room.h"
#include "server_game.h"
#include "server_player.h"
#include "featureset.h"
#include "get_pb_extension.h"
#include "pb/commands.pb.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_list_rooms.pb.h"
#include "pb/event_notify_user.pb.h"
#include "pb/event_room_say.pb.h"
#include "pb/event_server_message.pb.h"
#include "pb/event_user_message.pb.h"
#include "pb/response.pb.h"
#include "pb/response_login.pb.h"
#include "pb/response_list_users.pb.h"
#include "pb/response_get_games_of_user.pb.h"
#include "pb/response_get_user_info.pb.h"
#include "pb/response_join_room.pb.h"
#include "pb/event_list_rooms.pb.h"
#include "pb/event_server_message.pb.h"
#include "pb/event_user_message.pb.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_room_say.pb.h"
#include "pb/response_list_users.pb.h"
#include "pb/response_login.pb.h"
#include "pb/serverinfo_user.pb.h"
#include "pb/event_notify_user.pb.h"
#include "server_database_interface.h"
#include "server_game.h"
#include "server_player.h"
#include "server_room.h"
#include <QDateTime>
#include <QDebug>
#include <google/protobuf/descriptor.h>
#include "featureset.h"
#include <math.h>
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server,
Server_DatabaseInterface *_databaseInterface,
QObject *parent)
: QObject(parent), Server_AbstractUserInterface(_server), deleted(false), databaseInterface(_databaseInterface),
authState(NotLoggedIn), acceptsUserListChanges(false), acceptsRoomListChanges(false),
idleClientWarningSent(false), timeRunning(0), lastDataReceived(0), lastActionReceived(0)
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent)
: QObject(parent),
Server_AbstractUserInterface(_server),
deleted(false),
databaseInterface(_databaseInterface),
authState(NotLoggedIn),
acceptsUserListChanges(false),
acceptsRoomListChanges(false),
idleClientWarningSent(false),
timeRunning(0),
lastDataReceived(0),
lastActionReceived(0)
{
connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout()));
}
@ -58,10 +51,10 @@ void Server_ProtocolHandler::prepareDestroy()
while (roomIterator.hasNext())
roomIterator.next().value()->removeClient(this);
QMap<int, QPair<int, int> > tempGames(getGames());
QMap<int, QPair<int, int>> tempGames(getGames());
server->roomsLock.lockForRead();
QMapIterator<int, QPair<int, int> > gameIterator(tempGames);
QMapIterator<int, QPair<int, int>> gameIterator(tempGames);
while (gameIterator.hasNext()) {
gameIterator.next();
@ -130,14 +123,15 @@ void Server_ProtocolHandler::sendProtocolItem(const RoomEvent &item)
transmitProtocolItem(msg);
}
Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont,
ResponseContainer &rc)
{
Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.session_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand;
const SessionCommand &sc = cont.session_command(i);
const int num = getPbExtension(sc);
if (num != SessionCommand::PING) { // don't log ping commands
if (num != SessionCommand::PING) { // don't log ping commands
if (num == SessionCommand::LOGIN) { // log login commands, but hide passwords
SessionCommand debugSc(sc);
debugSc.MutableExtension(Command_Login::ext)->clear_password();
@ -149,16 +143,33 @@ Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(co
} else
logDebugMessage(QString::fromStdString(sc.ShortDebugString()));
}
switch ((SessionCommand::SessionCommandType) num) {
case SessionCommand::PING: resp = cmdPing(sc.GetExtension(Command_Ping::ext), rc); break;
case SessionCommand::LOGIN: resp = cmdLogin(sc.GetExtension(Command_Login::ext), rc); break;
case SessionCommand::MESSAGE: resp = cmdMessage(sc.GetExtension(Command_Message::ext), rc); break;
case SessionCommand::GET_GAMES_OF_USER: resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc); break;
case SessionCommand::GET_USER_INFO: resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc); break;
case SessionCommand::LIST_ROOMS: resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc); break;
case SessionCommand::JOIN_ROOM: resp = cmdJoinRoom(sc.GetExtension(Command_JoinRoom::ext), rc); break;
case SessionCommand::LIST_USERS: resp = cmdListUsers(sc.GetExtension(Command_ListUsers::ext), rc); break;
default: resp = processExtendedSessionCommand(num, sc, rc);
switch ((SessionCommand::SessionCommandType)num) {
case SessionCommand::PING:
resp = cmdPing(sc.GetExtension(Command_Ping::ext), rc);
break;
case SessionCommand::LOGIN:
resp = cmdLogin(sc.GetExtension(Command_Login::ext), rc);
break;
case SessionCommand::MESSAGE:
resp = cmdMessage(sc.GetExtension(Command_Message::ext), rc);
break;
case SessionCommand::GET_GAMES_OF_USER:
resp = cmdGetGamesOfUser(sc.GetExtension(Command_GetGamesOfUser::ext), rc);
break;
case SessionCommand::GET_USER_INFO:
resp = cmdGetUserInfo(sc.GetExtension(Command_GetUserInfo::ext), rc);
break;
case SessionCommand::LIST_ROOMS:
resp = cmdListRooms(sc.GetExtension(Command_ListRooms::ext), rc);
break;
case SessionCommand::JOIN_ROOM:
resp = cmdJoinRoom(sc.GetExtension(Command_JoinRoom::ext), rc);
break;
case SessionCommand::LIST_USERS:
resp = cmdListUsers(sc.GetExtension(Command_ListUsers::ext), rc);
break;
default:
resp = processExtendedSessionCommand(num, sc, rc);
}
if (resp != Response::RespOk)
finalResponseCode = resp;
@ -166,7 +177,8 @@ Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(co
return finalResponseCode;
}
Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const CommandContainer &cont,
ResponseContainer &rc)
{
if (authState == NotLoggedIn)
return Response::RespLoginNeeded;
@ -184,11 +196,19 @@ Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const
const RoomCommand &sc = cont.room_command(i);
const int num = getPbExtension(sc);
logDebugMessage(QString::fromStdString(sc.ShortDebugString()));
switch ((RoomCommand::RoomCommandType) num) {
case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc); break;
case RoomCommand::ROOM_SAY: resp = cmdRoomSay(sc.GetExtension(Command_RoomSay::ext), room, rc); break;
case RoomCommand::CREATE_GAME: resp = cmdCreateGame(sc.GetExtension(Command_CreateGame::ext), room, rc); break;
case RoomCommand::JOIN_GAME: resp = cmdJoinGame(sc.GetExtension(Command_JoinGame::ext), room, rc); break;
switch ((RoomCommand::RoomCommandType)num) {
case RoomCommand::LEAVE_ROOM:
resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc);
break;
case RoomCommand::ROOM_SAY:
resp = cmdRoomSay(sc.GetExtension(Command_RoomSay::ext), room, rc);
break;
case RoomCommand::CREATE_GAME:
resp = cmdCreateGame(sc.GetExtension(Command_CreateGame::ext), room, rc);
break;
case RoomCommand::JOIN_GAME:
resp = cmdJoinGame(sc.GetExtension(Command_JoinGame::ext), room, rc);
break;
}
if (resp != Response::RespOk)
finalResponseCode = resp;
@ -196,9 +216,11 @@ Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const
return finalResponseCode;
}
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const CommandContainer &cont,
ResponseContainer &rc)
{
static QList<GameCommand::GameCommandType> antifloodCommandsWhiteList = QList<GameCommand::GameCommandType>()
static QList<GameCommand::GameCommandType> antifloodCommandsWhiteList =
QList<GameCommand::GameCommandType>()
// draw/undo card draw (example: drawing 10 cards one by one from the deck)
<< GameCommand::DRAW_CARDS
<< GameCommand::UNDO_DRAW
@ -217,7 +239,7 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
if (authState == NotLoggedIn)
return Response::RespLoginNeeded;
QMap<int, QPair<int, int> > gameMap = getGames();
QMap<int, QPair<int, int>> gameMap = getGames();
if (!gameMap.contains(cont.game_id()))
return Response::RespNotInRoom;
const QPair<int, int> roomIdAndPlayerId = gameMap.value(cont.game_id());
@ -231,12 +253,8 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
Server_Game *game = room->getGames().value(cont.game_id());
if (!game) {
if (room->getExternalGames().contains(cont.game_id())) {
server->sendIsl_GameCommand(cont,
room->getExternalGames().value(cont.game_id()).server_id(),
userInfo->session_id(),
roomIdAndPlayerId.first,
roomIdAndPlayerId.second
);
server->sendIsl_GameCommand(cont, room->getExternalGames().value(cont.game_id()).server_id(),
userInfo->session_id(), roomIdAndPlayerId.first, roomIdAndPlayerId.second);
return Response::RespNothing;
}
return Response::RespNotInRoom;
@ -255,14 +273,15 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.game_command_size() - 1; i >= 0; --i) {
const GameCommand &sc = cont.game_command(i);
logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) + QString::fromStdString(sc.ShortDebugString()));
logDebugMessage(QString("game %1 player %2: ").arg(cont.game_id()).arg(roomIdAndPlayerId.second) +
QString::fromStdString(sc.ShortDebugString()));
if (commandCountingInterval > 0) {
int totalCount = 0;
if (commandCountOverTime.isEmpty())
commandCountOverTime.prepend(0);
if(!antifloodCommandsWhiteList.contains((GameCommand::GameCommandType) getPbExtension(sc)))
if (!antifloodCommandsWhiteList.contains((GameCommand::GameCommandType)getPbExtension(sc)))
++commandCountOverTime[0];
for (int i = 0; i < commandCountOverTime.size(); ++i)
@ -282,7 +301,8 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const
return finalResponseCode;
}
Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer(const CommandContainer &cont,
ResponseContainer &rc)
{
if (!userInfo)
return Response::RespLoginNeeded;
@ -305,7 +325,8 @@ Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer(
return finalResponseCode;
}
Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(const CommandContainer &cont,
ResponseContainer &rc)
{
if (!userInfo)
return Response::RespLoginNeeded;
@ -365,7 +386,7 @@ void Server_ProtocolHandler::pingClockTimeout()
int interval = server->getMessageCountingInterval();
if (interval > 0) {
if(pingclockinterval > 0) {
if (pingclockinterval > 0) {
messageSizeOverTime.prepend(0);
if (messageSizeOverTime.size() > (msgcountinterval / pingclockinterval))
messageSizeOverTime.removeLast();
@ -394,7 +415,8 @@ void Server_ProtocolHandler::pingClockTimeout()
}
}
if (((timeRunning - lastActionReceived) >= ceil(server->getIdleClientTimeout() *.9)) && (!idleClientWarningSent) && (server->getIdleClientTimeout() > 0)) {
if (((timeRunning - lastActionReceived) >= ceil(server->getIdleClientTimeout() * .9)) &&
(!idleClientWarningSent) && (server->getIdleClientTimeout() > 0)) {
Event_NotifyUser event;
event.set_type(Event_NotifyUser::IDLEWARNING);
SessionEvent *se = prepareSessionEvent(event);
@ -414,7 +436,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdPing(const Command_Ping & /*cm
Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc)
{
QString userName = QString::fromStdString(cmd.user_name()).simplified();
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
QString clientVersion = QString::fromStdString(cmd.clientver()).simplified();
@ -430,7 +452,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
for (int i = 0; i < cmd.clientfeatures().size(); ++i)
receivedClientFeatures.insert(QString::fromStdString(cmd.clientfeatures(i)).simplified(), false);
missingClientFeatures = features.identifyMissingFeatures(receivedClientFeatures, server->getServerRequiredFeatureList());
missingClientFeatures =
features.identifyMissingFeatures(receivedClientFeatures, server->getServerRequiredFeatureList());
if (!missingClientFeatures.isEmpty()) {
if (features.isRequiredFeaturesMissing(missingClientFeatures, server->getServerRequiredFeatureList())) {
@ -447,7 +470,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
QString reasonStr;
int banSecondsLeft = 0;
QString connectionType = getConnectionType();
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr, banSecondsLeft, clientId, clientVersion, connectionType);
AuthenticationResult res = server->loginUser(this, userName, QString::fromStdString(cmd.password()), reasonStr,
banSecondsLeft, clientId, clientVersion, connectionType);
switch (res) {
case UserIsBanned: {
Response_Login *re = new Response_Login;
@ -457,18 +481,24 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
rc.setResponseExtension(re);
return Response::RespUserIsBanned;
}
case NotLoggedIn: return Response::RespWrongPassword;
case WouldOverwriteOldSession: return Response::RespWouldOverwriteOldSession;
case NotLoggedIn:
return Response::RespWrongPassword;
case WouldOverwriteOldSession:
return Response::RespWouldOverwriteOldSession;
case UsernameInvalid: {
Response_Login *re = new Response_Login;
re->set_denied_reason_str(reasonStr.toStdString());
rc.setResponseExtension(re);
return Response::RespUsernameInvalid;
}
case RegistrationRequired: return Response::RespRegistrationRequired;
case ClientIdRequired: return Response::RespClientIdRequired;
case UserIsInactive: return Response::RespAccountNotActivated;
default: authState = res;
case RegistrationRequired:
return Response::RespRegistrationRequired;
case ClientIdRequired:
return Response::RespClientIdRequired;
case UserIsInactive:
return Response::RespAccountNotActivated;
default:
authState = res;
}
// limit the number of non-privileged users that can connect to the server based on configuration settings
@ -535,12 +565,16 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message
userInterface->sendProtocolItem(*se);
rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, se);
databaseInterface->logMessage(userInfo->id(), QString::fromStdString(userInfo->name()), QString::fromStdString(userInfo->address()), QString::fromStdString(cmd.message()), Server_DatabaseInterface::MessageTargetChat, userInterface->getUserInfo()->id(), receiver);
databaseInterface->logMessage(userInfo->id(), QString::fromStdString(userInfo->name()),
QString::fromStdString(userInfo->address()), QString::fromStdString(cmd.message()),
Server_DatabaseInterface::MessageTargetChat, userInterface->getUserInfo()->id(),
receiver);
resetIdleTimer();
return Response::RespOk;
}
Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd, ResponseContainer &rc)
Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_GetGamesOfUser &cmd,
ResponseContainer &rc)
{
if (authState == NotLoggedIn)
return Response::RespLoginNeeded;
@ -581,13 +615,13 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetU
ServerInfo_User_Container *infoSource = server->findUser(userName);
if (!infoSource) {
re->mutable_user_info()->CopyFrom(databaseInterface->getUserData(userName,true));
re->mutable_user_info()->CopyFrom(databaseInterface->getUserData(userName, true));
} else {
re->mutable_user_info()->CopyFrom(infoSource->copyUserInfo(true, false, userInfo->user_level() & ServerInfo_User::IsModerator));
re->mutable_user_info()->CopyFrom(
infoSource->copyUserInfo(true, false, userInfo->user_level() & ServerInfo_User::IsModerator));
}
}
rc.setResponseExtension(re);
return Response::RespOk;
}
@ -640,7 +674,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoo
Event_RoomSay roomChatHistory;
roomChatHistory.set_message(chatMessage.sender_name() + ": " + chatMessage.message());
roomChatHistory.set_message_type(Event_RoomSay::ChatHistory);
roomChatHistory.set_time_of(QDateTime::fromString(QString::fromStdString(chatMessage.time())).toMSecsSinceEpoch());
roomChatHistory.set_time_of(
QDateTime::fromString(QString::fromStdString(chatMessage.time())).toMSecsSinceEpoch());
rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(roomChatHistory));
}
@ -672,14 +707,16 @@ Response::ResponseCode Server_ProtocolHandler::cmdListUsers(const Command_ListUs
return Response::RespOk;
}
Response::ResponseCode Server_ProtocolHandler::cmdLeaveRoom(const Command_LeaveRoom & /*cmd*/, Server_Room *room, ResponseContainer & /*rc*/)
Response::ResponseCode
Server_ProtocolHandler::cmdLeaveRoom(const Command_LeaveRoom & /*cmd*/, Server_Room *room, ResponseContainer & /*rc*/)
{
rooms.remove(room->getId());
room->removeClient(this);
return Response::RespOk;
}
Response::ResponseCode Server_ProtocolHandler::cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room, ResponseContainer & /*rc*/)
Response::ResponseCode
Server_ProtocolHandler::cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room, ResponseContainer & /*rc*/)
{
QString msg = QString::fromStdString(cmd.message());
@ -697,19 +734,23 @@ Response::ResponseCode Server_ProtocolHandler::cmdRoomSay(const Command_RoomSay
for (int i = 0; i < messageCountOverTime.size(); ++i)
totalCount += messageCountOverTime[i];
if ((totalSize > server->getMaxMessageSizePerInterval()) || (totalCount > server->getMaxMessageCountPerInterval()))
if ((totalSize > server->getMaxMessageSizePerInterval()) ||
(totalCount > server->getMaxMessageCountPerInterval()))
return Response::RespChatFlood;
}
msg.replace(QChar('\n'), QChar(' '));
room->say(QString::fromStdString(userInfo->name()), msg);
databaseInterface->logMessage(userInfo->id(), QString::fromStdString(userInfo->name()), QString::fromStdString(userInfo->address()), msg, Server_DatabaseInterface::MessageTargetRoom, room->getId(), room->getName());
databaseInterface->logMessage(userInfo->id(), QString::fromStdString(userInfo->name()),
QString::fromStdString(userInfo->address()), msg,
Server_DatabaseInterface::MessageTargetRoom, room->getId(), room->getName());
return Response::RespOk;
}
Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc)
Response::ResponseCode
Server_ProtocolHandler::cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc)
{
if (authState == NotLoggedIn)
return Response::RespLoginNeeded;
@ -731,14 +772,18 @@ Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_Creat
// When server doesn't permit registered users to exist, do not honor only-reg setting
bool onlyRegisteredUsers = cmd.only_registered() && (server->permitUnregisteredUsers());
Server_Game *game = new Server_Game(copyUserInfo(false), gameId, description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), onlyRegisteredUsers, cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), room);
Server_Game *game = new Server_Game(
copyUserInfo(false), gameId, description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes,
cmd.only_buddies(), onlyRegisteredUsers, cmd.spectators_allowed(), cmd.spectators_need_password(),
cmd.spectators_can_talk(), cmd.spectators_see_everything(), room);
game->addPlayer(this, rc, false, false);
room->addGame(game);
return Response::RespOk;
}
Response::ResponseCode Server_ProtocolHandler::cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc)
Response::ResponseCode
Server_ProtocolHandler::cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc)
{
if (authState == NotLoggedIn)
return Response::RespLoginNeeded;

View file

@ -1,12 +1,12 @@
#ifndef SERVER_PROTOCOLHANDLER_H
#define SERVER_PROTOCOLHANDLER_H
#include <QObject>
#include <QPair>
#include "server.h"
#include "server_abstractuserinterface.h"
#include "pb/response.pb.h"
#include "pb/server_message.pb.h"
#include "server.h"
#include "server_abstractuserinterface.h"
#include <QObject>
#include <QPair>
class Features;
class Server_DatabaseInterface;
@ -42,25 +42,29 @@ class Command_RoomSay;
class Command_CreateGame;
class Command_JoinGame;
class Server_ProtocolHandler : public QObject, public Server_AbstractUserInterface {
class Server_ProtocolHandler : public QObject, public Server_AbstractUserInterface
{
Q_OBJECT
protected:
QMap<int, Server_Room *> rooms;
bool deleted;
Server_DatabaseInterface *databaseInterface;
AuthenticationResult authState;
bool acceptsUserListChanges;
bool acceptsRoomListChanges;
bool idleClientWarningSent;
virtual void logDebugMessage(const QString & /* message */) { }
virtual void logDebugMessage(const QString & /* message */)
{
}
private:
QList<int> messageSizeOverTime, messageCountOverTime, commandCountOverTime;
int timeRunning, lastDataReceived, lastActionReceived;
QTimer *pingClock;
virtual void transmitProtocolItem(const ServerMessage &item) = 0;
Response::ResponseCode cmdPing(const Command_Ping &cmd, ResponseContainer &rc);
Response::ResponseCode cmdLogin(const Command_Login &cmd, ResponseContainer &rc);
Response::ResponseCode cmdMessage(const Command_Message &cmd, ResponseContainer &rc);
@ -73,39 +77,63 @@ private:
Response::ResponseCode cmdRoomSay(const Command_RoomSay &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdCreateGame(const Command_CreateGame &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedSessionCommand(int /* cmdType */, const SessionCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
virtual Response::ResponseCode
processExtendedSessionCommand(int /* cmdType */, const SessionCommand & /* cmd */, ResponseContainer & /* rc */)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedModeratorCommand(int /* cmdType */, const ModeratorCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
virtual Response::ResponseCode
processExtendedModeratorCommand(int /* cmdType */, const ModeratorCommand & /* cmd */, ResponseContainer & /* rc */)
{
return Response::RespFunctionNotAllowed;
}
Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedAdminCommand(int /* cmdType */, const AdminCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
virtual Response::ResponseCode
processExtendedAdminCommand(int /* cmdType */, const AdminCommand & /* cmd */, ResponseContainer & /* rc */)
{
return Response::RespFunctionNotAllowed;
}
void resetIdleTimer();
private slots:
void pingClockTimeout();
public slots:
void prepareDestroy();
public:
Server_ProtocolHandler(Server *_server, Server_DatabaseInterface *_databaseInterface, QObject *parent = 0);
~Server_ProtocolHandler();
bool getAcceptsUserListChanges() const { return acceptsUserListChanges; }
bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; }
bool getAcceptsUserListChanges() const
{
return acceptsUserListChanges;
}
bool getAcceptsRoomListChanges() const
{
return acceptsRoomListChanges;
}
virtual QString getAddress() const = 0;
virtual QString getConnectionType() const = 0;
Server_DatabaseInterface *getDatabaseInterface() const { return databaseInterface; }
Server_DatabaseInterface *getDatabaseInterface() const
{
return databaseInterface;
}
int getLastCommandTime() const { return timeRunning - lastDataReceived; }
int getLastCommandTime() const
{
return timeRunning - lastDataReceived;
}
void processCommandContainer(const CommandContainer &cont);
void sendProtocolItem(const Response &item);
void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item);
void sendProtocolItem(const RoomEvent &item);
};
#endif

View file

@ -1,6 +1,6 @@
#include "server_remoteuserinterface.h"
#include "server.h"
#include "pb/serverinfo_user.pb.h"
#include "server.h"
void Server_RemoteUserInterface::sendProtocolItem(const Response &item)
{

View file

@ -3,12 +3,19 @@
#include "server_abstractuserinterface.h"
class Server_RemoteUserInterface : public Server_AbstractUserInterface {
class Server_RemoteUserInterface : public Server_AbstractUserInterface
{
public:
Server_RemoteUserInterface(Server *_server, const ServerInfo_User_Container &_userInfoContainer) : Server_AbstractUserInterface(_server, _userInfoContainer) { }
int getLastCommandTime() const { return 0; }
Server_RemoteUserInterface(Server *_server, const ServerInfo_User_Container &_userInfoContainer)
: Server_AbstractUserInterface(_server, _userInfoContainer)
{
}
int getLastCommandTime() const
{
return 0;
}
void sendProtocolItem(const Response &item);
void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item);

View file

@ -1,8 +1,10 @@
#include "server_response_containers.h"
#include <google/protobuf/descriptor.h>
#include "server_game.h"
#include <google/protobuf/descriptor.h>
GameEventStorageItem::GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients)
GameEventStorageItem::GameEventStorageItem(const ::google::protobuf::Message &_event,
int _playerId,
EventRecipients _recipients)
: event(new GameEvent), recipients(_recipients)
{
event->GetReflection()->MutableMessage(event, _event.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_event);
@ -14,8 +16,7 @@ GameEventStorageItem::~GameEventStorageItem()
delete event;
}
GameEventStorage::GameEventStorage()
: gameEventContext(0), privatePlayerId(0)
GameEventStorage::GameEventStorage() : gameEventContext(0), privatePlayerId(0)
{
}
@ -30,10 +31,15 @@ void GameEventStorage::setGameEventContext(const ::google::protobuf::Message &_g
{
delete gameEventContext;
gameEventContext = new GameEventContext;
gameEventContext->GetReflection()->MutableMessage(gameEventContext, _gameEventContext.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(_gameEventContext);
gameEventContext->GetReflection()
->MutableMessage(gameEventContext, _gameEventContext.GetDescriptor()->FindExtensionByName("ext"))
->CopyFrom(_gameEventContext);
}
void GameEventStorage::enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients, int _privatePlayerId)
void GameEventStorage::enqueueGameEvent(const ::google::protobuf::Message &event,
int playerId,
GameEventStorageItem::EventRecipients recipients,
int _privatePlayerId)
{
gameEventList.append(new GameEventStorageItem(event, playerId, recipients));
if (_privatePlayerId != -1)
@ -44,7 +50,7 @@ void GameEventStorage::sendToGame(Server_Game *game)
{
if (gameEventList.isEmpty())
return;
GameEventContainer *contPrivate = new GameEventContainer;
GameEventContainer *contOthers = new GameEventContainer;
for (int i = 0; i < gameEventList.size(); ++i) {
@ -63,8 +69,7 @@ void GameEventStorage::sendToGame(Server_Game *game)
game->sendGameEventContainer(contOthers, GameEventStorageItem::SendToOthers, privatePlayerId);
}
ResponseContainer::ResponseContainer(int _cmdId)
: cmdId(_cmdId), responseExtension(0)
ResponseContainer::ResponseContainer(int _cmdId) : cmdId(_cmdId), responseExtension(0)
{
}

View file

@ -1,63 +1,119 @@
#ifndef SERVER_RESPONSE_CONTAINERS_H
#define SERVER_RESPONSE_CONTAINERS_H
#include <QPair>
#include <QList>
#include "pb/server_message.pb.h"
#include <QList>
#include <QPair>
namespace google { namespace protobuf { class Message; } }
namespace google
{
namespace protobuf
{
class Message;
}
} // namespace google
class Server_Game;
class GameEventStorageItem {
class GameEventStorageItem
{
public:
enum EventRecipient { SendToPrivate = 0x01, SendToOthers = 0x02};
enum EventRecipient
{
SendToPrivate = 0x01,
SendToOthers = 0x02
};
Q_DECLARE_FLAGS(EventRecipients, EventRecipient)
private:
GameEvent *event;
EventRecipients recipients;
public:
GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients);
~GameEventStorageItem();
const GameEvent &getGameEvent() const { return *event; }
EventRecipients getRecipients() const { return recipients; }
const GameEvent &getGameEvent() const
{
return *event;
}
EventRecipients getRecipients() const
{
return recipients;
}
};
Q_DECLARE_OPERATORS_FOR_FLAGS(GameEventStorageItem::EventRecipients)
class GameEventStorage {
class GameEventStorage
{
private:
::google::protobuf::Message *gameEventContext;
QList<GameEventStorageItem *> gameEventList;
int privatePlayerId;
public:
GameEventStorage();
~GameEventStorage();
void setGameEventContext(const ::google::protobuf::Message &_gameEventContext);
::google::protobuf::Message *getGameEventContext() const { return gameEventContext; }
const QList<GameEventStorageItem *> &getGameEventList() const { return gameEventList; }
int getPrivatePlayerId() const { return privatePlayerId; }
void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int _privatePlayerId = -1);
::google::protobuf::Message *getGameEventContext() const
{
return gameEventContext;
}
const QList<GameEventStorageItem *> &getGameEventList() const
{
return gameEventList;
}
int getPrivatePlayerId() const
{
return privatePlayerId;
}
void enqueueGameEvent(const ::google::protobuf::Message &event,
int playerId,
GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate |
GameEventStorageItem::SendToOthers,
int _privatePlayerId = -1);
void sendToGame(Server_Game *game);
};
class ResponseContainer {
class ResponseContainer
{
private:
int cmdId;
::google::protobuf::Message *responseExtension;
QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > preResponseQueue, postResponseQueue;
QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *>> preResponseQueue, postResponseQueue;
public:
ResponseContainer(int _cmdId);
~ResponseContainer();
int getCmdId() const { return cmdId; }
void setResponseExtension(::google::protobuf::Message *_responseExtension) { responseExtension = _responseExtension; }
::google::protobuf::Message *getResponseExtension() const { return responseExtension; }
void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); }
void enqueuePostResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { postResponseQueue.append(qMakePair(type, item)); }
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &getPreResponseQueue() const { return preResponseQueue; }
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &getPostResponseQueue() const { return postResponseQueue; }
int getCmdId() const
{
return cmdId;
}
void setResponseExtension(::google::protobuf::Message *_responseExtension)
{
responseExtension = _responseExtension;
}
::google::protobuf::Message *getResponseExtension() const
{
return responseExtension;
}
void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item)
{
preResponseQueue.append(qMakePair(type, item));
}
void enqueuePostResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item)
{
postResponseQueue.append(qMakePair(type, item));
}
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *>> &getPreResponseQueue() const
{
return preResponseQueue;
}
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *>> &getPostResponseQueue() const
{
return postResponseQueue;
}
};
#endif

View file

@ -1,42 +1,54 @@
#include "server_room.h"
#include "server_protocolhandler.h"
#include "server_game.h"
#include <QDebug>
#include "server_protocolhandler.h"
#include <QDateTime>
#include <QDebug>
#include "pb/commands.pb.h"
#include "pb/room_commands.pb.h"
#include "pb/event_join_room.pb.h"
#include "pb/event_leave_room.pb.h"
#include "pb/event_list_games.pb.h"
#include "pb/event_room_say.pb.h"
#include "pb/serverinfo_room.pb.h"
#include "pb/room_commands.pb.h"
#include "pb/serverinfo_chat_message.pb.h"
#include "pb/serverinfo_room.pb.h"
#include <google/protobuf/descriptor.h>
Server_Room::Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, const QString &_privilegeLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent)
: QObject(parent), id(_id), chatHistorySize(_chatHistorySize), name(_name), description(_description), permissionLevel(_permissionLevel), privilegeLevel(_privilegeLevel), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), gamesLock(QReadWriteLock::Recursive)
Server_Room::Server_Room(int _id,
int _chatHistorySize,
const QString &_name,
const QString &_description,
const QString &_permissionLevel,
const QString &_privilegeLevel,
bool _autoJoin,
const QString &_joinMessage,
const QStringList &_gameTypes,
Server *parent)
: QObject(parent), id(_id), chatHistorySize(_chatHistorySize), name(_name), description(_description),
permissionLevel(_permissionLevel), privilegeLevel(_privilegeLevel), autoJoin(_autoJoin),
joinMessage(_joinMessage), gameTypes(_gameTypes), gamesLock(QReadWriteLock::Recursive)
{
connect(this, SIGNAL(gameListChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)), Qt::QueuedConnection);
connect(this, SIGNAL(gameListChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)),
Qt::QueuedConnection);
}
Server_Room::~Server_Room()
{
qDebug("Server_Room destructor");
gamesLock.lockForWrite();
const QList<Server_Game *> gameList = games.values();
for (int i = 0; i < gameList.size(); ++i)
delete gameList[i];
games.clear();
gamesLock.unlock();
usersLock.lockForWrite();
users.clear();
usersLock.unlock();
}
bool Server_Room::userMayJoin(const ServerInfo_User & userInfo)
bool Server_Room::userMayJoin(const ServerInfo_User &userInfo)
{
if (permissionLevel.toLower() == "administrator" || permissionLevel.toLower() == "moderator")
@ -45,15 +57,11 @@ bool Server_Room::userMayJoin(const ServerInfo_User & userInfo)
if (permissionLevel.toLower() == "registered" && !(userInfo.user_level() & ServerInfo_User::IsRegistered))
return false;
if (privilegeLevel.toLower() != "none")
{
if (privilegeLevel.toLower() == "privileged")
{
if (privilegeLevel.toLower() != "none") {
if (privilegeLevel.toLower() == "privileged") {
if (privilegeLevel.toLower() == "none")
return false;
}
else
{
} else {
if (privilegeLevel.toLower() != QString::fromStdString(userInfo.privlevel()).toLower())
return false;
}
@ -66,7 +74,8 @@ Server *Server_Room::getServer() const
return static_cast<Server *>(parent());
}
const ServerInfo_Room &Server_Room::getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes, bool includeExternalData) const
const ServerInfo_Room &
Server_Room::getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes, bool includeExternalData) const
{
result.set_room_id(id);
result.set_name(name.toStdString());
@ -74,7 +83,7 @@ const ServerInfo_Room &Server_Room::getInfo(ServerInfo_Room &result, bool comple
result.set_auto_join(autoJoin);
result.set_permissionlevel(permissionLevel.toStdString());
result.set_privilegelevel(privilegeLevel.toStdString());
gamesLock.lockForRead();
result.set_game_count(games.size() + externalGames.size());
if (complete) {
@ -88,7 +97,7 @@ const ServerInfo_Room &Server_Room::getInfo(ServerInfo_Room &result, bool comple
}
}
gamesLock.unlock();
usersLock.lockForRead();
result.set_player_count(users.size() + externalUsers.size());
if (complete) {
@ -102,14 +111,14 @@ const ServerInfo_Room &Server_Room::getInfo(ServerInfo_Room &result, bool comple
}
}
usersLock.unlock();
if (complete || showGameTypes)
for (int i = 0; i < gameTypes.size(); ++i) {
ServerInfo_GameType *gameTypeInfo = result.add_gametype_list();
gameTypeInfo->set_game_type_id(i);
gameTypeInfo->set_description(gameTypes[i].toStdString());
}
return result;
}
@ -117,7 +126,9 @@ RoomEvent *Server_Room::prepareRoomEvent(const ::google::protobuf::Message &room
{
RoomEvent *event = new RoomEvent;
event->set_room_id(id);
event->GetReflection()->MutableMessage(event, roomEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(roomEvent);
event->GetReflection()
->MutableMessage(event, roomEvent.GetDescriptor()->FindExtensionByName("ext"))
->CopyFrom(roomEvent);
return event;
}
@ -126,21 +137,21 @@ void Server_Room::addClient(Server_ProtocolHandler *client)
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(client->copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event));
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
usersLock.lockForWrite();
users.insert(QString::fromStdString(client->getUserInfo()->name()), client);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// XXX This can be removed during the next client update.
gamesLock.lockForRead();
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
}
@ -148,22 +159,22 @@ void Server_Room::removeClient(Server_ProtocolHandler *client)
{
usersLock.lockForWrite();
users.remove(QString::fromStdString(client->getUserInfo()->name()));
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
Event_LeaveRoom event;
event.set_name(client->getUserInfo()->name());
sendRoomEvent(prepareRoomEvent(event));
// XXX This can be removed during the next client update.
gamesLock.lockForRead();
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
}
@ -174,7 +185,7 @@ void Server_Room::addExternalUser(const ServerInfo_User &userInfo)
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(userInfoContainer.copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event), false);
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
@ -182,7 +193,7 @@ void Server_Room::addExternalUser(const ServerInfo_User &userInfo)
externalUsers.insert(QString::fromStdString(userInfo.name()), userInfoContainer);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
emit roomInfoChanged(roomInfo);
}
@ -191,17 +202,17 @@ void Server_Room::removeExternalUser(const QString &name)
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
usersLock.lockForWrite();
if (externalUsers.contains(name))
externalUsers.remove(name);
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
Event_LeaveRoom event;
event.set_name(name.toStdString());
sendRoomEvent(prepareRoomEvent(event), false);
emit roomInfoChanged(roomInfo);
}
@ -210,7 +221,7 @@ void Server_Room::updateExternalGameList(const ServerInfo_Game &gameInfo)
// This function is always called from the Server thread with server->roomsMutex locked.
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
gamesLock.lockForWrite();
if (!gameInfo.has_player_count() && externalGames.contains(gameInfo.game_id()))
externalGames.remove(gameInfo.game_id());
@ -218,16 +229,18 @@ void Server_Room::updateExternalGameList(const ServerInfo_Game &gameInfo)
externalGames.insert(gameInfo.game_id(), gameInfo);
roomInfo.set_game_count(games.size() + externalGames.size());
gamesLock.unlock();
broadcastGameListUpdate(gameInfo, false);
emit roomInfoChanged(roomInfo);
}
Response::ResponseCode Server_Room::processJoinGameCommand(const Command_JoinGame &cmd, ResponseContainer &rc, Server_AbstractUserInterface *userInterface)
Response::ResponseCode Server_Room::processJoinGameCommand(const Command_JoinGame &cmd,
ResponseContainer &rc,
Server_AbstractUserInterface *userInterface)
{
// This function is called from the Server thread and from the S_PH thread.
// server->roomsMutex is always locked.
QReadLocker roomGamesLocker(&gamesLock);
Server_Game *g = games.value(cmd.game_id());
if (!g) {
@ -235,31 +248,34 @@ Response::ResponseCode Server_Room::processJoinGameCommand(const Command_JoinGam
CommandContainer cont;
cont.set_cmd_id(rc.getCmdId());
RoomCommand *roomCommand = cont.add_room_command();
roomCommand->GetReflection()->MutableMessage(roomCommand, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
getServer()->sendIsl_RoomCommand(cont, externalGames.value(cmd.game_id()).server_id(), userInterface->getUserInfo()->session_id(), id);
roomCommand->GetReflection()
->MutableMessage(roomCommand, cmd.GetDescriptor()->FindExtensionByName("ext"))
->CopyFrom(cmd);
getServer()->sendIsl_RoomCommand(cont, externalGames.value(cmd.game_id()).server_id(),
userInterface->getUserInfo()->session_id(), id);
return Response::RespNothing;
} else
return Response::RespNameNotFound;
}
QMutexLocker gameLocker(&g->gameMutex);
Response::ResponseCode result = g->checkJoin(userInterface->getUserInfo(), QString::fromStdString(cmd.password()), cmd.spectator(), cmd.override_restrictions());
Response::ResponseCode result = g->checkJoin(userInterface->getUserInfo(), QString::fromStdString(cmd.password()),
cmd.spectator(), cmd.override_restrictions());
if (result == Response::RespOk)
g->addPlayer(userInterface, rc, cmd.spectator());
return result;
}
void Server_Room::say(const QString &userName, const QString &s, bool sendToIsl)
{
Event_RoomSay event;
event.set_name(userName.toStdString());
event.set_message(s.toStdString());
sendRoomEvent(prepareRoomEvent(event), sendToIsl);
if (chatHistorySize != 0) {
ServerInfo_ChatMessage chatMessage;
QDateTime dateTime = dateTime.currentDateTimeUtc();
@ -275,7 +291,6 @@ void Server_Room::say(const QString &userName, const QString &s, bool sendToIsl)
chatHistory << chatMessage;
historyLock.unlock();
}
}
void Server_Room::sendRoomEvent(RoomEvent *event, bool sendToIsl)
@ -287,10 +302,10 @@ void Server_Room::sendRoomEvent(RoomEvent *event, bool sendToIsl)
userIterator.next().value()->sendProtocolItem(*event);
}
usersLock.unlock();
if (sendToIsl)
static_cast<Server *>(parent())->sendIsl_RoomEvent(*event);
delete event;
}
@ -305,10 +320,10 @@ void Server_Room::addGame(Server_Game *game)
{
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
gamesLock.lockForWrite();
connect(game, SIGNAL(gameInfoChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)));
game->gameMutex.lock();
games.insert(game->getGameId(), game);
ServerInfo_Game gameInfo;
@ -316,7 +331,7 @@ void Server_Room::addGame(Server_Game *game)
roomInfo.set_game_count(games.size() + externalGames.size());
game->gameMutex.unlock();
gamesLock.unlock();
// XXX This can be removed during the next client update.
usersLock.lockForRead();
roomInfo.set_player_count(users.size() + externalUsers.size());
@ -331,32 +346,32 @@ void Server_Room::removeGame(Server_Game *game)
{
// No need to lock gamesLock or gameMutex. This method is only
// called from ~Server_Game, which locks both mutexes anyway beforehand.
disconnect(game, 0, this, 0);
ServerInfo_Game gameInfo;
game->getInfo(gameInfo);
emit gameListChanged(gameInfo);
games.remove(game->getGameId());
ServerInfo_Room roomInfo;
roomInfo.set_room_id(id);
roomInfo.set_game_count(games.size() + externalGames.size());
// XXX This can be removed during the next client update.
usersLock.lockForRead();
roomInfo.set_player_count(users.size() + externalUsers.size());
usersLock.unlock();
// -----------
emit roomInfoChanged(roomInfo);
}
int Server_Room::getGamesCreatedByUser(const QString &userName) const
{
QReadLocker locker(&gamesLock);
QMapIterator<int, Server_Game *> gamesIterator(games);
int result = 0;
while (gamesIterator.hasNext())
@ -368,7 +383,7 @@ int Server_Room::getGamesCreatedByUser(const QString &userName) const
QList<ServerInfo_Game> Server_Room::getGamesOfUser(const QString &userName) const
{
QReadLocker locker(&gamesLock);
QList<ServerInfo_Game> result;
QMapIterator<int, Server_Game *> gamesIterator(games);
while (gamesIterator.hasNext()) {

View file

@ -1,15 +1,15 @@
#ifndef SERVER_ROOM_H
#define SERVER_ROOM_H
#include <QList>
#include <QMap>
#include <QObject>
#include <QStringList>
#include <QMutex>
#include <QReadWriteLock>
#include "serverinfo_user_container.h"
#include "pb/response.pb.h"
#include "pb/serverinfo_chat_message.pb.h"
#include "serverinfo_user_container.h"
#include <QList>
#include <QMap>
#include <QMutex>
#include <QObject>
#include <QReadWriteLock>
#include <QStringList>
class Server_DatabaseInterface;
class Server_ProtocolHandler;
@ -24,11 +24,13 @@ class Command_JoinGame;
class ResponseContainer;
class Server_AbstractUserInterface;
class Server_Room : public QObject {
class Server_Room : public QObject
{
Q_OBJECT
signals:
void roomInfoChanged(const ServerInfo_Room &roomInfo);
void gameListChanged(const ServerInfo_Game &gameInfo);
private:
int id;
int chatHistorySize;
@ -46,44 +48,93 @@ private:
QList<ServerInfo_ChatMessage> chatHistory;
private slots:
void broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl = true);
public:
mutable QReadWriteLock usersLock;
mutable QReadWriteLock gamesLock;
mutable QReadWriteLock historyLock;
Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, const QString &_privilegeLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent );
Server_Room(int _id,
int _chatHistorySize,
const QString &_name,
const QString &_description,
const QString &_permissionLevel,
const QString &_privilegeLevel,
bool _autoJoin,
const QString &_joinMessage,
const QStringList &_gameTypes,
Server *parent);
~Server_Room();
int getId() const { return id; }
QString getName() const { return name; }
QString getDescription() const { return description; }
QString getRoomPermission() const { return permissionLevel; }
QString getRoomPrivilege() const { return privilegeLevel; }
bool getAutoJoin() const { return autoJoin; }
int getId() const
{
return id;
}
QString getName() const
{
return name;
}
QString getDescription() const
{
return description;
}
QString getRoomPermission() const
{
return permissionLevel;
}
QString getRoomPrivilege() const
{
return privilegeLevel;
}
bool getAutoJoin() const
{
return autoJoin;
}
bool userMayJoin(const ServerInfo_User &userInfo);
QString getJoinMessage() const { return joinMessage; }
const QStringList &getGameTypes() const { return gameTypes; }
const QMap<int, Server_Game *> &getGames() const { return games; }
const QMap<int, ServerInfo_Game> &getExternalGames() const { return externalGames; }
QString getJoinMessage() const
{
return joinMessage;
}
const QStringList &getGameTypes() const
{
return gameTypes;
}
const QMap<int, Server_Game *> &getGames() const
{
return games;
}
const QMap<int, ServerInfo_Game> &getExternalGames() const
{
return externalGames;
}
Server *getServer() const;
const ServerInfo_Room &getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes = false, bool includeExternalData = true) const;
const ServerInfo_Room &
getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes = false, bool includeExternalData = true) const;
int getGamesCreatedByUser(const QString &name) const;
QList<ServerInfo_Game> getGamesOfUser(const QString &name) const;
QList<ServerInfo_ChatMessage> & getChatHistory() { return chatHistory; }
QList<ServerInfo_ChatMessage> &getChatHistory()
{
return chatHistory;
}
void addClient(Server_ProtocolHandler *client);
void removeClient(Server_ProtocolHandler *client);
void addExternalUser(const ServerInfo_User &userInfo);
void removeExternalUser(const QString &name);
const QMap<QString, ServerInfo_User_Container> &getExternalUsers() const { return externalUsers; }
const QMap<QString, ServerInfo_User_Container> &getExternalUsers() const
{
return externalUsers;
}
void updateExternalGameList(const ServerInfo_Game &gameInfo);
Response::ResponseCode processJoinGameCommand(const Command_JoinGame &cmd, ResponseContainer &rc, Server_AbstractUserInterface *userInterface);
Response::ResponseCode processJoinGameCommand(const Command_JoinGame &cmd,
ResponseContainer &rc,
Server_AbstractUserInterface *userInterface);
void say(const QString &userName, const QString &s, bool sendToIsl = true);
void addGame(Server_Game *game);
void removeGame(Server_Game *game);
void sendRoomEvent(RoomEvent *event, bool sendToIsl = true);
RoomEvent *prepareRoomEvent(const ::google::protobuf::Message &roomEvent);
};

View file

@ -1,8 +1,7 @@
#include "serverinfo_user_container.h"
#include "pb/serverinfo_user.pb.h"
ServerInfo_User_Container::ServerInfo_User_Container(ServerInfo_User *_userInfo)
: userInfo(_userInfo)
ServerInfo_User_Container::ServerInfo_User_Container(ServerInfo_User *_userInfo) : userInfo(_userInfo)
{
}
@ -29,7 +28,10 @@ void ServerInfo_User_Container::setUserInfo(const ServerInfo_User &_userInfo)
userInfo = new ServerInfo_User(_userInfo);
}
ServerInfo_User &ServerInfo_User_Container::copyUserInfo(ServerInfo_User &result, bool complete, bool internalInfo, bool sessionInfo) const
ServerInfo_User &ServerInfo_User_Container::copyUserInfo(ServerInfo_User &result,
bool complete,
bool internalInfo,
bool sessionInfo) const
{
if (userInfo) {
result.CopyFrom(*userInfo);
@ -38,15 +40,14 @@ ServerInfo_User &ServerInfo_User_Container::copyUserInfo(ServerInfo_User &result
result.clear_address();
result.clear_clientid();
}
if (!internalInfo)
{
if (!internalInfo) {
result.clear_id();
result.clear_email();
}
if (!complete)
result.clear_avatar_bmp();
}
return result;
return result;
}
ServerInfo_User ServerInfo_User_Container::copyUserInfo(bool complete, bool internalInfo, bool sessionInfo) const

View file

@ -3,17 +3,23 @@
class ServerInfo_User;
class ServerInfo_User_Container {
class ServerInfo_User_Container
{
protected:
ServerInfo_User *userInfo;
public:
ServerInfo_User_Container(ServerInfo_User *_userInfo = 0);
ServerInfo_User_Container(const ServerInfo_User &_userInfo);
ServerInfo_User_Container(const ServerInfo_User_Container &other);
virtual ~ServerInfo_User_Container();
ServerInfo_User *getUserInfo() const { return userInfo; }
ServerInfo_User *getUserInfo() const
{
return userInfo;
}
void setUserInfo(const ServerInfo_User &_userInfo);
ServerInfo_User &copyUserInfo(ServerInfo_User &result, bool complete, bool internalInfo = false, bool sessionInfo = false) const;
ServerInfo_User &
copyUserInfo(ServerInfo_User &result, bool complete, bool internalInfo = false, bool sessionInfo = false) const;
ServerInfo_User copyUserInfo(bool complete, bool internalInfo = false, bool sessionInfo = false) const;
};