Now net game is near available, but exception occurs...
authorunc0rr
Tue, 27 Dec 2005 10:20:55 +0000
changeset 31 99888245a4e8
parent 30 794e98e11b66
child 32 78bff13b11c0
Now net game is near available, but exception occurs...
QTfrontend/game.cpp
QTfrontend/game.h
QTfrontend/gamecmds.cpp
QTfrontend/hwform.cpp
QTfrontend/hwform.h
QTfrontend/hwform.ui
QTfrontend/netclient.cpp
QTfrontend/netclient.h
--- a/QTfrontend/game.cpp	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/game.cpp	Tue Dec 27 10:20:55 2005 +0000
@@ -57,6 +57,8 @@
 	IPCSocket = 0;
 	TeamCount = 0;
 	seed = "";
+	cfgdir.setPath(cfgdir.homePath());
+	cfgdir.cd(".hedgewars");
 }
 
 void HWGame::NewConnection()
@@ -84,23 +86,7 @@
 
 void HWGame::SendTeamConfig(int index)
 {
-	QFile teamcfg(teams[index]);
-	if (!teamcfg.open(QIODevice::ReadOnly))
-	{
-		return ;
-	}
-	QTextStream stream(&teamcfg);
-	stream.setCodec("UTF-8");
-	QString str;
-
-	while (!stream.atEnd())
-	{
-		str = stream.readLine();
-		if (str.startsWith(";") || (str.length() > 254)) continue;
-		str.prepend("e");
-		SendIPC(str.toLocal8Bit());
-	}
-	teamcfg.close();
+	LocalCFG(teams[index]);
 }
 
 void HWGame::SendConfig()
@@ -108,14 +94,15 @@
 	if (gameType == gtDemo)
 	{
 		SENDIPC("TD");
-		SendIPCRaw(toSendBuf->constData(), toSendBuf->size());
+		RawSendIPC(*toSendBuf);
 		delete toSendBuf;
 		return ;
 	}
 	SENDIPC("TL");
-	SENDIPC("e$gmflags 0");
+//	SENDIPC("e$gmflags 0");
 	SENDIPC("eaddteam");
 	SendTeamConfig(0);
+//	if () SENDIPC("rdriven");
 	SENDIPC("ecolor 65535");
 	SENDIPC("eadd hh0 0");
 	SENDIPC("eadd hh1 0");
@@ -138,12 +125,21 @@
 	{
 		case '?':
 		{
-			SENDIPC("!");
+			if (gameType == gtNet)
+				emit SendNet(QByteArray("\x01""?"));
+			else
+				SENDIPC("!");
 			break;
 		}
 		case 'C':
 		{
-			SendConfig();
+			if (gameType == gtNet)
+			{
+				SENDIPC("TN");
+				emit SendNet(QByteArray("\x01""C"));
+			}
+			else
+				SendConfig();
 			break;
 		}
 		case '+':
@@ -152,6 +148,10 @@
 		}
 		default:
 		{
+			if (gameType == gtNet)
+			{
+				emit SendNet(QByteArray::fromRawData(msgbuf, msgsize));
+			}
 			demo->append(msgsize);
 			demo->append(QByteArray::fromRawData(msgbuf, msgsize));
 		}
@@ -179,10 +179,16 @@
 	demo->append(buf);
 }
 
-void HWGame::SendIPCRaw(const char * msg, quint32 len)
+void HWGame::RawSendIPC(const QByteArray & buf)
 {
-	IPCSocket->write(msg, len);
-	demo->append(QByteArray::fromRawData(msg, len));
+	IPCSocket->write(buf);
+	demo->append(buf);
+}
+
+void HWGame::FromNet(const QByteArray & msg)
+{
+	// ?local config?
+	RawSendIPC(msg);
 }
 
 void HWGame::ClientRead()
@@ -209,11 +215,8 @@
 
 void HWGame::Start()
 {
-	gameType = gtLocal;
-	if (TeamCount < 2) return;
 	QProcess * process;
 	QStringList arguments;
-	seedgen.GenRNDStr(seed, 10);
 	process = new QProcess;
 	arguments << resolutions[0][vid_Resolution];
 	arguments << resolutions[1][vid_Resolution];
@@ -222,9 +225,6 @@
 	arguments << seed;
 	arguments << (vid_Fullscreen ? "1" : "0");
 	process->start("hw", arguments);
-	demo = new QByteArray;
-	demo->append(seed.toLocal8Bit());
-	demo->append(10);
 }
 
 void HWGame::AddTeam(const QString & teamname)
@@ -336,3 +336,45 @@
 	process->start("hw", arguments);
 	demo = new QByteArray;
 }
+
+void HWGame::StartNet(const QString & netseed)
+{
+	gameType = gtNet;
+	seed = netseed;
+	Start();
+	demo = new QByteArray;
+	demo->append(seed.toLocal8Bit());
+	demo->append(10);
+}
+
+void HWGame::StartLocal()
+{
+	gameType = gtLocal;
+	if (TeamCount < 2) return;
+	seedgen.GenRNDStr(seed, 10);
+	Start();
+	demo = new QByteArray;
+	demo->append(seed.toLocal8Bit());
+	demo->append(10);
+}
+
+void HWGame::LocalCFG(const QString & teamname)
+{
+	QFile teamcfg(cfgdir.absolutePath() + "/" + teamname + ".cfg");
+	if (!teamcfg.open(QIODevice::ReadOnly))
+	{
+		return ;
+	}
+	QTextStream stream(&teamcfg);
+	stream.setCodec("UTF-8");
+	QString str;
+
+	while (!stream.atEnd())
+	{
+		str = stream.readLine();
+		if (str.startsWith(";") || (str.length() > 254)) continue;
+		str.prepend("e");
+		SendIPC(str.toLocal8Bit());
+	}
+	teamcfg.close();
+}
--- a/QTfrontend/game.h	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/game.h	Tue Dec 27 10:20:55 2005 +0000
@@ -39,6 +39,7 @@
 #include <QTcpSocket>
 #include <QByteArray>
 #include <QString>
+#include <QDir>
 #include "team.h"
 #include "rndstr.h"
 
@@ -51,9 +52,17 @@
 	Q_OBJECT
 public:
 	HWGame(int Resolution, bool Fullscreen);
-	void Start();
 	void AddTeam(const QString & team);
 	void PlayDemo(const QString & demofilename);
+	void StartLocal();
+	void StartNet(const QString & netseed);
+
+signals:
+	void SendNet(const QByteArray & msg);
+
+public slots:
+	void FromNet(const QByteArray & msg);
+	void LocalCFG(const QString & teamname);
 
 private:
     enum GameType {
@@ -75,13 +84,15 @@
 	int vid_Resolution;
 	bool vid_Fullscreen;
 	GameType gameType;
+	QDir cfgdir;
 
+	void Start();
 	void SendConfig();
 	void SendTeamConfig(int index);
 	void ParseMessage();
 	void SendIPC(const char * msg, quint8 len);
 	void SendIPC(const QByteArray & buf);
-	void SendIPCRaw(const char * msg, quint32 len);
+	void RawSendIPC(const QByteArray & buf);
 	void SaveDemo(const QString & filename);
 	QString GetThemeBySeed();
 
--- a/QTfrontend/gamecmds.cpp	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/gamecmds.cpp	Tue Dec 27 10:20:55 2005 +0000
@@ -37,4 +37,4 @@
     : QWidget(parent)
 {
 
-}
\ No newline at end of file
+}
--- a/QTfrontend/hwform.cpp	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/hwform.cpp	Tue Dec 27 10:20:55 2005 +0000
@@ -134,13 +134,15 @@
 			if (str.startsWith(";")) continue;
 			if (str.startsWith("resolution "))
 			{
-				str.remove(0, 11);
-				ui.CBResolution->setCurrentIndex(str.toLong());
+				ui.CBResolution->setCurrentIndex(str.mid(11).toLong());
 			} else
 			if (str.startsWith("fullscreen "))
 			{
-				str.remove(0, 11);
-				ui.CBFullscreen->setChecked(str.toLong());
+				ui.CBFullscreen->setChecked(str.mid(11).toLong());
+			} else
+			if (str.startsWith("nick "))
+			{
+				ui.editNetNick->setText(str.mid(5));
 			}
 		}
 		settings.close();
@@ -156,6 +158,7 @@
 	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.BtnNetCFGBack,	SIGNAL(clicked()),	this, SLOT(GoToNetChat()));
 	connect(ui.BtnNewTeam,	SIGNAL(clicked()),	this, SLOT(NewTeam()));
 	connect(ui.BtnEditTeam,	SIGNAL(clicked()),	this, SLOT(EditTeam()));
 	connect(ui.BtnTeamSave,	SIGNAL(clicked()),	this, SLOT(TeamSave()));
@@ -165,6 +168,10 @@
 	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.BtnNetChatJoin,	SIGNAL(clicked()),	this, SLOT(NetJoin()));
+	connect(ui.BtnNetChatCreate,	SIGNAL(clicked()),	this, SLOT(NetCreate()));
+	connect(ui.BtnNetCFGAddTeam,	SIGNAL(clicked()),	this, SLOT(NetAddTeam()));
+	connect(ui.BtnNetCFGGo,	SIGNAL(clicked()),	this, SLOT(NetStartGame()));
 	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);
@@ -244,9 +251,9 @@
 void HWForm::SimpleGame()
 {
 	game = new HWGame(ui.CBResolution->currentIndex(), ui.CBFullscreen->isChecked());
-	game->AddTeam(cfgdir.absolutePath() + "/team.cfg");
-	game->AddTeam(cfgdir.absolutePath() + "/team.cfg");
-	game->Start();
+	game->AddTeam("team.cfg");
+	game->AddTeam("team.cfg");
+	game->StartLocal();
 }
 
 void HWForm::CBGrave_activated(const QString & gravename)
@@ -277,6 +284,7 @@
 	stream << "; Generated by Hedgewars, do not modify" << endl;
 	stream << "resolution " << ui.CBResolution->currentIndex() << endl;
 	stream << "fullscreen " << ui.CBFullscreen->isChecked() << endl;
+	stream << "nick " << ui.editNetNick->text() << endl;
 	settings.close();
 }
 
@@ -297,10 +305,11 @@
 
 void HWForm::NetConnect()
 {
-	hwnet = new HWNet();
-	hwnet->Connect("localhost", 6667);
+	hwnet = new HWNet(ui.CBResolution->currentIndex(), ui.CBFullscreen->isChecked());
+	hwnet->Connect("172.19.5.168", 6667, ui.editNetNick->text());
 	connect(hwnet, SIGNAL(Connected()), this, SLOT(GoToNetChat()));
 	connect(hwnet, SIGNAL(AddGame(const QString &)), this, SLOT(AddGame(const QString &)));
+	connect(hwnet, SIGNAL(EnteredGame()), this, SLOT(NetGameEnter()));
 }
 
 void HWForm::NetDisconnect()
@@ -313,3 +322,31 @@
 {
 	ui.ChannelsList->addItem(chan);
 }
+
+void HWForm::NetGameEnter()
+{
+	ui.Pages->setCurrentIndex(ID_PAGE_NETCFG);
+}
+
+void HWForm::NetJoin()
+{
+	hwnet->JoinGame("#hw");
+}
+
+void HWForm::NetCreate()
+{
+	hwnet->JoinGame("#hw");
+}
+
+void HWForm::NetAddTeam()
+{
+	HWTeam team("team");
+	team.SetCfgDir(cfgdir.absolutePath());
+	team.LoadFromFile();
+	hwnet->AddTeam(team);
+}
+
+void HWForm::NetStartGame()
+{
+	hwnet->StartGame();
+}
--- a/QTfrontend/hwform.h	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/hwform.h	Tue Dec 27 10:20:55 2005 +0000
@@ -71,7 +71,12 @@
 	void PlayDemo();
 	void NetConnect();
 	void NetDisconnect();
+	void NetJoin();
+	void NetCreate();
 	void AddGame(const QString & chan);
+	void NetAddTeam();
+	void NetGameEnter();
+	void NetStartGame();
 
 public slots:
 	void CBGrave_activated(const QString & gravename);
@@ -92,6 +97,7 @@
 #define ID_PAGE_DEMOS 4
 #define ID_PAGE_NET 5
 #define ID_PAGE_NETCHAT 6
-#define ID_PAGE_MAIN 7
+#define ID_PAGE_NETCFG 7
+#define ID_PAGE_MAIN 8
 
 #endif
--- a/QTfrontend/hwform.ui	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/hwform.ui	Tue Dec 27 10:20:55 2005 +0000
@@ -50,7 +50,7 @@
      </size>
     </property>
     <property name="currentIndex" >
-     <number>6</number>
+     <number>2</number>
     </property>
     <widget class="QWidget" name="page" >
      <widget class="QPushButton" name="BtnSimpleGame" >
@@ -379,8 +379,8 @@
          <rect>
           <x>0</x>
           <y>0</y>
-          <width>181</width>
-          <height>270</height>
+          <width>99</width>
+          <height>29</height>
          </rect>
         </property>
         <attribute name="label" >
@@ -596,6 +596,35 @@
        <bool>false</bool>
       </property>
      </widget>
+     <widget class="QLabel" name="label" >
+      <property name="geometry" >
+       <rect>
+        <x>10</x>
+        <y>233</y>
+        <width>47</width>
+        <height>13</height>
+       </rect>
+      </property>
+      <property name="text" >
+       <string>Net nick</string>
+      </property>
+     </widget>
+     <widget class="QLineEdit" name="editNetNick" >
+      <property name="geometry" >
+       <rect>
+        <x>60</x>
+        <y>230</y>
+        <width>113</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text" >
+       <string>unnamed</string>
+      </property>
+      <property name="maxLength" >
+       <number>30</number>
+      </property>
+     </widget>
     </widget>
     <widget class="QWidget" name="page" >
      <widget class="QPushButton" name="BtnMPBack" >
@@ -777,6 +806,46 @@
      </widget>
     </widget>
     <widget class="QWidget" name="page" >
+     <widget class="QPushButton" name="BtnNetChatDisconnect" >
+      <property name="geometry" >
+       <rect>
+        <x>460</x>
+        <y>390</y>
+        <width>161</width>
+        <height>41</height>
+       </rect>
+      </property>
+      <property name="font" >
+       <font>
+        <family>MS Shell Dlg</family>
+        <pointsize>14</pointsize>
+        <weight>50</weight>
+        <italic>false</italic>
+        <bold>false</bold>
+        <underline>false</underline>
+        <strikeout>false</strikeout>
+       </font>
+      </property>
+      <property name="text" >
+       <string>Disconnect</string>
+      </property>
+      <property name="checkable" >
+       <bool>false</bool>
+      </property>
+      <property name="checked" >
+       <bool>false</bool>
+      </property>
+     </widget>
+     <widget class="QListWidget" name="ChannelsList" >
+      <property name="geometry" >
+       <rect>
+        <x>20</x>
+        <y>10</y>
+        <width>201</width>
+        <height>331</height>
+       </rect>
+      </property>
+     </widget>
      <widget class="QPushButton" name="BtnNetChatJoin" >
       <property name="geometry" >
        <rect>
@@ -837,10 +906,12 @@
        <bool>false</bool>
       </property>
      </widget>
-     <widget class="QPushButton" name="BtnNetChatDisconnect" >
+    </widget>
+    <widget class="QWidget" name="page" >
+     <widget class="QPushButton" name="BtnNetCFGBack" >
       <property name="geometry" >
        <rect>
-        <x>460</x>
+        <x>260</x>
         <y>390</y>
         <width>161</width>
         <height>41</height>
@@ -858,7 +929,7 @@
        </font>
       </property>
       <property name="text" >
-       <string>Disconnect</string>
+       <string>Back</string>
       </property>
       <property name="checkable" >
        <bool>false</bool>
@@ -867,15 +938,65 @@
        <bool>false</bool>
       </property>
      </widget>
-     <widget class="QListWidget" name="ChannelsList" >
+     <widget class="QPushButton" name="BtnNetCFGAddTeam" >
       <property name="geometry" >
        <rect>
-        <x>20</x>
-        <y>10</y>
-        <width>201</width>
-        <height>331</height>
+        <x>260</x>
+        <y>290</y>
+        <width>161</width>
+        <height>41</height>
        </rect>
       </property>
+      <property name="font" >
+       <font>
+        <family>MS Shell Dlg</family>
+        <pointsize>14</pointsize>
+        <weight>50</weight>
+        <italic>false</italic>
+        <bold>false</bold>
+        <underline>false</underline>
+        <strikeout>false</strikeout>
+       </font>
+      </property>
+      <property name="text" >
+       <string>Add Team</string>
+      </property>
+      <property name="checkable" >
+       <bool>false</bool>
+      </property>
+      <property name="checked" >
+       <bool>false</bool>
+      </property>
+     </widget>
+     <widget class="QPushButton" name="BtnNetCFGGo" >
+      <property name="geometry" >
+       <rect>
+        <x>260</x>
+        <y>340</y>
+        <width>161</width>
+        <height>41</height>
+       </rect>
+      </property>
+      <property name="font" >
+       <font>
+        <family>MS Shell Dlg</family>
+        <pointsize>14</pointsize>
+        <weight>50</weight>
+        <italic>false</italic>
+        <bold>false</bold>
+        <underline>false</underline>
+        <strikeout>false</strikeout>
+       </font>
+      </property>
+      <property name="text" >
+       <string>Go!</string>
+      </property>
+      <property name="checkable" >
+       <bool>false</bool>
+      </property>
+      <property name="checked" >
+       <bool>false</bool>
+      </property>
      </widget>
     </widget>
     <widget class="QWidget" name="pageMain" >
--- a/QTfrontend/netclient.cpp	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/netclient.cpp	Tue Dec 27 10:20:55 2005 +0000
@@ -33,16 +33,25 @@
 
 #include <QMessageBox>
 #include "netclient.h"
+#include "game.h"
 
-HWNet::HWNet()
+#include <QtDebug>
+
+#define chkp qDebug() << "hw chkp in " << __FILE__ << ":" << __LINE__
+
+HWNet::HWNet(int Resolution, bool Fullscreen)
 	: QObject()
 {
+	gameResolution = Resolution;
+	gameFullscreen = Fullscreen;
 	state = nsDisconnected;
-	IRCmsg_cmd_param = new QRegExp("^[A-Z]+ :.+$");
+	IRCmsg_cmd_text = new QRegExp("^[A-Z]+ :.+$");
 	IRCmsg_number_param = new QRegExp("^:\\S+ [0-9]{3} .+$");
-	IRCmsg_who_cmd_param = new QRegExp("^:\\S+ [A-Z]+ \\S+");
-	IRCmsg_who_cmd_param_text = new QRegExp("^:\\S+ [A-Z]+ \\S+ :.+$");
+	IRCmsg_who_cmd_target = new QRegExp("^:\\S+ [A-Z]+ \\S+$"); // last \\S should mean 'the 1st char is not ":"'
+	IRCmsg_who_cmd_text = new QRegExp("^:\\S+ [A-Z]+ :.+$");
+	IRCmsg_who_cmd_target_text = new QRegExp("^:\\S+ [A-Z]+ \\S+ :.+$");
 	isOp = false;
+	teamsCount = 0;
 
 	connect(&NetSocket, SIGNAL(readyRead()), this, SLOT(ClientRead()));
 	connect(&NetSocket, SIGNAL(connected()), this, SLOT(OnConnect()));
@@ -92,8 +101,8 @@
 void HWNet::OnConnect()
 {
 	state = nsConnected;
-	SendNet(QString("USER hwgame 1 2 Hedgewars game"));
-	SendNet(QString("NICK %1").arg(mynick));
+	RawSendNet(QString("USER hwgame 1 2 Hedgewars game"));
+	RawSendNet(QString("NICK %1").arg(mynick));
 }
 
 void HWNet::OnDisconnect()
@@ -103,8 +112,13 @@
 
 void HWNet::Perform()
 {
-//	SendNet(QString("LIST"));
-	SendNet(QString("JOIN #alex"));
+
+}
+
+void HWNet::JoinGame(const QString & game)
+{
+	state = nsJoining;
+	RawSendNet(QString("JOIN %1").arg(game));
 }
 
 void HWNet::Disconnect()
@@ -124,50 +138,69 @@
 		default:
 		{
 			state = nsQuitting;
-			SendNet(QString("QUIT :oops"));
+			RawSendNet(QString("QUIT :oops"));
 		}
 	}
 }
 
-void HWNet::SendNet(const QString & str)
+void HWNet::RawSendNet(const QString & str)
 {
-	SendNet(str.toLatin1());
+	RawSendNet(str.toLatin1());
 }
 
-void HWNet::SendNet(const QByteArray & buf)
+void HWNet::RawSendNet(const QByteArray & buf)
 {
 	if (buf.size() > 510) return;
 	NetSocket.write(buf);
 	NetSocket.write("\x0d\x0a", 2);
 }
 
+void HWNet::SendNet(const QByteArray & buf)
+{
+	if ((state == nsGaming) || (state == nsStarting))
+	{
+		QString msg = QString(buf.toBase64());
+		if (msg == "AUM=")
+		{
+			ConfigAsked();
+		} else
+		{
+			RawSendNet(QString("PRIVMSG %1 :"MAGIC_CHAR MAGIC_CHAR"%2").arg(channel, msg));
+		}
+	}
+}
+
 void HWNet::ParseLine(const QString & msg)
 {
 	//QMessageBox::information(0, "", msg);
-	if (IRCmsg_cmd_param->exactMatch(msg))
+	if (IRCmsg_cmd_text->exactMatch(msg))
 	{
-		msgcmd_paramHandler(msg);
+		msgcmd_textHandler(msg);
 	} else
 	if (IRCmsg_number_param->exactMatch(msg))
 	{
 		msgnumber_paramHandler(msg);
 	} else
-	if (IRCmsg_who_cmd_param->exactMatch(msg))
+	if (IRCmsg_who_cmd_text->exactMatch(msg))
 	{
-		msgwho_cmd_paramHandler(msg);
+		msgwho_cmd_textHandler(msg);
 	} else
-	if (IRCmsg_who_cmd_param_text->exactMatch(msg))
+	if (IRCmsg_who_cmd_target->exactMatch(msg))
 	{
-		msgwho_cmd_param_textHandler(msg);
+		msgwho_cmd_targetHandler(msg);
+	} else
+	if (IRCmsg_who_cmd_target_text->exactMatch(msg))
+	{
+		msgwho_cmd_target_textHandler(msg);
 	}
 }
 
-void HWNet::msgcmd_paramHandler(const QString & msg)
+void HWNet::msgcmd_textHandler(const QString & msg)
 {
 	QStringList list = msg.split(" :");
 	if (list[0] == "PING")
 	{
-		SendNet(QString("PONG %1").arg(list[1]));
+		RawSendNet(QString("PONG %1").arg(list[1]));
 	}
 }
 
@@ -209,7 +242,6 @@
 			{
 				opnick = "";
 			}
-			SendNet(QString("PRIVMSG #alex :%1 ops here").arg(opCount));
 			opCount = 0;
 			break;
 		}
@@ -221,7 +253,7 @@
 	}
 }
 
-void HWNet::msgwho_cmd_paramHandler(const QString & msg)
+void HWNet::msgwho_cmd_targetHandler(const QString & msg)
 {
 	QStringList list = msg.split(" ");
 	QString who = list[0].mid(1).split("!")[0];
@@ -234,7 +266,24 @@
 	}
 }
 
-void HWNet::msgwho_cmd_param_textHandler(const QString & msg)
+void HWNet::msgwho_cmd_textHandler(const QString & msg)
+{
+	int pos = msg.indexOf(" :");
+	QString text = msg.mid(pos + 2);
+	QStringList list = msg.mid(0, pos).split(" ");
+	QString who = list[0].mid(1).split("!")[0];
+	if (list[1] == "JOIN")
+	{
+		if (who == mynick)
+		{
+			channel = text;
+			state = nsJoined;
+			emit EnteredGame();
+			RawSendNet(QString("PRIVMSG %1 :Hello!").arg(channel));
+		}
+	}
+}
+void HWNet::msgwho_cmd_target_textHandler(const QString & msg)
 {
 	int pos = msg.indexOf(" :");
 	QString text = msg.mid(pos + 2);
@@ -242,6 +291,162 @@
 	QString who = list[0].mid(1).split("!")[0];
 	if (list[1] == "PRIVMSG")
 	{
-		SendNet(QString("PRIVMSG #alex :%1 said \"%2\" to %3").arg(who, text, list[2]));
+		if (list[2] == opnick)
+		{
+			hwp_opmsg(who, text);
+		} else
+		if (list[2] == channel)
+		{
+			hwp_chanmsg(who, text);
+		}
+	}
+}
+
+void HWNet::hwp_opmsg(const QString & who, const QString & msg)
+{
+	if (state != nsJoined)
+		return ;
+	if (!msg.startsWith(MAGIC_CHAR))
+		return ;
+	QStringList list = msg.split(MAGIC_CHAR, QString::SkipEmptyParts);
+	if (list[0] == "A")
+	{
+		list.removeFirst();
+		if (list.size() != 9)
+			return ;
+		if (teamsCount < 5)
+		{
+			teams[teamsCount].nick = who;
+			teams[teamsCount].hhs = list;
+			teamsCount++;
+			QString teamnames;
+			for(int i = 0; i < teamsCount; i++)
+			{
+				teamnames += MAGIC_CHAR;
+				teamnames += teams[i].hhs[0];
+			}
+			RawSendNet(QString("PRIVMSG %1 :"MAGIC_CHAR"Teams%2").arg(channel, teamnames));
+		}
+	}
+}
+
+void HWNet::ConfigAsked()
+{
+	configasks++;
+	if (configasks == playerscnt)
+	{
+		quint32 color = 65535;
+		for (int i = 0; i < teamsCount; i++)
+		{
+chkp;			SENDCFGSTRNET("eaddteam");
+			QString msg;
+			msg = MAGIC_CHAR "T" MAGIC_CHAR + teams[i].nick + MAGIC_CHAR + teams[i].hhs.join(MAGIC_CHAR);
+			RawSendNet(QString("PRIVMSG %1 :%2").arg(channel, msg));
+			hwp_chanmsg(mynick, msg);
+			SENDCFGSTRNET(QString("ecolor %1").arg(color));
+			SENDCFGSTRNET("eadd hh0 0");
+			SENDCFGSTRNET("eadd hh1 0");
+			SENDCFGSTRNET("eadd hh2 0");
+			color <<= 8;
+		}
+chkp;		SENDCFGSTRNET("!");
 	}
 }
+
+void HWNet::hwp_chanmsg(const QString & who, const QString & msg)
+{
+	if ((state < nsJoined) || (state > nsGaming))
+	{
+		return ;
+	}
+	if ((state == nsJoined) && (msg.startsWith(MAGIC_CHAR"Start!"MAGIC_CHAR)) && (who == opnick))
+	{
+		state = nsStarting;
+		RunGame(msg.mid(7));
+		return ;
+	}
+	if ((state == nsStarting) && (msg == MAGIC_CHAR MAGIC_CHAR "AUM="))
+	{
+		if (mynick == opnick) ConfigAsked();
+		return ;
+	}
+	if ((state == nsStarting) && (msg.startsWith(MAGIC_CHAR"T"MAGIC_CHAR)))
+	{
+		NetTeamAdded(msg.mid(3));
+	}
+	if (state != nsGaming)
+	{
+		return;
+	}
+	if (msg.startsWith(MAGIC_CHAR MAGIC_CHAR)) // HWP message
+	{
+		emit FromNet(QByteArray::fromBase64(msg.mid(2).toLocal8Bit()));
+	} else // smth other
+	{
+
+	}
+}
+
+void HWNet::NetTeamAdded(const QString & msg)
+{
+	QStringList list = msg.split(MAGIC_CHAR, QString::SkipEmptyParts);
+	if (list.size() != 10)
+		return ;
+	if (list[0] == mynick)
+	{
+chkp;		emit LocalCFG(list[1]);
+	} else
+	{
+chkp;		SENDCFGSTRLOC("erdriven");
+		SENDCFGSTRLOC(QString("ename team %1").arg(list[2]));
+		for (int i = 0; i < 8; i++)
+		{
+			SENDCFGSTRLOC(QString("ename hh%1").arg(i) + list[i + 3]);
+		}
+chkp;	}
+}
+
+void HWNet::AddTeam(const HWTeam & team)
+{
+	if (state != nsJoined)
+	{
+		return ;
+	}
+	RawSendNet(QString("PRIVMSG %1 :").arg(opnick) + MAGIC_CHAR "A" MAGIC_CHAR +
+			team.TeamName + MAGIC_CHAR + team.HHName[0] + MAGIC_CHAR + team.HHName[1] + MAGIC_CHAR +
+			team.HHName[2] + MAGIC_CHAR + team.HHName[3] + MAGIC_CHAR + team.HHName[4] + MAGIC_CHAR +
+			team.HHName[5] + MAGIC_CHAR + team.HHName[6] + MAGIC_CHAR + team.HHName[7]);
+}
+
+void HWNet::StartGame()
+{
+	if ((opnick != mynick) || (state != nsJoined))
+	{
+		return ;
+	}
+	QStringList players;
+	for (int i = 0; i < teamsCount; i++)
+	{
+		if (!players.contains(teams[i].nick))
+		{
+			players.append(teams[i].nick);
+		}
+	}
+	playerscnt = players.size();
+	configasks = 0;
+
+	QString seed;
+	seedgen.GenRNDStr(seed, 10);
+	QString msg = QString(MAGIC_CHAR"Start!"MAGIC_CHAR"%1").arg(seed);
+	RawSendNet(QString("PRIVMSG %1 :%2").arg(channel, msg));
+	hwp_chanmsg(mynick, msg);
+}
+
+void HWNet::RunGame(const QString & seed)
+{
+	HWGame * game = new HWGame(gameResolution, gameFullscreen);
+	connect(game, SIGNAL(SendNet(const QByteArray &)), this, SLOT(SendNet(const QByteArray &)));
+	connect(this, SIGNAL(FromNet(const QByteArray &)), game, SLOT(FromNet(const QByteArray &)));
+	connect(this, SIGNAL(LocalCFG(const QString &)), game, SLOT(LocalCFG(const QString &)));
+	game->StartNet(seed);
+}
--- a/QTfrontend/netclient.h	Tue Dec 27 10:19:21 2005 +0000
+++ b/QTfrontend/netclient.h	Tue Dec 27 10:20:55 2005 +0000
@@ -37,46 +37,89 @@
 #include <QObject>
 #include <QTcpSocket>
 #include <QRegExp>
+#include <QStringList>
+#include "team.h"
+#include "rndstr.h"
+
+#define MAGIC_CHAR "\x02"
+
+struct netTeam
+{
+	QString nick;
+	QStringList hhs;
+};
 
 class HWNet : public QObject
 {
 	Q_OBJECT
 
 public:
-    HWNet();
+    HWNet(int Resolution, bool Fullscreen);
 	void Connect(const QString & hostName, quint16 port, const QString & nick);
 	void Disconnect();
-	void SendNet(const QString & buf);
-	void SendNet(const QByteArray & buf);
+	void JoinGame(const QString & game);
+	void AddTeam(const HWTeam & team);
+	void StartGame();
 
 signals:
 	void Connected();
 	void AddGame(const QString & chan);
+	void EnteredGame();
+	void FromNet(const QByteArray & buf);
+	void LocalCFG(const QString & team);
+
+public slots:
+	void SendNet(const QByteArray & buf);
 
 private:
 	enum NetState {
-		nsDisconnected = 0,
-		nsConnecting   = 1,
-		nsConnected    = 3,
-		nsQuitting     = 5
+		nsDisconnected	= 0,
+		nsConnecting	= 1,
+		nsConnected	= 3,
+		nsJoining	= 4,
+		nsJoined	= 5,
+		nsStarting	= 6,
+		nsGaming	= 7,
+		nsQuitting	= 8
 	};
 
 	QTcpSocket NetSocket;
 	NetState state;
-	QRegExp * IRCmsg_cmd_param;
+	QRegExp * IRCmsg_cmd_text;
 	QRegExp * IRCmsg_number_param;
-	QRegExp * IRCmsg_who_cmd_param;
-	QRegExp * IRCmsg_who_cmd_param_text;
+	QRegExp * IRCmsg_who_cmd_target;
+	QRegExp * IRCmsg_who_cmd_target_text;
+	QRegExp * IRCmsg_who_cmd_text;
 	QString mynick;
 	QString opnick;
+	QString channel;
 	bool isOp;
 	quint32 opCount;
+	netTeam teams[5];
+	quint8 teamsCount;
+	int gameResolution;
+	bool gameFullscreen;
+	RNDStr seedgen;
+	int playerscnt;
+	int configasks;
+
+	void RawSendNet(const QString & buf);
+	void RawSendNet(const QByteArray & buf);
 
 	void ParseLine(const QString & msg);
-	void msgcmd_paramHandler(const QString & msg);
+	void msgcmd_textHandler(const QString & msg);
 	void msgnumber_paramHandler(const QString & msg);
-	void msgwho_cmd_paramHandler(const QString & msg);
-	void msgwho_cmd_param_textHandler(const QString & msg);
+	void msgwho_cmd_targetHandler(const QString & msg);
+	void msgwho_cmd_textHandler(const QString & msg);
+	void msgwho_cmd_target_textHandler(const QString & msg);
+
+	void hwp_opmsg(const QString & who, const QString & msg);
+	void hwp_chanmsg(const QString & who, const QString & msg);
+	void ConfigAsked();
+	void NetTeamAdded(const QString & msg);
+
+	void RunGame(const QString & seed);
+
 
 private slots:
 	void ClientRead();
@@ -86,4 +129,21 @@
 	void displayError(QAbstractSocket::SocketError socketError);
 };
 
+#define SENDCFGSTRNET(a)   {\
+							QByteArray strmsg; \
+							strmsg.append(a); \
+							quint8 sz = strmsg.size(); \
+							QByteArray enginemsg = QByteArray((char *)&sz, 1) + strmsg; \
+							emit FromNet(enginemsg); \
+							RawSendNet(QString("PRIVMSG %1 :"MAGIC_CHAR MAGIC_CHAR"%2").arg(channel, QString(enginemsg.toBase64()))); \
+						}
+
+#define SENDCFGSTRLOC(a)   {\
+							QByteArray strmsg; \
+							strmsg.append(a); \
+							quint8 sz = strmsg.size(); \
+							QByteArray enginemsg = QByteArray((char *)&sz, 1) + strmsg; \
+							emit FromNet(enginemsg); \
+						}
+
 #endif