QTfrontend/netconnectedclient.cpp
changeset 1374 f33fa81e583d
parent 1373 ca719502b87f
child 1375 c95c6887b289
equal deleted inserted replaced
1373:ca719502b87f 1374:f33fa81e583d
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2006-2008 Igor Ulyanov <iulyanov@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include <QTcpServer>
       
    20 #include <QTcpSocket>
       
    21 #include <QStringList>
       
    22 #include <QDebug>
       
    23 
       
    24 #include "netconnectedclient.h"
       
    25 #include "netserver.h"
       
    26 
       
    27 extern char delimeter;
       
    28 
       
    29 HWConnectedClient::HWConnectedClient(HWNetServer* hwserver, QTcpSocket* client) :
       
    30   readyToStart(false),
       
    31   m_hwserver(hwserver),
       
    32   m_client(client)
       
    33 {
       
    34   connect(client, SIGNAL(disconnected()), this, SLOT(ClientDisconnect()));
       
    35   connect(client, SIGNAL(readyRead()), this, SLOT(ClientRead()));
       
    36 }
       
    37 
       
    38 HWConnectedClient::~HWConnectedClient()
       
    39 {
       
    40 }
       
    41 
       
    42 void HWConnectedClient::ClientDisconnect()
       
    43 {
       
    44   emit(HWClientDisconnected(this));
       
    45 }
       
    46 
       
    47 void HWConnectedClient::ClientRead()
       
    48 {
       
    49   try {
       
    50 	while (m_client->canReadLine()) {
       
    51 		QString s = QString::fromUtf8(m_client->readLine().trimmed());
       
    52 		if (s.size() == 0) {
       
    53 			ParseCmd(cmdbuf);
       
    54 			cmdbuf.clear();
       
    55 		} else
       
    56 			cmdbuf << s;
       
    57 	}
       
    58   } catch(ShouldDisconnectException& e) {
       
    59     m_client->close();
       
    60   }
       
    61 }
       
    62 
       
    63 void HWConnectedClient::ParseCmd(const QStringList & lst)
       
    64 {
       
    65 //qDebug() << "Server: Parsing:" << lst;
       
    66   if(!lst.size())
       
    67   {
       
    68     qWarning("Net server: Bad message");
       
    69     return;
       
    70   }
       
    71   if (lst[0] == "NICK") {
       
    72     if(lst.size() < 2)
       
    73     {
       
    74       qWarning("Net server: Bad 'NICK' message");
       
    75 	  return;
       
    76     }
       
    77     if(m_hwserver->haveNick(lst[1])) {
       
    78       RawSendNet(QString("ERRONEUSNICKNAME"));
       
    79       throw ShouldDisconnectException();
       
    80     }
       
    81 
       
    82     client_nick=lst[1];
       
    83     RawSendNet(QString("CONNECTED"));
       
    84     if(m_hwserver->isChiefClient(this)) {
       
    85       RawSendNet(QString("CONFIGASKED"));
       
    86     }
       
    87     else {
       
    88       RawSendNet(QString("SLAVE"));
       
    89       // send teams
       
    90       QList<QStringList> team_conf=m_hwserver->getTeamsConfig();
       
    91       for(QList<QStringList>::iterator tmit=team_conf.begin(); tmit!=team_conf.end(); ++tmit) {
       
    92 	    RawSendNet(QString("ADDTEAM:")+delimeter+tmit->join(QString(delimeter)));
       
    93       }
       
    94       // send config
       
    95       QMap<QString, QStringList> conf=m_hwserver->getGameCfg();
       
    96       for(QMap<QString, QStringList>::iterator it=conf.begin(); it!=conf.end(); ++it) {
       
    97 	    RawSendNet(QString("CONFIG_PARAM")+delimeter+it.key()+delimeter+it.value().join(QString(delimeter)));
       
    98       }
       
    99     }
       
   100     m_hwserver->sendNicks(this);
       
   101     m_hwserver->sendOthers(this, QString("JOINED")+delimeter+client_nick);
       
   102     return;
       
   103   }
       
   104 
       
   105   if(client_nick=="")
       
   106   {
       
   107   	qWarning() << "Net server: Message from unnamed client:" << lst;
       
   108   	return;
       
   109   }
       
   110 
       
   111   if (lst[0]=="START:") {
       
   112     readyToStart=true;
       
   113     if(m_hwserver->shouldStart(this)) {
       
   114       // start
       
   115       m_hwserver->sendAll("RUNGAME");
       
   116       m_hwserver->resetStart();
       
   117     }
       
   118     return;
       
   119   }
       
   120 
       
   121   if(lst[0]=="HHNUM") {
       
   122     if (lst.size()<4) {
       
   123       qWarning() << "Net server: Bad 'HHNUM' message:" << lst;
       
   124       return;
       
   125     }
       
   126     if(!m_hwserver->isChiefClient(this))
       
   127     {
       
   128       return; // permission denied
       
   129     }
       
   130     const QString confstr=lst[0]+"+"+lst[1]+"+"+lst[2];
       
   131     QMap<QString, QStringList>::iterator it=m_hwserver->m_gameCfg.find(confstr);
       
   132     int oldTeamHHNum = it==m_hwserver->m_gameCfg.end() ? 0 : it.value()[0].toUInt();
       
   133     int newTeamHHNum = lst[3].toUInt();
       
   134     m_hwserver->hhnum+=newTeamHHNum-oldTeamHHNum;
       
   135 qDebug() << "HHNUM hhnum = " << m_hwserver->hhnum;
       
   136     // create CONFIG_PARAM to save HHNUM at server from lst
       
   137     QStringList tmp = lst;
       
   138     tmp=QStringList("CONFIG_PARAM") << confstr << lst[3];
       
   139     m_hwserver->sendOthers(this, tmp.join(QString(delimeter)));
       
   140     m_hwserver->m_gameCfg[tmp[1]]=tmp.mid(2);
       
   141 qDebug() << QString("[%1] = %2").arg(tmp[1]).arg(tmp.mid(2)[0]);
       
   142     return;
       
   143   }
       
   144 
       
   145   if(lst[0]=="CONFIG_PARAM") {
       
   146     if (lst.size()<3) {
       
   147       qWarning() << "Net server: Bad 'CONFIG_PARAM' message:" << lst;
       
   148       return;
       
   149     }
       
   150 
       
   151     if(!m_hwserver->isChiefClient(this))
       
   152     {
       
   153       return; // permission denied
       
   154     }
       
   155     else m_hwserver->m_gameCfg[lst[1]]=lst.mid(2);
       
   156   }
       
   157 
       
   158   if(lst[0]=="ADDTEAM:") {
       
   159     if(lst.size() < 14)
       
   160     {
       
   161       qWarning("Net server: Bad 'ADDTEAM' message");
       
   162 	  return;
       
   163     }
       
   164     QStringList tmp = lst;
       
   165     tmp.pop_front();
       
   166 
       
   167     // add team ID
       
   168     static unsigned int netTeamID=0;
       
   169     tmp.insert(1, QString::number(++netTeamID));
       
   170 
       
   171     // hedgehogs num count
       
   172     int maxAdd = 18 - m_hwserver->hhnum;
       
   173     if (maxAdd <= 0)
       
   174     {
       
   175 	  qWarning("Net server: 'ADDTEAM' message: rejecting");
       
   176 	  return; // reject command
       
   177     }
       
   178     if (netIDbyTeamName(tmp[0]) > 0)
       
   179     {
       
   180 	  qWarning("Net server: 'ADDTEAM' message: rejecting (have team with same name)");
       
   181 	  return; // reject command
       
   182 
       
   183     }
       
   184     int toAdd=maxAdd < 4 ? maxAdd : 4;
       
   185     m_hwserver->hhnum+=toAdd;
       
   186 qDebug() << "to add = " << toAdd << "m_hwserver->hhnum = " << m_hwserver->hhnum;
       
   187     // hedgehogs num config
       
   188     QString hhnumCfg=QString("CONFIG_PARAM%1HHNUM+%2+%3%1%4").arg(delimeter).arg(tmp[0])\
       
   189       .arg(netTeamID)\
       
   190       .arg(toAdd);
       
   191 
       
   192     // creating color config for new team
       
   193     QString colorCfg=QString("CONFIG_PARAM%1TEAM_COLOR+%2+%3%1%4").arg(delimeter).arg(tmp[0])\
       
   194       .arg(netTeamID)\
       
   195       .arg(tmp.takeAt(2));
       
   196 
       
   197     m_hwserver->m_gameCfg[colorCfg.split(delimeter)[1]]=colorCfg.split(delimeter).mid(2);
       
   198     m_hwserver->m_gameCfg[hhnumCfg.split(delimeter)[1]]=hhnumCfg.split(delimeter).mid(2);
       
   199     m_teamsCfg.push_back(tmp);
       
   200 qDebug() << QString("[%1] = %2").arg(hhnumCfg.split(delimeter)[1]).arg(hhnumCfg.split(delimeter).mid(2)[0]);
       
   201     m_hwserver->sendOthers(this, QString("ADDTEAM:")+delimeter+tmp.join(QString(delimeter)));
       
   202     RawSendNet(QString("TEAM_ACCEPTED%1%2%1%3").arg(delimeter).arg(tmp[0]).arg(tmp[1]));
       
   203     m_hwserver->sendAll(colorCfg);
       
   204     m_hwserver->sendAll(hhnumCfg);
       
   205     return;
       
   206   }
       
   207 
       
   208   if(lst[0]=="REMOVETEAM:") {
       
   209     if(lst.size() < 2)
       
   210     {
       
   211       qWarning("Net server: Bad 'REMOVETEAM' message");
       
   212       return;
       
   213     }
       
   214 
       
   215 	for(QMap<QString, QStringList>::iterator it=m_hwserver->m_gameCfg.begin(); it!=m_hwserver->m_gameCfg.end(); ++it)
       
   216 	{
       
   217 		QStringList hhTmpList=it.key().split('+');
       
   218 		if(hhTmpList[0] == "HHNUM")
       
   219 		{
       
   220 			if(hhTmpList[1]==lst[1])
       
   221 			{
       
   222 				m_hwserver->hhnum-=it.value()[0].toUInt();
       
   223 				m_hwserver->m_gameCfg.remove(it.key());
       
   224 				
       
   225 				for(QList<QStringList>::iterator it=m_teamsCfg.begin(); it!=m_teamsCfg.end(); ++it)
       
   226 					if((*it)[0] == lst[1])
       
   227 						m_teamsCfg.erase(it);
       
   228 
       
   229 				qDebug() << "REMOVETEAM hhnum = " << m_hwserver->hhnum;
       
   230 				break;
       
   231 			}
       
   232 		}
       
   233 	}
       
   234 
       
   235     unsigned int netID=removeTeam(lst[1]);
       
   236     m_hwserver->sendOthers(this, QString("REMOVETEAM:")+delimeter+lst[1]+delimeter+QString::number(netID));
       
   237     return;
       
   238   }
       
   239 
       
   240   m_hwserver->sendOthers(this, lst.join(QString(delimeter)));
       
   241 }
       
   242 
       
   243 unsigned int HWConnectedClient::netIDbyTeamName(const QString& tname)
       
   244 {
       
   245 	for(QList<QStringList>::iterator it=m_teamsCfg.begin(); it!=m_teamsCfg.end(); ++it)
       
   246 		if((*it)[0]==tname)
       
   247 			return (*it)[1].toUInt();
       
   248 
       
   249 	return 0;
       
   250 }
       
   251 
       
   252 unsigned int HWConnectedClient::removeTeam(const QString& tname)
       
   253 {
       
   254 	unsigned int netID = netIDbyTeamName(tname);
       
   255 	
       
   256 	if (netID == 0)
       
   257 		qDebug() << QString("removeTeam: team '%1' not found").arg(tname);
       
   258 
       
   259 	return netID;
       
   260 }
       
   261 
       
   262 QList<QStringList> HWConnectedClient::getTeamNames() const
       
   263 {
       
   264   return m_teamsCfg;
       
   265 }
       
   266 
       
   267 void HWConnectedClient::RawSendNet(const QString & str)
       
   268 {
       
   269   RawSendNet(str.toUtf8());
       
   270 }
       
   271 
       
   272 void HWConnectedClient::RawSendNet(const QByteArray & buf)
       
   273 {
       
   274   m_client->write(buf);
       
   275   m_client->write("\n\n", 2);
       
   276 }
       
   277 
       
   278 QString HWConnectedClient::getClientNick() const
       
   279 {
       
   280   return client_nick;
       
   281 }
       
   282 
       
   283 bool HWConnectedClient::isReady() const
       
   284 {
       
   285   return readyToStart;
       
   286 }
       
   287 
       
   288 QString HWConnectedClient::getHedgehogsDescription() const
       
   289 {
       
   290   return QString();//pclent_team->TeamGameConfig(65535, 4, 100, true).join((QString)delimeter);
       
   291 }