Viergewinnt (four-in-a-row) implementation in c++ and QT
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

findserver.cpp 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* VierGewinnt - A simple 4-in-a-row network game
  2. *
  3. * Copyright (c) 2008 by Sebastian Lohff, seba@seba-geek.de
  4. * http://www.seba-geek.de
  5. *
  6. * This file is part of VierGewinnt.
  7. *
  8. * VierGewinnt is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * VierGewinnt is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with VierGewinnt. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include "findserver.h"
  22. #include <QtNetwork>
  23. #include <QDataStream>
  24. #include <QtDebug>
  25. FindServerWidget::FindServerWidget(QWidget *parent) : QWidget(parent) {
  26. setFixedSize(640, 480);
  27. setWindowTitle(tr("Sebas Netzwerk-VierGewinnt Client")+" - "+tr("Serverliste"));
  28. masterserver = "1.proj.seba-geek.de"; // srv1.proj.seba-geek.de
  29. masterport = 31415;
  30. // net stuff
  31. mysock = new QTcpSocket;
  32. connect(mysock, SIGNAL(connected()), this, SLOT(procNet()));
  33. connect(mysock, SIGNAL(readyRead()), this, SLOT(procNet()));
  34. connect(mysock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(procNetError(QAbstractSocket::SocketError)));
  35. connect(mysock, SIGNAL(disconnected()), this, SLOT(procNetDisconnect()));
  36. // dialoge
  37. masterdialog = new SelectMasterDialog(this);
  38. cgamedialog = new CreateGameDialog(mysock); /* , this */
  39. vwinwid = new VierGewinntWidget(mysock, this);
  40. about = new AboutDialog(this);
  41. // networkbrowser
  42. nettable = new QTreeWidget;
  43. nettable->setColumnCount(5);
  44. // nettable->setMaximumWidth(400);
  45. QStringList header;
  46. header << tr("Id") << tr("Spielname") << tr("Spieler") << tr("Spielfeld") << tr("Gewinnt") << "";
  47. nettable->setHeaderLabels(header);
  48. // nettable->resizeColumnToContents(0);
  49. // nettable->resizeColumnToContents(1);
  50. // nettable->resizeColumnToContents(2);
  51. // buttonreihe
  52. buttonrow = new QHBoxLayout;
  53. refresh = new QPushButton(tr("Erneuern"));
  54. connect(refresh, SIGNAL(clicked()), this, SLOT(refreshServerList()));
  55. create = new QPushButton(tr("Erstellen"));
  56. connect(create, SIGNAL(clicked()), this, SLOT(createGame()));
  57. join = new QPushButton(tr("Beitreten"));
  58. connect(join, SIGNAL(clicked()), this, SLOT(joinGame()));
  59. othermaster = new QPushButton(tr("Anderer Masterserver"));
  60. connect(othermaster, SIGNAL(clicked()), this, SLOT(changeMaster()));
  61. butabout = new QPushButton(tr("Über"));
  62. connect(butabout, SIGNAL(clicked()), about, SLOT(exec()));
  63. buttonrow->addWidget(refresh);
  64. buttonrow->addWidget(create);
  65. buttonrow->addWidget(join);
  66. buttonrow->addStretch();
  67. buttonrow->addWidget(othermaster);
  68. buttonrow->addWidget(butabout);
  69. // network drunter
  70. status = new QTextEdit;
  71. status->setReadOnly(true);
  72. status->setMaximumHeight(80);
  73. addLog(tr("Drücke Erneuern um eine Serverliste zu erhalten"));
  74. // layout stuff
  75. layout = new QVBoxLayout;
  76. layout->addWidget(nettable);
  77. layout->addLayout(buttonrow);
  78. layout->addWidget(status);
  79. setLayout(layout);
  80. loginstate = 0;
  81. refreshonconnect = false;
  82. ingame = false;
  83. }
  84. void FindServerWidget::refreshServerList() {
  85. if(mysock->state()==QTcpSocket::UnconnectedState) {
  86. refreshonconnect = true;
  87. startConnect();
  88. } else {
  89. QTextStream sockstream(mysock);
  90. addLog(tr("Fordere Liste an..."));
  91. nettable->clear();
  92. sockstream << "LIST\n";
  93. }
  94. }
  95. void FindServerWidget::changeMaster() {
  96. // this->hide();
  97. masterdialog->setData(masterserver, masterport);
  98. masterdialog->show();
  99. if(masterdialog->exec()== QDialog::Accepted) {
  100. masterserver = masterdialog->getMasterServer();
  101. masterport = masterdialog->getMasterPort();
  102. mysock->close();
  103. startConnect();
  104. }
  105. }
  106. void FindServerWidget::createGame() {
  107. if(mysock->state()==QTcpSocket::UnconnectedState)
  108. startConnect();
  109. // this->setDisabled(true);
  110. // this->hide();
  111. // cgamedialog->reset();
  112. cgamedialog->show();
  113. if(cgamedialog->exec()== QDialog::Accepted) {
  114. addLog(tr("Spiel erstellt"));
  115. vwinwid->init(7, 6);
  116. qDebug() << "i am still here!";
  117. } else {
  118. // this->setDisabled(false);
  119. // mysock->close();
  120. }
  121. // this->show();
  122. }
  123. void FindServerWidget::joinGame() {
  124. QTreeWidgetItem *myitem = nettable->currentItem();
  125. if(myitem==0) {
  126. QMessageBox msgbox(this);
  127. msgbox.setText(tr("Es wurde kein Spiel zum beitreten ausgewählt"));
  128. msgbox.exec();
  129. return;
  130. }
  131. if(mysock->state()==QTcpSocket::UnconnectedState)
  132. startConnect();
  133. // initing the field (here we have the data)
  134. vwinwid->init(7, 6); // to be changed when custom fields are allowed
  135. // get id
  136. int gameid = myitem->text(0).toInt();
  137. addLog(tr("Trete Spiel bei.."));
  138. QTextStream mytext(mysock);
  139. mytext << "JOIN " << gameid << "\n";
  140. }
  141. void FindServerWidget::procNet() {
  142. QTextStream sockstream(mysock);
  143. QString tmpbuf;
  144. switch(loginstate) {
  145. case 0:{
  146. sockstream << "VERSION viergewinnt-qt\n";
  147. loginstate++;
  148. }break;
  149. case 1:
  150. tmpbuf = mysock->readLine();
  151. if(tmpbuf.contains("ACK VERSION")) {
  152. addLog(tr("Version akzeptiert"));
  153. sockstream << "SELECT VierGewinnt\n";
  154. loginstate++;
  155. } else {
  156. addLog(tr("Version nicht akzeptiert, kein GNS-Server!"));
  157. mysock->close();
  158. }
  159. break;
  160. case 2:
  161. tmpbuf = mysock->readLine();
  162. if(tmpbuf.contains("ACK SELECT")) {
  163. loginstate++;
  164. addLog(tr("Modul ausgewählt"));
  165. if(refreshonconnect) {
  166. refreshServerList();
  167. refreshonconnect = false;
  168. }
  169. } else {
  170. addLog(tr("VierGewinnt-Modul nicht gefunden!"));
  171. mysock->close();
  172. }
  173. break;
  174. default:
  175. // list, join or error
  176. // tmpbuf = mysock->readLine();
  177. // addLog("Got INput: "+sockstream.readLine());
  178. do {
  179. QTextStream sockstream2(mysock->readLine());
  180. sockstream2 >> tmpbuf;
  181. if(tmpbuf=="ERROR") {
  182. sockstream2 >> tmpbuf;
  183. int myerrno = tmpbuf.toInt();
  184. if(myerrno==121) {
  185. addLog(tr("Keine Spiele offen :("));
  186. } else if(myerrno==125) {
  187. addLog(tr("Konnte nicht beitreten: Spiel voll"));
  188. } else if(myerrno==124) {
  189. addLog(tr("Spiel konnte nicht gefunden werden"));
  190. } else if(tmpbuf=="Not") {
  191. sockstream2 >> tmpbuf;
  192. if(tmpbuf=="your") {
  193. vwinwid->ackAdd(false);
  194. }
  195. } else if(tmpbuf=="Row") {
  196. vwinwid->ackAdd(false);
  197. } else {
  198. qDebug() << "Unbekannter Fehler: " << tmpbuf;
  199. // addLog(tr("Unbekannter error: ")+tmpbuf);
  200. }
  201. } else if(tmpbuf=="GAME") {
  202. QStringList qstrlst;
  203. QString tmpbuf2;
  204. sockstream2 >> tmpbuf; // id
  205. qstrlst << tmpbuf;
  206. sockstream2 >> tmpbuf2; // player in
  207. sockstream2 >> tmpbuf; // player max
  208. tmpbuf2 += "/";
  209. tmpbuf2 += tmpbuf;
  210. sockstream2 >> tmpbuf; // game's name
  211. qstrlst << tmpbuf;
  212. qstrlst << tmpbuf2;
  213. sockstream2 >> tmpbuf2; // x
  214. sockstream2 >> tmpbuf; // y
  215. tmpbuf2 += "x";
  216. tmpbuf2 += tmpbuf;
  217. qstrlst << tmpbuf2;
  218. sockstream2 >> tmpbuf; // for the win
  219. qstrlst << tmpbuf;
  220. nettable->addTopLevelItem(new QTreeWidgetItem(qstrlst));
  221. } else if(tmpbuf=="ACK") {
  222. sockstream2 >> tmpbuf;
  223. if(tmpbuf=="CREATE") {
  224. addLog("Spiel erstellt, warte auf Mitspieler");
  225. vwinwid->clientExited();
  226. this->hide();
  227. vwinwid->show();
  228. } else if(tmpbuf=="JOIN") {
  229. // set data to mainwindow
  230. goToGameWindow();
  231. } else if(tmpbuf=="ADD") {
  232. vwinwid->ackAdd(true);
  233. }
  234. } else if(tmpbuf=="INFO") {
  235. sockstream2 >> tmpbuf;
  236. if(tmpbuf=="START") {
  237. vwinwid->startGame();
  238. qDebug() << "Game Started!";
  239. } else if(tmpbuf=="TURN") {
  240. sockstream2 >> tmpbuf;
  241. vwinwid->setTurn(tmpbuf.toInt()==1);
  242. } else if(tmpbuf=="ADD") {
  243. sockstream2 >> tmpbuf;
  244. vwinwid->add(tmpbuf.toInt(), VierGewinntWidget::o);
  245. } else if(tmpbuf=="GAME") {
  246. sockstream2 >> tmpbuf;
  247. if(tmpbuf=="STOP") {
  248. vwinwid->clientExited();
  249. }
  250. } else if(tmpbuf=="STATUS") {
  251. sockstream2 >> tmpbuf;
  252. vwinwid->newGame(tmpbuf=="WON");
  253. // REQ NEW GAME Message ignored, handled here
  254. } else if(tmpbuf=="CLIENT") {
  255. sockstream2 >> tmpbuf;
  256. if(tmpbuf=="NEW") {
  257. vwinwid->ackNewGame();
  258. }
  259. } else if(tmpbuf=="NEW") {
  260. sockstream2 >> tmpbuf;
  261. if(tmpbuf=="GAME") {
  262. vwinwid->startGame();
  263. }
  264. } else if(tmpbuf=="SCORE") {
  265. QString tmpbuf2;
  266. sockstream2 >> tmpbuf;
  267. sockstream2 >> tmpbuf2;
  268. vwinwid->setScore(tmpbuf.toInt(), tmpbuf2.toInt());
  269. }
  270. } else {
  271. qDebug() << "Unhandled TMPBUF: " << tmpbuf;
  272. }
  273. } while(!sockstream.atEnd());
  274. break;
  275. }
  276. }
  277. void FindServerWidget::procNetError(QAbstractSocket::SocketError e) {
  278. switch(e) {
  279. case QAbstractSocket::HostNotFoundError:
  280. addLog(tr("Fehler: Der Master-Server Hostname konnte nicht aufgelöst werden!"));
  281. break;
  282. case QAbstractSocket::ConnectionRefusedError:
  283. addLog(tr("Fehler: Verbindungsversuch zum Master-Server ist fehlgeschlagen!"));
  284. break;
  285. case QAbstractSocket::RemoteHostClosedError:
  286. procNetDisconnect();
  287. break;
  288. default:
  289. addLog(tr("Netzwerkfehler: '%1'").arg(mysock->errorString()));
  290. break;
  291. }
  292. qDebug() << "Networ error: " << mysock->errorString();
  293. }
  294. void FindServerWidget::procNetDisconnect() {
  295. vwinwid->hide();
  296. this->show();
  297. nettable->clear();
  298. addLog(tr("Die Verbindung zum Masterserver wurde getrennt."));
  299. }
  300. void FindServerWidget::addLog(QString str) {
  301. status->append(str);
  302. qDebug() << "Log: " << str;
  303. }
  304. void FindServerWidget::startConnect() {
  305. loginstate = 0;
  306. ingame = false;
  307. addLog((tr("Versuche Verbindung zu ")+masterserver+" ..."));
  308. mysock->connectToHost(masterserver, masterport);
  309. }
  310. void FindServerWidget::goToGameWindow() {
  311. qDebug() << "SHOW togamewindow";
  312. this->hide();
  313. vwinwid->startGame();
  314. vwinwid->show();
  315. }