summaryrefslogtreecommitdiffstats
path: root/pacman-c++/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'pacman-c++/server.cpp')
-rw-r--r--pacman-c++/server.cpp146
1 files changed, 134 insertions, 12 deletions
diff --git a/pacman-c++/server.cpp b/pacman-c++/server.cpp
index 51dcc24..50ee3b7 100644
--- a/pacman-c++/server.cpp
+++ b/pacman-c++/server.cpp
@@ -1,18 +1,24 @@
1#include "server.h" 1#include "server.h"
2
3#include <QtNetwork/QTcpServer>
4#include <QtNetwork/QTcpSocket>
5#include "util.h" 2#include "util.h"
6#include "pacman.pb.h" 3#include "pacman.pb.h"
7#include "block.h" 4#include "block.h"
5#include "anyoption.h"
6#include <QtNetwork/QTcpServer>
7#include <QtNetwork/QTcpSocket>
8#include <QTextStream>
8 9
9Server::Server(QWidget *parent) 10Server::Server(QWidget *parent)
10 : SceneHolder(parent) 11 : SceneHolder(parent), m_bindaddress(QHostAddress::Any),
12 m_port(Constants::Networking::port), m_numbots(0)
11{ 13{
14 /* determine max players by using order array */
15 for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers);
16}
12 17
13 qDebug() << "[Server] Waiting for clients"; 18bool Server::run()
14 waitForClientConnections(); 19{
15 qDebug() << "[Server] All Clients connected"; 20 if (!waitForClientConnections())
21 return false;
16 22
17 Transmission::map_t map = Util::createDemoMap(); 23 Transmission::map_t map = Util::createDemoMap();
18 updateMap(map); 24 updateMap(map);
@@ -22,6 +28,7 @@ Server::Server(QWidget *parent)
22 QTimer *timer = new QTimer(this); 28 QTimer *timer = new QTimer(this);
23 connect(timer, SIGNAL(timeout()), this, SLOT(tick())); 29 connect(timer, SIGNAL(timeout()), this, SLOT(tick()));
24 timer->start(Constants::tick); 30 timer->start(Constants::tick);
31 return true;
25} 32}
26 33
27void Server::tick() 34void Server::tick()
@@ -147,12 +154,21 @@ invalid_direction:
147 return map; 154 return map;
148} 155}
149 156
150void Server::waitForClientConnections() 157bool Server::waitForClientConnections()
151{ 158{
152 QTcpServer *tcpSrv = new QTcpServer(this);
153 // server must stay alive as long as sockets (qt parent mem mechanism) 159 // server must stay alive as long as sockets (qt parent mem mechanism)
154 tcpSrv->listen(QHostAddress::Any, Constants::Networking::port); 160 QTcpServer *tcpSrv = new QTcpServer(this);
161 tcpSrv->listen(m_bindaddress, m_port);
162 if (!tcpSrv->isListening())
163 {
164 qCritical() << "Error while creating socket:" << qPrintable(tcpSrv->errorString());
165 return false;
166 }
155 167
168 qDebug() << "[Server] Listening on:"
169 << qPrintable(QString("%1:%2").arg(tcpSrv->serverAddress().toString())
170 .arg(tcpSrv->serverPort()));
171 qDebug() << "[Server] Waiting for clients";
156 ProtoBuf::WhoAmI packet; 172 ProtoBuf::WhoAmI packet;
157#define SINGLE 173#define SINGLE
158#ifdef SINGLE 174#ifdef SINGLE
@@ -177,6 +193,9 @@ void Server::waitForClientConnections()
177 193
178 qDebug() << "[Connect] New Player: color=" << color; 194 qDebug() << "[Connect] New Player: color=" << color;
179 } 195 }
196
197 qDebug() << "[Server] All Clients connected";
198 return true;
180} 199}
181 200
182void Server::sendUpdate(Transmission::map_t map) 201void Server::sendUpdate(Transmission::map_t map)
@@ -229,6 +248,103 @@ void Server::keyPressUpdate()
229 } 248 }
230} 249}
231 250
251bool Server::parseCommandline()
252{
253 AnyOption opt;
254 opt.setVerbose();
255
256 /* usage strings must remain valid until parsing is done */
257 QString exec = QFileInfo(qApp->applicationFilePath()).fileName();
258 QByteArray usage;
259 QTextStream out(&usage, QIODevice::ReadWrite | QIODevice::Text);
260 out << "Usage: " << exec << " [OPTION]" << endl
261 << "Usage: " << exec << " -h" << endl
262 << endl;
263 out << " -b, --bind <bind_address>" << endl
264 << " Specifies the ip address on which the server listens for connections" << endl
265 << " Default: " << m_bindaddress.toString() << endl
266 << endl;
267 opt.setOption("bind", 'b');
268 out << " -p, --port <port>" << endl
269 << " Specifies the port on which the server listens for connections" << endl
270 << " Default: " << m_port << endl
271 << endl;
272 opt.setOption("port", 'p');
273 out << " -m, --maxplayers [1.." << m_maxplayers << "]" << endl
274 << " Specifies the maximum number of players/pacmans" << endl
275 << " Default: " << m_maxplayers << endl
276 << endl;
277 opt.setOption("maxplayers", 'm');
278 out << " --bots [0..maxplayers-1]" << endl
279 << " Specifies the number of AI pacmans/bots" << endl
280 << " Default: " << m_numbots << endl
281 << endl;
282 opt.setOption("bots");
283 out << " -h, --help" << endl
284 << " Prints this help message" << endl;
285 opt.setFlag("help", 'h');
286 out.flush();
287 opt.addUsage(usage.constData());
288 opt.processCommandArgs(qApp->argc(), qApp->argv());
289
290 if (opt.getFlag("help") || opt.getFlag('h'))
291 {
292 opt.printUsage();
293 return false;
294 }
295
296 if (opt.getValue("port") != NULL)
297 {
298 bool ok;
299 m_port = QString(opt.getValue("port")).toUInt(&ok);
300 if (!ok || m_port < 1 || m_port > 65535)
301 {
302 qCritical() << "Invalid port-option:" << opt.getValue("port") << endl
303 << "Port must be between 1 and 65535";
304 return false;
305 }
306 }
307
308 if (opt.getValue("bind") != NULL)
309 {
310 m_bindaddress = opt.getValue("bind");
311 if (m_bindaddress.isNull())
312 {
313 qCritical() << "Invalid bind-option:" << opt.getValue("bind") << endl
314 << "Bind address must be an ip address";
315 return false;
316 }
317 }
318
319 if (opt.getValue("maxplayers") != NULL)
320 {
321 bool ok;
322 unsigned int maxplayers = QString(opt.getValue("maxplayers")).toUInt(&ok);
323 if (!ok || maxplayers < 1 || maxplayers > m_maxplayers)
324 {
325 qCritical() << "Invalid maxplayers-option:" << opt.getValue("maxplayers") << endl
326 << "Maxplayers must be between 1 and" << m_maxplayers;
327 return false;
328 }
329 m_maxplayers = maxplayers;
330 }
331
332 if (opt.getValue("bots") != NULL)
333 {
334 bool ok;
335 unsigned int numbots = QString(opt.getValue("bots")).toUInt(&ok);
336 if (!ok || numbots >= m_maxplayers)
337 {
338 qCritical() << "Invalid numbots-options:" << opt.getValue("bots") << endl
339 << "AI pacmans/bots must be between 0 and" << m_maxplayers - 1;
340 return false;
341 }
342 m_numbots = numbots;
343 }
344
345 return true;
346}
347
232bool Constants::server = true; 348bool Constants::server = true;
233 349
234int main(int argc, char ** argv) 350int main(int argc, char ** argv)
@@ -244,8 +360,14 @@ int main(int argc, char ** argv)
244 360
245 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); 361 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
246 362
247 Server Server; 363 int ret = 0;
248 int ret = app.exec(); 364 Server server;
365 if (!ret && !server.parseCommandline())
366 ret = 1;
367 if (!ret && !server.run())
368 ret = 1;
369 if (!ret)
370 ret = app.exec();
249 371
250 /* Delete all global objects allocated by libprotobuf */ 372 /* Delete all global objects allocated by libprotobuf */
251 google::protobuf::ShutdownProtobufLibrary(); 373 google::protobuf::ShutdownProtobufLibrary();