# HG changeset patch # User unc0rr # Date 1134766789 0 # Node ID 59f7db859b8a4124c92eeafec6e534ce995bd299 # Parent c374fe590272bb074f5359a2d12205e334e93108 - clear demos list before adding items - start to implement net game diff -r c374fe590272 -r 59f7db859b8a QTfrontend/QTfrontend.pro --- a/QTfrontend/QTfrontend.pro Fri Dec 16 20:57:14 2005 +0000 +++ b/QTfrontend/QTfrontend.pro Fri Dec 16 20:59:49 2005 +0000 @@ -10,6 +10,6 @@ QT += network # Input -HEADERS += binds.h game.h hwform.h sdlkeys.h team.h rndstr.h sha1.h gamecmds.h +HEADERS += binds.h game.h hwform.h sdlkeys.h team.h rndstr.h sha1.h gamecmds.h netclient.h FORMS += hwform.ui -SOURCES += game.cpp main.cpp hwform.cpp team.cpp rndstr.cpp sha1.cpp gamecmds.cpp +SOURCES += game.cpp main.cpp hwform.cpp team.cpp rndstr.cpp sha1.cpp gamecmds.cpp netclient.cpp diff -r c374fe590272 -r 59f7db859b8a QTfrontend/game.cpp --- a/QTfrontend/game.cpp Fri Dec 16 20:57:14 2005 +0000 +++ b/QTfrontend/game.cpp Fri Dec 16 20:59:49 2005 +0000 @@ -49,7 +49,7 @@ IPCServer->setMaxPendingConnections(1); if (!IPCServer->listen(QHostAddress("127.0.0.1"), IPC_PORT)) { - QMessageBox::critical(this, tr("Error"), + QMessageBox::critical(0, tr("Error"), tr("Unable to start the server: %1.") .arg(IPCServer->errorString())); } @@ -121,6 +121,7 @@ SENDIPC("eadd hh1 0"); SENDIPC("eadd hh2 0"); SENDIPC("eadd hh3 0"); + SENDIPC("eadd hh4 0"); SENDIPC("eaddteam"); SendTeamConfig(1); SENDIPC("ecolor 16776960"); @@ -128,6 +129,7 @@ SENDIPC("eadd hh1 1"); SENDIPC("eadd hh2 1"); SENDIPC("eadd hh3 1"); + SENDIPC("eadd hh4 1"); } void HWGame::ParseMessage() @@ -169,7 +171,7 @@ void HWGame::SendIPC(const QByteArray & buf) { - if (buf.size() > 255) return; + if (buf.size() > MAXMSGCHARS) return; quint8 len = buf.size(); IPCSocket->write((char *)&len, 1); IPCSocket->write(buf); @@ -249,12 +251,12 @@ quint32 len = themes.size(); if (len == 0) { - QMessageBox::critical(this, "Error", "Cannot access themes.cfg or bad data", "OK"); + QMessageBox::critical(0, "Error", "Cannot access themes.cfg or bad data", "OK"); return "avematan"; } if (seed.isEmpty()) { - QMessageBox::critical(this, "Error", "seed not defined", "OK"); + QMessageBox::critical(0, "Error", "seed not defined", "OK"); return "avematan"; } quint32 k = 0; @@ -270,7 +272,7 @@ QFile demofile(filename); if (!demofile.open(QIODevice::WriteOnly)) { - QMessageBox::critical(this, + QMessageBox::critical(0, tr("Error"), tr("Cannot save demo to file %s").arg(filename), tr("Quit")); @@ -288,7 +290,7 @@ QFile demofile(demofilename); if (!demofile.open(QIODevice::ReadOnly)) { - QMessageBox::critical(this, + QMessageBox::critical(0, tr("Error"), tr("Cannot open demofile %s").arg(demofilename), tr("Quit")); @@ -312,7 +314,7 @@ quint32 index = toSendBuf->indexOf(10); if (!index) { - QMessageBox::critical(this, + QMessageBox::critical(0, tr("Error"), tr("Corrupted demo file %s").arg(demofilename), tr("Quit")); diff -r c374fe590272 -r 59f7db859b8a QTfrontend/game.h --- a/QTfrontend/game.h Fri Dec 16 20:57:14 2005 +0000 +++ b/QTfrontend/game.h Fri Dec 16 20:59:49 2005 +0000 @@ -35,7 +35,6 @@ #define GAME_H #include -#include #include #include #include @@ -47,7 +46,7 @@ #define MAXMSGCHARS 255 #define SENDIPC(a) SendIPC(a, sizeof(a) - 1) -class HWGame : public QDialog +class HWGame : public QObject { Q_OBJECT public: diff -r c374fe590272 -r 59f7db859b8a QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Fri Dec 16 20:57:14 2005 +0000 +++ b/QTfrontend/hwform.cpp Fri Dec 16 20:59:49 2005 +0000 @@ -146,23 +146,27 @@ settings.close(); } - connect(ui.BtnSPBack, SIGNAL(clicked()), this, SLOT(GoToMain())); - connect(ui.BtnDemosBack, SIGNAL(clicked()), this, SLOT(GoToMain())); - connect(ui.BtnSetupBack, SIGNAL(clicked()), this, SLOT(GoToMain())); - connect(ui.BtnMPBack, SIGNAL(clicked()), this, SLOT(GoToMain())); - connect(ui.BtnSinglePlayer, SIGNAL(clicked()), this, SLOT(GoToSinglePlayer())); - connect(ui.BtnSetup, SIGNAL(clicked()), this, SLOT(GoToSetup())); - connect(ui.BtnMultiplayer, SIGNAL(clicked()), this, SLOT(GoToMultiplayer())); - connect(ui.BtnDemos, SIGNAL(clicked()), this, SLOT(GoToDemos())); - connect(ui.BtnNewTeam, SIGNAL(clicked()), this, SLOT(NewTeam())); - connect(ui.BtnEditTeam, SIGNAL(clicked()), this, SLOT(EditTeam())); - connect(ui.BtnTeamSave, SIGNAL(clicked()), this, SLOT(TeamSave())); - connect(ui.BtnTeamDiscard, SIGNAL(clicked()), this, SLOT(TeamDiscard())); - connect(ui.BtnSimpleGame, SIGNAL(clicked()), this, SLOT(SimpleGame())); - connect(ui.BtnSaveOptions, SIGNAL(clicked()), this, SLOT(SaveOptions())); - connect(ui.BtnPlayDemo, SIGNAL(clicked()), this, SLOT(PlayDemo())); - connect(ui.CBGrave, SIGNAL(activated(const QString &)), this, SLOT(CBGrave_activated(const QString &))); - connect(ui.CBFort, SIGNAL(activated(const QString &)), this, SLOT(CBFort_activated(const QString &))); + connect(ui.BtnSPBack, SIGNAL(clicked()), this, SLOT(GoToMain())); + connect(ui.BtnDemosBack, SIGNAL(clicked()), this, SLOT(GoToMain())); + connect(ui.BtnSetupBack, SIGNAL(clicked()), this, SLOT(GoToMain())); + connect(ui.BtnMPBack, SIGNAL(clicked()), this, SLOT(GoToMain())); + connect(ui.BtnNetBack, SIGNAL(clicked()), this, SLOT(GoToMain())); + connect(ui.BtnSinglePlayer, SIGNAL(clicked()), this, SLOT(GoToSinglePlayer())); + connect(ui.BtnSetup, SIGNAL(clicked()), this, SLOT(GoToSetup())); + connect(ui.BtnMultiplayer, SIGNAL(clicked()), this, SLOT(GoToMultiplayer())); + connect(ui.BtnDemos, SIGNAL(clicked()), this, SLOT(GoToDemos())); + connect(ui.BtnNet, SIGNAL(clicked()), this, SLOT(GoToNet())); + connect(ui.BtnNewTeam, SIGNAL(clicked()), this, SLOT(NewTeam())); + connect(ui.BtnEditTeam, SIGNAL(clicked()), this, SLOT(EditTeam())); + connect(ui.BtnTeamSave, SIGNAL(clicked()), this, SLOT(TeamSave())); + connect(ui.BtnTeamDiscard, SIGNAL(clicked()), this, SLOT(TeamDiscard())); + connect(ui.BtnSimpleGame, SIGNAL(clicked()), this, SLOT(SimpleGame())); + connect(ui.BtnSaveOptions, SIGNAL(clicked()), this, SLOT(SaveOptions())); + connect(ui.BtnPlayDemo, SIGNAL(clicked()), this, SLOT(PlayDemo())); + connect(ui.BtnNetConnect, SIGNAL(clicked()), this, SLOT(NetConnect())); + connect(ui.BtnNetChatDisconnect, SIGNAL(clicked()), this, SLOT(NetDisconnect())); + connect(ui.CBGrave, SIGNAL(activated(const QString &)), this, SLOT(CBGrave_activated(const QString &))); + connect(ui.CBFort, SIGNAL(activated(const QString &)), this, SLOT(CBFort_activated(const QString &))); ui.Pages->setCurrentIndex(ID_PAGE_MAIN); } @@ -192,10 +196,21 @@ tmpdir.cd(DATA_PATH); tmpdir.cd("Demos"); tmpdir.setFilter(QDir::Files); + ui.DemosList->clear(); ui.DemosList->addItems(tmpdir.entryList(QStringList("*.hwd_1")).replaceInStrings(QRegExp("^(.*).hwd_1"), "\\1")); ui.Pages->setCurrentIndex(ID_PAGE_DEMOS); } +void HWForm::GoToNet() +{ + ui.Pages->setCurrentIndex(ID_PAGE_NET); +} + +void HWForm::GoToNetChat() +{ + ui.Pages->setCurrentIndex(ID_PAGE_NETCHAT); +} + void HWForm::NewTeam() { tmpTeam = new HWTeam("unnamed"); @@ -280,4 +295,21 @@ game->PlayDemo(QString(DATA_PATH) + "/Demos/" + curritem->text() + ".hwd_1"); } +void HWForm::NetConnect() +{ + hwnet = new HWNet(); + hwnet->Connect("localhost", 6667); + connect(hwnet, SIGNAL(Connected()), this, SLOT(GoToNetChat())); + connect(hwnet, SIGNAL(AddGame(const QString &)), this, SLOT(AddGame(const QString &))); +} +void HWForm::NetDisconnect() +{ + hwnet->Disconnect(); + GoToNet(); +} + +void HWForm::AddGame(const QString & chan) +{ + ui.ChannelsList->addItem(chan); +} diff -r c374fe590272 -r 59f7db859b8a QTfrontend/hwform.h --- a/QTfrontend/hwform.h Fri Dec 16 20:57:14 2005 +0000 +++ b/QTfrontend/hwform.h Fri Dec 16 20:59:49 2005 +0000 @@ -41,6 +41,7 @@ #include "binds.h" #include "game.h" #include "team.h" +#include "netclient.h" class HWForm : public QMainWindow { @@ -59,6 +60,8 @@ void GoToSetup(); void GoToMultiplayer(); void GoToDemos(); + void GoToNet(); + void GoToNetChat(); void NewTeam(); void EditTeam(); void TeamSave(); @@ -66,6 +69,9 @@ void SimpleGame(); void SaveOptions(); void PlayDemo(); + void NetConnect(); + void NetDisconnect(); + void AddGame(const QString & chan); public slots: void CBGrave_activated(const QString & gravename); @@ -76,6 +82,7 @@ HWGame * game; QDir cfgdir; HWTeam * tmpTeam; + HWNet * hwnet; }; #define ID_PAGE_SINGLEPLAYER 0 @@ -83,6 +90,8 @@ #define ID_PAGE_SETUP 2 #define ID_PAGE_MULTIPLAYER 3 #define ID_PAGE_DEMOS 4 -#define ID_PAGE_MAIN 5 +#define ID_PAGE_NET 5 +#define ID_PAGE_NETCHAT 6 +#define ID_PAGE_MAIN 7 #endif diff -r c374fe590272 -r 59f7db859b8a QTfrontend/hwform.ui --- a/QTfrontend/hwform.ui Fri Dec 16 20:57:14 2005 +0000 +++ b/QTfrontend/hwform.ui Fri Dec 16 20:59:49 2005 +0000 @@ -50,7 +50,7 @@ - 1 + 6 @@ -372,7 +372,7 @@ 0 - 1 + 0 @@ -380,7 +380,7 @@ 0 0 181 - 297 + 270 @@ -397,8 +397,8 @@ 0 0 - 163 - 252 + 99 + 29 @@ -673,6 +673,16 @@ false + + + + 170 + 10 + 311 + 311 + + + @@ -703,13 +713,167 @@ false - + + + + + + 250 + 140 + 161 + 41 + + + + + MS Shell Dlg + 14 + 50 + false + false + false + false + + + + Connect + + + false + + + false + + + + + + 250 + 390 + 161 + 41 + + + + + MS Shell Dlg + 14 + 50 + false + false + false + false + + + + Back + + + false + + + false + + + + + - 170 + 460 + 290 + 161 + 41 + + + + + MS Shell Dlg + 14 + 50 + false + false + false + false + + + + Join + + + false + + + false + + + + + + 460 + 340 + 161 + 41 + + + + + MS Shell Dlg + 14 + 50 + false + false + false + false + + + + Create + + + false + + + false + + + + + + 460 + 390 + 161 + 41 + + + + + MS Shell Dlg + 14 + 50 + false + false + false + false + + + + Disconnect + + + false + + + false + + + + + + 20 10 - 311 - 311 + 201 + 331 @@ -835,36 +999,6 @@ false - - - - 230 - 170 - 161 - 41 - - - - - MS Shell Dlg - 14 - 50 - false - false - false - false - - - - Net game - - - false - - - false - - @@ -895,6 +1029,36 @@ false + + + + 230 + 170 + 161 + 41 + + + + + MS Shell Dlg + 14 + 50 + false + false + false + false + + + + Net game + + + false + + + false + + diff -r c374fe590272 -r 59f7db859b8a QTfrontend/netclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QTfrontend/netclient.cpp Fri Dec 16 20:59:49 2005 +0000 @@ -0,0 +1,179 @@ +/* + * Hedgewars, a worms-like game + * Copyright (c) 2005 Andrey Korotaev + * + * Distributed under the terms of the BSD-modified licence: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "netclient.h" + +HWNet::HWNet() + : QObject() +{ + state = nsDisconnected; + IRCmsg_cmd_param = new QRegExp("^[A-Z]+ :.+$"); + IRCmsg_number_param = new QRegExp("^:\\S+ [0-9]{3} .+$"); + + connect(&NetSocket, SIGNAL(readyRead()), this, SLOT(ClientRead())); + connect(&NetSocket, SIGNAL(connected()), this, SLOT(OnConnect())); + connect(&NetSocket, SIGNAL(disconnected()), this, SLOT(OnDisconnect())); + connect(&NetSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, + SLOT(displayError(QAbstractSocket::SocketError))); +} + +void HWNet::ClientRead() +{ + while (NetSocket.canReadLine()) + { + ParseLine(NetSocket.readLine().trimmed()); + } +} + +void HWNet::displayError(QAbstractSocket::SocketError socketError) +{ + switch (socketError) + { + case QAbstractSocket::RemoteHostClosedError: + break; + case QAbstractSocket::HostNotFoundError: + QMessageBox::information(0, tr("Error"), + tr("The host was not found. Please check the host name and port settings.")); + break; + case QAbstractSocket::ConnectionRefusedError: + QMessageBox::information(0, tr("Error"), + tr("Connection refused")); + break; + default: + QMessageBox::information(0, tr("Error"), + NetSocket.errorString()); + } +} + +void HWNet::Connect(const QString & hostName, quint16 port) +{ + state = nsConnecting; + NetSocket.connectToHost(hostName, port); +} + + +void HWNet::OnConnect() +{ + state = nsConnected; + SendNet(QString("USER hwgame 1 2 Hedgewars game")); + SendNet(QString("NICK Hedgewars")); +} + +void HWNet::OnDisconnect() +{ + state = nsDisconnected; +} + +void HWNet::Perform() +{ + SendNet(QString("LIST")); + SendNet(QString("JOIN #hw")); +} + +void HWNet::Disconnect() +{ + switch (state) + { + case nsDisconnected: + { + break; + } + case nsConnecting: + case nsQuitting: + { + NetSocket.disconnect(); + break; + } + default: + { + state = nsQuitting; + SendNet(QString("QUIT :oops")); + } + } +} + +void HWNet::SendNet(const QString & str) +{ + SendNet(str.toLatin1()); +} + +void HWNet::SendNet(const QByteArray & buf) +{ + if (buf.size() > 510) return; + NetSocket.write(buf); + NetSocket.write("\x0d\x0a", 2); +} + +void HWNet::ParseLine(const QString & msg) +{ + if (IRCmsg_cmd_param->exactMatch(msg)) + { + msgcmd_paramHandler(msg); + } else + if (IRCmsg_number_param->exactMatch(msg)) + { + msgnumber_paramHandler(msg); + } +} + +void HWNet::msgcmd_paramHandler(const QString & msg) +{ + QStringList list = msg.split(" :"); + if (list[0] == "PING") + { + SendNet(QString("PONG %1").arg(list[1])); + } +} + +void HWNet::msgnumber_paramHandler(const QString & msg) +{ + QStringList list = msg.split(" "); + bool ok; + quint16 number = list[1].toInt(&ok); + if (!ok) + return ; + switch (number) + { + case 001 : + { + Perform(); + emit Connected(); + break; + } + case 322 : + { + emit AddGame(list[3]); + } + } +} diff -r c374fe590272 -r 59f7db859b8a QTfrontend/netclient.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/QTfrontend/netclient.h Fri Dec 16 20:59:49 2005 +0000 @@ -0,0 +1,81 @@ +/* + * Hedgewars, a worms-like game + * Copyright (c) 2005 Andrey Korotaev + * + * Distributed under the terms of the BSD-modified licence: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * with the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef NET_H +#define NET_H + +#include +#include +#include + +class HWNet : public QObject +{ + Q_OBJECT + +public: + HWNet(); + void Connect(const QString & hostName, quint16 port); + void Disconnect(); + void SendNet(const QString & buf); + void SendNet(const QByteArray & buf); + +signals: + void Connected(); + void AddGame(const QString & chan); + +private: + enum NetState { + nsDisconnected = 0, + nsConnecting = 1, + nsConnected = 3, + nsQuitting = 5 + }; + + QTcpSocket NetSocket; + NetState state; + QRegExp * IRCmsg_cmd_param; + QRegExp * IRCmsg_number_param; + + void ParseLine(const QString & msg); + void msgcmd_paramHandler(const QString & msg); + void msgnumber_paramHandler(const QString & msg); + +private slots: + void ClientRead(); + void OnConnect(); + void OnDisconnect(); + void Perform(); + void displayError(QAbstractSocket::SocketError socketError); +}; + +#endif