diff --git a/.travis.yml b/.travis.yml index 803f316c..74f6feff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,6 @@ os: compiler: - gcc - clang -script: mkdir build && cd build && cmake .. && make +script: mkdir build && cd build && cmake .. -DWITH_SERVER=1 && make install: ./travis-dependencies.sh cache: apt diff --git a/CMakeLists.txt b/CMakeLists.txt index 8542836a..6f19f769 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,7 @@ IF(MSVC) ELSEIF (CMAKE_COMPILER_IS_GNUCXX) # linux/gcc, bsd/gcc, windows/mingw set(CMAKE_CXX_FLAGS_RELEASE "-s -O2") - set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0") + set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -W-noerror=sign-compare -Wno-error=reorder -Wno-error=missing-declarations") ELSE() # other: osx/llvm, bsd/llvm set(CMAKE_CXX_FLAGS_RELEASE "-O2") diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index 130c85b5..4dc9af2b 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -31,7 +31,7 @@ enum ClientStatus { StatusConnecting, StatusAwaitingWelcome, StatusLoggingIn, - StatusLoggedIn, + StatusLoggedIn }; class AbstractClient : public QObject { diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 5a942b0f..eff101f9 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -16,7 +16,7 @@ const int CardDatabase::versionNeeded = 3; -QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardSet *set) +static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardSet *set) { xml.writeStartElement("set"); xml.writeTextElement("name", set->getShortName()); @@ -275,18 +275,18 @@ CardInfo::CardInfo(CardDatabase *_db, bool _cipt, int _tableRow, const SetList &_sets, - QMap _muIds) + MuidMap _muIds) : db(_db), name(_name), isToken(_isToken), sets(_sets), - muIds(_muIds), manacost(_manacost), cardtype(_cardtype), powtough(_powtough), text(_text), colors(_colors), loyalty(_loyalty), + muIds(_muIds), cipt(_cipt), tableRow(_tableRow), pixmap(NULL) @@ -434,7 +434,7 @@ int CardInfo::getPreferredMuId() return muIds[getPreferredSet()->getShortName()]; } -QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) +static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) { xml.writeStartElement("card"); xml.writeTextElement("name", info->getName()); @@ -473,7 +473,7 @@ QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) } CardDatabase::CardDatabase(QObject *parent) - : QObject(parent), loadStatus(NotLoaded), noCard(0) + : QObject(parent), noCard(0), loadStatus(NotLoaded) { connect(settingsCache, SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged())); connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase())); @@ -610,7 +610,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) if (xml.name() == "card") { QString name, manacost, type, pt, text; QStringList colors; - QMap muids; + MuidMap muids; SetList sets; int tableRow = 0; int loyalty = 0; diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 70d77bca..09edeff4 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -20,6 +20,9 @@ class QNetworkRequest; typedef QMap QStringMap; +// If we don't typedef this, CardInfo::CardInfo will refuse to compile on OS X < 10.9 +typedef QMap MuidMap; + class CardSet : public QList { private: QString shortName, longName; @@ -100,7 +103,7 @@ private: QString text; QStringList colors; int loyalty; - QMap muIds; + MuidMap muIds; bool cipt; int tableRow; QPixmap *pixmap; @@ -118,7 +121,7 @@ public: bool _cipt = false, int _tableRow = 0, const SetList &_sets = SetList(), - QMap muids = QMap()); + MuidMap muids = MuidMap()); ~CardInfo(); const QString &getName() const { return name; } bool getIsToken() const { return isToken; } diff --git a/cockatrice/src/cardfilter.h b/cockatrice/src/cardfilter.h index 47a85ea6..e5f88123 100644 --- a/cockatrice/src/cardfilter.h +++ b/cockatrice/src/cardfilter.h @@ -26,9 +26,9 @@ public: }; private: + QString trm; enum Type t; enum Attr a; - QString trm; public: CardFilter(QString term, Type type, Attr attr) : trm(term), t(type), a(attr) {}; diff --git a/cockatrice/src/decklistmodel.cpp b/cockatrice/src/decklistmodel.cpp index de18a9c5..ec10ff05 100644 --- a/cockatrice/src/decklistmodel.cpp +++ b/cockatrice/src/decklistmodel.cpp @@ -342,6 +342,9 @@ void DeckListModel::sort(int column, Qt::SortOrder order) break; case 2: sortMethod = ByPrice; + break; + default: + sortMethod = ByName; } root->setSortMethod(sortMethod); sortHelper(root, order); diff --git a/cockatrice/src/filtertree.h b/cockatrice/src/filtertree.h index 9a5fc531..a6c4536d 100644 --- a/cockatrice/src/filtertree.h +++ b/cockatrice/src/filtertree.h @@ -66,7 +66,7 @@ public: const CardFilter::Attr attr; LogicMap(CardFilter::Attr a, FilterTree *parent) - : attr(a), p(parent) {} + : p(parent), attr(a) {} const FilterItemList *findTypeList(CardFilter::Type type) const; FilterItemList *typeList(CardFilter::Type type); FilterTreeNode *parent() const; @@ -81,7 +81,7 @@ public: const CardFilter::Type type; FilterItemList(CardFilter::Type t, LogicMap *parent) - : type(t), p(parent) {} + : p(parent), type(t) {} CardFilter::Attr attr() const { return p->attr; } FilterTreeNode *parent() const { return p; } int termIndex(const QString &term) const; diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp index 84765814..b7e2c0ea 100644 --- a/cockatrice/src/main.cpp +++ b/cockatrice/src/main.cpp @@ -56,7 +56,7 @@ QString translationPath = QString(); #endif #if QT_VERSION < 0x050000 -void myMessageOutput(QtMsgType /*type*/, const char *msg) +static void myMessageOutput(QtMsgType /*type*/, const char *msg) { QFile file("qdebug.txt"); file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text); @@ -65,7 +65,7 @@ void myMessageOutput(QtMsgType /*type*/, const char *msg) file.close(); } #else -void myMessageOutput(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg) +static void myMessageOutput(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg) { QFile file("qdebug.txt"); file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text); diff --git a/cockatrice/src/main.h b/cockatrice/src/main.h index 4a1d234f..9237f23c 100644 --- a/cockatrice/src/main.h +++ b/cockatrice/src/main.h @@ -13,4 +13,6 @@ extern QString translationPath; void installNewTranslator(); +bool settingsValid(); + #endif diff --git a/cockatrice/src/messagelogwidget.cpp b/cockatrice/src/messagelogwidget.cpp index ec9b90cb..d40b1068 100644 --- a/cockatrice/src/messagelogwidget.cpp +++ b/cockatrice/src/messagelogwidget.cpp @@ -86,12 +86,16 @@ void MessageLogWidget::logLeaveSpectator(QString name) appendHtml(tr("%1 is not watching the game any more.").arg(sanitizeHtml(name))); } -void MessageLogWidget::logDeckSelect(Player *player, QString deckHash) +void MessageLogWidget::logDeckSelect(Player *player, QString deckHash, int sideboardSize) { - if (isFemale(player)) - appendHtml(tr("%1 has loaded a deck (%2).", "female").arg(sanitizeHtml(player->getName())).arg(deckHash)); + const char* gender = isFemale(player) ? "female" : "male"; + if (sideboardSize < 0) + appendHtml(tr("%1 has loaded a deck (%2).", gender).arg(sanitizeHtml(player->getName())).arg(deckHash)); else - appendHtml(tr("%1 has loaded a deck (%2).", "male").arg(sanitizeHtml(player->getName())).arg(deckHash)); + appendHtml(tr("%1 has loaded a deck with %2 sideboard cards (%3).", gender). + arg(sanitizeHtml(player->getName())). + arg(sideboardSize). + arg(deckHash)); } void MessageLogWidget::logReadyStart(Player *player) diff --git a/cockatrice/src/messagelogwidget.h b/cockatrice/src/messagelogwidget.h index 1747a338..2b12b3c5 100644 --- a/cockatrice/src/messagelogwidget.h +++ b/cockatrice/src/messagelogwidget.h @@ -48,7 +48,7 @@ public slots: void logKicked(); void logJoinSpectator(QString name); void logLeaveSpectator(QString name); - void logDeckSelect(Player *player, QString deckHash); + void logDeckSelect(Player *player, QString deckHash, int sideboardSize); void logReadyStart(Player *player); void logNotReadyStart(Player *player); void logSetSideboardLock(Player *player, bool locked); diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index cee00037..b99fff02 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -1012,7 +1012,10 @@ void TabGame::eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged & break; } case GameEventContext::DECK_SELECT: { - messageLog->logDeckSelect(player, QString::fromStdString(context.GetExtension(Context_DeckSelect::ext).deck_hash())); + Context_DeckSelect deckSelect = context.GetExtension(Context_DeckSelect::ext); + messageLog->logDeckSelect(player, + QString::fromStdString(deckSelect.deck_hash()), + deckSelect.sideboard_size()); break; } case GameEventContext::SET_SIDEBOARD_LOCK: { diff --git a/common/decklist.cpp b/common/decklist.cpp index e81a0629..90b5cb7e 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -180,6 +180,7 @@ bool InnerDecklistNode::compare(AbstractDecklistNode *other) const case 2: return comparePrice(other); } + return 0; } bool InnerDecklistNode::compareNumber(AbstractDecklistNode *other) const @@ -226,6 +227,7 @@ bool AbstractDecklistCardNode::compare(AbstractDecklistNode *other) const case ByPrice: return compareTotalPrice(other); } + return 0; } bool AbstractDecklistCardNode::compareNumber(AbstractDecklistNode *other) const @@ -351,6 +353,7 @@ DeckList::DeckList() root = new InnerDecklistNode; } +// TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator DeckList::DeckList(const DeckList &other) : name(other.name), comments(other.comments), @@ -630,12 +633,27 @@ QStringList DeckList::getCardList() const return result.toList(); } +int DeckList::getSideboardSize() const +{ + int size = 0; + for (int i = 0; i < root->size(); ++i) { + InnerDecklistNode *node = dynamic_cast(root->at(i)); + if (node->getName() != "side") + continue; + for (int j = 0; j < node->size(); j++) { + DecklistCardNode *card = dynamic_cast(node->at(j)); + size += card->getNumber(); + } + } + return size; +} + DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zoneName) { InnerDecklistNode *zoneNode = dynamic_cast(root->findChild(zoneName)); if (!zoneNode) zoneNode = new InnerDecklistNode(zoneName, root); - + DecklistCardNode *node = new DecklistCardNode(cardName, 1, zoneNode); updateDeckHash(); return node; diff --git a/common/decklist.h b/common/decklist.h index 94df407a..2eed52fc 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -160,7 +160,9 @@ public: void cleanList(); bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); } QStringList getCardList() const; - + + int getSideboardSize() const; + QString getDeckHash() const { return deckHash; } void updateDeckHash(); diff --git a/common/pb/context_deck_select.proto b/common/pb/context_deck_select.proto index df4a95b5..f36c8b6c 100644 --- a/common/pb/context_deck_select.proto +++ b/common/pb/context_deck_select.proto @@ -1,8 +1,9 @@ import "game_event_context.proto"; message Context_DeckSelect { - extend GameEventContext { - optional Context_DeckSelect ext = 1002; - } - optional string deck_hash = 1; + extend GameEventContext { + optional Context_DeckSelect ext = 1002; + } + optional string deck_hash = 1; + optional int32 sideboard_size = 2 [default = -1]; } diff --git a/common/server_player.cpp b/common/server_player.cpp index a029abed..76cd260d 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -657,6 +657,7 @@ Response::ResponseCode Server_Player::cmdDeckSelect(const Command_DeckSelect &cm Context_DeckSelect context; context.set_deck_hash(deck->getDeckHash().toStdString()); + context.set_sideboard_size(deck->getSideboardSize()); ges.setGameEventContext(context); Response_DeckDownload *re = new Response_DeckDownload; diff --git a/common/server_response_containers.cpp b/common/server_response_containers.cpp index 8b6d2730..bc36222e 100644 --- a/common/server_response_containers.cpp +++ b/common/server_response_containers.cpp @@ -64,7 +64,7 @@ void GameEventStorage::sendToGame(Server_Game *game) } ResponseContainer::ResponseContainer(int _cmdId) - : responseExtension(0), cmdId(_cmdId) + : cmdId(_cmdId), responseExtension(0) { } diff --git a/oracle/src/oracleimporter.h b/oracle/src/oracleimporter.h index 1f705eeb..4c36a211 100644 --- a/oracle/src/oracleimporter.h +++ b/oracle/src/oracleimporter.h @@ -17,7 +17,7 @@ public: bool getImport() const { return import; } void setImport(bool _import) { import = _import; } SetToDownload(const QString &_shortName, const QString &_longName, const QVariant &_cards, bool _import) - : shortName(_shortName), longName(_longName), cards(_cards), import(_import) { } + : shortName(_shortName), longName(_longName), import(_import), cards(_cards) { } bool operator<(const SetToDownload &set) const { return longName.compare(set.longName, Qt::CaseInsensitive) < 0; } }; diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index bce91360..c50ff9f1 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -5,6 +5,8 @@ logfile=server.log name="My Cockatrice server" id=1 number_pools=1 +writelog=1 +logfilters="" [servernetwork] active=0 diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index 3eac4f36..2dbbc5e5 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #ifdef Q_OS_UNIX # include @@ -11,99 +12,122 @@ #endif ServerLogger::ServerLogger(bool _logToConsole, QObject *parent) - : QObject(parent), logToConsole(_logToConsole), flushRunning(false) + : QObject(parent), logToConsole(_logToConsole), flushRunning(false) { } ServerLogger::~ServerLogger() { - flushBuffer(); - // This does not work with the destroyed() signal as this destructor is called after the main event loop is done. - thread()->quit(); + flushBuffer(); + // This does not work with the destroyed() signal as this destructor is called after the main event loop is done. + thread()->quit(); } void ServerLogger::startLog(const QString &logFileName) { - if (!logFileName.isEmpty()) { - logFile = new QFile("server.log", this); - logFile->open(QIODevice::Append); + if (!logFileName.isEmpty()) { + logFile = new QFile("server.log", this); + logFile->open(QIODevice::Append); #ifdef Q_OS_UNIX - ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); + ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); - snHup = new QSocketNotifier(sigHupFD[1], QSocketNotifier::Read, this); - connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup())); + snHup = new QSocketNotifier(sigHupFD[1], QSocketNotifier::Read, this); + connect(snHup, SIGNAL(activated(int)), this, SLOT(handleSigHup())); #endif - } else - logFile = 0; - - connect(this, SIGNAL(sigFlushBuffer()), this, SLOT(flushBuffer()), Qt::QueuedConnection); + } else + logFile = 0; + + connect(this, SIGNAL(sigFlushBuffer()), this, SLOT(flushBuffer()), Qt::QueuedConnection); } void ServerLogger::logMessage(QString message, void *caller) { - if (!logFile) - return; - - bufferMutex.lock(); - QString callerString; - if (caller) - callerString = QString::number((qulonglong) caller, 16) + " "; - buffer.append(QDateTime::currentDateTime().toString() + " " + callerString + message); - bufferMutex.unlock(); - - emit sigFlushBuffer(); + if (!logFile) + return; + + QString callerString; + if (caller) + callerString = QString::number((qulonglong) caller, 16) + " "; + + //filter out all log entries based on values in configuration file + QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat); + bool shouldWeWriteLog = settings->value("server/writelog").toBool(); + QString logFilters = settings->value("server/logfilters").toString(); + QStringList listlogFilters = logFilters.split(",", QString::SkipEmptyParts); + bool shouldWeSkipLine = false; + + if (!shouldWeWriteLog) + return; + + if (!logFilters.trimmed().isEmpty()){ + shouldWeSkipLine = true; + foreach(QString logFilter, listlogFilters){ + if (message.contains(logFilter, Qt::CaseInsensitive)){ + shouldWeSkipLine = false; + break; + } + } + } + + if (shouldWeSkipLine) + return; + + bufferMutex.lock(); + buffer.append(QDateTime::currentDateTime().toString() + " " + callerString + message); + bufferMutex.unlock(); + emit sigFlushBuffer(); } void ServerLogger::flushBuffer() { - if (flushRunning) - return; - - flushRunning = true; - QTextStream stream(logFile); - forever { - bufferMutex.lock(); - if (buffer.isEmpty()) { - bufferMutex.unlock(); - flushRunning = false; - return; - } - QString message = buffer.takeFirst(); - bufferMutex.unlock(); - - stream << message << "\n"; - stream.flush(); - - if (logToConsole) - std::cout << message.toStdString() << std::endl; - } + if (flushRunning) + return; + + flushRunning = true; + QTextStream stream(logFile); + forever { + bufferMutex.lock(); + if (buffer.isEmpty()) { + bufferMutex.unlock(); + flushRunning = false; + return; + } + QString message = buffer.takeFirst(); + bufferMutex.unlock(); + + stream << message << "\n"; + stream.flush(); + + if (logToConsole) + std::cout << message.toStdString() << std::endl; + } } void ServerLogger::hupSignalHandler(int /*unused*/) { #ifdef Q_OS_UNIX - if (!logFile) - return; - - char a = 1; - ::write(sigHupFD[0], &a, sizeof(a)); + if (!logFile) + return; + + char a = 1; + ::write(sigHupFD[0], &a, sizeof(a)); #endif } void ServerLogger::handleSigHup() { #ifdef Q_OS_UNIX - if (!logFile) - return; - - snHup->setEnabled(false); - char tmp; - ::read(sigHupFD[1], &tmp, sizeof(tmp)); - - logFile->close(); - logFile->open(QIODevice::Append); - - snHup->setEnabled(true); + if (!logFile) + return; + + snHup->setEnabled(false); + char tmp; + ::read(sigHupFD[1], &tmp, sizeof(tmp)); + + logFile->close(); + logFile->open(QIODevice::Append); + + snHup->setEnabled(true); #endif } diff --git a/travis-dependencies.sh b/travis-dependencies.sh index 533a213b..0c6c62e6 100755 --- a/travis-dependencies.sh +++ b/travis-dependencies.sh @@ -2,7 +2,7 @@ if [[ $TRAVIS_OS_NAME == "osx" ]] ; then brew update - brew install qt cmake protobuf + brew install qt cmake protobuf libgcrypt else sudo apt-get update -qq sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev