diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index e24a899d..c3cc92a7 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -44,7 +44,8 @@ HEADERS += src/counter.h \ src/window_sets.h \ src/abstractgraphicsitem.h \ src/dlg_settings.h \ - src/phasestoolbar.h + src/phasestoolbar.h \ + src/chatwidget.h SOURCES += src/counter.cpp \ src/gameselector.cpp \ src/dlg_creategame.cpp \ @@ -82,5 +83,6 @@ SOURCES += src/counter.cpp \ src/window_sets.cpp \ src/abstractgraphicsitem.cpp \ src/dlg_settings.cpp \ - src/phasestoolbar.cpp + src/phasestoolbar.cpp \ + src/chatwidget.cpp TRANSLATIONS += translations/cockatrice_de.ts translations/cockatrice_en.ts diff --git a/cockatrice/src/chatwidget.cpp b/cockatrice/src/chatwidget.cpp new file mode 100644 index 00000000..3d044d58 --- /dev/null +++ b/cockatrice/src/chatwidget.cpp @@ -0,0 +1,85 @@ +#include +#include "chatwidget.h" +#include "client.h" + +ChannelWidget::ChannelWidget(QWidget *parent) + : QWidget(parent) +{ + playerList = new QListWidget; + + textEdit = new QTextEdit; + sayEdit = new QLineEdit; + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->addWidget(textEdit); + vbox->addWidget(sayEdit); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->addLayout(vbox); + hbox->addWidget(playerList); + + setLayout(hbox); +} + +ChatWidget::ChatWidget(Client *_client, QWidget *parent) + : QWidget(parent), client(_client) +{ + channelList = new QTreeWidget; + tab = new QTabWidget; + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->addWidget(channelList); + hbox->addWidget(tab, 1); + + retranslateUi(); + setLayout(hbox); +} + +void ChatWidget::retranslateUi() +{ + QTreeWidgetItem *header = channelList->headerItem(); + Q_ASSERT(header != 0); + header->setText(0, tr("Channel")); + header->setText(1, tr("Description")); + header->setText(2, tr("Players")); +} + +void ChatWidget::enableChat() +{ + connect(client, SIGNAL(chatEvent(const ChatEventData &)), this, SLOT(chatEvent(const ChatEventData &))); + client->chatListChannels(); + show(); +} + +void ChatWidget::disableChat() +{ + disconnect(client, 0, this, 0); + hide(); +} + +void ChatWidget::chatEvent(const ChatEventData &data) +{ + const QStringList &msg = data.getEventData(); + switch (data.getEventType()) { + case eventChatListChannels: { + if (msg.size() != 3) + break; + channelList->addTopLevelItem(new QTreeWidgetItem(QStringList() << msg[0] << msg[1] << msg[2])); + break; + } + case eventChatJoinChannel: { + break; + } + case eventChatListPlayers: { + break; + } + case eventChatLeaveChannel: { + break; + } + case eventChatSay: { + break; + } + default: { + } + } +} diff --git a/cockatrice/src/chatwidget.h b/cockatrice/src/chatwidget.h new file mode 100644 index 00000000..3f1a6353 --- /dev/null +++ b/cockatrice/src/chatwidget.h @@ -0,0 +1,38 @@ +#ifndef CHATWIDGET_H +#define CHATWIDGET_H + +#include +#include "servereventdata.h" + +class QListWidget; +class QTextEdit; +class QLineEdit; +class QTreeWidget; +class QTabWidget; +class Client; + +class ChannelWidget : public QWidget { +private: + QListWidget *playerList; + QTextEdit *textEdit; + QLineEdit *sayEdit; +public: + ChannelWidget(QWidget *parent = 0); +}; + +class ChatWidget : public QWidget { + Q_OBJECT +private: + QTreeWidget *channelList; + QTabWidget *tab; + Client *client; +private slots: + void chatEvent(const ChatEventData &data); +public: + ChatWidget(Client *_client, QWidget *parent = 0); + void retranslateUi(); + void enableChat(); + void disableChat(); +}; + +#endif diff --git a/cockatrice/src/client.cpp b/cockatrice/src/client.cpp index 1e05f3f7..cd8407c3 100644 --- a/cockatrice/src/client.cpp +++ b/cockatrice/src/client.cpp @@ -110,6 +110,8 @@ void Client::readLine() emit playerIdReceived(id, data[1]); } else emit gameEvent(event); + } else if (prefix == "chat") { + emit chatEvent(ChatEventData(line)); } else if (prefix == "resp") { if (values.size() != 2) { // XXX @@ -231,6 +233,26 @@ void Client::ping() cmd("ping"); } +PendingCommand *Client::chatListChannels() +{ + return cmd("chat_list_channels"); +} + +PendingCommand *Client::chatJoinChannel(const QString &name) +{ + return cmd(QString("chat_join_channel|%1").arg(name)); +} + +PendingCommand *Client::chatLeaveChannel(const QString &name) +{ + return cmd(QString("chat_leave_channel|%1").arg(name)); +} + +PendingCommand *Client::chatSay(const QString &channel, const QString &s) +{ + return cmd(QString("chat_say|%1|%2").arg(channel).arg(s)); +} + PendingCommand *Client::listGames() { return cmd("list_games"); diff --git a/cockatrice/src/client.h b/cockatrice/src/client.h index 8939fd38..4abde05e 100644 --- a/cockatrice/src/client.h +++ b/cockatrice/src/client.h @@ -57,6 +57,7 @@ signals: void responseReceived(int msgid, ServerResponse resp); void playerIdReceived(int id, QString name); void gameEvent(const ServerEventData &msg); + void chatEvent(const ChatEventData &msg); void serverTimeout(); void logSocketError(const QString &errorString); void serverError(ServerResponse resp); @@ -90,6 +91,10 @@ public: void connectToServer(const QString &hostname, unsigned int port, const QString &_playerName, const QString &_password); void disconnectFromServer(); public slots: + PendingCommand *chatListChannels(); + PendingCommand *chatJoinChannel(const QString &name); + PendingCommand *chatLeaveChannel(const QString &name); + PendingCommand *chatSay(const QString &name, const QString &s); PendingCommand *listGames(); PendingCommand *listPlayers(); PendingCommand *createGame(const QString &description, const QString &password, unsigned int maxPlayers); diff --git a/cockatrice/src/game.cpp b/cockatrice/src/game.cpp index 12ba6aee..f3638983 100644 --- a/cockatrice/src/game.cpp +++ b/cockatrice/src/game.cpp @@ -300,9 +300,12 @@ void Game::gameEvent(const ServerEventData &msg) p->gameEvent(msg); break; } - case eventInvalid: + case eventInvalid: { qDebug("Unhandled global event"); } + default: { + } + } } } diff --git a/cockatrice/src/gameselector.cpp b/cockatrice/src/gameselector.cpp index 02891695..7616f8a4 100644 --- a/cockatrice/src/gameselector.cpp +++ b/cockatrice/src/gameselector.cpp @@ -27,18 +27,13 @@ GameSelector::GameSelector(Client *_client, QWidget *parent) connect(createButton, SIGNAL(clicked()), this, SLOT(actCreate())); connect(joinButton, SIGNAL(clicked()), this, SLOT(actJoin())); - - connect(client, SIGNAL(gameListEvent(ServerGame *)), gameListModel, SLOT(updateGameList(ServerGame *))); - connect(client, SIGNAL(statusChanged(ProtocolStatus)), this, SLOT(statusChanged(ProtocolStatus))); - - client->listGames(); } void GameSelector::actCreate() { DlgCreateGame dlg(client, this); if (dlg.exec()) - deleteLater(); + disableGameList(); } void GameSelector::actRefresh() @@ -49,7 +44,7 @@ void GameSelector::actRefresh() void GameSelector::statusChanged(ProtocolStatus status) { if (status == StatusDisconnected) - deleteLater(); + disableGameList(); } void GameSelector::checkResponse(ServerResponse response) @@ -58,7 +53,7 @@ void GameSelector::checkResponse(ServerResponse response) joinButton->setEnabled(true); if (response == RespOk) - deleteLater(); + disableGameList(); else { QMessageBox::critical(this, tr("Error"), tr("XXX")); return; @@ -84,3 +79,18 @@ void GameSelector::actJoin() createButton->setEnabled(false); joinButton->setEnabled(false); } + +void GameSelector::enableGameList() +{ + connect(client, SIGNAL(gameListEvent(ServerGame *)), gameListModel, SLOT(updateGameList(ServerGame *))); + connect(client, SIGNAL(statusChanged(ProtocolStatus)), this, SLOT(statusChanged(ProtocolStatus))); + client->listGames(); + show(); +} + +void GameSelector::disableGameList() +{ + disconnect(client, 0, this, 0); + hide(); + gameListModel->cleanList(); +} diff --git a/cockatrice/src/gameselector.h b/cockatrice/src/gameselector.h index 2d4b447c..b8937ad3 100644 --- a/cockatrice/src/gameselector.h +++ b/cockatrice/src/gameselector.h @@ -13,6 +13,8 @@ class GameSelector : public QWidget { Q_OBJECT public: GameSelector(Client *_client, QWidget *parent = 0); + void enableGameList(); + void disableGameList(); private slots: void actCreate(); void actRefresh(); diff --git a/cockatrice/src/gamesmodel.cpp b/cockatrice/src/gamesmodel.cpp index cf542c44..848b6ce0 100644 --- a/cockatrice/src/gamesmodel.cpp +++ b/cockatrice/src/gamesmodel.cpp @@ -69,8 +69,10 @@ void GamesModel::updateGameList(ServerGame *game) void GamesModel::cleanList() { + beginRemoveRows(QModelIndex(), 0, gameList.size() - 1); QListIterator i(gameList); while (i.hasNext()) delete i.next(); gameList.clear(); + endRemoveRows(); } diff --git a/cockatrice/src/gamesmodel.h b/cockatrice/src/gamesmodel.h index 545939ba..ef352fb9 100644 --- a/cockatrice/src/gamesmodel.h +++ b/cockatrice/src/gamesmodel.h @@ -16,11 +16,11 @@ public: QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; ServerGame *getGame(int row); + void cleanList(); public slots: void updateGameList(ServerGame *game); private: QList gameList; - void cleanList(); }; #endif diff --git a/cockatrice/src/servereventdata.cpp b/cockatrice/src/servereventdata.cpp index cf7ba9f4..df97bf60 100644 --- a/cockatrice/src/servereventdata.cpp +++ b/cockatrice/src/servereventdata.cpp @@ -3,49 +3,57 @@ // Message structure for server events: // {"private","public"}|PlayerId|PlayerName|EventType|EventData -const int event_count = 21; -const event_string event_strings[event_count] = { - {eventPlayerId, "player_id"}, - {eventSay, "say"}, - {eventName, "name"}, - {eventJoin, "join"}, - {eventLeave, "leave"}, - {eventReadyStart, "ready_start"}, - {eventSetupZones, "setup_zones"}, - {eventGameStart, "game_start"}, - {eventShuffle, "shuffle"}, - {eventRollDice, "roll_dice"}, - {eventDraw, "draw"}, - {eventMoveCard, "move_card"}, - {eventCreateToken, "create_token"}, - {eventSetCardAttr, "set_card_attr"}, - {eventAddCounter, "add_counter"}, - {eventSetCounter, "set_counter"}, - {eventDelCounter, "del_counter"}, - {eventSetActivePlayer, "set_active_player"}, - {eventSetActivePhase, "set_active_phase"}, - {eventDumpZone, "dump_zone"}, - {eventStopDumpZone, "stop_dump_zone"} -}; +QHash ServerEventData::eventHash; ServerEventData::ServerEventData(const QString &line) { - QStringList values = line.split("|"); + if (eventHash.isEmpty()) { + eventHash.insert("player_id", eventPlayerId); + eventHash.insert("say", eventSay); + eventHash.insert("name", eventName); + eventHash.insert("join", eventJoin); + eventHash.insert("leave", eventLeave); + eventHash.insert("ready_start", eventReadyStart); + eventHash.insert("setup_zones", eventSetupZones); + eventHash.insert("game_start", eventGameStart); + eventHash.insert("shuffle", eventShuffle); + eventHash.insert("roll_dice", eventRollDice); + eventHash.insert("draw", eventDraw); + eventHash.insert("move_card", eventMoveCard); + eventHash.insert("create_token", eventCreateToken); + eventHash.insert("set_card_attr", eventSetCardAttr); + eventHash.insert("add_counter", eventAddCounter); + eventHash.insert("set_counter", eventSetCounter); + eventHash.insert("del_counter", eventDelCounter); + eventHash.insert("set_active_player", eventSetActivePlayer); + eventHash.insert("set_active_phase", eventSetActivePhase); + eventHash.insert("dump_zone", eventDumpZone); + eventHash.insert("stop_dump_zone", eventStopDumpZone); + } + + QStringList values = line.split('|'); IsPublic = !values.takeFirst().compare("public"); PlayerId = values.takeFirst().toInt(); PlayerName = values.takeFirst(); - - QString type = values.takeFirst(); - bool found = false; - for (int i = 0; i < event_count; i++) - if (!type.compare(event_strings[i].str)) { - EventType = event_strings[i].type; - found = true; - break; - } - if (!found) - EventType = eventInvalid; - + EventType = eventHash.value(values.takeFirst(), eventInvalid); EventData = values; } + +QHash ChatEventData::eventHash; + +ChatEventData::ChatEventData(const QString &line) +{ + if (eventHash.isEmpty()) { + eventHash.insert("list_channels", eventChatListChannels); + eventHash.insert("join_channel", eventChatJoinChannel); + eventHash.insert("list_players", eventChatListPlayers); + eventHash.insert("leave_channel", eventChatLeaveChannel); + eventHash.insert("say", eventChatSay); + } + + QStringList values = line.split('|'); + values.removeFirst(); + eventType = eventHash.value(values.takeFirst(), eventChatInvalid); + eventData = values; +} diff --git a/cockatrice/src/servereventdata.h b/cockatrice/src/servereventdata.h index f471fc22..50233af5 100644 --- a/cockatrice/src/servereventdata.h +++ b/cockatrice/src/servereventdata.h @@ -2,6 +2,7 @@ #define SERVEREVENTDATA_H #include +#include enum ServerEventType { eventInvalid, @@ -28,16 +29,10 @@ enum ServerEventType { eventStopDumpZone }; -struct event_string { - ServerEventType type; - char *str; -}; - -extern const int event_count; -extern const event_string event_strings[]; - class ServerEventData { private: + static QHash eventHash; + bool IsPublic; int PlayerId; QString PlayerName; @@ -47,9 +42,30 @@ public: ServerEventData(const QString &line); bool getPublic() const { return IsPublic; } int getPlayerId() const { return PlayerId; } - QString getPlayerName() const { return PlayerName; } + const QString &getPlayerName() const { return PlayerName; } ServerEventType getEventType() const { return EventType; } - QStringList getEventData() const { return EventData; } + const QStringList &getEventData() const { return EventData; } +}; + +enum ChatEventType { + eventChatInvalid, + eventChatListChannels, + eventChatJoinChannel, + eventChatListPlayers, + eventChatLeaveChannel, + eventChatSay +}; + +class ChatEventData { +private: + static QHash eventHash; + + ChatEventType eventType; + QStringList eventData; +public: + ChatEventData(const QString &line); + ChatEventType getEventType() const { return eventType; } + const QStringList &getEventData() const { return eventData; } }; #endif diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index fc7696d2..4e1b1f54 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -35,6 +35,7 @@ #include "zoneviewzone.h" #include "zoneviewwidget.h" #include "zoneviewlayout.h" +#include "chatwidget.h" void MainWindow::hoverCard(QString name) { @@ -86,8 +87,8 @@ void MainWindow::statusChanged(ProtocolStatus _status) phasesToolbar->setActivePhase(-1); phasesToolbar->setEnabled(false); - GameSelector *gameSelector = new GameSelector(client); - viewLayout->insertWidget(0, gameSelector); + gameSelector->enableGameList(); + chatWidget->enableChat(); break; } case StatusPlaying: @@ -211,6 +212,7 @@ void MainWindow::retranslateUi() sayLabel->setText(tr("&Say:")); cardInfo->retranslateUi(); + chatWidget->retranslateUi(); } void MainWindow::createActions() @@ -272,6 +274,7 @@ MainWindow::MainWindow(QTranslator *_translator, QWidget *parent) scene = new QGraphicsScene(0, 0, 1096, 1160, this); view = new GameView(scene); + view->hide(); // view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); @@ -285,6 +288,12 @@ MainWindow::MainWindow(QTranslator *_translator, QWidget *parent) sayLabel = new QLabel; sayEdit = new QLineEdit; sayLabel->setBuddy(sayEdit); + + client = new Client(this); + gameSelector = new GameSelector(client); + gameSelector->hide(); + chatWidget = new ChatWidget(client); + chatWidget->hide(); QHBoxLayout *hLayout = new QHBoxLayout; hLayout->addWidget(sayLabel); @@ -296,6 +305,8 @@ MainWindow::MainWindow(QTranslator *_translator, QWidget *parent) verticalLayout->addLayout(hLayout); viewLayout = new QVBoxLayout; + viewLayout->addWidget(gameSelector); + viewLayout->addWidget(chatWidget); viewLayout->addWidget(view); phasesToolbar = new PhasesToolbar; @@ -312,7 +323,6 @@ MainWindow::MainWindow(QTranslator *_translator, QWidget *parent) connect(sayEdit, SIGNAL(returnPressed()), this, SLOT(actSay())); - client = new Client(this); connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout())); connect(client, SIGNAL(statusChanged(ProtocolStatus)), this, SLOT(statusChanged(ProtocolStatus))); connect(client, SIGNAL(playerIdReceived(int, QString)), this, SLOT(playerIdReceived(int, QString))); diff --git a/cockatrice/src/window_main.h b/cockatrice/src/window_main.h index 460ca2bc..39f821e5 100644 --- a/cockatrice/src/window_main.h +++ b/cockatrice/src/window_main.h @@ -40,6 +40,8 @@ class ServerZoneCard; class ZoneViewLayout; class ZoneViewWidget; class PhasesToolbar; +class GameSelector; +class ChatWidget; class MainWindow : public QMainWindow { Q_OBJECT @@ -80,6 +82,8 @@ private: QLabel *sayLabel; QLineEdit *sayEdit; PhasesToolbar *phasesToolbar; + GameSelector *gameSelector; + ChatWidget *chatWidget; Client *client; QGraphicsScene *scene; diff --git a/servatrice/servatrice.pro b/servatrice/servatrice.pro index 626dc610..89d87379 100755 --- a/servatrice/servatrice.pro +++ b/servatrice/servatrice.pro @@ -21,7 +21,8 @@ HEADERS += src/server.h src/servergame.h src/serversocket.h \ src/counter.h \ src/abstractrng.h \ src/rng_qt.h \ - src/returnmessage.h + src/returnmessage.h \ + src/chatchannel.h SOURCES += src/main.cpp \ src/server.cpp \ src/servergame.cpp \ @@ -30,4 +31,5 @@ SOURCES += src/main.cpp \ src/card.cpp \ src/counter.cpp \ src/rng_qt.cpp \ - src/returnmessage.cpp + src/returnmessage.cpp \ + src/chatchannel.cpp diff --git a/servatrice/src/chatchannel.cpp b/servatrice/src/chatchannel.cpp new file mode 100644 index 00000000..f8f1528e --- /dev/null +++ b/servatrice/src/chatchannel.cpp @@ -0,0 +1,39 @@ +#include "chatchannel.h" +#include "serversocket.h" + +ChatChannel::ChatChannel(const QString &_name, const QString &_description) + : name(_name), description(_description) +{ +} + +void ChatChannel::addPlayer(ServerSocket *player) +{ + QString str = QString("chat|join_channel|%1|%2").arg(name).arg(player->getPlayerName()); + for (int i = 0; i < size(); ++i) + at(i)->msg(str); + + append(player); + + for (int i = 0; i < size(); ++i) + player->msg(QString("chat|list_players|%1|%2").arg(name).arg(at(i)->getPlayerName())); + + emit channelInfoChanged(); +} + +void ChatChannel::removePlayer(ServerSocket *player) +{ + QString str = QString("chat|leave_channel|%1|%2").arg(name).arg(player->getPlayerName()); + + removeAt(indexOf(player)); + for (int i = 0; i < size(); ++i) + at(i)->msg(str); + + emit channelInfoChanged(); +} + +void ChatChannel::say(ServerSocket *player, const QString &s) +{ + QString str = QString("chat|say|%1|%2|%3").arg(name).arg(player->getPlayerName()).arg(s); + for (int i = 0; i < size(); ++i) + at(i)->msg(str); +} diff --git a/servatrice/src/chatchannel.h b/servatrice/src/chatchannel.h new file mode 100644 index 00000000..822b8489 --- /dev/null +++ b/servatrice/src/chatchannel.h @@ -0,0 +1,25 @@ +#ifndef CHATCHANNEL_H +#define CHATCHANNEL_H + +#include +#include + +class ServerSocket; + +class ChatChannel : public QObject, public QList { + Q_OBJECT +signals: + void channelInfoChanged(); +private: + QString name; + QString description; +public: + ChatChannel(const QString &_name, const QString &_description); + QString getName() const { return name; } + QString getDescription() const { return description; } + void addPlayer(ServerSocket *player); + void removePlayer(ServerSocket *player); + void say(ServerSocket *player, const QString &s); +}; + +#endif diff --git a/servatrice/src/returnmessage.cpp b/servatrice/src/returnmessage.cpp index 210f2644..14d1eca3 100644 --- a/servatrice/src/returnmessage.cpp +++ b/servatrice/src/returnmessage.cpp @@ -10,6 +10,7 @@ bool ReturnMessage::send(ReturnCode code) switch (code) { case ReturnNothing: return true; case ReturnOk: returnCodeString = "ok"; break; + case ReturnNameNotFound: returnCodeString = "name_not_found"; break; case ReturnLoginNeeded: returnCodeString = "login_needed"; break; case ReturnSyntaxError: returnCodeString = "syntax"; break; case ReturnContextError: returnCodeString = "context"; break; diff --git a/servatrice/src/returnmessage.h b/servatrice/src/returnmessage.h index 37837bca..58a464a1 100644 --- a/servatrice/src/returnmessage.h +++ b/servatrice/src/returnmessage.h @@ -9,7 +9,7 @@ private: unsigned int msg_id; QString cmd; public: - enum ReturnCode { ReturnNothing, ReturnOk, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong }; + enum ReturnCode { ReturnNothing, ReturnOk, ReturnNameNotFound, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong }; ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { } unsigned int getMsgId() const { return msg_id; } void setMsgId(unsigned int _msg_id) { msg_id = _msg_id; } diff --git a/servatrice/src/server.cpp b/servatrice/src/server.cpp index b8aa8c9a..3b477a69 100644 --- a/servatrice/src/server.cpp +++ b/servatrice/src/server.cpp @@ -22,6 +22,7 @@ #include "serversocket.h" #include "counter.h" #include "rng_qt.h" +#include "chatchannel.h" #include #include @@ -35,6 +36,9 @@ Server::Server(QObject *parent) QString dbType = settings->value("database/type").toString(); if (dbType == "mysql") openDatabase(); + + chatChannelList << new ChatChannel("channel1", "testchannel 1"); + chatChannelList << new ChatChannel("channel2", "testchannel 2"); } Server::~Server() diff --git a/servatrice/src/server.h b/servatrice/src/server.h index 467f62e9..299a0d7a 100644 --- a/servatrice/src/server.h +++ b/servatrice/src/server.h @@ -27,6 +27,7 @@ class ServerSocket; class QSqlDatabase; class QSettings; class AbstractRNG; +class ChatChannel; enum AuthenticationResult { PasswordWrong = 0, PasswordRight = 1, UnknownUser = 2 }; @@ -45,6 +46,7 @@ public: bool checkGamePassword(int gameId, const QString &password); AuthenticationResult checkUserPassword(const QString &user, const QString &password); QList listOpenGames(); + QList getChatChannelList() { return chatChannelList; } ServerGame *getGame(int gameId); AbstractRNG *getRNG() const { return rng; } void broadcastGameListUpdate(ServerGame *game); @@ -53,6 +55,7 @@ private: void incomingConnection(int SocketId); QList games; QList players; + QList chatChannelList; int nextGameId; AbstractRNG *rng; }; diff --git a/servatrice/src/serversocket.cpp b/servatrice/src/serversocket.cpp index d16157e0..dbc393b9 100644 --- a/servatrice/src/serversocket.cpp +++ b/servatrice/src/serversocket.cpp @@ -28,6 +28,7 @@ #include "counter.h" #include "card.h" #include "abstractrng.h" +#include "chatchannel.h" ServerSocket::ServerSocket(Server *_server, QObject *parent) : QTcpSocket(parent), server(_server), game(0), PlayerStatus(StatusNormal), authState(PasswordWrong), acceptsGameListChanges(false) @@ -166,6 +167,11 @@ const ServerSocket::CommandProperties ServerSocket::commandList[ServerSocket::nu {"ping", false, false, false, QList(), &ServerSocket::cmdPing}, {"login", false, false, false, QList() << QVariant::String << QVariant::String, &ServerSocket::cmdLogin}, + {"chat_list_channels", true, false, false, QList(), &ServerSocket::cmdChatListChannels}, + {"chat_join_channel", true, false, false, QList() << QVariant::String, &ServerSocket::cmdChatJoinChannel}, + {"chat_leave_channel", true, false, false, QList() << QVariant::String, &ServerSocket::cmdChatLeaveChannel}, + {"chat_say", true, false, false, QList() << QVariant::String + << QVariant::String, &ServerSocket::cmdChatSay}, {"list_games", true, false, false, QList(), &ServerSocket::cmdListGames}, {"create_game", true, false, false, QList() << QVariant::String << QVariant::String @@ -231,6 +237,55 @@ ReturnMessage::ReturnCode ServerSocket::cmdLogin(const QList ¶ms) return ReturnMessage::ReturnOk; } +ReturnMessage::ReturnCode ServerSocket::cmdChatListChannels(const QList &/*params*/) +{ + QList chatChannelList = server->getChatChannelList(); + for (int i = 0; i < chatChannelList.size(); ++i) + msg(QString("chat|list_channels|%1|%2|%3").arg(chatChannelList[i]->getName()).arg(chatChannelList[i]->getDescription()).arg(chatChannelList[i]->size())); + + acceptsChatChannelListChanges = true; + return ReturnMessage::ReturnOk; +} + +ReturnMessage::ReturnCode ServerSocket::cmdChatJoinChannel(const QList ¶ms) +{ + for (int i = 0; i < chatChannels.size(); ++i) + if (chatChannels[i]->getName() == params[0]) + return ReturnMessage::ReturnContextError; + + QList allChannels = server->getChatChannelList(); + for (int i = 0; i < allChannels.size(); ++i) + if (allChannels[i]->getName() == params[0]) { + allChannels[i]->addPlayer(this); + chatChannels << allChannels[i]; + return ReturnMessage::ReturnOk; + } + return ReturnMessage::ReturnNameNotFound; +} + +ReturnMessage::ReturnCode ServerSocket::cmdChatLeaveChannel(const QList ¶ms) +{ + for (int i = 0; i < chatChannels.size(); ++i) { + ChatChannel *c = chatChannels[i]; + if (c->getName() == params[0]) { + chatChannels.removeAt(i); + c->removePlayer(this); + return ReturnMessage::ReturnOk; + } + } + return ReturnMessage::ReturnNameNotFound; +} + +ReturnMessage::ReturnCode ServerSocket::cmdChatSay(const QList ¶ms) +{ + for (int i = 0; i < chatChannels.size(); ++i) + if (chatChannels[i]->getName() == params[0]) { + chatChannels[i]->say(this, params[1].toString()); + return ReturnMessage::ReturnOk; + } + return ReturnMessage::ReturnNameNotFound; +} + ReturnMessage::ReturnCode ServerSocket::cmdListGames(const QList &/*params*/) { QList gameList = server->listOpenGames(); diff --git a/servatrice/src/serversocket.h b/servatrice/src/serversocket.h index 1b7b1874..5aee3148 100644 --- a/servatrice/src/serversocket.h +++ b/servatrice/src/serversocket.h @@ -55,11 +55,15 @@ private: QList paramTypes; CommandHandler handler; }; - static const int numberCommands = 27; + static const int numberCommands = 31; static const CommandProperties commandList[numberCommands]; ReturnMessage::ReturnCode cmdPing(const QList ¶ms); ReturnMessage::ReturnCode cmdLogin(const QList ¶ms); + ReturnMessage::ReturnCode cmdChatListChannels(const QList ¶ms); + ReturnMessage::ReturnCode cmdChatJoinChannel(const QList ¶ms); + ReturnMessage::ReturnCode cmdChatLeaveChannel(const QList ¶ms); + ReturnMessage::ReturnCode cmdChatSay(const QList ¶ms); ReturnMessage::ReturnCode cmdListGames(const QList ¶ms); ReturnMessage::ReturnCode cmdCreateGame(const QList ¶ms); ReturnMessage::ReturnCode cmdJoinGame(const QList ¶ms); @@ -88,6 +92,7 @@ private: Server *server; ServerGame *game; + QList chatChannels; QList DeckList; QList SideboardList; QList zones; @@ -105,6 +110,7 @@ private: ReturnMessage *remsg; AuthenticationResult authState; bool acceptsGameListChanges; + bool acceptsChatChannelListChanges; public: ServerSocket(Server *_server, QObject *parent = 0); ~ServerSocket();