diff --git a/README.md b/README.md index 1d79addc..f67c6fcc 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Dependencies: - [protobuf](http://code.google.com/p/protobuf/) - [CMake](http://www.cmake.org/) -The server requires an additional dependency: +The server requires an additional dependency when compiled under Qt4: - [libgcrypt](http://www.gnu.org/software/libgcrypt/) diff --git a/cmake/NSIS.template.in b/cmake/NSIS.template.in index c04169c8..3c8514e6 100644 --- a/cmake/NSIS.template.in +++ b/cmake/NSIS.template.in @@ -51,21 +51,24 @@ Section "Application" SecApplication SectionEnd Section "Update configuration" SecUpdateConfig - WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "carddatabase" "$APPDATA\Cockatrice\cards.xml" - WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "decks" "$APPDATA\Cockatrice\decks" - WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "pics" "$APPDATA\Cockatrice\pics" - WriteRegStr HKCU "Software\Cockatrice\Cockatrice\sound" "path" "$APPDATA\Cockatrice\sounds" + SetShellVarContext current + WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "carddatabase" "$LOCALAPPDATA\Cockatrice\cards.xml" + WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "decks" "$LOCALAPPDATA\Cockatrice\decks" + WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "pics" "$LOCALAPPDATA\Cockatrice\pics" + WriteRegStr HKCU "Software\Cockatrice\Cockatrice\sound" "path" "$LOCALAPPDATA\Cockatrice\sounds" SectionEnd Section "Start menu item" SecStartMenu + SetShellVarContext all createDirectory "$SMPROGRAMS\Cockatrice" createShortCut "$SMPROGRAMS\Cockatrice\Cockatrice.lnk" "$INSTDIR\cockatrice.exe" '--debug-output' createShortCut "$SMPROGRAMS\Cockatrice\Oracle.lnk" "$INSTDIR\oracle.exe" + createShortCut "$SMPROGRAMS\Cockatrice\Servatrice.lnk" "$INSTDIR\servatrice.exe" createShortCut "$SMPROGRAMS\Cockatrice\Usermanual.lnk" "$INSTDIR\Usermanual.pdf" SectionEnd Section Uninstall -SetShellVarContext all + SetShellVarContext all RMDir /r "$INSTDIR\zonebg" RMDir /r "$INSTDIR\plugins" RMDir /r "$INSTDIR\sounds" @@ -73,18 +76,23 @@ SetShellVarContext all Delete "$INSTDIR\uninstall.exe" Delete "$INSTDIR\cockatrice.exe" Delete "$INSTDIR\oracle.exe" + Delete "$INSTDIR\servatrice.exe" Delete "$INSTDIR\Usermanual.pdf" Delete "$INSTDIR\libprotobuf.lib" Delete "$INSTDIR\Qt*.dll" Delete "$INSTDIR\icu*.dll" Delete "$INSTDIR\qt.conf" Delete "$INSTDIR\qdebug.txt" + Delete "$INSTDIR\servatrice.sql" + Delete "$INSTDIR\servatrice.ini.example" RMDir "$INSTDIR" RMDir "$SMPROGRAMS\Cockatrice" - DeleteRegKey HKCU "Software\Cockatrice" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" + + SetShellVarContext current + DeleteRegKey HKCU "Software\Cockatrice" SectionEnd LangString DESC_SecApplication ${LANG_ENGLISH} "Cockatrice program files" diff --git a/cmake/headerimage.bmp b/cmake/headerimage.bmp index 73c88d6d..625680c3 100644 Binary files a/cmake/headerimage.bmp and b/cmake/headerimage.bmp differ diff --git a/cmake/leftimage.bmp b/cmake/leftimage.bmp index e89fdd95..aea76267 100644 Binary files a/cmake/leftimage.bmp and b/cmake/leftimage.bmp differ diff --git a/cockatrice/resources/appicon.icns b/cockatrice/resources/appicon.icns index 4bd00ffc..f521035e 100644 Binary files a/cockatrice/resources/appicon.icns and b/cockatrice/resources/appicon.icns differ diff --git a/cockatrice/resources/appicon.ico b/cockatrice/resources/appicon.ico index 9a4885f4..4cf839bc 100644 Binary files a/cockatrice/resources/appicon.ico and b/cockatrice/resources/appicon.ico differ diff --git a/cockatrice/resources/back.svg b/cockatrice/resources/back.svg index 0377ecb2..3dd1c69c 100644 --- a/cockatrice/resources/back.svg +++ b/cockatrice/resources/back.svg @@ -1,5 +1,6 @@ + + version="1.0" + inkscape:export-filename="C:\Users\Matt\Documents\GitHub\Cockatrice\cockatrice\resources\back_new.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + + + + + + + + + xlink:href="#linearGradient3009" + id="linearGradient3015" + x1="10.096291" + y1="329.42294" + x2="229.81081" + y2="12.591727" + gradientUnits="userSpaceOnUse" /> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inkscape:window-width="1920" + inkscape:window-height="1028" + inkscape:window-x="-8" + inkscape:window-y="-8" + inkscape:window-maximized="1" /> @@ -149,40 +658,377 @@ image/svg+xml + + id="layer1" + style="display:inline" + sodipodi:insensitive="true"> + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-opacity:0" + id="rect3004" + width="240" + height="340" + x="0" + y="0.57232106" + rx="10" + ry="10" /> + style="fill:url(#linearGradient3015);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.00535154;stroke-opacity:0;display:inline" + id="rect3007" + width="220.67607" + height="318.77353" + x="10.096291" + y="11.610939" /> + + + + + + + style="fill:#ff5555;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-opacity:0;display:inline" + id="path5297-7" + sodipodi:cx="-96.635925" + sodipodi:cy="76.534889" + sodipodi:rx="2.8846545" + sodipodi:ry="2.8846545" + d="m -93.751271,76.534889 a 2.8846545,2.8846545 0 1 1 -5.769309,0 2.8846545,2.8846545 0 1 1 5.769309,0 z" + transform="translate(118.51147,240.79097)" /> + sodipodi:type="arc" + style="fill:url(#linearGradient5324-8);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-opacity:0;display:inline" + id="path5299-6-1" + sodipodi:cx="-24.925219" + sodipodi:cy="38.493507" + sodipodi:rx="1.4573514" + sodipodi:ry="1.1418424" + d="m -23.467867,38.493507 a 1.4573514,1.1418424 0 1 1 -2.914703,0 1.4573514,1.1418424 0 1 1 2.914703,0 z" + transform="matrix(-1.3207348,0.77962891,-1.166227,-1.9837166,33.337282,413.41782)" /> + + + + + + + + + + + + + + diff --git a/cockatrice/resources/cockatrice.png b/cockatrice/resources/cockatrice.png index ed79b88a..200d2480 100644 Binary files a/cockatrice/resources/cockatrice.png and b/cockatrice/resources/cockatrice.png differ diff --git a/cockatrice/resources/cockatrice.svg b/cockatrice/resources/cockatrice.svg index 991a53c6..1cd1f217 100644 --- a/cockatrice/resources/cockatrice.svg +++ b/cockatrice/resources/cockatrice.svg @@ -1,5 +1,6 @@ + + inkscape:version="0.48.5 r10040" + sodipodi:docname="cockatrice.svg"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2621" /> + + + + + + + + id="linearGradient3779"> + style="stop-color:#99ff00;stop-opacity:1;" /> + style="stop-color:#0f620f;stop-opacity:1;" /> + id="stop3815" /> + style="stop-color:#007400;stop-opacity:0.40000001;" /> + id="stop4579" /> + id="stop3817" /> + id="linearGradient3841"> + style="stop-color:white;stop-opacity:1;" /> + style="stop-color:#fefce9;stop-opacity:0;" /> + + + + + - + id="linearGradient3999-4"> + + + + id="linearGradient4009-4"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2621-2" /> + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2571-9" /> + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2519-8" /> + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2467-1" /> + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2650-6" /> + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2578-7" /> + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective2511-5" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -180,95 +635,142 @@ image/svg+xml + - - - - - - - + id="g3026"> + transform="matrix(0.99103064,0,0,0.98943856,1.2668213,1.9022887)" + id="layer4" + style="display:inline" + clip-path="none"> + + + - - - + id="g3342" + transform="matrix(1.0090505,0,0,1.0106742,411.46737,-30.548174)" + style="fill:#ffffff;fill-opacity:1"> + + + + + + + + + - + id="layer1" + style="display:none"> + d="m 300,149.64285 a 149.64285,149.64285 0 1 1 -299.28570557,0 149.64285,149.64285 0 1 1 299.28570557,0 z" + transform="matrix(1.0015936,0,0,1.0000039,-0.00173336,0.71369073)" + id="path3221" + style="fill:url(#linearGradient4005);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0;filter:url(#filter4089)" /> + + + diff --git a/cockatrice/resources/hand.svg b/cockatrice/resources/hand.svg index 8c28fd59..7c34d7cc 100644 --- a/cockatrice/resources/hand.svg +++ b/cockatrice/resources/hand.svg @@ -14,10 +14,13 @@ height="500" id="svg2" sodipodi:version="0.32" - inkscape:version="0.47pre4 r22446" - sodipodi:docname="back.svg" + inkscape:version="0.48.5 r10040" + sodipodi:docname="hand.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" - version="1.0"> + version="1.0" + inkscape:export-filename="C:\Users\Matt\Documents\GitHub\Cockatrice\cockatrice\resources\hand_new.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> - - - - - - - - - + id="linearGradient4766-8-0-3-31"> + + + + x1="-20.65873" + y1="37.909077" + x2="-25.41811" + y2="38.523342" /> + + + + + x1="-20.65873" + y1="37.909077" + x2="-25.41811" + y2="38.523342" /> + + + + + x1="-20.65873" + y1="37.909077" + x2="-25.41811" + y2="38.523342" /> + + + + + x1="-20.65873" + y1="37.909077" + x2="-25.41811" + y2="38.523342" /> + + + + + + + + + x1="-20.65873" + y1="37.909077" + x2="-25.41811" + y2="38.523342" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -377,7 +3435,7 @@ image/svg+xml - + @@ -387,99 +3445,992 @@ id="layer1" transform="translate(0,160)"> + id="g4178-7" + transform="matrix(0.89531447,-0.44543462,0.44543462,0.89531447,-0.7217683,-5.4209005)"> - - - - - + style="display:inline" + id="layer1-1-4" + inkscape:label="boarder"> + + - - - - - + style="display:inline" + inkscape:label="inlay" + id="layer3-0"> + + + inkscape:label="dots" + id="layer4-0"> + + + + + + + + + + + + + + + - - - + transform="translate(-380.13559,-22.492048)" + id="g3866-2-5"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 79a225ec..59f1ca17 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -76,8 +76,8 @@ void SetList::sortByKey() qSort(begin(), end(), CompareFunctor()); } -PictureToLoad::PictureToLoad(CardInfo *_card, bool _stripped, bool _hq) - : card(_card), stripped(_stripped), setIndex(0), hq(_hq) +PictureToLoad::PictureToLoad(CardInfo *_card, bool _hq) + : card(_card), setIndex(0), hq(_hq) { if (card) { sortedSets = card->getSets(); @@ -135,14 +135,14 @@ void PictureLoader::processLoadQueue() mutex.unlock(); //The list of paths to the folders in which to search for images - QList picsPaths = QList() << _picsPath + "/CUSTOM/" + ptl.getCard()->getCorrectedName() + ".full"; + QList picsPaths = QList() << _picsPath + "/CUSTOM/" + ptl.getCard()->getCorrectedName(); QString setName=ptl.getSetName(); if(!setName.isEmpty()) { - picsPaths << _picsPath + "/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full" - << _picsPath + "/downloadedPics/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full"; + picsPaths << _picsPath + "/" + setName + "/" + ptl.getCard()->getCorrectedName() + << _picsPath + "/downloadedPics/" + setName + "/" + ptl.getCard()->getCorrectedName(); } QImage image; @@ -153,6 +153,12 @@ void PictureLoader::processLoadQueue() //Iterates through the list of paths, searching for images with the desired name with any QImageReader-supported extension for (int i = 0; i < picsPaths.length() && !found; i ++) { imgReader.setFileName(picsPaths.at(i)); + if (imgReader.read(&image)) { + emit imageLoaded(ptl.getCard(), image); + found = true; + break; + } + imgReader.setFileName(picsPaths.at(i) + ".full"); if (imgReader.read(&image)) { emit imageLoaded(ptl.getCard(), image); found = true; @@ -257,14 +263,14 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply) const QByteArray &picData = reply->peek(reply->size()); //peek is used to keep the data in the buffer for use by QImageReader QImage testImage; - + QImageReader imgReader; imgReader.setDecideFormatFromContent(true); imgReader.setDevice(reply); QString extension = "." + imgReader.format(); //the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the QImageReader buffer if (extension == ".jpeg") extension = ".jpg"; - + if (imgReader.read(&testImage)) { QString setName = cardBeingDownloaded.getSetName(); if(!setName.isEmpty()) @@ -274,11 +280,7 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply) return; } - QString suffix; - if (!cardBeingDownloaded.getStripped()) - suffix = ".full"; - - QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + extension); + QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + extension); if (!newPic.open(QIODevice::WriteOnly)) return; newPic.write(picData); @@ -306,11 +308,11 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply) startNextPicDownload(); } -void PictureLoader::loadImage(CardInfo *card, bool stripped) +void PictureLoader::loadImage(CardInfo *card) { QMutexLocker locker(&mutex); - loadQueue.append(PictureToLoad(card, stripped)); + loadQueue.append(PictureToLoad(card)); emit startLoadQueue(); } @@ -491,7 +493,7 @@ void CardInfo::updatePixmapCache() qDebug() << "Updating pixmap cache for" << name; clearPixmapCache(); loadPixmap(); - + emit pixmapUpdated(); } @@ -603,7 +605,7 @@ CardDatabase::~CardDatabase() { clear(); delete noCard; - + pictureLoader->deleteLater(); pictureLoaderThread->wait(); delete pictureLoaderThread; @@ -617,7 +619,7 @@ void CardDatabase::clear() delete setIt.value(); } sets.clear(); - + QHashIterator i(cards); while (i.hasNext()) { i.next(); @@ -708,7 +710,7 @@ void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml) } } -void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) +void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml, bool tokens) { while (!xml.atEnd()) { if (xml.readNext() == QXmlStreamReader::EndElement) @@ -760,16 +762,38 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml) else if (xml.name() == "token") isToken = xml.readElementText().toInt(); } - addCard(new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, customPicURLs, customPicURLsHq, muids)); + + if (isToken == tokens) { + addCard(new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, customPicURLs, customPicURLsHq, muids)); + } } } } +CardInfo *CardNameMap::findByPrefix(const std::string &prefix) { + int count = 0; + CardInfo *found; + + for (CardNameMap::iterator it = this->begin(); it != this->end(); ++it) { + if (std::mismatch(prefix.begin(), prefix.end(), + it.key().toStdString().begin()).first == prefix.end()) { + count++; + found = it.value(); + } + } + + return (count == 1 ? found : NULL); +} + CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) { + CardInfo *foundCard; + if (cardName.isEmpty()) return noCard; else if (cardMap.contains(cardName)) return cardMap.value(cardName); + else if ((foundCard = cardMap.findByPrefix(cardName.toStdString()))) + return foundCard; else if (createIfNotFound) { CardInfo *newCard = new CardInfo(this, cardName, true); newCard->addToSet(getSet("TK")); @@ -779,7 +803,7 @@ CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &card return 0; } -LoadStatus CardDatabase::loadFromFile(const QString &fileName) +LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens) { QFile file(fileName); file.open(QIODevice::ReadOnly); @@ -802,7 +826,7 @@ LoadStatus CardDatabase::loadFromFile(const QString &fileName) if (xml.name() == "sets") loadSetsFromXml(xml); else if (xml.name() == "cards") - loadCardsFromXml(xml); + loadCardsFromXml(xml, tokens); } } } @@ -837,7 +861,9 @@ bool CardDatabase::saveToFile(const QString &fileName, bool tokens) QHashIterator cardIterator(cards); while (cardIterator.hasNext()) { CardInfo *card = cardIterator.next().value(); - xml << card; + if (tokens == card->getIsToken()) { + xml << card; + } } xml.writeEndElement(); // cards @@ -871,7 +897,7 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens) { LoadStatus tempLoadStatus = NotLoaded; if (!path.isEmpty()) - tempLoadStatus = loadFromFile(path); + tempLoadStatus = loadFromFile(path, tokens); if (tempLoadStatus == Ok) { SetList allSets; @@ -936,7 +962,7 @@ void CardDatabase::cacheCardPixmaps(const QStringList &cardNames) void CardDatabase::loadImage(CardInfo *card) { - pictureLoader->loadImage(card, false); + pictureLoader->loadImage(card); } void CardDatabase::imageLoaded(CardInfo *card, QImage image) diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 91abac59..68732a4d 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -47,14 +47,12 @@ public: class PictureToLoad { private: CardInfo *card; - bool stripped; SetList sortedSets; int setIndex; bool hq; public: - PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true); + PictureToLoad(CardInfo *_card = 0, bool _hq = true); CardInfo *getCard() const { return card; } - bool getStripped() const { return stripped; } QString getSetName() const; bool nextSet(); bool getHq() const { return hq; } @@ -79,7 +77,7 @@ public: void setPicsPath(const QString &path); void setPicDownload(bool _picDownload); void setPicDownloadHq(bool _picDownloadHq); - void loadImage(CardInfo *card, bool stripped); + void loadImage(CardInfo *card); private slots: void picDownloadFinished(QNetworkReply *reply); public slots: @@ -182,7 +180,13 @@ signals: enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards }; -typedef QHash CardNameMap; + +class CardNameMap: public QHash +{ + public: + CardInfo *findByPrefix(const std::string &prefix); +}; + typedef QHash SetNameMap; class CardDatabase : public QObject { @@ -210,7 +214,7 @@ protected: LoadStatus loadStatus; private: static const int versionNeeded; - void loadCardsFromXml(QXmlStreamReader &xml); + void loadCardsFromXml(QXmlStreamReader &xml, bool tokens); void loadSetsFromXml(QXmlStreamReader &xml); CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound); @@ -231,7 +235,7 @@ public: CardSet *getSet(const QString &setName); QList getCardList() const { return cards.values(); } SetList getSetList() const; - LoadStatus loadFromFile(const QString &fileName); + LoadStatus loadFromFile(const QString &fileName, bool tokens = false); bool saveToFile(const QString &fileName, bool tokens = false); QStringList getAllColors() const; QStringList getAllMainCardTypes() const; diff --git a/cockatrice/src/carddragitem.cpp b/cockatrice/src/carddragitem.cpp index 0ddb9109..0ebab9a4 100644 --- a/cockatrice/src/carddragitem.cpp +++ b/cockatrice/src/carddragitem.cpp @@ -84,7 +84,9 @@ void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) sc->removeItem(c); } } - currentZone->handleDropEvent(dragItemList, startZone, (sp - currentZone->scenePos()).toPoint()); + + if(currentZone) + currentZone->handleDropEvent(dragItemList, startZone, (sp - currentZone->scenePos()).toPoint()); event->accept(); } diff --git a/cockatrice/src/dlg_connect.cpp b/cockatrice/src/dlg_connect.cpp index d1955d14..152d62b9 100644 --- a/cockatrice/src/dlg_connect.cpp +++ b/cockatrice/src/dlg_connect.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "dlg_connect.h" DlgConnect::DlgConnect(QWidget *parent) @@ -32,6 +34,19 @@ DlgConnect::DlgConnect(QWidget *parent) savePasswordCheckBox = new QCheckBox(tr("&Save password")); savePasswordCheckBox->setChecked(settings.value("save_password", 1).toInt()); + autoConnectCheckBox = new QCheckBox(tr("A&uto connect at start")); + if(savePasswordCheckBox->isChecked()) + { + autoConnectCheckBox->setChecked(settings.value("auto_connect", 0).toInt()); + autoConnectCheckBox->setEnabled(true); + } else { + settings.setValue("auto_connect", 0); + autoConnectCheckBox->setChecked(0); + autoConnectCheckBox->setEnabled(false); + } + + connect(savePasswordCheckBox, SIGNAL(stateChanged(int)), this, SLOT(passwordSaved(int))); + QGridLayout *grid = new QGridLayout; grid->addWidget(hostLabel, 0, 0); grid->addWidget(hostEdit, 0, 1); @@ -42,10 +57,11 @@ DlgConnect::DlgConnect(QWidget *parent) grid->addWidget(passwordLabel, 3, 0); grid->addWidget(passwordEdit, 3, 1); grid->addWidget(savePasswordCheckBox, 4, 0, 1, 2); + grid->addWidget(autoConnectCheckBox, 5, 0, 1, 2); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(actCancel())); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(grid); @@ -57,6 +73,16 @@ DlgConnect::DlgConnect(QWidget *parent) setMinimumWidth(300); } +void DlgConnect::passwordSaved(int state) +{ + if(savePasswordCheckBox->isChecked()) { + autoConnectCheckBox->setEnabled(true); + } else { + autoConnectCheckBox->setChecked(0); + autoConnectCheckBox->setEnabled(false); + } +} + void DlgConnect::actOk() { QSettings settings; @@ -66,7 +92,19 @@ void DlgConnect::actOk() settings.setValue("playername", playernameEdit->text()); settings.setValue("password", savePasswordCheckBox->isChecked() ? passwordEdit->text() : QString()); settings.setValue("save_password", savePasswordCheckBox->isChecked() ? 1 : 0); + settings.setValue("auto_connect", autoConnectCheckBox->isChecked() ? 1 : 0); settings.endGroup(); accept(); } + +void DlgConnect::actCancel() +{ + QSettings settings; + settings.beginGroup("server"); + settings.setValue("save_password", savePasswordCheckBox->isChecked() ? 1 : 0); + settings.setValue("auto_connect", autoConnectCheckBox->isChecked() ? 1 : 0); + settings.endGroup(); + + reject(); +} diff --git a/cockatrice/src/dlg_connect.h b/cockatrice/src/dlg_connect.h index 87fe4ed9..6f135aa0 100644 --- a/cockatrice/src/dlg_connect.h +++ b/cockatrice/src/dlg_connect.h @@ -18,10 +18,12 @@ public: QString getPassword() const { return passwordEdit->text(); } private slots: void actOk(); + void actCancel(); + void passwordSaved(int state); private: QLabel *hostLabel, *portLabel, *playernameLabel, *passwordLabel; QLineEdit *hostEdit, *portEdit, *playernameEdit, *passwordEdit; - QCheckBox *savePasswordCheckBox; + QCheckBox *savePasswordCheckBox, *autoConnectCheckBox; }; #endif diff --git a/cockatrice/src/keysignals.cpp b/cockatrice/src/keysignals.cpp index 5db58cb5..bbd94dbb 100644 --- a/cockatrice/src/keysignals.cpp +++ b/cockatrice/src/keysignals.cpp @@ -56,6 +56,10 @@ bool KeySignals::eventFilter(QObject * /*object*/, QEvent *event) { && kevent->modifiers().testFlag(Qt::ControlModifier) ) emit onCtrlAltRBracket(); + break; + case Qt::Key_S: + emit onS(); + break; default: return false; diff --git a/cockatrice/src/keysignals.h b/cockatrice/src/keysignals.h index 693488c5..94c9dd39 100644 --- a/cockatrice/src/keysignals.h +++ b/cockatrice/src/keysignals.h @@ -18,6 +18,7 @@ signals: void onCtrlAltEqual(); void onCtrlAltLBracket(); void onCtrlAltRBracket(); + void onS(); protected: virtual bool eventFilter(QObject *, QEvent *event); diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index d8d21fd9..16b77eae 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -100,7 +100,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_pare : QObject(_parent), game(_parent), shortcutsActive(false), - defaultNumberTopCards(3), + defaultNumberTopCards(1), lastTokenDestroy(true), id(_id), active(false), @@ -1092,8 +1092,12 @@ void Player::eventCreateToken(const Event_CreateToken &event) return; CardItem *card = new CardItem(this, QString::fromStdString(event.card_name()), event.card_id()); + // use db PT if not provided in event + if (!QString::fromStdString(event.pt()).isEmpty()) + card->setPT(QString::fromStdString(event.pt())); + else + card->setPT(db->getCard(QString::fromStdString(event.card_name()))->getPowTough()); card->setColor(QString::fromStdString(event.color())); - card->setPT(QString::fromStdString(event.pt())); card->setAnnotation(QString::fromStdString(event.annotation())); card->setDestroyOnZoneChange(event.destroy_on_zone_change()); diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 5f504aa3..5821d352 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -48,6 +48,8 @@ SettingsCache::SettingsCache() priceTagSource = settings->value("deckeditor/pricetagsource", 0).toInt(); ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool(); + + attemptAutoConnect = settings->value("server/auto_connect", 0).toBool(); } void SettingsCache::setLang(const QString &_lang) @@ -267,6 +269,12 @@ void SettingsCache::setMainWindowGeometry(const QByteArray &_mainWindowGeometry) settings->setValue("interface/main_window_geometry", mainWindowGeometry); } +void SettingsCache::setAutoConnect(const bool &_autoConnect) +{ + attemptAutoConnect = _autoConnect; + settings->setValue("server/auto_connect", attemptAutoConnect ? 1 : 0); +} + void SettingsCache::copyPath(const QString &src, const QString &dst) { // test source && return if inexistent diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index 3b4d612d..b222a58b 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -57,6 +57,7 @@ private: bool ignoreUnregisteredUsers; QString picUrl; QString picUrlHq; + bool attemptAutoConnect; public: SettingsCache(); const QByteArray &getMainWindowGeometry() const { return mainWindowGeometry; } @@ -93,6 +94,7 @@ public: QString getPicUrl() const { return picUrl; } QString getPicUrlHq() const { return picUrlHq; } void copyPath(const QString &src, const QString &dst); + bool getAutoConnect() const { return attemptAutoConnect; } public slots: void setMainWindowGeometry(const QByteArray &_mainWindowGeometry); void setLang(const QString &_lang); @@ -127,6 +129,7 @@ public slots: void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers); void setPicUrl(const QString &_picUrl); void setPicUrlHq(const QString &_picUrlHq); + void setAutoConnect(const bool &_autoConnect); }; extern SettingsCache *settingsCache; diff --git a/cockatrice/src/tab_deck_editor.cpp b/cockatrice/src/tab_deck_editor.cpp index c0138931..82a356d1 100644 --- a/cockatrice/src/tab_deck_editor.cpp +++ b/cockatrice/src/tab_deck_editor.cpp @@ -141,6 +141,8 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent) #endif deckView->installEventFilter(&deckViewKeySignals); connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &))); + connect(deckView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actSwapCard())); + connect(&deckViewKeySignals, SIGNAL(onS()), this, SLOT(actSwapCard())); connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement())); connect(&deckViewKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actIncrement())); connect(&deckViewKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrement())); @@ -571,6 +573,27 @@ void TabDeckEditor::addCardHelper(QString zoneName) setModified(true); } +void TabDeckEditor::actSwapCard() +{ + const QModelIndex currentIndex = deckView->selectionModel()->currentIndex(); + if (!currentIndex.isValid()) + return; + const QString cardName = currentIndex.sibling(currentIndex.row(), 1).data().toString(); + const QModelIndex gparent = currentIndex.parent().parent(); + if (!gparent.isValid()) + return; + + const QString zoneName = gparent.sibling(gparent.row(), 1).data().toString(); + actDecrement(); + + const QString otherZoneName = zoneName == "Maindeck" ? "side" : "main"; + + QModelIndex newCardIndex = deckModel->addCard(cardName, otherZoneName); + recursiveExpand(newCardIndex); + deckView->setCurrentIndex(newCardIndex); + setModified(true); +} + void TabDeckEditor::actAddCard() { addCardHelper("main"); diff --git a/cockatrice/src/tab_deck_editor.h b/cockatrice/src/tab_deck_editor.h index b3ba8dcf..dd3b56ac 100644 --- a/cockatrice/src/tab_deck_editor.h +++ b/cockatrice/src/tab_deck_editor.h @@ -53,6 +53,7 @@ private slots: void actClearSearch(); + void actSwapCard(); void actAddCard(); void actAddCardToSideboard(); void actRemoveCard(); diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 43b0624e..51a09418 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -359,7 +359,7 @@ void MainWindow::createMenus() } MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), localServer(0) + : QMainWindow(parent), localServer(0), bHasActivated(false) { QPixmapCache::setCacheLimit(200000); @@ -417,5 +417,16 @@ void MainWindow::changeEvent(QEvent *event) { if (event->type() == QEvent::LanguageChange) retranslateUi(); + else if(event->type() == QEvent::ActivationChange) { + if(isActiveWindow() && !bHasActivated){ + bHasActivated = true; + if(settingsCache->getAutoConnect()) { + qDebug() << "Attempting auto-connect..."; + DlgConnect dlg(this); + client->connectToServer(dlg.getHost(), dlg.getPort(), dlg.getPlayerName(), dlg.getPassword()); + } + } + } + QMainWindow::changeEvent(event); } diff --git a/cockatrice/src/window_main.h b/cockatrice/src/window_main.h index 07ad1d71..e804bbe6 100644 --- a/cockatrice/src/window_main.h +++ b/cockatrice/src/window_main.h @@ -71,6 +71,7 @@ private: QThread *clientThread; LocalServer *localServer; + bool bHasActivated; public: MainWindow(QWidget *parent = 0); ~MainWindow(); diff --git a/cockatrice/translations/cockatrice_cs.ts b/cockatrice/translations/cockatrice_cs.ts index bfd7fb3b..7d9db950 100644 --- a/cockatrice/translations/cockatrice_cs.ts +++ b/cockatrice/translations/cockatrice_cs.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - Cesta k pozadí ruky: + Cesta k pozadí ruky: Path to stack background: - Cesta k pozadí stacku: + Cesta k pozadí stacku: Path to table background: - Cesta k pozadí stolu: + Cesta k pozadí stolu: Path to player info background: - Cesta k pozadí informací o uživateli: + Cesta k pozadí informací o uživateli: Path to picture of card back: - Cesta k rubu karet: + Cesta k rubu karet: @@ -1063,7 +1063,7 @@ This is only saved for moderators and cannot be seen by the banned person.DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - &Povolit zobrazovaní cen (použijí se data z blacklotusproject.com) + &Povolit zobrazovaní cen (použijí se data z blacklotusproject.com) @@ -1202,30 +1202,35 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: &Hostitel: - + &Port: &Port: - + Player &name: Jméno &hráče: - + P&assword: H&eslo: - + &Save password + + + A&uto connect at start + + &OK &OK @@ -1235,7 +1240,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Zrušit - + Connect to server Připojit k serveru @@ -1636,7 +1641,7 @@ This is only saved for moderators and cannot be seen by the banned person. Your card database is invalid. Would you like to go back and set the correct path? - Cesta k databázi je neplatná. Chcete se vrátit a nastavit správnou? + Cesta k databázi je neplatná. Chcete se vrátit a nastavit správnou? @@ -2022,7 +2027,7 @@ Would you like to change your database location setting? Path to card database: - Karetní databáze: + Karetní databáze: @@ -2141,7 +2146,7 @@ Reason for shutdown: %1 Czech: - Čeština: + Čeština: Slovak: @@ -2204,7 +2209,7 @@ Reason for shutdown: %1 Invalid login data. - Nesprávné údaje uživatele. + Nesprávné údaje uživatele. @@ -2518,12 +2523,12 @@ Lokální verze je %1, verze serveru je %2. %1 has loaded a deck (%2). female - %1 nahrál balíček %2. + %1 nahrál balíček %2. %1 has loaded a deck (%2). male - %1 nahrál balíček %2. + %1 nahrál balíček %2. @@ -4624,7 +4629,7 @@ Lokální verze je %1, verze serveru je %2. Administration - Administrace + Administrace @@ -4933,7 +4938,7 @@ Prosím vložte jméno: Deck storage - Uložiště balíčků + Uložiště balíčků @@ -5218,14 +5223,14 @@ Prosím vložte jméno: TabServer Server - Server + Server TabUserLists User lists - Seznam uživatelů + Seznam uživatelů diff --git a/cockatrice/translations/cockatrice_de.ts b/cockatrice/translations/cockatrice_de.ts index fedd2a5a..ec90f35a 100644 --- a/cockatrice/translations/cockatrice_de.ts +++ b/cockatrice/translations/cockatrice_de.ts @@ -1,6 +1,6 @@ - + @@ -66,23 +66,23 @@ Path to hand background: - Hintergrundbild für die Hand: + Hintergrundbild für die Hand: Path to stack background: - Hintergrundbild für den Stapel: + Hintergrundbild für den Stapel: Path to table background: - Hintergrundbild für das Spielfeld: + Hintergrundbild für das Spielfeld: Path to player info background: - Hintergrundbild für den Spielerbereich: + Hintergrundbild für den Spielerbereich: Path to picture of card back: - Pfad zum Bild der Kartenrückseite: + Pfad zum Bild der Kartenrückseite: @@ -1384,7 +1384,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - Karten&preisfunktionen anschalten (benutzt Daten von blacklotusproject.com) + Karten&preisfunktionen anschalten (benutzt Daten von blacklotusproject.com) @@ -1545,30 +1545,35 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic DlgConnect - + &Host: &Server: - + &Port: &Port: - + Player &name: Spieler&name: - + P&assword: P&asswort: - + &Save password Passwort &speichern + + + A&uto connect at start + + &OK &OK @@ -1578,7 +1583,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic &Abbruch - + Connect to server Verbinde zum Server @@ -2030,7 +2035,7 @@ Dies wird nur für Moderatoren gespeichert und kann von der gebannten Person nic Your card database is invalid. Would you like to go back and set the correct path? - Ihre Kartendatenbank ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? + Ihre Kartendatenbank ist ungültig. Möchten Sie zurückgehen und den korrekten Pfad einstellen? @@ -2684,11 +2689,11 @@ Would you like to change your database location setting? Path to card database: - Pfad zur Kartendatenbank: + Pfad zur Kartendatenbank: Path to token database: - Pfad zur Spielsteindatenbank: + Pfad zur Spielsteindatenbank: @@ -2842,7 +2847,7 @@ Grund für die Abschaltung: %1 Czech: - Tschechisch: + Tschechisch: @@ -2904,7 +2909,7 @@ Grund für die Abschaltung: %1 Invalid login data. - Ungültige Anmeldedaten. + Ungültige Anmeldedaten. @@ -3709,12 +3714,12 @@ Lokale Version ist %1, Serverversion ist %2. %1 has loaded a deck (%2). female - %1 hat ein Deck geladen (%2). + %1 hat ein Deck geladen (%2). %1 has loaded a deck (%2). male - %1 hat ein Deck geladen (%2). + %1 hat ein Deck geladen (%2). @@ -4985,7 +4990,7 @@ Lokale Version ist %1, Serverversion ist %2. Ctrl+H - Ctrl+H + Ctrl+H @@ -5652,11 +5657,11 @@ Lokale Version ist %1, Serverversion ist %2. Cockatrice decks (*.cod) - Cockatrice Decks (*.cod) + Cockatrice Decks (*.cod) Plain text decks (*.dec *.mwDeck) - Text Decks (*.dec *.mwDeck) + Text Decks (*.dec *.mwDeck) @@ -5792,11 +5797,11 @@ Lokale Version ist %1, Serverversion ist %2. &OK - &OK + &OK &Cancel - &Abbrechen + &Abbrechen @@ -5847,7 +5852,7 @@ Lokale Version ist %1, Serverversion ist %2. Administration - Wartung + Wartung @@ -5897,7 +5902,7 @@ Lokale Version ist %1, Serverversion ist %2. &Search... - &Suchen... + &Suchen... @@ -5976,11 +5981,11 @@ Lokale Version ist %1, Serverversion ist %2. Return - Return + Return Enter - Enter + Enter @@ -5989,11 +5994,11 @@ Lokale Version ist %1, Serverversion ist %2. Ctrl+Return - Ctrl+Return + Ctrl+Return Ctrl+Enter - Ctrl+Enter + Ctrl+Enter @@ -6179,7 +6184,7 @@ Bitte geben Sie einen Namen ein: Deck storage - Deckspeicherplatz + Deckspeicherplatz @@ -6456,7 +6461,7 @@ Bitte geben Sie einen Namen ein: Game replays - Replays + Replays @@ -6504,7 +6509,7 @@ Bitte geben Sie einen Namen ein: TabServer Server - Server + Server @@ -6526,7 +6531,7 @@ Bitte geben Sie einen Namen ein: TabUserLists User lists - Benutzerlisten + Benutzerlisten diff --git a/cockatrice/translations/cockatrice_en.ts b/cockatrice/translations/cockatrice_en.ts index ea397a18..4f52e8a1 100644 --- a/cockatrice/translations/cockatrice_en.ts +++ b/cockatrice/translations/cockatrice_en.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -725,32 +725,37 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: - + &Port: - + Player &name: - + P&assword: - + &Save password - + + A&uto connect at start + + + + Connect to server diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 3a77a6c9..a9431d75 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - Ruta a la imagen de fondo de la mano: + Ruta a la imagen de fondo de la mano: Path to stack background: - Ruta a la imagen de fondo de la pila: + Ruta a la imagen de fondo de la pila: Path to table background: - Ruta a la imagen de fondo de la mesa: + Ruta a la imagen de fondo de la mesa: Path to player info background: - Ruta a la imagen de fondo de la información del jugador: + Ruta a la imagen de fondo de la información del jugador: Path to picture of card back: - Ruta al reverso de las cartas: + Ruta al reverso de las cartas: @@ -1315,7 +1315,7 @@ Se almacenará unicamente para moderadores y no podrá ser visto por la persona DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - Activar tag de &precios (usando datos de blacklotusproject.com) + Activar tag de &precios (usando datos de blacklotusproject.com) @@ -1461,30 +1461,35 @@ Se almacenará unicamente para moderadores y no podrá ser visto por la persona DlgConnect - + &Host: &Dirección: - + &Port: &Puerto: - + Player &name: &Nombre del jugador: - + P&assword: &Contraseña: - + &Save password &Guardar contraseña + + + A&uto connect at start + + &OK &Aceptar @@ -1494,7 +1499,7 @@ Se almacenará unicamente para moderadores y no podrá ser visto por la persona &Cancelar - + Connect to server Conectar con el servidor @@ -1911,7 +1916,7 @@ Se almacenará unicamente para moderadores y no podrá ser visto por la persona Your card database is invalid. Would you like to go back and set the correct path? - Tu base de datos de cartas es invalida. ¿Deseas volver y seleccionar la ruta correcta? + Tu base de datos de cartas es invalida. ¿Deseas volver y seleccionar la ruta correcta? @@ -2299,11 +2304,11 @@ Would you like to change your database location setting? Path to card database: - Ruta a la base de datos de las cartas: + Ruta a la base de datos de las cartas: Path to token database: - Ruta a la base de datos de fichas: + Ruta a la base de datos de fichas: @@ -2457,7 +2462,7 @@ Motivo para la desconexión: %1 Czech: - Checo: + Checo: @@ -2519,7 +2524,7 @@ Motivo para la desconexión: %1 Invalid login data. - Datos de conexión invalidos. + Datos de conexión invalidos. @@ -3107,12 +3112,12 @@ La versión local es %1, la versión remota es %2. %1 has loaded a deck (%2). female - %1 ha cargado el mazo %2. + %1 ha cargado el mazo %2. %1 has loaded a deck (%2). male - %1 ha cargado el mazo %2. + %1 ha cargado el mazo %2. @@ -4482,7 +4487,7 @@ La versión local es %1, la versión remota es %2. Ctrl+H - Ctrl+H + Ctrl+H @@ -4782,11 +4787,11 @@ La versión local es %1, la versión remota es %2. Cockatrice decks (*.cod) - Mazos de Cockatrice (*.cod) + Mazos de Cockatrice (*.cod) Plain text decks (*.dec *.mwDeck) - Archivos de texto plano (*.dec *.mwDeck) + Archivos de texto plano (*.dec *.mwDeck) @@ -4922,11 +4927,11 @@ La versión local es %1, la versión remota es %2. &OK - &Aceptar + &Aceptar &Cancel - &Cancelar + &Cancelar @@ -4973,7 +4978,7 @@ La versión local es %1, la versión remota es %2. Administration - Administración + Administración @@ -4999,7 +5004,7 @@ La versión local es %1, la versión remota es %2. TabDeckEditor &Search... - &Buscar... + &Buscar... @@ -5098,11 +5103,11 @@ La versión local es %1, la versión remota es %2. Return - Return + Return Enter - Enter + Enter @@ -5111,11 +5116,11 @@ La versión local es %1, la versión remota es %2. Ctrl+Return - Ctrl+Return + Ctrl+Return Ctrl+Enter - Ctrl+Enter + Ctrl+Enter @@ -5301,7 +5306,7 @@ Por favor, introduzca un nombre: Deck storage - Almacen de mazos + Almacen de mazos @@ -5550,7 +5555,7 @@ Por favor, introduzca un nombre: Game replays - Replays de partidas + Replays de partidas @@ -5598,14 +5603,14 @@ Por favor, introduzca un nombre: TabServer Server - Servidor + Servidor TabUserLists User lists - Lista de usuarios + Lista de usuarios diff --git a/cockatrice/translations/cockatrice_fr.ts b/cockatrice/translations/cockatrice_fr.ts index 3c68cd30..68c590f0 100644 --- a/cockatrice/translations/cockatrice_fr.ts +++ b/cockatrice/translations/cockatrice_fr.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -55,11 +55,35 @@ Path to player info background: - Chemin vers l'image de fond d'affichage d'informations: + Chemin vers l'image de fond d'informations joueur: Path to picture of card back: Chemin vers l'image de dos des cartes: + + + Hand background: + Image de fond de la zone de main: + + + + Stack background: + Image de fond de la pile: + + + + Table background: + Image de fond de la zone de jeu: + + + + Player info background: + Image de fond de la zone d'informations joueur: + + + + Card back: + Dos de carte: @@ -1154,7 +1178,7 @@ Cette information sera consultable uniquement par les modérateurs.DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - Activer le guide de &prix des cartes (source : blacklotusproject.com) + Activer le guide de &prix des cartes (source : blacklotusproject.com) @@ -1300,30 +1324,35 @@ Cette information sera consultable uniquement par les modérateurs. DlgConnect - + &Host: &Hôte: - + &Port: &Port: - + Player &name: &Nom du joueur: - + P&assword: Mot de p&asse: - + &Save password + + + A&uto connect at start + + &OK &OK @@ -1333,7 +1362,7 @@ Cette information sera consultable uniquement par les modérateurs.&Annuler - + Connect to server Connexion au serveur @@ -1738,7 +1767,7 @@ Cette information sera consultable uniquement par les modérateurs. Your card database is invalid. Would you like to go back and set the correct path? - Votre base de carte est invalide. Souhaitez-vous redéfinir le chemin d'accès? + Votre base de carte est invalide. Souhaitez-vous redéfinir le chemin d'accès? @@ -2133,7 +2162,7 @@ Would you like to change your database location setting? Path to card database: - Chemin vers la base de cartes: + Chemin vers la base de cartes: @@ -2229,7 +2258,7 @@ Would you like to change your database location setting? Invalid login data. - Information de connexion érronée. + Information de connexion érronée. @@ -2312,7 +2341,7 @@ Raison de la fermeture : %1 Czech: - Tchèque : + Tchèque : Slovak: @@ -2961,12 +2990,12 @@ La version la plus récente est %1, l'ancienne version est %2. %1 has loaded a deck (%2). female - %1 a chargé le deck %2. + %1 a chargé le deck %2. %1 has loaded a deck (%2). male - %1 a chargé le deck %2. + %1 a chargé le deck %2. @@ -4750,11 +4779,11 @@ La version la plus récente est %1, l'ancienne version est %2. &OK - &OK + &OK &Cancel - &Annuler + &Annuler @@ -4801,7 +4830,7 @@ La version la plus récente est %1, l'ancienne version est %2. Administration - Administration + Administration @@ -5129,7 +5158,7 @@ Entrez un nom s'il vous plaît: Deck storage - Stockage de deck + Stockage de deck @@ -5423,14 +5452,14 @@ Entrez un nom s'il vous plaît: TabServer Server - Serveur + Serveur TabUserLists User lists - Listes de l'utilisateur + Listes de l'utilisateur diff --git a/cockatrice/translations/cockatrice_gd.ts b/cockatrice/translations/cockatrice_gd.ts index 7003d25c..e2a262e0 100644 --- a/cockatrice/translations/cockatrice_gd.ts +++ b/cockatrice/translations/cockatrice_gd.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -755,30 +755,35 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: Ò&stair: - + &Port: &Port: - + Player &name: &Ainm a' chluicheadair: - + P&assword: &Facal-faire: - + &Save password + + + A&uto connect at start + + &OK &Ceart ma-thà @@ -788,7 +793,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Sguir dheth - + Connect to server Dèan ceangal ris an fhrithealaiche @@ -3786,11 +3791,11 @@ Local version is %1, remote version is %2. &OK - &Ceart ma-thà + &Ceart ma-thà &Cancel - &Sguir dheth + &Sguir dheth @@ -4404,7 +4409,7 @@ Please enter a name: TabServer Server - Fhrithealaiche + Fhrithealaiche diff --git a/cockatrice/translations/cockatrice_it.ts b/cockatrice/translations/cockatrice_it.ts index 111a7096..bcaae287 100644 --- a/cockatrice/translations/cockatrice_it.ts +++ b/cockatrice/translations/cockatrice_it.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - Percorso sfondo della mano: + Percorso sfondo della mano: Path to stack background: - Percorso sfondo della pila: + Percorso sfondo della pila: Path to table background: - Percorso sfondo del tavolo: + Percorso sfondo del tavolo: Path to player info background: - Percorso sfondo info giocatore: + Percorso sfondo info giocatore: Path to picture of card back: - Percorso sfondo retro delle carte: + Percorso sfondo retro delle carte: @@ -959,7 +959,7 @@ Questo è solo visibile ai moderatori e non alla persona bannata. DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - Abilita la &ricerca del costo (utilizzando i dati di blacklotusproject.com) + Abilita la &ricerca del costo (utilizzando i dati di blacklotusproject.com) @@ -1098,30 +1098,35 @@ Questo è solo visibile ai moderatori e non alla persona bannata. DlgConnect - + &Host: &Host: - + &Port: &Porta: - + Player &name: Nome &Giocatore: - + P&assword: P&assword: - + &Save password &Salva password + + + A&uto connect at start + + &OK &OK @@ -1131,7 +1136,7 @@ Questo è solo visibile ai moderatori e non alla persona bannata. &Annulla - + Connect to server Connetti al server @@ -1532,7 +1537,7 @@ Questo è solo visibile ai moderatori e non alla persona bannata. Your card database is invalid. Would you like to go back and set the correct path? - Il tuo database è invalido. Vuoi tornare indietro e impostare il percorso corretto? + Il tuo database è invalido. Vuoi tornare indietro e impostare il percorso corretto? @@ -1922,11 +1927,11 @@ Would you like to change your database location setting? Path to card database: - Percorso database delle carte: + Percorso database delle carte: Path to token database: - Percorso database pedine: + Percorso database pedine: @@ -2048,7 +2053,7 @@ Ragione dello spegnimento: %1 Czech: - Ceco: + Ceco: Slovak: @@ -2111,7 +2116,7 @@ Ragione dello spegnimento: %1 Invalid login data. - Dati login non validi. + Dati login non validi. @@ -2348,12 +2353,12 @@ La tua versione è la %1, la versione online è la %2. %1 has loaded a deck (%2). female - %1 ha aperto un mazzo %2. + %1 ha aperto un mazzo %2. %1 has loaded a deck (%2). male - %1 ha aperto un mazzo %2. + %1 ha aperto un mazzo %2. @@ -3792,7 +3797,7 @@ La tua versione è la %1, la versione online è la %2. Ctrl+H - Ctrl+H + Ctrl+H @@ -4134,11 +4139,11 @@ La tua versione è la %1, la versione online è la %2. Cockatrice decks (*.cod) - Mazzi Cockatrice (*.cod) + Mazzi Cockatrice (*.cod) Plain text decks (*.dec *.mwDeck) - Mazzi in formato testo (*.dec *.mwDeck) + Mazzi in formato testo (*.dec *.mwDeck) @@ -4267,11 +4272,11 @@ La tua versione è la %1, la versione online è la %2. &OK - &OK + &OK &Cancel - &Annulla + &Annulla @@ -4318,14 +4323,14 @@ La tua versione è la %1, la versione online è la %2. Administration - Amministrazione + Amministrazione TabDeckEditor &Search... - &Cerca... + &Cerca... @@ -4424,11 +4429,11 @@ La tua versione è la %1, la versione online è la %2. Return - Return + Return Enter - Invio + Invio @@ -4437,11 +4442,11 @@ La tua versione è la %1, la versione online è la %2. Ctrl+Return - Ctrl+Return + Ctrl+Return Ctrl+Enter - Ctrl+Invio + Ctrl+Invio @@ -4626,7 +4631,7 @@ Please enter a name: Deck storage - Cartella mazzi + Cartella mazzi @@ -4875,7 +4880,7 @@ Please enter a name: Game replays - Replay partite + Replay partite @@ -4915,14 +4920,14 @@ Please enter a name: TabServer Server - Server + Server TabUserLists User lists - Lista utenti + Lista utenti diff --git a/cockatrice/translations/cockatrice_ja.ts b/cockatrice/translations/cockatrice_ja.ts index a3e9da12..388dfb50 100644 --- a/cockatrice/translations/cockatrice_ja.ts +++ b/cockatrice/translations/cockatrice_ja.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - 手札の背景画像へのパス: + 手札の背景画像へのパス: Path to stack background: - スタックゾーンの背景画像へのパス: + スタックゾーンの背景画像へのパス: Path to table background: - テーブルの背景画像へのパス: + テーブルの背景画像へのパス: Path to player info background: - プレイヤー画像へのパス: + プレイヤー画像へのパス: Path to picture of card back: - カード背面画像へのパス: + カード背面画像へのパス: @@ -780,7 +780,7 @@ This is only saved for moderators and cannot be seen by the banned person.DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - 価格タグを表示可能に(blacklotusproject.comからのデータを使用) + 価格タグを表示可能に(blacklotusproject.comからのデータを使用) @@ -919,32 +919,37 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: ホストIP: - + &Port: ポート: - + Player &name: プレイヤーネーム: - + P&assword: パスワード: - + &Save password - + + A&uto connect at start + + + + Connect to server サーバーに接続 @@ -1309,7 +1314,7 @@ This is only saved for moderators and cannot be seen by the banned person. Your card database is invalid. Would you like to go back and set the correct path? - あなたのカードデータベースは無効です.前に戻って正しいパスを設定してください. + あなたのカードデータベースは無効です.前に戻って正しいパスを設定してください. @@ -1697,7 +1702,7 @@ Would you like to change your database location setting? Path to card database: - カードデータベースのパス: + カードデータベースのパス: @@ -1823,7 +1828,7 @@ Reason for shutdown: %1 Czech: - チェコ語: + チェコ語: Slovak: @@ -1886,7 +1891,7 @@ Reason for shutdown: %1 Invalid login data. - 無効なログインデータです. + 無効なログインデータです. @@ -3148,12 +3153,12 @@ Local version is %1, remote version is %2. %1 has loaded a deck (%2). female - %1はデッキ%2をロードしました. + %1はデッキ%2をロードしました. %1 has loaded a deck (%2). male - %1はデッキ%2をロードしました. + %1はデッキ%2をロードしました. @@ -4039,11 +4044,11 @@ Local version is %1, remote version is %2. &OK - OK + OK &Cancel - Cancel + Cancel @@ -4090,7 +4095,7 @@ Local version is %1, remote version is %2. Administration - 管理者 + 管理者 @@ -4399,7 +4404,7 @@ Please enter a name: Deck storage - デッキストレージ + デッキストレージ @@ -4692,14 +4697,14 @@ Please enter a name: TabServer Server - サーバー + サーバー TabUserLists User lists - ユーザーリスト + ユーザーリスト diff --git a/cockatrice/translations/cockatrice_pl.ts b/cockatrice/translations/cockatrice_pl.ts index 7b5e8bed..a47a06a7 100644 --- a/cockatrice/translations/cockatrice_pl.ts +++ b/cockatrice/translations/cockatrice_pl.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -670,7 +670,7 @@ This is only saved for moderators and cannot be seen by the banned person.DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - Włącz oznaczenia &ceny (korzystając z danych z blacklotusproject.com) + Włącz oznaczenia &ceny (korzystając z danych z blacklotusproject.com) @@ -809,32 +809,37 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: - + &Port: - + Player &name: - + P&assword: - + &Save password - + + A&uto connect at start + + + + Connect to server @@ -1605,7 +1610,7 @@ Would you like to change your database location setting? Path to card database: - Ścieżka do bazy kart: + Ścieżka do bazy kart: @@ -4454,14 +4459,14 @@ Please enter a name: TabServer Server - Serwer + Serwer TabUserLists User lists - Lista użytkowników + Lista użytkowników diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index 44a33758..ebc3ba18 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - Caminho para o fundo da mão: + Caminho para o fundo da mão: Path to stack background: - Caminho para o fundo da pilha: + Caminho para o fundo da pilha: Path to table background: - Caminho para o fundo da mesa: + Caminho para o fundo da mesa: Path to player info background: - Caminho para o fundo das informações do jogador: + Caminho para o fundo das informações do jogador: Path to picture of card back: - Caminho para a imagem do verso dos cards: + Caminho para a imagem do verso dos cards: @@ -1264,30 +1264,35 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: &Servidor: - + &Port: &Porta: - + Player &name: Nome do &jogador: - + P&assword: S&enha: - + &Save password + + + A&uto connect at start + + &OK &OK @@ -1297,7 +1302,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Cancelar - + Connect to server Conectar ao servidor @@ -1702,7 +1707,7 @@ This is only saved for moderators and cannot be seen by the banned person. Your card database is invalid. Would you like to go back and set the correct path? - O seu banco de dados de cards é inválido. Você gostaria de voltar e corrigir o caminho? + O seu banco de dados de cards é inválido. Você gostaria de voltar e corrigir o caminho? @@ -2086,7 +2091,7 @@ Would you like to change your database location setting? Path to card database: - Caminho para o banco de dados dos cards: + Caminho para o banco de dados dos cards: @@ -2193,7 +2198,7 @@ Would you like to change your database location setting? Invalid login data. - Informações de login inválidas. + Informações de login inválidas. @@ -2882,7 +2887,7 @@ A versão local é %1 e a versão remota é %2. %1 has loaded a deck (%2). female - %1 carregou o deck %2. + %1 carregou o deck %2. %1 has loaded a deck (%2). @@ -4732,7 +4737,7 @@ A versão local é %1 e a versão remota é %2. Administration - Administração + Administração @@ -5060,7 +5065,7 @@ Por favor, entre um nome: Deck storage - Armazenamento de decks + Armazenamento de decks @@ -5353,14 +5358,14 @@ Por favor, entre um nome: TabServer Server - Servidor + Servidor TabUserLists User lists - Listas de usuários + Listas de usuários diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index 8364309f..e9a2c17f 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - Directório da imagem de fundo da mão: + Directório da imagem de fundo da mão: Path to stack background: - Directório da imagem de fundo da pilha: + Directório da imagem de fundo da pilha: Path to table background: - Directório da imagem de fundo do campo de batalha: + Directório da imagem de fundo do campo de batalha: Path to player info background: - Directório da imagem de fundo da informação de jogador: + Directório da imagem de fundo da informação de jogador: Path to picture of card back: - Directório da imagem do verso da carta: + Directório da imagem do verso da carta: @@ -1181,7 +1181,7 @@ Isto apenas é guardado para os moderadores e não é visível para a pessoa ban DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - &Permitir função de tag de preços (utilizando informação de blacklotusproject.com) + &Permitir função de tag de preços (utilizando informação de blacklotusproject.com) @@ -1327,30 +1327,35 @@ Isto apenas é guardado para os moderadores e não é visível para a pessoa ban DlgConnect - + &Host: &Servidor: - + &Port: &Porta: - + Player &name: &Nome do jogador: - + P&assword: P&assword: - + &Save password &Guardar password + + + A&uto connect at start + + &OK &OK @@ -1360,7 +1365,7 @@ Isto apenas é guardado para os moderadores e não é visível para a pessoa ban &Cancelar - + Connect to server Ligar ao servidor @@ -1761,7 +1766,7 @@ Isto apenas é guardado para os moderadores e não é visível para a pessoa ban Your card database is invalid. Would you like to go back and set the correct path? - A sua base de dados é inválida. Gostaria de voltar atrás e corrigir o directório? + A sua base de dados é inválida. Gostaria de voltar atrás e corrigir o directório? @@ -2155,11 +2160,11 @@ Would you like to change your database location setting? Path to card database: - Directório da base de dados de cartas: + Directório da base de dados de cartas: Path to token database: - Directório da base de dados de fichas: + Directório da base de dados de fichas: @@ -2264,7 +2269,7 @@ Would you like to change your database location setting? Invalid login data. - Informação de login incorrecta. + Informação de login incorrecta. @@ -2339,7 +2344,7 @@ Motivo para o encerramento: %1 Czech: - Checo: + Checo: Slovak: @@ -3662,12 +3667,12 @@ Versão local é %1, versão remota é %2. %1 has loaded a deck (%2). female - %1 carregou o deck %2. + %1 carregou o deck %2. %1 has loaded a deck (%2). male - %1 carregou o deck %2. + %1 carregou o deck %2. @@ -4260,7 +4265,7 @@ Versão local é %1, versão remota é %2. Ctrl+H - Ctrl+H + Ctrl+H @@ -4622,11 +4627,11 @@ Versão local é %1, versão remota é %2. Cockatrice decks (*.cod) - Decks do Cockatrice (*.cod) + Decks do Cockatrice (*.cod) Plain text decks (*.dec *.mwDeck) - Decks baseados em texto simples (*.dec *.mwDeck) + Decks baseados em texto simples (*.dec *.mwDeck) @@ -4762,11 +4767,11 @@ Versão local é %1, versão remota é %2. &OK - &OK + &OK &Cancel - &Cancelar + &Cancelar @@ -4813,7 +4818,7 @@ Versão local é %1, versão remota é %2. Administration - Administração + Administração @@ -4839,7 +4844,7 @@ Versão local é %1, versão remota é %2. TabDeckEditor &Search... - &Procurar... + &Procurar... @@ -4938,11 +4943,11 @@ Versão local é %1, versão remota é %2. Return - Return + Return Enter - Enter + Enter @@ -4951,11 +4956,11 @@ Versão local é %1, versão remota é %2. Ctrl+Return - Ctrl+Return + Ctrl+Return Ctrl+Enter - Ctrl+Enter + Ctrl+Enter @@ -5141,7 +5146,7 @@ Por favor introduza um nome: Deck storage - Armazenamento de decks + Armazenamento de decks @@ -5390,7 +5395,7 @@ Por favor introduza um nome: Game replays - Replays de jogos + Replays de jogos @@ -5438,14 +5443,14 @@ Por favor introduza um nome: TabServer Server - Servidor + Servidor TabUserLists User lists - Lista de utilizadores + Lista de utilizadores diff --git a/cockatrice/translations/cockatrice_ru.ts b/cockatrice/translations/cockatrice_ru.ts index 9580ccd5..881b7093 100644 --- a/cockatrice/translations/cockatrice_ru.ts +++ b/cockatrice/translations/cockatrice_ru.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - Рука: + Рука: Path to stack background: - Стек: + Стек: Path to table background: - Поле битвы: + Поле битвы: Path to player info background: - Панель игрока: + Панель игрока: Path to picture of card back: - Рубашки карт: + Рубашки карт: @@ -1091,7 +1091,7 @@ This is only saved for moderators and cannot be seen by the banned person.DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - Подписывать &цены (по данным blacklotusproject.com) + Подписывать &цены (по данным blacklotusproject.com) @@ -1230,30 +1230,35 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: &Хост: - + &Port: &Порт: - + Player &name: &Ник: - + P&assword: П&ароль: - + &Save password + + + A&uto connect at start + + &OK &Ок @@ -1263,7 +1268,7 @@ This is only saved for moderators and cannot be seen by the banned person.&Отмена - + Connect to server Соединение @@ -1668,7 +1673,7 @@ This is only saved for moderators and cannot be seen by the banned person. Your card database is invalid. Would you like to go back and set the correct path? - База карт не найдена. Вернуться и задать правильный путь? + База карт не найдена. Вернуться и задать правильный путь? @@ -2058,7 +2063,7 @@ Would you like to change your database location setting? Path to card database: - Путь к базе карт: + Путь к базе карт: @@ -2179,7 +2184,7 @@ Reason for shutdown: %1 Czech: - Чешский: + Чешский: Slovak: @@ -2242,7 +2247,7 @@ Reason for shutdown: %1 Invalid login data. - Неверный логин/пароль. + Неверный логин/пароль. @@ -2852,12 +2857,12 @@ Local version is %1, remote version is %2. %1 has loaded a deck (%2). female - %1 загрузила колоду %2. + %1 загрузила колоду %2. %1 has loaded a deck (%2). male - %1 загрузил колоду %2. + %1 загрузил колоду %2. @@ -4653,11 +4658,11 @@ Local version is %1, remote version is %2. &OK - &Ок + &Ок &Cancel - &Отмена + &Отмена @@ -4704,7 +4709,7 @@ Local version is %1, remote version is %2. Administration - Администрирование + Администрирование @@ -4997,7 +5002,7 @@ Please enter a name: Deck storage - Хранилище колод + Хранилище колод @@ -5282,14 +5287,14 @@ Please enter a name: TabServer Server - Сервер + Сервер TabUserLists User lists - Панели пользователей + Панели пользователей diff --git a/cockatrice/translations/cockatrice_sk.ts b/cockatrice/translations/cockatrice_sk.ts index 7f8295f6..7539da25 100644 --- a/cockatrice/translations/cockatrice_sk.ts +++ b/cockatrice/translations/cockatrice_sk.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -725,32 +725,37 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: - + &Port: - + Player &name: - + P&assword: - + &Save password - + + A&uto connect at start + + + + Connect to server diff --git a/cockatrice/translations/cockatrice_sv.ts b/cockatrice/translations/cockatrice_sv.ts index 8a402f35..62e5378e 100644 --- a/cockatrice/translations/cockatrice_sv.ts +++ b/cockatrice/translations/cockatrice_sv.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -43,23 +43,23 @@ Path to hand background: - Sökväg till handbakgrund: + Sökväg till handbakgrund: Path to stack background: - Sökväg till stapelbakgrund: + Sökväg till stapelbakgrund: Path to table background: - Sökväg till bordbakgrund: + Sökväg till bordbakgrund: Path to player info background: - Sökväg till spelarinfobakgrund: + Sökväg till spelarinfobakgrund: Path to picture of card back: - Sökväg till kortbaksidans bild: + Sökväg till kortbaksidans bild: @@ -923,7 +923,7 @@ Detta sparas endast för moderatorer och kan inte ses av den bannlysta personen. DeckEditorSettingsPage Enable &price tag feature (using data from blacklotusproject.com) - Aktivera &prislappsfunktionen (använder data från blacklotusproject.com) + Aktivera &prislappsfunktionen (använder data från blacklotusproject.com) @@ -1062,30 +1062,35 @@ Detta sparas endast för moderatorer och kan inte ses av den bannlysta personen. DlgConnect - + &Host: &Värd: - + &Port: &Port: - + Player &name: Spelar&namn: - + P&assword: &Lösenord: - + &Save password &Spara lösenord + + + A&uto connect at start + + &OK &OK @@ -1095,7 +1100,7 @@ Detta sparas endast för moderatorer och kan inte ses av den bannlysta personen. &Avbryt - + Connect to server Anslut till server @@ -1492,7 +1497,7 @@ Detta sparas endast för moderatorer och kan inte ses av den bannlysta personen. Your card database is invalid. Would you like to go back and set the correct path? - Din kortdatabas är ogiltig. Vill du gå tillbaka och ange den korrekta sökvägen? + Din kortdatabas är ogiltig. Vill du gå tillbaka och ange den korrekta sökvägen? @@ -1878,11 +1883,11 @@ Would you like to change your database location setting? Path to card database: - Sökväg till kortdatabas: + Sökväg till kortdatabas: Path to token database: - Sökväg till jetongdatabas: + Sökväg till jetongdatabas: @@ -2030,7 +2035,7 @@ Anledning till nedstängning: %1 Czech: - Tjeckiska: + Tjeckiska: @@ -2063,7 +2068,7 @@ Anledning till nedstängning: %1 Invalid login data. - Ogiltig inloggningsdata. + Ogiltig inloggningsdata. @@ -2280,12 +2285,12 @@ Lokal version är %1, avlägsen version är %2. %1 has loaded a deck (%2). female - %1 har laddat en lek (%2). + %1 har laddat en lek (%2). %1 has loaded a deck (%2). male - %1 har laddat en lek (%2). + %1 har laddat en lek (%2). @@ -4054,11 +4059,11 @@ Lokal version är %1, avlägsen version är %2. Cockatrice decks (*.cod) - Cockatricelekar (*.cod) + Cockatricelekar (*.cod) Plain text decks (*.dec *.mwDeck) - Klartextlekar (*.dec *.mwDeck) + Klartextlekar (*.dec *.mwDeck) @@ -4187,11 +4192,11 @@ Lokal version är %1, avlägsen version är %2. &OK - &OK + &OK &Cancel - &Avbryt + &Avbryt @@ -4238,14 +4243,14 @@ Lokal version är %1, avlägsen version är %2. Administration - Administration + Administration TabDeckEditor &Search... - &Sök... + &Sök... @@ -4529,7 +4534,7 @@ Please enter a name: Deck storage - Leklagring + Leklagring @@ -4778,7 +4783,7 @@ Please enter a name: Game replays - Spelrepriser + Spelrepriser @@ -4818,14 +4823,14 @@ Please enter a name: TabServer Server - Server + Server TabUserLists User lists - Användarlistor + Användarlistor diff --git a/cockatrice/translations/cockatrice_zh_CN.ts b/cockatrice/translations/cockatrice_zh_CN.ts index 04d26fca..21ccff1a 100644 --- a/cockatrice/translations/cockatrice_zh_CN.ts +++ b/cockatrice/translations/cockatrice_zh_CN.ts @@ -1,6 +1,6 @@ - + AbstractCounter @@ -725,32 +725,37 @@ This is only saved for moderators and cannot be seen by the banned person. DlgConnect - + &Host: - + &Port: - + Player &name: - + P&assword: - + &Save password - + + A&uto connect at start + + + + Connect to server diff --git a/common/server.cpp b/common/server.cpp index 6ab4750e..ff49a6dc 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -34,7 +34,6 @@ #include #include #include -#include Server::Server(bool _threaded, QObject *parent) : QObject(parent), threaded(_threaded), nextLocalGameId(0) @@ -132,8 +131,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString } else if (authState == UnknownUser) { // Change user name so that no two users have the same names, // don't interfere with registered user names though. - QSettings settings("servatrice.ini", QSettings::IniFormat); - bool requireReg = settings.value("authentication/regonly", 0).toBool(); + bool requireReg = databaseInterface->getRequireRegistration(); if (requireReg) { qDebug("Login denied: registration required"); databaseInterface->unlockSessionTables(); diff --git a/common/server_database_interface.h b/common/server_database_interface.h index 798ae9d9..a08e9526 100644 --- a/common/server_database_interface.h +++ b/common/server_database_interface.h @@ -2,6 +2,7 @@ #define SERVER_DATABASE_INTERFACE_H #include +#include #include "server.h" @@ -32,6 +33,8 @@ public: virtual void lockSessionTables() { } virtual void unlockSessionTables() { } virtual bool userSessionExists(const QString & /* userName */) { return false; } + + virtual bool getRequireRegistration() { return false; } }; #endif diff --git a/oracle/src/oracleimporter.cpp b/oracle/src/oracleimporter.cpp index 6a099eb4..48172c48 100644 --- a/oracle/src/oracleimporter.cpp +++ b/oracle/src/oracleimporter.cpp @@ -210,11 +210,13 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data) } } - CardInfo *card = addCard(set->getShortName(), cardName, cardIsToken, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n")); + if (!cardIsToken) { + CardInfo *card = addCard(set->getShortName(), cardName, cardIsToken, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n")); - if (!set->contains(card)) { - card->addToSet(set); - cards++; + if (!set->contains(card)) { + card->addToSet(set); + cards++; + } } } diff --git a/oracle/src/oraclewizard.cpp b/oracle/src/oraclewizard.cpp index c1c8b982..79ad5414 100644 --- a/oracle/src/oraclewizard.cpp +++ b/oracle/src/oraclewizard.cpp @@ -7,6 +7,7 @@ #endif #include #include +#include #include #include #include @@ -403,15 +404,13 @@ bool SaveSetsPage::validatePage() QStandardPaths::standardLocations(QStandardPaths::DataLocation).first(); #endif QSettings* settings = new QSettings(this); - QString savePath = settings->value("paths/carddatabase").toString(); - if (savePath.isEmpty()) { - QDir().mkpath(dataDir); - } + QString defaultPath = settings->value("paths/carddatabase").toString(); QString windowName = tr("Save card database"); QString fileType = tr("XML; card database (*.xml)"); + do { QString fileName; - if (savePath.isEmpty()) { + if (defaultPath.isEmpty()) { if (defaultPathCheckBox->isChecked()) fileName = dataDir + "/cards.xml"; else @@ -420,19 +419,25 @@ bool SaveSetsPage::validatePage() } else { if (defaultPathCheckBox->isChecked()) - fileName = savePath; + fileName = defaultPath; else - fileName = QFileDialog::getSaveFileName(this, windowName, savePath, fileType); + fileName = QFileDialog::getSaveFileName(this, windowName, defaultPath, fileType); } if (fileName.isEmpty()) { return false; } + + QFileInfo fi(fileName); + QDir fileDir(fi.path()); + if (!fileDir.exists() && !fileDir.mkpath(fileDir.absolutePath())) { + return false; + } if (wizard()->importer->saveToFile(fileName)) { ok = true; QMessageBox::information(this, tr("Success"), tr("The card database has been saved successfully.")); } else { - QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to the desired location.")); + QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to %1").arg(fileName));; if (defaultPathCheckBox->isChecked()) defaultPathCheckBox->setChecked(false); } diff --git a/servatrice/CMakeLists.txt b/servatrice/CMakeLists.txt index 42e2bb74..4d719f6b 100644 --- a/servatrice/CMakeLists.txt +++ b/servatrice/CMakeLists.txt @@ -4,8 +4,6 @@ PROJECT(servatrice) -FIND_PACKAGE(Libgcrypt REQUIRED) - SET(servatrice_SOURCES src/main.cpp src/passwordhasher.cpp @@ -14,10 +12,24 @@ SET(servatrice_SOURCES src/servatrice_database_interface.cpp src/server_logger.cpp src/serversocketinterface.cpp + src/settingscache.cpp src/isl_interface.cpp ${VERSION_STRING_CPP} ) +set(servatrice_RESOURCES servatrice.qrc) + +if(WIN32) + set(servatrice_SOURCES ${servatrice_SOURCES} servatrice.rc) +endif(WIN32) + + +if(APPLE) + set(MACOSX_BUNDLE_ICON_FILE appicon.icns) + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + set(servatrice_SOURCES ${servatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns) +ENDIF(APPLE) + set(SERVATRICE_LIBS) # Qt4 stuff @@ -29,6 +41,11 @@ if(Qt4_FOUND) INCLUDE(${QT_USE_FILE}) include_directories(${QT_INCLUDES}) LIST(APPEND SERVATRICE_LIBS ${QT_LIBRARIES}) + + # Libgcrypt is required only with Qt4 to support SHA512 hashing + FIND_PACKAGE(Libgcrypt REQUIRED) + INCLUDE_DIRECTORIES(${LIBGCRYPT_INCLUDE_DIR}) + QT4_ADD_RESOURCES(servatrice_RESOURCES_RCC ${servatrice_RESOURCES}) endif() # qt5 stuff @@ -50,6 +67,8 @@ if(Qt5Widgets_FOUND) list(APPEND SERVATRICE_LIBS Sql) endif() + QT5_ADD_RESOURCES(servatrice_RESOURCES_RCC ${servatrice_RESOURCES}) + # guess plugins and libraries directory set(QT_PLUGINS_DIR "${Qt5Widgets_DIR}/../../../plugins") get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION) @@ -60,13 +79,12 @@ SET(QT_DONT_USE_QTGUI TRUE) # Include directories INCLUDE_DIRECTORIES(../common) -INCLUDE_DIRECTORIES(${LIBGCRYPT_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/../common) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) # Build servatrice binary and link it -ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_MOC_SRCS}) +ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_RESOURCES_RCC} ${servatrice_MOC_SRCS}) if(Qt4_FOUND) if(MSVC) @@ -87,12 +105,18 @@ endif() if(UNIX) if(APPLE) INSTALL(TARGETS servatrice BUNDLE DESTINATION ./) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/servatrice.ini.example DESTINATION ./servatrice.app/Contents/Resources/) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/servatrice.sql DESTINATION ./servatrice.app/Contents/Resources/) else() # Assume linux INSTALL(TARGETS servatrice RUNTIME DESTINATION bin/) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/servatrice.ini.example DESTINATION share/servatice/) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/servatrice.sql DESTINATION share/servatice/) endif() elseif(WIN32) INSTALL(TARGETS servatrice RUNTIME DESTINATION ./) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/servatrice.ini.example DESTINATION ./) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/servatrice.sql DESTINATION ./) endif() if(APPLE) diff --git a/servatrice/resources/appicon.icns b/servatrice/resources/appicon.icns new file mode 100644 index 00000000..2dece9b0 Binary files /dev/null and b/servatrice/resources/appicon.icns differ diff --git a/servatrice/resources/appicon.ico b/servatrice/resources/appicon.ico new file mode 100644 index 00000000..35663487 Binary files /dev/null and b/servatrice/resources/appicon.ico differ diff --git a/servatrice/resources/servatrice.png b/servatrice/resources/servatrice.png new file mode 100644 index 00000000..7d701ef0 Binary files /dev/null and b/servatrice/resources/servatrice.png differ diff --git a/servatrice/resources/servatrice.svg b/servatrice/resources/servatrice.svg new file mode 100644 index 00000000..580a04be --- /dev/null +++ b/servatrice/resources/servatrice.svg @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/servatrice/servatrice.desktop b/servatrice/servatrice.desktop new file mode 100644 index 00000000..635afe6b --- /dev/null +++ b/servatrice/servatrice.desktop @@ -0,0 +1,8 @@ +#!/usr/bin/env xdg-open +[Desktop Entry] +Version=1.0 +Type=Application +Name=Servatrice +Exec=servatrice +Icon=servatrice +Categories=Game;CardGame; diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 14926463..05a5ba3a 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -1,50 +1,160 @@ +; Servatrice configuration file +; +; This is the main configuration file for Servatrice; while using a configuration is not mandatory, +; you may want to customize some aspects of your servatrice instance, like its name, port or the way +; users can authenticate to the server. + + [server] -port=4747 -statusupdate=15000 -logfile=server.log + +; This is the name that servatrice exposes to the users; the default value is pretty boring name="My Cockatrice server" + +; Multiple servatrice servers can run on the same host using the same database; each server instance +; must have a different id; the default id is 1 id=1 + +; The TCP port number servatrice will listen on for clients; default is 4747 +port=4747 + +; Servatrice can scale up to serve big number of users using more than one parallel thread of execution; +; If your server is hosting a lot of players and they frequently report of being unable to login or +; long delays (lag), you may want to try increasing this value; default is 1. number_pools=1 + +; When database is enabled, servatrice writes the server status in the "update" database table; this +; setting defines every how many milliseconds servatrice will update its status; default is 15000 (15 secs) +statusupdate=15000 + +; Do you want servatrice to write important events and errors to a logfile? Default is 1 (yes). writelog=1 + +; Choose a name for the log file, if enabled; you can specify an absolute path or a path relative to +; the servatrice executable; the default file name is server.log (in the same path as servatrice) +logfile=server.log + +; You may want to silence some commonly recurring messages in the logfile. This setting can contain a +; comma-separed list of words; if any message that is about to be logged contains at least one of these words, +; it won't be logged. Default is empty; example: "kittens,ponies,faires" logfilters="" -[servernetwork] -active=0 -port=14747 -ssl_cert=ssl_cert.pem -ssl_key=ssl_key.pem [authentication] + +; Servatrice can authenticate users connecting. It currently supports 3 different authentication methods: +; * none: no authentication, accept every user; +; * password: require users to specify a common password to log in; +; * sql: authenticate users against the "users" table of the database; +; Please note that only the "sql" method permits to have registered users and store their data on the server. method=none + +; if the chosen authentication method is password, here you can define the password your users will use to log in +password=123456 + +; Accept only registered users? default is 0 (accept unregistered users) regonly=0 + [database] + +; Database type. Valid values are: +; * none: no database; +; * mysql: mysql or compatible database; type=none + +; Prefix used in he database for table names; default is cockatrice prefix=cockatrice + +; Database connection parameter: server hostname or IP hostname=localhost + +; Database connection parameter: database name database=servatrice + +; Database connection parameter: database user user=servatrice + +; Database connection parameter: database user's password password=foobar [rooms] + +; A servtrice server can expose to the users different "rooms" to chat and create games. Rooms can be defined +; with two different methods: +; config: rooms are defined in this configuration (see the following example) +; sql: rooms are defined in the "rooms" table of the database method=config + +; Example configuration for a server with rooms configured in the configuration file. Number of rooms defined roomlist\size=1 + +; Room name for the room number 1 roomlist\1\name="General room" + +; Room description for the room number 1 roomlist\1\description="Play anything here." + +; Wether to make users autojoin this room when connected to the server roomlist\1\autojoin=true + +; Message displayed to each user when he joins room number 1 roomlist\1\joinmessage="This message is only here to show that rooms can have a join message." + +; Number of game types allowed (defined) in the room number 1 roomlist\1\game_types\size=3 + +; Name of the three game types for the room number 1 roomlist\1\game_types\1\name="GameType1" roomlist\1\game_types\2\name="GameType2" roomlist\1\game_types\3\name="GameType3" + [game] -max_game_inactivity_time=120 + +; Maximum time in seconds a player can stay inactive, with his client hot even responding to pings, before is +; considered disconnected; default is 15 max_player_inactivity_time=15 +; Maximum time in seconds all players in a game can stay inactive before the game is automatically closed; +; default is 120 +max_game_inactivity_time=120 + + [security] + +; Maximum number of users that can connect from the same IP address; useful to avoid bots, default is 4 max_users_per_address=4 + +; Servatrice can avoid users from flooding rooms with large number messages in an interval of time. +; This setting defines the length in seconds of the considered interval; default is 10 message_counting_interval=10 + +; Maximum size in characters of all messages in an interval before new messages gets dropped; default is 1000 max_message_size_per_interval=1000 + +; Maximum number of messages in an interval before new messages gets dropped; default is 10 max_message_count_per_interval=10 + +; Maximum number of games a single user can create; default is 5 max_games_per_user=5 + + +; EXPERIMENTAL - NOT WORKING YET +; The following settings are relative to the server network functionality, that is not yet complete. +; Avoid enabling it unless you are willing to test it and help its development. + +[servernetwork] + +; Servatrice servers can connect themselves and build a network. This settins enable the ability of servatrice +; of waiting for other server's connections and connect to other servers. Other servers can be defined in the +; "servers" table of the database. Default is 0 (disabled) +active=0 + +; The TCP port number servatrice will listen on for other servers; default is 14747 +port=14747 + +; Server-to-server communication needs a valid certificate in PEM format. Enter its filename in this setting +ssl_cert=ssl_cert.pem + +; Filename of the private key for the server-to-server certificate +ssl_key=ssl_key.pem diff --git a/servatrice/servatrice.qrc b/servatrice/servatrice.qrc new file mode 100644 index 00000000..f9cf3ef9 --- /dev/null +++ b/servatrice/servatrice.qrc @@ -0,0 +1,5 @@ + + + resources/servatrice.svg + + diff --git a/servatrice/servatrice.rc b/servatrice/servatrice.rc new file mode 100644 index 00000000..cf949f31 --- /dev/null +++ b/servatrice/servatrice.rc @@ -0,0 +1 @@ +ID1_ICON1 ICON DISCARDABLE "resources/appicon.ico" diff --git a/servatrice/servatrice.sql b/servatrice/servatrice.sql index 6e83f1f2..70b96a02 100644 --- a/servatrice/servatrice.sql +++ b/servatrice/servatrice.sql @@ -1,4 +1,4 @@ --- phpMyAdmin SQL Dump +-- phpMyAdmin SQL Dump -- version 2.11.8.1deb1ubuntu0.2 -- http://www.phpmyadmin.net -- @@ -208,3 +208,18 @@ CREATE TABLE `cockatrice_replays_access` ( KEY `id_game` (`id_game`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +CREATE TABLE IF NOT EXISTS `cockatrice_rooms` ( +`id` int(7) unsigned NOT NULL auto_increment, +`name` varchar(50) NOT NULL, +`descr` varchar(255) NOT NULL, +`auto_join` tinyint(1) default 0, +`join_message` varchar(255) NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `cockatrice_rooms_gametypes` ( +`id_room` int(7) unsigned NOT NULL, +`name` varchar(50) NOT NULL, +PRIMARY KEY (`id_room`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + diff --git a/servatrice/src/main.cpp b/servatrice/src/main.cpp index d90e0634..6c29e8be 100644 --- a/servatrice/src/main.cpp +++ b/servatrice/src/main.cpp @@ -20,13 +20,14 @@ #include #include +#include #include #include -#include #include #include "passwordhasher.h" #include "servatrice.h" #include "server_logger.h" +#include "settingscache.h" #include "rng_sfmt.h" #include "version_string.h" #include @@ -37,6 +38,7 @@ RNG_Abstract *rng; ServerLogger *logger; QThread *loggerThread; +SettingsCache *settingsCache; /* Prototypes */ @@ -150,6 +152,10 @@ int main(int argc, char *argv[]) bool testRandom = args.contains("--test-random"); bool testHashFunction = args.contains("--test-hash"); bool logToConsole = args.contains("--log-to-console"); + QString configPath; + int hasConfigPath=args.indexOf("--config"); + if(hasConfigPath > -1 && args.count() > hasConfigPath + 1) + configPath = args.at(hasConfigPath + 1); qRegisterMetaType >("QList"); @@ -158,7 +164,9 @@ int main(int argc, char *argv[]) QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); #endif - QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat); + configPath = SettingsCache::guessConfigurationPath(configPath); + qWarning() << "Using configuration file: " << configPath; + settingsCache = new SettingsCache(configPath); loggerThread = new QThread; loggerThread->setObjectName("logger"); @@ -166,7 +174,7 @@ int main(int argc, char *argv[]) logger->moveToThread(loggerThread); loggerThread->start(); - QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settings->value("server/logfile").toString())); + QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settingsCache->value("server/logfile", QString("server.log")).toString())); #if QT_VERSION < 0x050000 if (logToConsole) @@ -209,7 +217,7 @@ int main(int argc, char *argv[]) if (testHashFunction) testHash(); - Servatrice *server = new Servatrice(settings); + Servatrice *server = new Servatrice(); QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection); int retval = 0; if (server->initServer()) { @@ -228,7 +236,7 @@ int main(int argc, char *argv[]) } delete rng; - delete settings; + delete settingsCache; logger->deleteLater(); loggerThread->wait(); diff --git a/servatrice/src/passwordhasher.cpp b/servatrice/src/passwordhasher.cpp index 0d8cda36..554c8f2f 100644 --- a/servatrice/src/passwordhasher.cpp +++ b/servatrice/src/passwordhasher.cpp @@ -1,32 +1,53 @@ #include "passwordhasher.h" -#include -#include -#include + +#if QT_VERSION < 0x050000 + #include + #include + #include +#else + #include +#endif void PasswordHasher::initialize() { - // These calls are required by libgcrypt before we use any of its functions. - gcry_check_version(0); - gcry_control(GCRYCTL_DISABLE_SECMEM, 0); - gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); +#if QT_VERSION < 0x050000 + // These calls are required by libgcrypt before we use any of its functions. + gcry_check_version(0); + gcry_control(GCRYCTL_DISABLE_SECMEM, 0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); +#endif } +#if QT_VERSION < 0x050000 QString PasswordHasher::computeHash(const QString &password, const QString &salt) { - const int algo = GCRY_MD_SHA512; - const int rounds = 1000; + const int algo = GCRY_MD_SHA512; + const int rounds = 1000; - QByteArray passwordBuffer = (salt + password).toUtf8(); - int hashLen = gcry_md_get_algo_dlen(algo); - char *hash = new char[hashLen], *tmp = new char[hashLen]; - gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size()); - for (int i = 1; i < rounds; ++i) { - memcpy(tmp, hash, hashLen); - gcry_md_hash_buffer(algo, hash, tmp, hashLen); - } - QString hashedPass = salt + QString(QByteArray(hash, hashLen).toBase64()); - delete[] tmp; - delete[] hash; - return hashedPass; + QByteArray passwordBuffer = (salt + password).toUtf8(); + int hashLen = gcry_md_get_algo_dlen(algo); + char *hash = new char[hashLen], *tmp = new char[hashLen]; + gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size()); + for (int i = 1; i < rounds; ++i) { + memcpy(tmp, hash, hashLen); + gcry_md_hash_buffer(algo, hash, tmp, hashLen); + } + QString hashedPass = salt + QString(QByteArray(hash, hashLen).toBase64()); + delete[] tmp; + delete[] hash; + return hashedPass; } +#else +QString PasswordHasher::computeHash(const QString &password, const QString &salt) +{ + QCryptographicHash::Algorithm algo = QCryptographicHash::Sha512; + const int rounds = 1000; + QByteArray hash = (salt + password).toUtf8(); + for (int i = 0; i < rounds; ++i) { + hash = QCryptographicHash::hash(hash, algo); + } + QString hashedPass = salt + QString(hash.toBase64()); + return hashedPass; +} +#endif diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 4c9b4a06..168c230c 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -18,7 +18,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include -#include #include #include #include @@ -28,6 +27,7 @@ #include "servatrice_database_interface.h" #include "servatrice_connection_pool.h" #include "server_room.h" +#include "settingscache.h" #include "serversocketinterface.h" #include "isl_interface.h" #include "server_logger.h" @@ -120,8 +120,8 @@ void Servatrice_IslServer::incomingConnection(int socketDescriptor) QMetaObject::invokeMethod(interface, "initServer", Qt::QueuedConnection); } -Servatrice::Servatrice(QSettings *_settings, QObject *parent) - : Server(true, parent), settings(_settings), uptime(0), shutdownTimer(0) +Servatrice::Servatrice(QObject *parent) + : Server(true, parent), uptime(0), shutdownTimer(0) { qRegisterMetaType("QSqlDatabase"); } @@ -134,22 +134,28 @@ Servatrice::~Servatrice() bool Servatrice::initServer() { - serverName = settings->value("server/name").toString(); - serverId = settings->value("server/id", 0).toInt(); - bool regServerOnly = settings->value("server/regonly", 0).toBool(); + serverName = settingsCache->value("server/name", "My Cockatrice server").toString(); + serverId = settingsCache->value("server/id", 0).toInt(); + bool regServerOnly = settingsCache->value("authentication/regonly", 0).toBool(); - const QString authenticationMethodStr = settings->value("authentication/method").toString(); + const QString authenticationMethodStr = settingsCache->value("authentication/method").toString(); if (authenticationMethodStr == "sql") { + qDebug() << "Authenticating method: sql"; authenticationMethod = AuthenticationSql; + } else if(authenticationMethodStr == "password") { + qDebug() << "Authenticating method: password"; + authenticationMethod = AuthenticationPassword; } else { if (regServerOnly) { - qDebug() << "Registration only server enabled but no DB Connection : Error."; + qDebug() << "Registration only server enabled but no authentication method defined: Error."; return false; } + + qDebug() << "Authenticating method: none"; authenticationMethod = AuthenticationNone; } - QString dbTypeStr = settings->value("database/type").toString(); + QString dbTypeStr = settingsCache->value("database/type").toString(); if (dbTypeStr == "mysql") databaseType = DatabaseMySql; else @@ -159,14 +165,14 @@ bool Servatrice::initServer() setDatabaseInterface(servatriceDatabaseInterface); if (databaseType != DatabaseNone) { - settings->beginGroup("database"); - dbPrefix = settings->value("prefix").toString(); + settingsCache->beginGroup("database"); + dbPrefix = settingsCache->value("prefix").toString(); servatriceDatabaseInterface->initDatabase("QMYSQL", - settings->value("hostname").toString(), - settings->value("database").toString(), - settings->value("user").toString(), - settings->value("password").toString()); - settings->endGroup(); + settingsCache->value("hostname").toString(), + settingsCache->value("database").toString(), + settingsCache->value("user").toString(), + settingsCache->value("password").toString()); + settingsCache->endGroup(); updateServerList(); @@ -174,7 +180,7 @@ bool Servatrice::initServer() servatriceDatabaseInterface->clearSessionTables(); } - const QString roomMethod = settings->value("rooms/method").toString(); + const QString roomMethod = settingsCache->value("rooms/method").toString(); if (roomMethod == "sql") { QSqlQuery query(servatriceDatabaseInterface->getDatabase()); query.prepare("select id, name, descr, auto_join, join_message from " + dbPrefix + "_rooms order by id asc"); @@ -198,47 +204,63 @@ bool Servatrice::initServer() )); } } else { - int size = settings->beginReadArray("rooms/roomlist"); + int size = settingsCache->beginReadArray("rooms/roomlist"); for (int i = 0; i < size; ++i) { - settings->setArrayIndex(i); + settingsCache->setArrayIndex(i); QStringList gameTypes; - int size2 = settings->beginReadArray("game_types"); + int size2 = settingsCache->beginReadArray("game_types"); for (int j = 0; j < size2; ++j) { - settings->setArrayIndex(j); - gameTypes.append(settings->value("name").toString()); + settingsCache->setArrayIndex(j); + gameTypes.append(settingsCache->value("name").toString()); } - settings->endArray(); + settingsCache->endArray(); Server_Room *newRoom = new Server_Room( i, - settings->value("name").toString(), - settings->value("description").toString(), - settings->value("autojoin").toBool(), - settings->value("joinmessage").toString(), + settingsCache->value("name").toString(), + settingsCache->value("description").toString(), + settingsCache->value("autojoin").toBool(), + settingsCache->value("joinmessage").toString(), gameTypes, this ); addRoom(newRoom); } - settings->endArray(); + + if(size==0) + { + // no room defined in config, add a dummy one + Server_Room *newRoom = new Server_Room( + 0, + "General room", + "Play anything here.", + true, + "", + QStringList("Standard"), + this + ); + addRoom(newRoom); + } + + settingsCache->endArray(); } updateLoginMessage(); - maxGameInactivityTime = settings->value("game/max_game_inactivity_time").toInt(); - maxPlayerInactivityTime = settings->value("game/max_player_inactivity_time").toInt(); + maxGameInactivityTime = settingsCache->value("game/max_game_inactivity_time", 120).toInt(); + maxPlayerInactivityTime = settingsCache->value("game/max_player_inactivity_time", 15).toInt(); - maxUsersPerAddress = settings->value("security/max_users_per_address").toInt(); - messageCountingInterval = settings->value("security/message_counting_interval").toInt(); - maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt(); - maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt(); - maxGamesPerUser = settings->value("security/max_games_per_user").toInt(); + maxUsersPerAddress = settingsCache->value("security/max_users_per_address", 4).toInt(); + messageCountingInterval = settingsCache->value("security/message_counting_interval", 10).toInt(); + maxMessageCountPerInterval = settingsCache->value("security/max_message_count_per_interval", 10).toInt(); + maxMessageSizePerInterval = settingsCache->value("security/max_message_size_per_interval", 1000).toInt(); + maxGamesPerUser = settingsCache->value("security/max_games_per_user", 5).toInt(); - try { if (settings->value("servernetwork/active", 0).toInt()) { + try { if (settingsCache->value("servernetwork/active", 0).toInt()) { qDebug() << "Connecting to ISL network."; - const QString certFileName = settings->value("servernetwork/ssl_cert").toString(); - const QString keyFileName = settings->value("servernetwork/ssl_key").toString(); + const QString certFileName = settingsCache->value("servernetwork/ssl_cert").toString(); + const QString keyFileName = settingsCache->value("servernetwork/ssl_key").toString(); qDebug() << "Loading certificate..."; QFile certFile(certFileName); if (!certFile.open(QIODevice::ReadOnly)) @@ -282,7 +304,7 @@ bool Servatrice::initServer() QMetaObject::invokeMethod(interface, "initClient", Qt::BlockingQueuedConnection); } - const int networkPort = settings->value("servernetwork/port", 14747).toInt(); + const int networkPort = settingsCache->value("servernetwork/port", 14747).toInt(); qDebug() << "Starting ISL server on port" << networkPort; islServer = new Servatrice_IslServer(this, cert, key, this); @@ -299,7 +321,7 @@ bool Servatrice::initServer() connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); pingClock->start(1000); - int statusUpdateTime = settings->value("server/statusupdate").toInt(); + int statusUpdateTime = settingsCache->value("server/statusupdate", 15000).toInt(); statusUpdateClock = new QTimer(this); connect(statusUpdateClock, SIGNAL(timeout()), this, SLOT(statusUpdate())); if (statusUpdateTime != 0) { @@ -307,10 +329,10 @@ bool Servatrice::initServer() statusUpdateClock->start(statusUpdateTime); } - const int numberPools = settings->value("server/number_pools", 1).toInt(); + const int numberPools = settingsCache->value("server/number_pools", 1).toInt(); gameServer = new Servatrice_GameServer(this, numberPools, servatriceDatabaseInterface->getDatabase(), this); gameServer->setMaxPendingConnections(1000); - const int gamePort = settings->value("server/port", 4747).toInt(); + const int gamePort = settingsCache->value("server/port", 4747).toInt(); qDebug() << "Starting server on port" << gamePort; if (gameServer->listen(QHostAddress::Any, gamePort)) qDebug() << "Server listening."; diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 2b991512..86da6dc5 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -32,7 +32,6 @@ Q_DECLARE_METATYPE(QSqlDatabase) -class QSettings; class QSqlQuery; class QTimer; @@ -89,7 +88,7 @@ class Servatrice : public Server { Q_OBJECT public: - enum AuthenticationMethod { AuthenticationNone, AuthenticationSql }; + enum AuthenticationMethod { AuthenticationNone, AuthenticationSql, AuthenticationPassword }; private slots: void statusUpdate(); void shutdownTimeout(); @@ -106,7 +105,6 @@ private: mutable QMutex loginMessageMutex; QString loginMessage; QString dbPrefix; - QSettings *settings; Servatrice_DatabaseInterface *servatriceDatabaseInterface; int serverId; int uptime; @@ -128,7 +126,7 @@ public slots: void scheduleShutdown(const QString &reason, int minutes); void updateLoginMessage(); public: - Servatrice(QSettings *_settings, QObject *parent = 0); + Servatrice(QObject *parent = 0); ~Servatrice(); bool initServer(); QString getServerName() const { return serverName; } diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index 58856f4f..a8c27e09 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -2,6 +2,7 @@ #include "servatrice_database_interface.h" #include "passwordhasher.h" #include "serversocketinterface.h" +#include "settingscache.h" #include "decklist.h" #include "pb/game_replay.pb.h" #include @@ -88,10 +89,22 @@ bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user) return (result.size() > 0); } +bool Servatrice_DatabaseInterface::getRequireRegistration() +{ + return settingsCache->value("authentication/regonly", 0).toBool(); +} + AuthenticationResult Servatrice_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &banSecondsLeft) { switch (server->getAuthenticationMethod()) { case Servatrice::AuthenticationNone: return UnknownUser; + case Servatrice::AuthenticationPassword: { + QString configPassword = settingsCache->value("authentication/password").toString(); + if (configPassword == password) + return PasswordRight; + + return NotLoggedIn; + } case Servatrice::AuthenticationSql: { if (!checkSql()) return UnknownUser; diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index e1d6d813..8e8ab5c6 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -50,7 +50,8 @@ public: void lockSessionTables(); void unlockSessionTables(); bool userSessionExists(const QString &userName); - + + bool getRequireRegistration(); }; #endif diff --git a/servatrice/src/server_logger.cpp b/servatrice/src/server_logger.cpp index a3e92aff..1a1e4bed 100644 --- a/servatrice/src/server_logger.cpp +++ b/servatrice/src/server_logger.cpp @@ -1,9 +1,9 @@ #include "server_logger.h" +#include "settingscache.h" #include #include #include #include -#include #include #ifdef Q_OS_UNIX # include @@ -26,7 +26,7 @@ ServerLogger::~ServerLogger() void ServerLogger::startLog(const QString &logFileName) { if (!logFileName.isEmpty()) { - logFile = new QFile("server.log", this); + logFile = new QFile(logFileName, this); logFile->open(QIODevice::Append); #ifdef Q_OS_UNIX ::socketpair(AF_UNIX, SOCK_STREAM, 0, sigHupFD); @@ -50,9 +50,8 @@ void ServerLogger::logMessage(QString message, void *caller) callerString = QString::number((qulonglong) caller, 16) + " "; //filter out all log entries based on values in configuration file - QSettings settings("servatrice.ini", QSettings::IniFormat); - bool shouldWeWriteLog = settings.value("server/writelog").toBool(); - QString logFilters = settings.value("server/logfilters").toString(); + bool shouldWeWriteLog = settingsCache->value("server/writelog").toBool(); + QString logFilters = settingsCache->value("server/logfilters").toString(); QStringList listlogFilters = logFilters.split(",", QString::SkipEmptyParts); bool shouldWeSkipLine = false; diff --git a/servatrice/src/settingscache.cpp b/servatrice/src/settingscache.cpp new file mode 100644 index 00000000..b2b74d74 --- /dev/null +++ b/servatrice/src/settingscache.cpp @@ -0,0 +1,43 @@ +#include "settingscache.h" +#include +#include +#if QT_VERSION >= 0x050000 + #include +#else + #include +#endif + +SettingsCache::SettingsCache(const QString & fileName, QSettings::Format format, QObject * parent) +:QSettings(fileName, format, parent) +{ + +} + +QString SettingsCache::guessConfigurationPath(QString & specificPath) +{ + const QString fileName="servatrice.ini"; + QString guessFileName; + + // specific path + if(!specificPath.isEmpty() && QFile::exists(specificPath)) + return specificPath; + + // application directory path + guessFileName = QCoreApplication::applicationDirPath() + "/" + fileName; + if(QFile::exists(guessFileName)) + return guessFileName; + +#ifdef Q_OS_UNIX + // /etc + guessFileName = "/etc/servatrice/" + fileName; + if(QFile::exists(guessFileName)) + return guessFileName; +#endif + +#if QT_VERSION >= 0x050000 + guessFileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + fileName; +#else + guessFileName = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/" + fileName; +#endif + return guessFileName; +} \ No newline at end of file diff --git a/servatrice/src/settingscache.h b/servatrice/src/settingscache.h new file mode 100644 index 00000000..7284d273 --- /dev/null +++ b/servatrice/src/settingscache.h @@ -0,0 +1,18 @@ +#ifndef SERVATRICE_SETTINGSCACHE_H +#define SERVATRICE_SETTINGSCACHE_H + +#include +#include + +class SettingsCache : public QSettings { + Q_OBJECT +private: + QSettings *settings; +public: + SettingsCache(const QString & fileName="servatrice.ini", QSettings::Format format=QSettings::IniFormat, QObject * parent = 0); + static QString guessConfigurationPath(QString & specificPath); +}; + +extern SettingsCache *settingsCache; + +#endif