Commit 00afe74a authored by woogerboy21's avatar woogerboy21
Browse files

Merge remote-tracking branch 'refs/remotes/Cockatrice/master' into mod_notify_onbanwarn

parents 3ed39193 36c3536e
......@@ -2,10 +2,16 @@
---
**Table of Contents**    [Cockatrice](#cockatrice) | [Get Involved] (#get-involved-) | [Community](#community-resources) | [Translation](#translation-status-) | [Building](#building--) | [Running](#running) | [License](#license-)
**Table of Contents**    [Cockatrice](#cockatrice) | [Downloads](#downloads) | [Get Involved] (#get-involved-) | [Community](#community-resources) | [Translation](#translation-status-) | [Building](#building--) | [Running](#running) | [License](#license-)
---
<br><pre>
<b>If you're getting started &#8674; [view our webpage](https://cockatrice.github.io/)</b><br>
<b>If you're trying to get support or suggest changes &#8674; [file an issue](https://github.com/Cockatrice/Cockatrice/issues/new)</b>
</pre><br>
# Cockatrice
Cockatrice is an open-source multiplatform software for playing card games,
......@@ -13,12 +19,15 @@ such as Magic: The Gathering, over a network. It is fully client-server based
to prevent any kind of cheating, though it supports single-player games without
a network interface as well. Both client and server are written in Qt, supporting both Qt4 and Qt5.<br>
# Downloads
We offer a download for both the last stable version (recommended for users) and the last development version. The development version contains the last implemented features, but can be unstable and unsuitable for gaming.
Downloads are hosted on [BinTray](https://bintray.com/).
- Latest stable version download: [ ![Download](https://api.bintray.com/packages/cockatrice/Cockatrice/Cockatrice/images/download.svg) ](https://bintray.com/cockatrice/Cockatrice/Cockatrice/_latestVersion)
- Latest development (unstable) version download: [ ![Download](https://api.bintray.com/packages/cockatrice/Cockatrice/Cockatrice-git/images/download.svg) ](https://bintray.com/cockatrice/Cockatrice/Cockatrice-git/_latestVersion)
We offer a download for all full releases and the latest development version (recommended). Full releases are checkpoints with major feature or UI enhancements between them, but are infrequently updated. The development version contains the most recently added features and bugfixes, but can be more unstable. Downloads for development versions are updated automatically with every change.
Downloads are hosted on [BinTray](https://bintray.com/cockatrice/Cockatrice).
- Latest development version (recommended): [ ![Download](https://api.bintray.com/packages/cockatrice/Cockatrice/Cockatrice-git/images/download.svg) ](https://bintray.com/cockatrice/Cockatrice/Cockatrice-git/_latestVersion#files)
- Latest full release: [ ![Download](https://api.bintray.com/packages/cockatrice/Cockatrice/Cockatrice/images/download.svg) ](https://bintray.com/cockatrice/Cockatrice/Cockatrice/_latestVersion#files)
# Get Involved [![Gitter chat](https://badges.gitter.im/Cockatrice/Cockatrice.png)](https://gitter.im/Cockatrice/Cockatrice)
......@@ -26,21 +35,20 @@ Chat with the Cockatrice developers on Gitter. Come here to talk about the appli
# Community Resources
- [Cockatrice Official Site](https://cockatrice.github.io)
- [Cockatrice Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki)
- [reddit r/Cockatrice](http://reddit.com/r/cockatrice)
- [Woogerworks](http://www.woogerworks.com) / [Chickatrice] (http://www.chickatrice.net/) / [Poixen](http://www.poixen.com/) (incomplete Serverlist)<br>
- [reddit r/Cockatrice](https://reddit.com/r/cockatrice)
# Translation Status [![Cockatrice on Transiflex](https://ds0k0en9abmn1.cloudfront.net/static/charts/images/tx-logo-micro.646b0065fce6.png)](https://www.transifex.com/projects/p/cockatrice/)
Cockatrice uses Transifex for translations. You can help us bring Cockatrice/Oracle to your language or edit single wordings by clicking on the associated charts below.<br>
Our [project page](https://www.transifex.com/projects/p/cockatrice/) offers a detailed overview for contributors.
Language statistics for `Cockatrice` *(on the left)* and `Oracle` *(on the right)*:
Cockatrice uses Transifex for translations. You can help us bring Cockatrice and Oracle to your language or just edit single wordings right from within your browser by simply visiting our [Transifex project page](https://www.transifex.com/projects/p/cockatrice/).<br>
[![Cockatrice translations](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[![Oracle translations](https://www.transifex.com/projects/p/cockatrice/resource/oracle/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/resource/oracle/)
| Cockatrice | Oracle |
|:-:|:-:|
| [![Cockatrice Translation Status](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/) | [![Oracle Translation Status](https://www.transifex.com/projects/p/cockatrice/resource/oracle/chart/image_png)](https://www.transifex.com/projects/p/cockatrice/) |
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information!<br>
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about contributing!<br>
# Building [![Travis Build Status - master](https://travis-ci.org/Cockatrice/Cockatrice.svg?branch=master)](https://travis-ci.org/Cockatrice/Cockatrice) [![Appveyor Build Status - master](https://ci.appveyor.com/api/projects/status/lp5h0dhk4mhmeps7/branch/master?svg=true)](https://ci.appveyor.com/project/Daenyth/cockatrice/branch/master)
......@@ -48,15 +56,15 @@ Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Tra
**Detailed compiling instructions are on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
Dependencies:
- [Qt](http://qt-project.org/)
- [protobuf](http://code.google.com/p/protobuf/)
- [CMake](http://www.cmake.org/)
- [Qt](https://www.qt.io/developers/)
- [protobuf](https://github.com/google/protobuf)
- [CMake](https://www.cmake.org/)
Oracle can optionally use zlib to load zipped files:
- [zlib](http://www.zlib.net/)
- [zlib](http://www.zlib.net/) (no https!)
The server requires an additional dependency when compiled under Qt4:
- [libgcrypt](http://www.gnu.org/software/libgcrypt/)
- [libgcrypt](https://www.gnu.org/software/libgcrypt/)
To compile:
......@@ -99,7 +107,7 @@ The following flags can be passed to `cmake`:
`servatrice` is the server<br>
# License [![GPLv2 License](https://img.shields.io/badge/license-GPLv2-blue.svg)](https://github.com/Cockatrice/Cockatrice/blob/master/COPYING)
# License [![GPLv2 License](https://img.shields.io/badge/License-GPLv2-blue.svg)](https://github.com/Cockatrice/Cockatrice/blob/master/COPYING)
Cockatrice is free software, licensed under the [GPLv2](https://github.com/Cockatrice/Cockatrice/blob/master/COPYING).
......@@ -157,8 +157,7 @@ void SetList::guessSortKeys()
}
}
CardInfo::CardInfo(CardDatabase *_db,
const QString &_name,
CardInfo::CardInfo(const QString &_name,
bool _isToken,
const QString &_manacost,
const QString &_cmc,
......@@ -176,8 +175,7 @@ CardInfo::CardInfo(CardDatabase *_db,
const QStringMap &_customPicURLs,
MuidMap _muIds
)
: db(_db),
name(_name),
: name(_name),
isToken(_isToken),
sets(_sets),
manacost(_manacost),
......@@ -188,6 +186,7 @@ CardInfo::CardInfo(CardDatabase *_db,
colors(_colors),
relatedCards(_relatedCards),
reverseRelatedCards(_reverseRelatedCards),
setsNames(),
upsideDownArt(_upsideDownArt),
loyalty(_loyalty),
customPicURLs(_customPicURLs),
......@@ -200,6 +199,8 @@ CardInfo::CardInfo(CardDatabase *_db,
for (int i = 0; i < sets.size(); i++)
sets[i]->append(this);
refreshCachedSetNames();
}
CardInfo::~CardInfo()
......@@ -249,6 +250,21 @@ void CardInfo::addToSet(CardSet *set)
{
set->append(this);
sets << set;
refreshCachedSetNames();
}
void CardInfo::refreshCachedSetNames()
{
// update the cached list of set names
QStringList setList;
for (int i = 0; i < sets.size(); i++)
{
if(sets[i]->getEnabled())
setList << sets[i]->getShortName();
}
setsNames = setList.join(", ");
}
QString CardInfo::simplifyName(const QString &name) {
......@@ -330,10 +346,7 @@ CardDatabase::CardDatabase(QObject *parent)
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase()));
connect(settingsCache, SIGNAL(tokenDatabasePathChanged()), this, SLOT(loadTokenDatabase()));
loadCardDatabase();
loadTokenDatabase();
noCard = new CardInfo(this);
noCard = new CardInfo();
}
CardDatabase::~CardDatabase()
......@@ -506,7 +519,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml, bool tokens)
}
if (isToken == tokens) {
addCard(new CardInfo(this, name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, reverseRelatedCards, upsideDown, loyalty, cipt, tableRow, sets, customPicURLs, muids));
addCard(new CardInfo(name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, reverseRelatedCards, upsideDown, loyalty, cipt, tableRow, sets, customPicURLs, muids));
}
}
}
......@@ -517,7 +530,7 @@ CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &card
return cardMap.value(cardName);
if (createIfNotFound) {
CardInfo *newCard = new CardInfo(this, cardName, true);
CardInfo *newCard = new CardInfo(cardName, true);
newCard->addToSet(getSet(CardDatabase::TOKENS_SETNAME));
cardMap.insert(cardName, newCard);
return newCard;
......@@ -619,23 +632,22 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
emit cardListChanged();
}
if (!tokens) {
if (!tokens)
loadStatus = tempLoadStatus;
qDebug() << "loadCardDatabase(): Path = " << path << " Status = " << loadStatus;
}
qDebug() << "loadCardDatabase(): Path =" << path << "Tokens =" << tokens << "Status =" << loadStatus;
return tempLoadStatus;
}
void CardDatabase::loadCardDatabase()
LoadStatus CardDatabase::loadCardDatabase()
{
loadCardDatabase(settingsCache->getCardDatabasePath(), false);
return loadCardDatabase(settingsCache->getCardDatabasePath(), false);
}
void CardDatabase::loadTokenDatabase()
LoadStatus CardDatabase::loadTokenDatabase()
{
loadCardDatabase(settingsCache->getTokenDatabasePath(), true);
return loadCardDatabase(settingsCache->getTokenDatabasePath(), true);
}
void CardDatabase::loadCustomCardDatabases(const QString &path)
......
......@@ -60,8 +60,6 @@ public:
class CardInfo : public QObject {
Q_OBJECT
private:
CardDatabase *db;
QString name;
/*
......@@ -84,6 +82,7 @@ private:
QStringList reverseRelatedCards;
// the cards thare are reverse-related to me
QStringList reverseRelatedCardsToMe;
QString setsNames;
bool upsideDownArt;
int loyalty;
QStringMap customPicURLs;
......@@ -92,9 +91,9 @@ private:
int tableRow;
QString pixmapCacheKey;
void refreshCachedSetNames();
public:
CardInfo(CardDatabase *_db,
const QString &_name = QString(),
CardInfo(const QString &_name = QString(),
bool _isToken = false,
const QString &_manacost = QString(),
const QString &_cmc = QString(),
......@@ -113,14 +112,15 @@ public:
MuidMap muids = MuidMap()
);
~CardInfo();
const QString &getName() const { return name; }
inline const QString &getName() const { return name; }
inline const QString &getSetsNames() const { return setsNames; }
const QString &getSimpleName() const { return simpleName; }
bool getIsToken() const { return isToken; }
const SetList &getSets() const { return sets; }
const QString &getManaCost() const { return manacost; }
const QString &getCmc() const { return cmc; }
const QString &getCardType() const { return cardtype; }
const QString &getPowTough() const { return powtough; }
inline const QString &getManaCost() const { return manacost; }
inline const QString &getCmc() const { return cmc; }
inline const QString &getCardType() const { return cardtype; }
inline const QString &getPowTough() const { return powtough; }
const QString &getText() const { return text; }
const QString &getPixmapCacheKey() const { return pixmapCacheKey; }
const int &getLoyalty() const { return loyalty; }
......@@ -229,12 +229,12 @@ public:
bool hasDetectedFirstRun();
void refreshCachedReverseRelatedCards();
public slots:
LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
LoadStatus loadCardDatabase();
LoadStatus loadTokenDatabase();
void loadCustomCardDatabases(const QString &path);
void emitCardListChanged();
private slots:
void loadCardDatabase();
void loadTokenDatabase();
LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
signals:
void cardListChanged();
void cardAdded(CardInfo *card);
......
......@@ -28,26 +28,16 @@ int CardDatabaseModel::columnCount(const QModelIndex &/*parent*/) const
QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if ((index.row() >= cardList.size()) || (index.column() >= CARDDBMODEL_COLUMNS))
return QVariant();
if (role != Qt::DisplayRole && role != SortRole)
if (!index.isValid() ||
index.row() >= cardList.size() ||
index.column() >= CARDDBMODEL_COLUMNS ||
(role != Qt::DisplayRole && role != SortRole))
return QVariant();
CardInfo *card = cardList.at(index.row());
switch (index.column()){
case NameColumn: return card->getName();
case SetListColumn: {
QStringList setList;
const QList<CardSet *> &sets = card->getSets();
for (int i = 0; i < sets.size(); i++)
{
if(sets[i]->getEnabled())
setList << sets[i]->getShortName();
}
return setList.join(", ");
}
case SetListColumn: return card->getSetsNames();
case ManaCostColumn: return role == SortRole ?
QString("%1%2").arg(card->getCmc(), 4, QChar('0')).arg(card->getManaCost()) :
card->getManaCost();
......@@ -139,8 +129,30 @@ CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent)
filterTree = NULL;
setFilterCaseSensitivity(Qt::CaseInsensitive);
setSortCaseSensitivity(Qt::CaseInsensitive);
loadedRowCount = 0;
}
bool CardDatabaseDisplayModel::canFetchMore(const QModelIndex & index) const
{
return loadedRowCount < sourceModel()->rowCount(index);
}
void CardDatabaseDisplayModel::fetchMore(const QModelIndex & index)
{
int remainder = sourceModel()->rowCount(index) - loadedRowCount;
int itemsToFetch = qMin(100, remainder);
beginInsertRows(QModelIndex(), loadedRowCount, loadedRowCount+itemsToFetch-1);
loadedRowCount += itemsToFetch;
endInsertRows();
}
int CardDatabaseDisplayModel::rowCount(const QModelIndex &parent) const
{
return qMin(QSortFilterProxyModel::rowCount(parent), loadedRowCount);
}
bool CardDatabaseDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const {
......
......@@ -42,6 +42,7 @@ private:
QString searchTerm;
QSet<QString> cardNameSet, cardTypes, cardColors;
FilterTree *filterTree;
int loadedRowCount;
public:
CardDatabaseDisplayModel(QObject *parent = 0);
void setFilterTree(FilterTree *filterTree);
......@@ -54,9 +55,13 @@ public:
void setCardTypes(const QSet<QString> &_cardTypes) { cardTypes = _cardTypes; invalidate(); }
void setCardColors(const QSet<QString> &_cardColors) { cardColors = _cardColors; invalidate(); }
void clearFilterAll();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
bool canFetchMore(const QModelIndex &parent) const;
void fetchMore(const QModelIndex &parent);
private slots:
void filterTreeChanged();
};
......
......@@ -145,7 +145,7 @@ void DlgEditTokens::actAddToken()
if (name.isEmpty())
return;
CardInfo *card = new CardInfo(cardDatabaseModel->getDatabase(), name, true);
CardInfo *card = new CardInfo(name, true);
card->addToSet(cardDatabaseModel->getDatabase()->getSet(CardDatabase::TOKENS_SETNAME));
card->setCardType("Token");
cardDatabaseModel->getDatabase()->addCard(card);
......
......@@ -163,12 +163,15 @@ int main(int argc, char *argv[])
#else
const QString dataDir = QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
if (!db->getLoadSuccess())
if (!db->loadCardDatabase(dataDir + "/cards.xml"))
settingsCache->setCardDatabasePath(dataDir + "/cards.xml");
if (settingsCache->getTokenDatabasePath().isEmpty())
if (settingsCache->getCardDatabasePath().isEmpty() ||
db->loadCardDatabase() != Ok)
settingsCache->setCardDatabasePath(dataDir + "/cards.xml");
if (settingsCache->getTokenDatabasePath().isEmpty() ||
db->loadTokenDatabase() != Ok)
settingsCache->setTokenDatabasePath(dataDir + "/tokens.xml");
if (!QDir(settingsCache->getDeckPath()).exists() || settingsCache->getDeckPath().isEmpty()) {
QDir().mkpath(dataDir + "/decks");
settingsCache->setDeckPath(dataDir + "/decks");
......
......@@ -58,7 +58,8 @@ void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
painter.fillPath(path, Qt::black);
const QColor barColor = QColor::fromHsv(120, 255, 255, 100);
painter.fillRect(0, 0, (width() - 1) * currentTime / maxTime, height() - 1, barColor);
quint64 w = (quint64)(width() - 1) * (quint64) currentTime / maxTime;
painter.fillRect(0, 0, w, height() - 1, barColor);
}
QSize ReplayTimelineWidget::sizeHint() const
......
......@@ -367,17 +367,16 @@ void TabDeckEditor::createCentralFrame()
databaseDisplayModel = new CardDatabaseDisplayModel(this);
databaseDisplayModel->setSourceModel(databaseModel);
databaseDisplayModel->setFilterKeyColumn(0);
databaseDisplayModel->sort(0, Qt::AscendingOrder);
databaseView = new QTreeView();
databaseView->setObjectName("databaseView");
databaseView->setFocusProxy(searchEdit);
databaseView->setModel(databaseDisplayModel);
databaseView->setUniformRowHeights(true);
databaseView->setRootIsDecorated(false);
databaseView->setAlternatingRowColors(true);
databaseView->setSortingEnabled(true);
databaseView->sortByColumn(0, Qt::AscendingOrder);
databaseView->setModel(databaseDisplayModel);
databaseView->resizeColumnToContents(0);
connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &)));
connect(databaseView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actAddCard()));
......
syntax = "proto2";
message AdminCommand {
enum AdminCommandType {
UPDATE_SERVER_MESSAGE = 1000;
......
syntax = "proto2";
enum CardAttribute {
AttrTapped = 1;
AttrAttacking = 2;
......
syntax = "proto2";
message color {
optional uint32 r = 1;
optional uint32 g = 2;
optional uint32 b = 3;
optional uint32 a = 4;
}
\ No newline at end of file
}
syntax = "proto2";
import "game_commands.proto";
message Command_AttachCard {
extend GameCommand {
......
syntax = "proto2";
import "game_commands.proto";
message Command_ChangeZoneProperties {
......
syntax = "proto2";
import "game_commands.proto";
message Command_Concede {
extend GameCommand {
......
syntax = "proto2";
import "game_commands.proto";
import "color.proto";
......
syntax = "proto2";
import "game_commands.proto";
import "color.proto";
......
syntax = "proto2";
import "game_commands.proto";
message Command_CreateToken {
extend GameCommand {
......
syntax = "proto2";
import "session_commands.proto";
message Command_DeckDel {
......
syntax = "proto2";
import "session_commands.proto";
message Command_DeckDelDir {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment