diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index d3e826a9..06dbc5f5 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -28,7 +28,6 @@ HEADERS += src/abstractcounter.h \ src/handcounter.h \ src/carddatabase.h \ src/gameview.h \ - src/deck_picturecacher.h \ src/decklistmodel.h \ src/dlg_load_deck_from_clipboard.h \ src/dlg_load_remote_deck.h \ @@ -111,7 +110,6 @@ SOURCES += src/abstractcounter.cpp \ src/handcounter.cpp \ src/carddatabase.cpp \ src/gameview.cpp \ - src/deck_picturecacher.cpp \ src/decklistmodel.cpp \ src/dlg_load_deck_from_clipboard.cpp \ src/dlg_load_remote_deck.cpp \ diff --git a/cockatrice/src/carddatabase.cpp b/cockatrice/src/carddatabase.cpp index 1087af1b..374dd864 100644 --- a/cockatrice/src/carddatabase.cpp +++ b/cockatrice/src/carddatabase.cpp @@ -60,6 +60,62 @@ void SetList::sortByKey() qSort(begin(), end(), CompareFunctor()); } +PictureLoadingThread::PictureLoadingThread(QObject *parent) + : QThread(parent) +{ +} + +PictureLoadingThread::~PictureLoadingThread() +{ + quit(); + wait(); +} + +void PictureLoadingThread::run() +{ + forever { + mutex.lock(); + if (loadQueue.isEmpty()) { + mutex.unlock(); + return; + } + CardInfo *card = loadQueue.takeFirst(); + QString correctedName = card->getCorrectedName(); + QString picsPath = _picsPath; + SetList sortedSets = card->getSets(); + mutex.unlock(); + + sortedSets.sortByKey(); + + QImage image; + for (int i = 0; i < sortedSets.size(); i++) { + if (image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName))) + break; + if (image.load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName).arg(1))) + break; + } + if (image.isNull()) + image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg("downloadedPics").arg(correctedName)); + + emit imageLoaded(card, image); + } +} + +void PictureLoadingThread::loadImage(CardInfo *card) +{ + QMutexLocker locker(&mutex); + loadQueue.append(card); + + if (!isRunning()) + start(LowPriority); +} + +void PictureLoadingThread::setPicsPath(const QString &path) +{ + QMutexLocker locker(&mutex); + _picsPath = path; +} + CardInfo::CardInfo(CardDatabase *_db, const QString &_name, const QString &_manacost, const QString &_cardtype, const QString &_powtough, const QString &_text, const QStringList &_colors, bool _cipt, int _tableRow, const SetList &_sets, const QString &_picURL) : db(_db), name(_name), sets(_sets), manacost(_manacost), cardtype(_cardtype), powtough(_powtough), text(_text), colors(_colors), picURL(_picURL), cipt(_cipt), tableRow(_tableRow), pixmap(NULL) { @@ -119,36 +175,24 @@ QPixmap *CardInfo::loadPixmap() if (pixmap) return pixmap; pixmap = new QPixmap(); - QString picsPath = settingsCache->getPicsPath(); - if (!QDir(picsPath).exists()) - return pixmap; if (getName().isEmpty()) { pixmap->load(settingsCache->getCardBackPicturePath()); return pixmap; } - SetList sortedSets = sets; - sortedSets.sortByKey(); - - QString debugOutput = QString("CardDatabase: loading pixmap for '%1' from ").arg(getName()); - for (int i = 0; i < sortedSets.size(); i++) - debugOutput.append(QString("%1, ").arg(sortedSets[i]->getShortName())); - qDebug(debugOutput.toLatin1()); - - QString correctedName = getCorrectedName(); - for (int i = 0; i < sortedSets.size(); i++) { - if (pixmap->load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName))) - return pixmap; - if (pixmap->load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(sortedSets[i]->getShortName()).arg(correctedName).arg(1))) - return pixmap; - } - if (pixmap->load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg("downloadedPics").arg(correctedName))) - return pixmap; - if (settingsCache->getPicDownload()) - db->startPicDownload(this); + db->loadImage(this); return pixmap; } +void CardInfo::imageLoaded(const QImage &image) +{ + if (!image.isNull()) { + *pixmap = QPixmap::fromImage(image); + emit pixmapUpdated(); + } else if (settingsCache->getPicDownload()) + db->startPicDownload(this); +} + QPixmap *CardInfo::getPixmap(QSize size) { qDebug(QString("CardInfo::getPixmap(%1, %2) for %3").arg(size.width()).arg(size.height()).arg(getName()).toLatin1()); @@ -243,6 +287,11 @@ CardDatabase::CardDatabase(QObject *parent) connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *))); loadCardDatabase(); + + loadingThread = new PictureLoadingThread(this); + loadingThread->setPicsPath(settingsCache->getPicsPath()); + connect(loadingThread, SIGNAL(imageLoaded(CardInfo *, QImage)), this, SLOT(imageLoaded(CardInfo *, QImage))); + loadingThread->start(); noCard = new CardInfo(this); noCard->loadPixmap(); // cache pixmap for card back @@ -532,3 +581,21 @@ QStringList CardDatabase::getAllMainCardTypes() const types.insert(cardIterator.next().value()->getMainCardType()); return types.toList(); } + +void CardDatabase::cacheCardPixmaps(const QStringList &cardNames) +{ + qDebug("pixmapCache started"); + for (int i = 0; i < cardNames.size(); ++i) + getCard(cardNames[i])->loadPixmap(); + qDebug("pixmapCache finished"); +} + +void CardDatabase::loadImage(CardInfo *card) +{ + loadingThread->loadImage(card); +} + +void CardDatabase::imageLoaded(CardInfo *card, QImage image) +{ + card->imageLoaded(image); +} \ No newline at end of file diff --git a/cockatrice/src/carddatabase.h b/cockatrice/src/carddatabase.h index 16822a8e..10e62aa5 100644 --- a/cockatrice/src/carddatabase.h +++ b/cockatrice/src/carddatabase.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include class CardDatabase; class CardInfo; @@ -35,6 +37,23 @@ public: void sortByKey(); }; +class PictureLoadingThread : public QThread { + Q_OBJECT +private: + QString _picsPath; + QList loadQueue; + QMutex mutex; +protected: + void run(); +public: + PictureLoadingThread(QObject *parent); + ~PictureLoadingThread(); + void setPicsPath(const QString &path); + void loadImage(CardInfo *card); +signals: + void imageLoaded(CardInfo *card, const QImage &image); +}; + class CardInfo : public QObject { Q_OBJECT private: @@ -85,6 +104,7 @@ public: QPixmap *getPixmap(QSize size); void clearPixmapCache(); void clearPixmapCacheMiss(); + void imageLoaded(const QImage &image); public slots: void updatePixmapCache(); signals: @@ -102,6 +122,7 @@ protected: bool downloadRunning; bool loadSuccess; CardInfo *noCard; + PictureLoadingThread *loadingThread; private: void loadCardsFromXml(QXmlStreamReader &xml); void loadSetsFromXml(QXmlStreamReader &xml); @@ -120,6 +141,8 @@ public: QStringList getAllColors() const; QStringList getAllMainCardTypes() const; bool getLoadSuccess() const { return loadSuccess; } + void cacheCardPixmaps(const QStringList &cardNames); + void loadImage(CardInfo *card); public slots: void clearPixmapCache(); bool loadCardDatabase(const QString &path); @@ -127,6 +150,7 @@ public slots: private slots: void picDownloadFinished(QNetworkReply *reply); void picDownloadChanged(); + void imageLoaded(CardInfo *card, QImage image); }; #endif diff --git a/cockatrice/src/deck_picturecacher.cpp b/cockatrice/src/deck_picturecacher.cpp deleted file mode 100644 index 8bd5f38e..00000000 --- a/cockatrice/src/deck_picturecacher.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include "deck_picturecacher.h" -#include "decklist.h" -#include "carddatabase.h" -#include "main.h" - -void Deck_PictureCacher::cacheHelper(InnerDecklistNode *item, QProgressDialog *progress) -{ - for (int i = 0; i < item->size(); i++) { - DecklistCardNode *node = dynamic_cast(item->at(i)); - if (node) { - db->getCard(node->getName())->loadPixmap(); - progress->setValue(progress->value() + 1); - } else - cacheHelper(dynamic_cast(item->at(i)), progress); - } -} - -void Deck_PictureCacher::cachePictures(DeckList *deck, QWidget *parent) -{ - int totalCards = deck->getRoot()->recursiveCount(); - - QProgressDialog progress(tr("Caching card pictures..."), QString(), 0, totalCards, parent); - progress.setMinimumDuration(1000); - progress.setWindowModality(Qt::WindowModal); - - cacheHelper(deck->getRoot(), &progress); -} - \ No newline at end of file diff --git a/cockatrice/src/deck_picturecacher.h b/cockatrice/src/deck_picturecacher.h deleted file mode 100644 index e278e508..00000000 --- a/cockatrice/src/deck_picturecacher.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef DECK_PICTURECACHER_H -#define DECK_PICTURECACHER_H - -#include - -class InnerDecklistNode; -class QProgressDialog; -class DeckList; -class QWidget; - -class Deck_PictureCacher : public QObject { - Q_OBJECT -private: - static void cacheHelper(InnerDecklistNode *item, QProgressDialog *progress); -public: - static void cachePictures(DeckList *deck, QWidget *parent); -}; - -#endif diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 13719e78..7f0e9e95 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -18,7 +18,6 @@ #include "zoneviewwidget.h" #include "deckview.h" #include "decklist.h" -#include "deck_picturecacher.h" #include "protocol_items.h" #include "dlg_load_remote_deck.h" #include "abstractclient.h" @@ -26,6 +25,7 @@ #include "arrowitem.h" #include "main.h" #include "settingscache.h" +#include "carddatabase.h" ReadyStartButton::ReadyStartButton(QWidget *parent) : QPushButton(parent), readyStart(false) @@ -131,7 +131,7 @@ void DeckViewContainer::deckSelectFinished(ProtocolResponse *r) if (!resp) return; - Deck_PictureCacher::cachePictures(resp->getDeck(), this); + db->cacheCardPixmaps(resp->getDeck()->getCardList()); deckView->setDeck(new DeckList(resp->getDeck())); readyStartButton->setEnabled(true); } @@ -508,7 +508,7 @@ void TabGame::eventGameStateChanged(Event_GameStateChanged *event, GameEventCont } player->processPlayerInfo(pl); if (player->getLocal() && !pl->getDeck()->isEmpty()) { - Deck_PictureCacher::cachePictures(pl->getDeck(), this); + db->cacheCardPixmaps(pl->getDeck()->getCardList()); deckViewContainers.value(player->getId())->setDeck(new DeckList(pl->getDeck())); } } diff --git a/cockatrice/src/window_deckeditor.cpp b/cockatrice/src/window_deckeditor.cpp index e9f2f44e..b72105a8 100644 --- a/cockatrice/src/window_deckeditor.cpp +++ b/cockatrice/src/window_deckeditor.cpp @@ -22,7 +22,6 @@ #include "carddatabasemodel.h" #include "decklistmodel.h" #include "cardinfowidget.h" -#include "deck_picturecacher.h" #include "dlg_cardsearch.h" #include "dlg_load_deck_from_clipboard.h" #include "main.h" @@ -466,8 +465,8 @@ void WndDeckEditor::setDeck(DeckList *_deck, const QString &_lastFileName, DeckL deckModel->sort(1); deckView->expandAll(); setWindowModified(false); - - Deck_PictureCacher::cachePictures(_deck, this); + + db->cacheCardPixmaps(_deck->getCardList()); deckView->expandAll(); setWindowModified(false); } diff --git a/cockatrice/translations/cockatrice_es.ts b/cockatrice/translations/cockatrice_es.ts index 44daecba..2b86c0ae 100644 --- a/cockatrice/translations/cockatrice_es.ts +++ b/cockatrice/translations/cockatrice_es.ts @@ -6,32 +6,32 @@ &Set counter... - E&stablecer contadores... + E&stablecer contador... Ctrl+L - Ctrl+L + Ctrl+L F11 - F11 + F11 F12 - F12 + F12 Set counter - Establecer contador + Establecer contador New value for counter '%1': - Nuevo valor para el contador '%1': + Nuevo valor para el contador '%1': @@ -175,12 +175,12 @@ &Play - + &Jugar &Hide - + &Ocultar @@ -1103,7 +1103,7 @@ Show &full games - + Ver partidas &sin plazas libres &Show full games @@ -1248,42 +1248,42 @@ Version %1 - + Versión %1 Authors: - + Autores: Translators: - + Traductores: Spanish: - + Español: Portugese (Portugal): - + Portugués (Portugal): Portugese (Brazil): - + Portugués (Brasil): French: - + Francés: Japanese: - + Japonés: @@ -1499,7 +1499,7 @@ %1 gives %2 control over %3. - + %1 entrega a %2 el control sobre %3. @@ -2165,7 +2165,7 @@ Put top card on &bottom - + Poner carta superior en la parte &inferior @@ -2337,32 +2337,32 @@ Rooms - + Salas Joi&n - E&ntrar + E&ntrar Room - + Sala Description - Descripción + Descripción Players - Jugadores + Jugadores Games - Partidas + Partidas @@ -2390,37 +2390,37 @@ Update server &message - + Actualizar &mensaje del servidor Server administration functions - + Funciones de administración del servidor &Unlock functions - + &Desbloquear funciones &Lock functions - + &Bloquear funciones Unlock administration functions - + Desbloquear funciones de administración Do you really want to unlock the administration functions? - + ¿Realmente quieres desbloquear las funciones de administración? Administration - + Administración @@ -2626,32 +2626,32 @@ Por favor, introduzca un nombre: &Say: - &Decir: + &Decir: Chat - + Chat &Room - + &Sala &Leave room - + &Dejar sala %1 has joined the room. - + %1 se ha unido a la sala. %1 has left the room. - + %1 ha dejado la sala. @@ -2667,12 +2667,12 @@ Por favor, introduzca un nombre: User information - + Información del usuario Real name: - + Nombre real: @@ -2687,22 +2687,22 @@ Por favor, introduzca un nombre: Administrator - + Administrador Judge - + Juez Registered user - + Usuario registrado Unregistered user - + Usuario no registrado @@ -2738,17 +2738,17 @@ Por favor, introduzca un nombre: Users in this room: %1 - + Usuarios en esta sala: %1 User &details - + &Detalles del usuario Direct &chat - + &Chat privado @@ -2837,14 +2837,15 @@ Por favor, introduzca un nombre: Error - Error + Error The deck could not be saved. Please check that the directory is writable and try again. - + El mazo no puede guardarse +Por favor, compruebe que tiene permisos de escritura en el directorio e intentelo de nuevo. @@ -2935,7 +2936,7 @@ Please check that the directory is writable and try again. The decklist has been modified. Do you want to save the changes? - La lista del mazo ha sido modificada + La lista del mazo ha sido modificada ¿Deseas guardar los cambios? diff --git a/cockatrice/translations/cockatrice_pt-br.ts b/cockatrice/translations/cockatrice_pt-br.ts index a69c1491..fc8b2485 100644 --- a/cockatrice/translations/cockatrice_pt-br.ts +++ b/cockatrice/translations/cockatrice_pt-br.ts @@ -6,32 +6,32 @@ &Set counter... - Alterar &marcador... + Alterar &marcador... Ctrl+L - Ctrl+L + Ctrl+L F11 - F11 + F11 F12 - F12 + F12 Set counter - Alterar marcador + Alterar marcador New value for counter '%1': - Novo valor para o marcador '%1': + Novo valor para o marcador '%1': @@ -171,12 +171,12 @@ &Play - + &Jogar &Hide - + &Ocultar @@ -957,7 +957,7 @@ Show &full games - + &Mostrar os jogos cheios &Show full games @@ -1106,42 +1106,42 @@ Version %1 - + Versão %1 Authors: - + Autores: Translators: - + Tradutores: Spanish: - + Espanhol: Portugese (Portugal): - + Português (Portugal): Portugese (Brazil): - + Português (Brasil): French: - + Francês: Japanese: - + Japonês: @@ -1357,7 +1357,7 @@ %1 gives %2 control over %3. - + %1 dá controle para %2 sobre %3. @@ -2015,7 +2015,7 @@ Put top card on &bottom - + Colocar o card do topo no &fundo @@ -2175,32 +2175,32 @@ Rooms - + Salas Joi&n - &Entrar + &Entrar Room - + Sala Description - Descrição + Descrição Players - Jogadores + Jogadores Games - Jogos + Jogos @@ -2228,37 +2228,37 @@ Update server &message - + &Atualizar mensagem do servidor Server administration functions - + Funções do administrador do servidor &Unlock functions - + &Desbloquear funções &Lock functions - + &Bloquear funções Unlock administration functions - + Desbloquear funções do administrador Do you really want to unlock the administration functions? - + Você quer mesmo desbloquear as funções do administrador? Administration - + Administração @@ -2464,32 +2464,32 @@ Por favor, entre um nome: &Say: - &Falar: + &Falar: Chat - + Chat &Room - + &Sala &Leave room - + S&air da sala %1 has joined the room. - + %1 entrou na sala. %1 has left the room. - + %1 saiu da sala. @@ -2505,12 +2505,12 @@ Por favor, entre um nome: User information - + Informação do usuário Real name: - + Nome real: @@ -2525,22 +2525,22 @@ Por favor, entre um nome: Administrator - + Administrador Judge - + Juiz Registered user - + Usuário registrado Unregistered user - + Usuário não registrado @@ -2576,17 +2576,17 @@ Por favor, entre um nome: Users in this room: %1 - + Usuários nesta sala: %1 User &details - + &Detalhes do usuário Direct &chat - + &Chat direto @@ -2675,14 +2675,15 @@ Por favor, entre um nome: Error - Erro + Erro The deck could not be saved. Please check that the directory is writable and try again. - + O deck não pôde ser salvo. +Por favor, verifique se o diretório não é somente leitura e tente novamente. diff --git a/cockatrice/translations/cockatrice_pt.ts b/cockatrice/translations/cockatrice_pt.ts index d24169af..07d4f7ea 100644 --- a/cockatrice/translations/cockatrice_pt.ts +++ b/cockatrice/translations/cockatrice_pt.ts @@ -6,32 +6,32 @@ &Set counter... - Definir &marcador... + Definir &marcador... Ctrl+L - Ctrl+L + Ctrl+L F11 - F11 + F11 F12 - F12 + F12 Set counter - Definir marcador + Definir marcador New value for counter '%1': - Novo valor para o marcador '%1': + Novo valor para o marcador '%1': @@ -176,7 +176,7 @@ &Hide - + Esco&nder @@ -550,7 +550,7 @@ Ready to s&tart - Pronto para &começar + &Pronto para começar @@ -1130,12 +1130,12 @@ Portugese (Portugal): - + Português (Portugal): Portugese (Brazil): - + Português (Brasil): @@ -1145,7 +1145,7 @@ Japanese: - + Japonês: @@ -2232,37 +2232,37 @@ Update server &message - + &Actualizar mensagem do servidor Server administration functions - + Funções do administrador do servidor &Unlock functions - + &Desbloquear funções &Lock functions - + &Bloquear funções Unlock administration functions - + Desbloquear funções de administração Do you really want to unlock the administration functions? - + Quer mesmo desbloquear as funçõesde administração? Administration - + Administração @@ -2509,12 +2509,12 @@ Por favor introduza um nome: User information - + Informação do utilizador Real name: - + Nome real: @@ -2585,12 +2585,12 @@ Por favor introduza um nome: User &details - + Detalhes do &utilizador Direct &chat - + Conversação &directa diff --git a/common/decklist.cpp b/common/decklist.cpp index 1e7e0b07..9d69b5df 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -468,6 +468,24 @@ void DeckList::cleanList() setComments(); } +void DeckList::getCardListHelper(InnerDecklistNode *item, QSet &result) const +{ + for (int i = 0; i < item->size(); ++i) { + DecklistCardNode *node = dynamic_cast(item->at(i)); + if (node) + result.insert(node->getName()); + else + getCardListHelper(dynamic_cast(item->at(i)), result); + } +} + +QStringList DeckList::getCardList() const +{ + QSet result; + getCardListHelper(root, result); + return result.toList(); +} + DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zoneName) { InnerDecklistNode *zoneNode = dynamic_cast(root->findChild(zoneName)); diff --git a/common/decklist.h b/common/decklist.h index d54959e2..37942174 100644 --- a/common/decklist.h +++ b/common/decklist.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "serializable_item.h" class CardDatabase; @@ -115,6 +116,7 @@ private: InnerDecklistNode *currentZone; SideboardPlan *currentSideboardPlan; QString currentElementText; + void getCardListHelper(InnerDecklistNode *node, QSet &result) const; signals: void deckLoaded(); public slots: @@ -149,6 +151,7 @@ public: void cleanList(); bool isEmpty() const { return root->isEmpty() && name.isEmpty() && comments.isEmpty() && sideboardPlans.isEmpty(); } + QStringList getCardList() const; InnerDecklistNode *getRoot() const { return root; } DecklistCardNode *addCard(const QString &cardName, const QString &zoneName); diff --git a/doc/protocol.txt b/doc/protocol.txt deleted file mode 100644 index 2e88f62f..00000000 --- a/doc/protocol.txt +++ /dev/null @@ -1,157 +0,0 @@ -1. Abstract - -The Cockatrice protocol is a client/server protocol intended for communication between -a card game client and a suitable server. It is designed with the goal in mind to make -playing card games, such as Magic the Gathering, over a network easy while eliminating -the possibility of unfair play. Because of that, the server stores all hidden information -and transmits pieces of it to clients only when necessary. - -2. Protocol structure - -All communication is done over a TCP/IP connection. The protocol is text based. -Strings are encoded in UTF-8 and have UNIX-style line endings (\n). - -There are four distinct types of messages: - - Command (section 3) - - Response (section 4) - - Event (section 5) - - List (section 6) - -3. Commands - -A command can only be sent from client to server and has the following structure: - {ID}|{command}|{parameter1}|{parameter2}... -"ID" is an arbitrary number to be chosen uniquely for each command. -"command" is a command identifier (see section 3). -It depends on the command identifier what has to be passed as parameters. - -3.1 ping - -Flags: - none -Parameters: - none -Valid response codes: - ok - -No effect. - -3.2 login - -Flags: - none -Parameters: - User name (string) - Password (string) -Valid response codes: - ok - password - -If the supplied credentials are correct, "ok" is returned and the connection state -is set to authenticated. (The server is not required to actually check the validity -of the credentials.) -Otherwise, "password" is returned. - -3.3 list_games - -Flags: - login needed -Parameters: - none -Valid response codes: - ok - -If the connection state is unauthenticated, "login_needed" is returned. -Otherwise, "ok" is returned and for each game currently, a list_games event XXX is -sent to the client. The "accepts game list changes" flag of the connection is set. - -3.4 create_game - -Flags: - login needed -Parameters: - Description (string) - Password (string) - Number of players (int) -Valid response codes: - ok - -A game with the given parameters is created. The client is set as creator of the -game and joins it automatically. The "accepts game list changes" flag of the connection -is unset. - -3.5 join_game - -Flags: - login needed -Parameters: - Game ID (int) - Password (string) -Valid response codes: - ok - password - -If the password for the given game is correct, the client leaves the current game -(if any) and joins the given game. The "accepts game list changes" flag of the connection -is unset. - -3.6 leave_game - -Flags: - login needed - game needed -Parameters: - none -Valid response codes: - ok - -The client leaves the current game. - -3.7 list_players - -Flags: - login needed - game needed -Parameters: - none - - -3.8 say -3.9 submit_deck -3.10 ready_start -3.11 shuffle -3.12 draw_cards -3.13 reveal_card -3.14 move_card -3.15 create_token -3.16 set_card_attr -3.17 inc_counter -3.18 add_counter -3.19 set_counter -3.20 del_counter -3.21 list_counters -3.22 list_zones -3.23 dump_zone -3.24 roll_dice -3.25 set_active_player -3.26 set_active_phase - -4. Responses - -After processing any command, the server sends a response to the client, indicating -whether the command was understood and valid. -A response can only be sent from server to client and has the following structure: - resp|{ID}|{resp-code} - -{ID} is the identifier belonging to the command in question. -{resp-code} contains information about the processing of the command. It can have the -following values: - ok (Success) - login_needed (Error: Command requires login) - syntax (Error: Invalid command or parameters) - context (Error: Command cannot be applied here) - password (Error: Wrong login data) - -The response code "syntax" is valid as a response to any command and is -hence not explicitly listed in section 3. The response code "login_needed" applies -to all commands with the "login needed" flag. \ No newline at end of file