1 /********************************************************************
3 * Copyright (C) 2008 Davide Pesavento
5 * This file is part of GoMoku3D.
7 * GoMoku3D is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * GoMoku3D is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GoMoku3D. If not, see <http://www.gnu.org/licenses/>.
20 *******************************************************************/
24 #include "ClientSocket.h"
26 #define HANDLER_SIGNATURE(token) \
27 void ClientSocket::parse_##token() { \
28 QString elementName = name().toString(); \
29 Q_ASSERT_X(elementName == #token, \
30 (QString("ClientSocket::parse_") + #token + "()").toUtf8().constData(), \
31 ("called while parsing " + elementName).toUtf8().constData()); \
34 ClientSocket::ClientSocket(QTcpSocket
*socket
) : StreamSocket(socket
)
36 connect(_socket
, SIGNAL(hostFound()), this, SLOT(notifyHostFound()));
37 connect(_socket
, SIGNAL(connected()), this, SLOT(openStream()));
40 void ClientSocket::joinGame(QString mode
, QString name
)
42 mode
= mode
.toLower();
44 Q_ASSERT_X(mode
== "player" || mode
== "spectator", "ClientSocket::joinGame()", "invalid mode value");
45 Q_ASSERT_X(!name
.isEmpty(), "ClientSocket::joinGame()", "null or empty string passed as name");
47 if (state() != Idle
) {
48 LOG("not sending <joinRequest> while state = " + stateString());
52 writeStartElement("joinRequest");
53 writeAttribute("gameMode", mode
);
54 writeCharacters(name
);
57 _localPlayerName
= name
;
58 changeState(AwaitingJoinAnswer
);
61 void ClientSocket::cancelJoin()
63 if (state() != AwaitingJoinAnswer
&& state() != AwaitingGameStart
) {
64 LOG("no previous join request can be cancelled (state = " + stateString() + ")");
68 writeTextElement("playerLeft", QString::number(-1));
70 _localPlayerName
= "";
74 void ClientSocket::notifyHostFound()
76 emit
statusChanged(YELLOW_TEXT(tr("connecting...")));
79 BEGIN_TERMINAL_HANDLER(joinACK
)
81 int id
= readElementText().toInt(&ok
);
82 if (!ok
|| id
< -1 || id
> 2) {
83 WARN(tr("invalid content in <joinACK> : %1").arg(readElementText()));
85 emit
joinAccepted(id
);
86 changeState(AwaitingGameStart
);
91 BEGIN_TERMINAL_HANDLER(joinNAK
)
93 int errorCode
= readElementText().toInt(&ok
);
95 WARN(tr("invalid content in <joinNAK> : %1").arg(readElementText()));
101 cause
= tr("You cannot join while a match\nis already in progress.");
104 cause
= tr("The name you have chosen is already\nbeing used by someone else.");
107 cause
= tr("The server you are connecting to\nis using an incompatible protocol version.");
110 cause
= tr("An unknown error occurred.");
112 _localPlayerName
= "";
113 emit
joinRefused(cause
);
118 BEGIN_NONTERMINAL_HANDLER(settings
)
120 QString playing
= attributes().value("playing").toString().toLower();
121 emit
receivedGameSettings(property("settings/d1").toInt(),
122 property("settings/d2").toInt(),
123 property("settings/numberOfPlayers").toInt(),
124 property("settings/timerDuration").toInt(),
125 playing
== "true" ? true : false);
128 END_NONTERMINAL_HANDLER(settings
)
130 BEGIN_TERMINAL_HANDLER(difficultyOne
)
132 int value
= readElementText().toInt(&ok
);
134 WARN(tr("invalid <difficultyOne> value in <settings> : %1").arg(readElementText()));
137 setProperty("settings/d1", QVariant(value
));
138 RESTORE_HANDLER("settings")
141 BEGIN_TERMINAL_HANDLER(difficultyTwo
)
143 int value
= readElementText().toInt(&ok
);
145 WARN(tr("invalid <difficultyTwo> value in <settings> : %1").arg(readElementText()));
148 setProperty("settings/d2", QVariant(value
));
149 RESTORE_HANDLER("settings")
152 BEGIN_TERMINAL_HANDLER(numberOfPlayers
)
154 int value
= readElementText().toInt(&ok
);
156 WARN(tr("invalid <numberOfPlayers> value in <settings> : %1").arg(readElementText()));
159 setProperty("settings/numberOfPlayers", QVariant(value
));
160 RESTORE_HANDLER("settings")
163 BEGIN_TERMINAL_HANDLER(timerDuration
)
165 int value
= readElementText().toInt(&ok
);
167 WARN(tr("invalid <timerDuration> value in <settings> : %1").arg(readElementText()));
170 setProperty("settings/timerDuration", QVariant(value
));
171 RESTORE_HANDLER("settings")
174 HANDLER_SIGNATURE(history
)
177 elementName
= name().toString();
178 if (isStartElement()) {
179 parse("history_" + elementName
);
180 } else if (isEndElement()) {
181 Q_ASSERT(elementName
== "history");
182 QList
<Move
> moveList
;
183 for (int i
= 0; i
< property("history/size").toInt(); i
++) {
184 QVariant x
= property(("history/move_" + QString::number(i
)).toUtf8().constData());
185 moveList
.append(x
.value
<Move
>());
187 emit
receivedHistory(moveList
);
188 setProperty("history/size", QVariant(0));
191 END_NONTERMINAL_HANDLER(history
)
193 void ClientSocket::parse_history_move() {
194 QString elementName
= name().toString();
195 qDebug() << "parsing" << "history_" + elementName
;
196 Q_ASSERT_X(elementName
== "move", "ClientSocket::parse_history_move()",
197 ("called while parsing " + elementName
).toUtf8().constData());
198 SET_HANDLER("history_move")
201 elementName
= name().toString();
202 if (isStartElement()) {
203 parse("history_" + elementName
);
204 } else if (isEndElement()) {
205 Q_ASSERT(elementName
== "move");
206 Move
m(property("move/player").toInt(),
207 property("move/point").value
<Point
>());
208 int n
= property("history/size").toInt();
209 setProperty(("history/move_" + QString::number(n
)).toUtf8().constData(), QVariant::fromValue(m
));
211 setProperty("history/size", QVariant(n
));
212 RESTORE_HANDLER("history")
215 LOG("unexpected data in <move> {" + tokenString() + "}");
221 void ClientSocket::parse_history_player() {
222 QString elementName
= name().toString();
223 qDebug() << "parsing" << "history_" + elementName
;
224 Q_ASSERT_X(elementName
== "player", "ClientSocket::parse_history_player()",
225 ("called while parsing " + elementName
).toUtf8().constData());
226 SET_HANDLER("history_player")
229 int id
= readElementText().toInt(&ok
);
231 WARN(tr("invalid <player> value in <move> : %1").arg(readElementText()));
234 setProperty("move/player", QVariant(id
));
235 RESTORE_HANDLER("history_move")
238 void ClientSocket::parse_history_point() {
239 QString elementName
= name().toString();
240 qDebug() << "parsing" << "history_" + elementName
;
241 Q_ASSERT_X(elementName
== "point", "ClientSocket::parse_history_point()",
242 ("called while parsing " + elementName
).toUtf8().constData());
243 SET_HANDLER("history_point")
246 elementName
= name().toString();
247 if (isStartElement()) {
248 parse("history_" + elementName
);
249 } else if (isEndElement()) {
250 Q_ASSERT(elementName
== "point");
251 Point
p(property("move/point/x").toInt(),
252 property("move/point/y").toInt(),
253 property("move/point/z").toInt());
254 setProperty("move/point", QVariant::fromValue(p
));
255 RESTORE_HANDLER("history_move")
258 LOG("unexpected data in <point> {" + tokenString() + "}");
264 void ClientSocket::parse_history_x() {
265 QString elementName
= name().toString();
266 qDebug() << "parsing" << "history_" + elementName
;
267 Q_ASSERT_X(elementName
== "x", "ClientSocket::parse_history_x()",
268 ("called while parsing " + elementName
).toUtf8().constData());
269 SET_HANDLER("history_x")
272 int value
= readElementText().toInt(&ok
);
274 WARN(tr("invalid <x> value in <point> : %1").arg(readElementText()));
277 setProperty("move/point/x", QVariant(value
));
278 RESTORE_HANDLER("history_point")
281 void ClientSocket::parse_history_y() {
282 QString elementName
= name().toString();
283 qDebug() << "parsing" << "history_" + elementName
;
284 Q_ASSERT_X(elementName
== "y", "ClientSocket::parse_history_y()",
285 ("called while parsing " + elementName
).toUtf8().constData());
286 SET_HANDLER("history_y")
289 int value
= readElementText().toInt(&ok
);
291 WARN(tr("invalid <y> value in <point> : %1").arg(readElementText()));
294 setProperty("move/point/y", QVariant(value
));
295 RESTORE_HANDLER("history_point")
298 void ClientSocket::parse_history_z() {
299 QString elementName
= name().toString();
300 qDebug() << "parsing" << "history_" + elementName
;
301 Q_ASSERT_X(elementName
== "z", "ClientSocket::parse_history_z()",
302 ("called while parsing " + elementName
).toUtf8().constData());
303 SET_HANDLER("history_z")
306 int value
= readElementText().toInt(&ok
);
308 WARN(tr("invalid <z> value in <point> : %1").arg(readElementText()));
311 setProperty("move/point/z", QVariant(value
));
312 RESTORE_HANDLER("history_point")