lobby_moc.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #include "lobby_moc.h"
  2. #include "ui_lobby_moc.h"
  3. #include "../lib/GameConstants.h"
  4. #include "../jsonutils.h"
  5. #include "../../lib/CConfigHandler.h"
  6. //#include "../../lib/VCMIDirs.h"
  7. SocketLobby::SocketLobby(QObject *parent) :
  8. QObject(parent)
  9. {
  10. socket = new QTcpSocket(this);
  11. connect(socket, SIGNAL(connected()), this, SLOT(connected()));
  12. connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
  13. connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
  14. connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64)));
  15. }
  16. void SocketLobby::connectServer(const QString & host, int port, const QString & usr)
  17. {
  18. const int connectionTimeout = 1000;
  19. username = usr;
  20. emit text("Connecting to " + host + ":" + QString::number(port));
  21. socket->connectToHost(host, port);
  22. if(!socket->waitForDisconnected(connectionTimeout) && !isConnected)
  23. {
  24. emit text("Error: " + socket->errorString());
  25. }
  26. }
  27. void SocketLobby::disconnectServer()
  28. {
  29. socket->disconnectFromHost();
  30. }
  31. void SocketLobby::requestNewSession(const QString & session, int totalPlayers, const QString & pswd)
  32. {
  33. const QString sessionMessage = ProtocolStrings[CREATE].arg(session, pswd, QString::number(totalPlayers));
  34. send(sessionMessage);
  35. }
  36. void SocketLobby::requestJoinSession(const QString & session, const QString & pswd)
  37. {
  38. const QString sessionMessage = ProtocolStrings[JOIN].arg(session, pswd);
  39. send(sessionMessage);
  40. }
  41. void SocketLobby::requestLeaveSession(const QString & session)
  42. {
  43. const QString sessionMessage = ProtocolStrings[LEAVE].arg(session);
  44. send(sessionMessage);
  45. }
  46. void SocketLobby::requestReadySession(const QString & session)
  47. {
  48. const QString sessionMessage = ProtocolStrings[READY].arg(session);
  49. send(sessionMessage);
  50. }
  51. void SocketLobby::send(const QString & msg)
  52. {
  53. socket->write(qPrintable(msg));
  54. }
  55. void SocketLobby::connected()
  56. {
  57. isConnected = true;
  58. emit text("Connected!");
  59. const QString greetingConst = ProtocolStrings[GREETING].arg(username, QString::fromStdString(GameConstants::VCMI_VERSION));
  60. send(greetingConst);
  61. }
  62. void SocketLobby::disconnected()
  63. {
  64. isConnected = false;
  65. emit text("Disconnected!");
  66. }
  67. void SocketLobby::bytesWritten(qint64 bytes)
  68. {
  69. qDebug() << "We wrote: " << bytes;
  70. }
  71. void SocketLobby::readyRead()
  72. {
  73. qDebug() << "Reading...";
  74. emit receive(socket->readAll());
  75. }
  76. ServerCommand::ServerCommand(ProtocolConsts cmd, const QStringList & args):
  77. command(cmd),
  78. arguments(args)
  79. {
  80. }
  81. Lobby::Lobby(QWidget *parent) :
  82. QWidget(parent),
  83. ui(new Ui::Lobby)
  84. {
  85. ui->setupUi(this);
  86. connect(&socketLobby, SIGNAL(text(QString)), this, SLOT(chatMessage(QString)));
  87. connect(&socketLobby, SIGNAL(receive(QString)), this, SLOT(dispatchMessage(QString)));
  88. }
  89. Lobby::~Lobby()
  90. {
  91. delete ui;
  92. }
  93. void Lobby::serverCommand(const ServerCommand & command) try
  94. {
  95. //initialize variables outside of switch block
  96. const QString statusPlaceholder("%1 %2\n");
  97. QString resText;
  98. const auto & args = command.arguments;
  99. int amount, tagPoint;
  100. QString joinStr;
  101. switch(command.command)
  102. {
  103. case ERROR:
  104. protocolAssert(args.size());
  105. chatMessage("System error:" + args[0]);
  106. break;
  107. case CREATED:
  108. protocolAssert(args.size());
  109. hostSession = args[0];
  110. session = args[0];
  111. chatMessage("System: new session started");
  112. break;
  113. case SESSIONS:
  114. protocolAssert(args.size());
  115. amount = args[0].toInt();
  116. protocolAssert(amount * 4 == (args.size() - 1));
  117. ui->sessionsTable->setRowCount(amount);
  118. tagPoint = 1;
  119. for(int i = 0; i < amount; ++i)
  120. {
  121. QTableWidgetItem * sessionNameItem = new QTableWidgetItem(args[tagPoint++]);
  122. ui->sessionsTable->setItem(i, 0, sessionNameItem);
  123. int playersJoined = args[tagPoint++].toInt();
  124. int playersTotal = args[tagPoint++].toInt();
  125. QTableWidgetItem * sessionPlayerItem = new QTableWidgetItem(QString("%1/%2").arg(playersJoined).arg(playersTotal));
  126. ui->sessionsTable->setItem(i, 1, sessionPlayerItem);
  127. QTableWidgetItem * sessionProtectedItem = new QTableWidgetItem(args[tagPoint++]);
  128. ui->sessionsTable->setItem(i, 2, sessionProtectedItem);
  129. }
  130. break;
  131. case JOINED:
  132. case KICKED:
  133. protocolAssert(args.size() == 2);
  134. joinStr = (command.command == JOINED ? "System: %1 joined to the session %2" : "System: %1 left session %2");
  135. if(args[1] == username)
  136. {
  137. ui->chat->clear(); //cleanup the chat
  138. chatMessage(joinStr.arg("you", args[0]));
  139. session = args[0];
  140. ui->stackedWidget->setCurrentWidget(command.command == JOINED ? ui->roomPage : ui->sessionsPage);
  141. }
  142. else
  143. {
  144. chatMessage(joinStr.arg(args[1], args[0]));
  145. }
  146. break;
  147. case STATUS:
  148. protocolAssert(args.size() > 0);
  149. amount = args[0].toInt();
  150. protocolAssert(amount * 2 == (args.size() - 1));
  151. tagPoint = 1;
  152. ui->roomChat->clear();
  153. resText.clear();
  154. for(int i = 0; i < amount; ++i, tagPoint += 2)
  155. {
  156. resText += statusPlaceholder.arg(args[tagPoint], args[tagPoint + 1] == "True" ? "ready" : "");
  157. }
  158. ui->roomChat->setPlainText(resText);
  159. break;
  160. case START:
  161. //actually start game
  162. break;
  163. case CHAT:
  164. protocolAssert(args.size() > 1);
  165. QString msg;
  166. for(int i = 1; i < args.size(); ++i)
  167. msg += args[i];
  168. chatMessage(QString("%1: %2").arg(args[0], msg));
  169. break;
  170. }
  171. }
  172. catch(const ProtocolError & e)
  173. {
  174. chatMessage(QString("System error: %1").arg(e.what()));
  175. }
  176. void Lobby::dispatchMessage(QString txt) try
  177. {
  178. if(txt.isEmpty())
  179. return;
  180. QStringList parseTags = txt.split(":>>");
  181. protocolAssert(parseTags.size() > 1 && parseTags[0].isEmpty() && !parseTags[1].isEmpty());
  182. for(int c = 1; c < parseTags.size(); ++c)
  183. {
  184. QStringList parseArgs = parseTags[c].split(":");
  185. protocolAssert(parseArgs.size() > 1);
  186. auto ctype = ProtocolStrings.key(parseArgs[0]);
  187. parseArgs.pop_front();
  188. ServerCommand cmd(ctype, parseArgs);
  189. serverCommand(cmd);
  190. }
  191. }
  192. catch(const ProtocolError & e)
  193. {
  194. chatMessage(QString("System error: %1").arg(e.what()));
  195. }
  196. void Lobby::chatMessage(QString txt)
  197. {
  198. QTextCursor curs(ui->chat->document());
  199. curs.movePosition(QTextCursor::End);
  200. curs.insertText(txt + "\n");
  201. }
  202. void Lobby::protocolAssert(bool expr)
  203. {
  204. if(!expr)
  205. throw ProtocolError("Protocol error");
  206. }
  207. void Lobby::on_messageEdit_returnPressed()
  208. {
  209. socketLobby.send(ProtocolStrings[MESSAGE].arg(ui->messageEdit->text()));
  210. ui->messageEdit->clear();
  211. }
  212. void Lobby::on_connectButton_toggled(bool checked)
  213. {
  214. if(checked)
  215. {
  216. username = ui->userEdit->text();
  217. Settings node = settings.write["launcher"];
  218. node["lobbyUrl"].String() = ui->hostEdit->text().toStdString();
  219. node["lobbyPort"].Integer() = ui->portEdit->text().toInt();
  220. node["lobbyUsername"].String() = username.toStdString();
  221. socketLobby.connectServer(ui->hostEdit->text(), ui->portEdit->text().toInt(), username);
  222. }
  223. else
  224. {
  225. socketLobby.disconnectServer();
  226. }
  227. }
  228. void Lobby::on_newButton_clicked()
  229. {
  230. bool ok;
  231. QString sessionName = QInputDialog::getText(this, tr("New session"), tr("Session name:"), QLineEdit::Normal, "", &ok);
  232. if(ok && !sessionName.isEmpty())
  233. socketLobby.requestNewSession(sessionName, 2, ui->passwordInput->text());
  234. }
  235. void Lobby::on_joinButton_clicked()
  236. {
  237. auto * item = ui->sessionsTable->item(ui->sessionsTable->currentRow(), 0);
  238. if(item)
  239. socketLobby.requestJoinSession(item->text(), ui->passwordInput->text());
  240. }
  241. void Lobby::on_buttonLeave_clicked()
  242. {
  243. socketLobby.requestLeaveSession(session);
  244. }
  245. void Lobby::on_buttonReady_clicked()
  246. {
  247. socketLobby.requestReadySession(session);
  248. }