|
|
/* VierGewinnt - A simple 4-in-a-row network game
|
|
|
*
|
|
|
* Copyright (c) 2008 by Sebastian Lohff, seba@seba-geek.de
|
|
|
* http://www.seba-geek.de
|
|
|
*
|
|
|
* This file is part of VierGewinnt.
|
|
|
*
|
|
|
* VierGewinnt is free software: you can redistribute it and/or modify
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
* (at your option) any later version.
|
|
|
*
|
|
|
* VierGewinnt is distributed in the hope that it will be useful,
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
* GNU General Public License for more details.
|
|
|
*
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
* along with VierGewinnt. If not, see <http://www.gnu.org/licenses/>.
|
|
|
*/
|
|
|
|
|
|
#include "findserver.h"
|
|
|
|
|
|
#include <QtNetwork>
|
|
|
#include <QDataStream>
|
|
|
#include <QtDebug>
|
|
|
|
|
|
FindServerWidget::FindServerWidget(QWidget *parent) : QWidget(parent) {
|
|
|
setFixedSize(640, 480);
|
|
|
setWindowTitle(tr("Sebas Netzwerk-VierGewinnt Client")+" - "+tr("Serverliste"));
|
|
|
masterserver = "1.proj.seba-geek.de"; // srv1.proj.seba-geek.de
|
|
|
masterport = 31415;
|
|
|
|
|
|
// net stuff
|
|
|
mysock = new QTcpSocket;
|
|
|
connect(mysock, SIGNAL(connected()), this, SLOT(procNet()));
|
|
|
connect(mysock, SIGNAL(readyRead()), this, SLOT(procNet()));
|
|
|
connect(mysock, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(procNetError(QAbstractSocket::SocketError)));
|
|
|
connect(mysock, SIGNAL(disconnected()), this, SLOT(procNetDisconnect()));
|
|
|
|
|
|
// dialoge
|
|
|
masterdialog = new SelectMasterDialog(this);
|
|
|
cgamedialog = new CreateGameDialog(mysock); /* , this */
|
|
|
vwinwid = new VierGewinntWidget(mysock, this);
|
|
|
about = new AboutDialog(this);
|
|
|
|
|
|
// networkbrowser
|
|
|
nettable = new QTreeWidget;
|
|
|
nettable->setColumnCount(5);
|
|
|
// nettable->setMaximumWidth(400);
|
|
|
QStringList header;
|
|
|
header << tr("Id") << tr("Spielname") << tr("Spieler") << tr("Spielfeld") << tr("Gewinnt") << "";
|
|
|
nettable->setHeaderLabels(header);
|
|
|
// nettable->resizeColumnToContents(0);
|
|
|
// nettable->resizeColumnToContents(1);
|
|
|
// nettable->resizeColumnToContents(2);
|
|
|
|
|
|
// buttonreihe
|
|
|
buttonrow = new QHBoxLayout;
|
|
|
refresh = new QPushButton(tr("Erneuern"));
|
|
|
connect(refresh, SIGNAL(clicked()), this, SLOT(refreshServerList()));
|
|
|
create = new QPushButton(tr("Erstellen"));
|
|
|
connect(create, SIGNAL(clicked()), this, SLOT(createGame()));
|
|
|
join = new QPushButton(tr("Beitreten"));
|
|
|
connect(join, SIGNAL(clicked()), this, SLOT(joinGame()));
|
|
|
othermaster = new QPushButton(tr("Anderer Masterserver"));
|
|
|
connect(othermaster, SIGNAL(clicked()), this, SLOT(changeMaster()));
|
|
|
butabout = new QPushButton(tr("<EFBFBD>ber"));
|
|
|
connect(butabout, SIGNAL(clicked()), about, SLOT(exec()));
|
|
|
|
|
|
|
|
|
|
|
|
buttonrow->addWidget(refresh);
|
|
|
buttonrow->addWidget(create);
|
|
|
buttonrow->addWidget(join);
|
|
|
buttonrow->addStretch();
|
|
|
buttonrow->addWidget(othermaster);
|
|
|
buttonrow->addWidget(butabout);
|
|
|
|
|
|
|
|
|
// network drunter
|
|
|
status = new QTextEdit;
|
|
|
status->setReadOnly(true);
|
|
|
status->setMaximumHeight(80);
|
|
|
addLog(tr("Dr<EFBFBD>cke Erneuern um eine Serverliste zu erhalten"));
|
|
|
|
|
|
// layout stuff
|
|
|
layout = new QVBoxLayout;
|
|
|
|
|
|
layout->addWidget(nettable);
|
|
|
layout->addLayout(buttonrow);
|
|
|
layout->addWidget(status);
|
|
|
|
|
|
setLayout(layout);
|
|
|
|
|
|
loginstate = 0;
|
|
|
refreshonconnect = false;
|
|
|
ingame = false;
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::refreshServerList() {
|
|
|
if(mysock->state()==QTcpSocket::UnconnectedState) {
|
|
|
refreshonconnect = true;
|
|
|
startConnect();
|
|
|
} else {
|
|
|
QTextStream sockstream(mysock);
|
|
|
addLog(tr("Fordere Liste an..."));
|
|
|
nettable->clear();
|
|
|
sockstream << "LIST\n";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::changeMaster() {
|
|
|
// this->hide();
|
|
|
masterdialog->setData(masterserver, masterport);
|
|
|
masterdialog->show();
|
|
|
if(masterdialog->exec()== QDialog::Accepted) {
|
|
|
masterserver = masterdialog->getMasterServer();
|
|
|
masterport = masterdialog->getMasterPort();
|
|
|
mysock->close();
|
|
|
startConnect();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::createGame() {
|
|
|
if(mysock->state()==QTcpSocket::UnconnectedState)
|
|
|
startConnect();
|
|
|
// this->setDisabled(true);
|
|
|
// this->hide();
|
|
|
// cgamedialog->reset();
|
|
|
cgamedialog->show();
|
|
|
if(cgamedialog->exec()== QDialog::Accepted) {
|
|
|
addLog(tr("Spiel erstellt"));
|
|
|
vwinwid->init(7, 6);
|
|
|
qDebug() << "i am still here!";
|
|
|
} else {
|
|
|
// this->setDisabled(false);
|
|
|
// mysock->close();
|
|
|
}
|
|
|
// this->show();
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::joinGame() {
|
|
|
QTreeWidgetItem *myitem = nettable->currentItem();
|
|
|
if(myitem==0) {
|
|
|
QMessageBox msgbox(this);
|
|
|
msgbox.setText(tr("Es wurde kein Spiel zum beitreten ausgew<65>hlt"));
|
|
|
msgbox.exec();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(mysock->state()==QTcpSocket::UnconnectedState)
|
|
|
startConnect();
|
|
|
|
|
|
// initing the field (here we have the data)
|
|
|
vwinwid->init(7, 6); // to be changed when custom fields are allowed
|
|
|
|
|
|
// get id
|
|
|
int gameid = myitem->text(0).toInt();
|
|
|
addLog(tr("Trete Spiel bei.."));
|
|
|
QTextStream mytext(mysock);
|
|
|
mytext << "JOIN " << gameid << "\n";
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::procNet() {
|
|
|
QTextStream sockstream(mysock);
|
|
|
QString tmpbuf;
|
|
|
switch(loginstate) {
|
|
|
case 0:{
|
|
|
sockstream << "VERSION viergewinnt-qt\n";
|
|
|
loginstate++;
|
|
|
}break;
|
|
|
case 1:
|
|
|
tmpbuf = mysock->readLine();
|
|
|
if(tmpbuf.contains("ACK VERSION")) {
|
|
|
addLog(tr("Version akzeptiert"));
|
|
|
sockstream << "SELECT VierGewinnt\n";
|
|
|
loginstate++;
|
|
|
} else {
|
|
|
addLog(tr("Version nicht akzeptiert, kein GNS-Server!"));
|
|
|
mysock->close();
|
|
|
}
|
|
|
break;
|
|
|
case 2:
|
|
|
tmpbuf = mysock->readLine();
|
|
|
if(tmpbuf.contains("ACK SELECT")) {
|
|
|
loginstate++;
|
|
|
addLog(tr("Modul ausgew<65>hlt"));
|
|
|
if(refreshonconnect) {
|
|
|
refreshServerList();
|
|
|
|
|
|
refreshonconnect = false;
|
|
|
}
|
|
|
} else {
|
|
|
addLog(tr("VierGewinnt-Modul nicht gefunden!"));
|
|
|
mysock->close();
|
|
|
}
|
|
|
break;
|
|
|
default:
|
|
|
// list, join or error
|
|
|
// tmpbuf = mysock->readLine();
|
|
|
// addLog("Got INput: "+sockstream.readLine());
|
|
|
|
|
|
do {
|
|
|
|
|
|
QTextStream sockstream2(mysock->readLine());
|
|
|
sockstream2 >> tmpbuf;
|
|
|
|
|
|
if(tmpbuf=="ERROR") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
int myerrno = tmpbuf.toInt();
|
|
|
if(myerrno==121) {
|
|
|
addLog(tr("Keine Spiele offen :("));
|
|
|
} else if(myerrno==125) {
|
|
|
addLog(tr("Konnte nicht beitreten: Spiel voll"));
|
|
|
} else if(myerrno==124) {
|
|
|
addLog(tr("Spiel konnte nicht gefunden werden"));
|
|
|
} else if(tmpbuf=="Not") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
if(tmpbuf=="your") {
|
|
|
vwinwid->ackAdd(false);
|
|
|
}
|
|
|
} else if(tmpbuf=="Row") {
|
|
|
vwinwid->ackAdd(false);
|
|
|
} else {
|
|
|
qDebug() << "Unbekannter Fehler: " << tmpbuf;
|
|
|
// addLog(tr("Unbekannter error: ")+tmpbuf);
|
|
|
}
|
|
|
} else if(tmpbuf=="GAME") {
|
|
|
QStringList qstrlst;
|
|
|
QString tmpbuf2;
|
|
|
sockstream2 >> tmpbuf; // id
|
|
|
qstrlst << tmpbuf;
|
|
|
sockstream2 >> tmpbuf2; // player in
|
|
|
sockstream2 >> tmpbuf; // player max
|
|
|
tmpbuf2 += "/";
|
|
|
tmpbuf2 += tmpbuf;
|
|
|
sockstream2 >> tmpbuf; // game's name
|
|
|
qstrlst << tmpbuf;
|
|
|
qstrlst << tmpbuf2;
|
|
|
sockstream2 >> tmpbuf2; // x
|
|
|
sockstream2 >> tmpbuf; // y
|
|
|
tmpbuf2 += "x";
|
|
|
tmpbuf2 += tmpbuf;
|
|
|
qstrlst << tmpbuf2;
|
|
|
sockstream2 >> tmpbuf; // for the win
|
|
|
qstrlst << tmpbuf;
|
|
|
nettable->addTopLevelItem(new QTreeWidgetItem(qstrlst));
|
|
|
} else if(tmpbuf=="ACK") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
if(tmpbuf=="CREATE") {
|
|
|
addLog("Spiel erstellt, warte auf Mitspieler");
|
|
|
vwinwid->clientExited();
|
|
|
this->hide();
|
|
|
vwinwid->show();
|
|
|
} else if(tmpbuf=="JOIN") {
|
|
|
// set data to mainwindow
|
|
|
goToGameWindow();
|
|
|
} else if(tmpbuf=="ADD") {
|
|
|
vwinwid->ackAdd(true);
|
|
|
}
|
|
|
} else if(tmpbuf=="INFO") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
if(tmpbuf=="START") {
|
|
|
vwinwid->startGame();
|
|
|
qDebug() << "Game Started!";
|
|
|
} else if(tmpbuf=="TURN") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
vwinwid->setTurn(tmpbuf.toInt()==1);
|
|
|
} else if(tmpbuf=="ADD") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
vwinwid->add(tmpbuf.toInt(), VierGewinntWidget::o);
|
|
|
} else if(tmpbuf=="GAME") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
if(tmpbuf=="STOP") {
|
|
|
vwinwid->clientExited();
|
|
|
}
|
|
|
} else if(tmpbuf=="STATUS") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
vwinwid->newGame(tmpbuf=="WON");
|
|
|
// REQ NEW GAME Message ignored, handled here
|
|
|
} else if(tmpbuf=="CLIENT") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
if(tmpbuf=="NEW") {
|
|
|
vwinwid->ackNewGame();
|
|
|
}
|
|
|
} else if(tmpbuf=="NEW") {
|
|
|
sockstream2 >> tmpbuf;
|
|
|
if(tmpbuf=="GAME") {
|
|
|
vwinwid->startGame();
|
|
|
}
|
|
|
} else if(tmpbuf=="SCORE") {
|
|
|
QString tmpbuf2;
|
|
|
sockstream2 >> tmpbuf;
|
|
|
sockstream2 >> tmpbuf2;
|
|
|
vwinwid->setScore(tmpbuf.toInt(), tmpbuf2.toInt());
|
|
|
}
|
|
|
} else {
|
|
|
qDebug() << "Unhandled TMPBUF: " << tmpbuf;
|
|
|
}
|
|
|
} while(!sockstream.atEnd());
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::procNetError(QAbstractSocket::SocketError e) {
|
|
|
switch(e) {
|
|
|
case QAbstractSocket::HostNotFoundError:
|
|
|
addLog(tr("Fehler: Der Master-Server Hostname konnte nicht aufgel<65>st werden!"));
|
|
|
break;
|
|
|
case QAbstractSocket::ConnectionRefusedError:
|
|
|
addLog(tr("Fehler: Verbindungsversuch zum Master-Server ist fehlgeschlagen!"));
|
|
|
break;
|
|
|
case QAbstractSocket::RemoteHostClosedError:
|
|
|
procNetDisconnect();
|
|
|
break;
|
|
|
default:
|
|
|
addLog(tr("Netzwerkfehler: '%1'").arg(mysock->errorString()));
|
|
|
break;
|
|
|
}
|
|
|
qDebug() << "Networ error: " << mysock->errorString();
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::procNetDisconnect() {
|
|
|
vwinwid->hide();
|
|
|
this->show();
|
|
|
nettable->clear();
|
|
|
addLog(tr("Die Verbindung zum Masterserver wurde getrennt."));
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::addLog(QString str) {
|
|
|
status->append(str);
|
|
|
qDebug() << "Log: " << str;
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::startConnect() {
|
|
|
loginstate = 0;
|
|
|
ingame = false;
|
|
|
addLog((tr("Versuche Verbindung zu ")+masterserver+" ..."));
|
|
|
mysock->connectToHost(masterserver, masterport);
|
|
|
}
|
|
|
|
|
|
void FindServerWidget::goToGameWindow() {
|
|
|
qDebug() << "SHOW togamewindow";
|
|
|
this->hide();
|
|
|
vwinwid->startGame();
|
|
|
vwinwid->show();
|
|
|
}
|