summaryrefslogtreecommitdiffstats
path: root/pacman-c++
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2011-05-05 00:57:07 +0200
committermanuel <manuel@mausz.at>2011-05-05 00:57:07 +0200
commitce48af53646cd9e7ec762fc1ac176b3aa620b11d (patch)
treef8fbf2cae8c7d0cbac2696a8f4cf94410bfb4928 /pacman-c++
parente54ccad07e256ba877bd41d70bd358bd0085bd1e (diff)
downloadfoop-ce48af53646cd9e7ec762fc1ac176b3aa620b11d.tar.gz
foop-ce48af53646cd9e7ec762fc1ac176b3aa620b11d.tar.bz2
foop-ce48af53646cd9e7ec762fc1ac176b3aa620b11d.zip
- refactorized the whole project and made a few subprojects
- replaced tcp with enet - added connect dialog - some smaller bugfixes
Diffstat (limited to 'pacman-c++')
-rw-r--r--pacman-c++/client/clicklabel.cpp (renamed from pacman-c++/clicklabel.cpp)0
-rw-r--r--pacman-c++/client/clicklabel.h (renamed from pacman-c++/clicklabel.h)0
-rw-r--r--pacman-c++/client/client.cpp (renamed from pacman-c++/client.cpp)110
-rw-r--r--pacman-c++/client/client.h (renamed from pacman-c++/client.h)3
-rw-r--r--pacman-c++/client/client.pro12
-rw-r--r--pacman-c++/client/mainwidget.cpp (renamed from pacman-c++/mainwidget.cpp)247
-rw-r--r--pacman-c++/client/mainwidget.h (renamed from pacman-c++/mainwidget.h)22
-rw-r--r--pacman-c++/common.pri21
-rw-r--r--pacman-c++/common/actor.cpp (renamed from pacman-c++/actor.cpp)0
-rw-r--r--pacman-c++/common/actor.h (renamed from pacman-c++/actor.h)0
-rw-r--r--pacman-c++/common/audio.cpp (renamed from pacman-c++/audio.cpp)0
-rw-r--r--pacman-c++/common/audio.h (renamed from pacman-c++/audio.h)0
-rw-r--r--pacman-c++/common/block.cpp (renamed from pacman-c++/block.cpp)0
-rw-r--r--pacman-c++/common/block.h (renamed from pacman-c++/block.h)0
-rw-r--r--pacman-c++/common/bonuspoint.cpp (renamed from pacman-c++/bonuspoint.cpp)0
-rw-r--r--pacman-c++/common/bonuspoint.h (renamed from pacman-c++/bonuspoint.h)0
-rw-r--r--pacman-c++/common/common.pro30
-rw-r--r--pacman-c++/common/constants.h (renamed from pacman-c++/constants.h)1
-rw-r--r--pacman-c++/common/gameentity.cpp (renamed from pacman-c++/gameentity.cpp)0
-rw-r--r--pacman-c++/common/gameentity.h (renamed from pacman-c++/gameentity.h)0
-rw-r--r--pacman-c++/common/pacman.qrc (renamed from pacman-c++/pacman.qrc)0
-rw-r--r--pacman-c++/common/pacman.rc (renamed from pacman-c++/pacman.rc)0
-rw-r--r--pacman-c++/common/pics/actor1.png (renamed from pacman-c++/pics/actor1.png)bin1231 -> 1231 bytes
-rw-r--r--pacman-c++/common/pics/actor1icon.png (renamed from pacman-c++/pics/actor1icon.png)bin232 -> 232 bytes
-rw-r--r--pacman-c++/common/pics/actor2.png (renamed from pacman-c++/pics/actor2.png)bin1257 -> 1257 bytes
-rw-r--r--pacman-c++/common/pics/actor2icon.png (renamed from pacman-c++/pics/actor2icon.png)bin233 -> 233 bytes
-rw-r--r--pacman-c++/common/pics/actor3.png (renamed from pacman-c++/pics/actor3.png)bin1226 -> 1226 bytes
-rw-r--r--pacman-c++/common/pics/actor3icon.png (renamed from pacman-c++/pics/actor3icon.png)bin231 -> 231 bytes
-rw-r--r--pacman-c++/common/pics/actor4.png (renamed from pacman-c++/pics/actor4.png)bin1536 -> 1536 bytes
-rw-r--r--pacman-c++/common/pics/actor4icon.png (renamed from pacman-c++/pics/actor4icon.png)bin233 -> 233 bytes
-rw-r--r--pacman-c++/common/pics/app.ico (renamed from pacman-c++/pics/app.ico)bin174 -> 174 bytes
-rw-r--r--pacman-c++/common/pics/block0.png (renamed from pacman-c++/pics/block0.png)bin479 -> 479 bytes
-rw-r--r--pacman-c++/common/pics/block1.png (renamed from pacman-c++/pics/block1.png)bin453 -> 453 bytes
-rw-r--r--pacman-c++/common/pics/block2.png (renamed from pacman-c++/pics/block2.png)bin476 -> 476 bytes
-rw-r--r--pacman-c++/common/pics/block3.png (renamed from pacman-c++/pics/block3.png)bin452 -> 452 bytes
-rw-r--r--pacman-c++/common/pics/block4.png (renamed from pacman-c++/pics/block4.png)bin471 -> 471 bytes
-rw-r--r--pacman-c++/common/pics/bonuspoints.png (renamed from pacman-c++/pics/bonuspoints.png)bin642 -> 642 bytes
-rw-r--r--pacman-c++/common/pics/pacman10-hp-sprite-2.png (renamed from pacman-c++/pics/pacman10-hp-sprite-2.png)bin6857 -> 6857 bytes
-rw-r--r--pacman-c++/common/pics/points.png (renamed from pacman-c++/pics/points.png)bin188 -> 188 bytes
-rw-r--r--pacman-c++/common/pics/soundoff.xpm (renamed from pacman-c++/pics/soundoff.xpm)0
-rw-r--r--pacman-c++/common/pics/soundon.xpm (renamed from pacman-c++/pics/soundon.xpm)0
-rw-r--r--pacman-c++/common/pixmapitem.cpp (renamed from pacman-c++/pixmapitem.cpp)0
-rw-r--r--pacman-c++/common/pixmapitem.h (renamed from pacman-c++/pixmapitem.h)0
-rw-r--r--pacman-c++/common/point.cpp (renamed from pacman-c++/point.cpp)0
-rw-r--r--pacman-c++/common/point.h (renamed from pacman-c++/point.h)0
-rw-r--r--pacman-c++/common/sceneholder.cpp (renamed from pacman-c++/sceneholder.cpp)28
-rw-r--r--pacman-c++/common/sceneholder.h (renamed from pacman-c++/sceneholder.h)1
-rw-r--r--pacman-c++/common/sound/ambient.ogg (renamed from pacman-c++/sound/ambient.ogg)bin23243 -> 23243 bytes
-rw-r--r--pacman-c++/common/sound/die.ogg (renamed from pacman-c++/sound/die.ogg)bin20271 -> 20271 bytes
-rw-r--r--pacman-c++/common/sound/eating_fruit.ogg (renamed from pacman-c++/sound/eating_fruit.ogg)bin8774 -> 8774 bytes
-rw-r--r--pacman-c++/common/sound/eating_ghost.ogg (renamed from pacman-c++/sound/eating_ghost.ogg)bin9238 -> 9238 bytes
-rw-r--r--pacman-c++/common/sound/intro.ogg (renamed from pacman-c++/sound/intro.ogg)bin45705 -> 45705 bytes
-rw-r--r--pacman-c++/common/sound/waka_waka.ogg (renamed from pacman-c++/sound/waka_waka.ogg)bin25855 -> 25855 bytes
-rw-r--r--pacman-c++/common/style.qss (renamed from pacman-c++/style.qss)0
-rw-r--r--pacman-c++/common/util.cpp (renamed from pacman-c++/util.cpp)41
-rw-r--r--pacman-c++/common/util.h (renamed from pacman-c++/util.h)10
-rw-r--r--pacman-c++/pacman.pro53
-rw-r--r--pacman-c++/pacman.server.pro50
-rw-r--r--pacman-c++/proto/pacman.proto (renamed from pacman-c++/pacman.proto)0
-rw-r--r--pacman-c++/proto/proto.pro9
-rw-r--r--pacman-c++/proto/protobuf.pri (renamed from pacman-c++/protobuf.pri)0
-rwxr-xr-xpacman-c++/rebuild-server.sh4
-rwxr-xr-xpacman-c++/rebuild.sh (renamed from pacman-c++/rebuild-client.sh)2
-rw-r--r--pacman-c++/server/anyoption.cpp (renamed from pacman-c++/anyoption.cpp)0
-rw-r--r--pacman-c++/server/anyoption.h (renamed from pacman-c++/anyoption.h)0
-rw-r--r--pacman-c++/server/server.cpp (renamed from pacman-c++/server.cpp)161
-rw-r--r--pacman-c++/server/server.h (renamed from pacman-c++/server.h)11
-rw-r--r--pacman-c++/server/server.pro10
68 files changed, 562 insertions, 264 deletions
diff --git a/pacman-c++/clicklabel.cpp b/pacman-c++/client/clicklabel.cpp
index 87b06b8..87b06b8 100644
--- a/pacman-c++/clicklabel.cpp
+++ b/pacman-c++/client/clicklabel.cpp
diff --git a/pacman-c++/clicklabel.h b/pacman-c++/client/clicklabel.h
index 494b1ee..494b1ee 100644
--- a/pacman-c++/clicklabel.h
+++ b/pacman-c++/client/clicklabel.h
diff --git a/pacman-c++/client.cpp b/pacman-c++/client/client.cpp
index 581778e..d064d9e 100644
--- a/pacman-c++/client.cpp
+++ b/pacman-c++/client/client.cpp
@@ -4,19 +4,26 @@
4#include "util.h" 4#include "util.h"
5#include "pacman.pb.h" 5#include "pacman.pb.h"
6 6
7extern "C" {
8#include "enet/enet.h"
9}
10
7Client::Client() 11Client::Client()
8 : m_ambientMuted(false) 12 : m_ambientMuted(false)
9{ 13{
10 m_settings = new QSettings(qApp->organizationName(), qApp->applicationName(), this); 14 m_settings = new QSettings(qApp->organizationName(), qApp->applicationName(), this);
11 createMenu(); 15 m_dialog = new QDialog(this);
12 m_mainWidget = new MainWidget(this); 16 m_mainWidget = new MainWidget(this);
17 createMenu();
13 m_mainWidget->setAmbientMuted(m_ambientMuted); 18 m_mainWidget->setAmbientMuted(m_ambientMuted);
14 setCentralWidget(m_mainWidget); 19 setCentralWidget(m_mainWidget);
20 showConnectDialog();
21 m_dialog->setFocus();
15} 22}
16 23
17void Client::createMenu() 24void Client::createMenu()
18{ 25{
19 QMenu *fileMenu = menuBar()->addMenu("File"); 26 QMenu *fileMenu = menuBar()->addMenu("&File");
20 27
21 bool sound = AudioManager::self()->isWorking(); 28 bool sound = AudioManager::self()->isWorking();
22 bool muted = !sound || m_settings->value("muted", false).toBool(); 29 bool muted = !sound || m_settings->value("muted", false).toBool();
@@ -55,7 +62,7 @@ void Client::createMenu()
55 toggleAmbientAction->setToolTip("Toggle Ambient Sound"); 62 toggleAmbientAction->setToolTip("Toggle Ambient Sound");
56 toggleAmbientAction->setCheckable(true); 63 toggleAmbientAction->setCheckable(true);
57 toggleAmbientAction->setChecked(!m_ambientMuted); 64 toggleAmbientAction->setChecked(!m_ambientMuted);
58 toggleAmbientAction->setDisabled(!sound); 65 toggleAmbientAction->setDisabled(muted);
59 fileMenu->addAction(toggleAmbientAction); 66 fileMenu->addAction(toggleAmbientAction);
60 if (sound) 67 if (sound)
61 { 68 {
@@ -63,6 +70,19 @@ void Client::createMenu()
63 connect(this, SIGNAL(setMuteActionsChecked(bool)), toggleAmbientAction, SLOT(setEnabled(bool))); 70 connect(this, SIGNAL(setMuteActionsChecked(bool)), toggleAmbientAction, SLOT(setEnabled(bool)));
64 } 71 }
65 72
73 /* connect/disconnect entry */
74 fileMenu->addSeparator();
75 QAction *connectAction = new QAction("C&onnect", this);
76 fileMenu->addAction(connectAction);
77 connect(connectAction, SIGNAL(triggered()), this, SLOT(showConnectDialog()));
78 connect(m_mainWidget, SIGNAL(connected(bool)), connectAction, SLOT(setDisabled(bool)));
79
80 QAction *disconnectAction = new QAction("Di&sconnect", this);
81 disconnectAction->setDisabled(true);
82 fileMenu->addAction(disconnectAction);
83 connect(disconnectAction, SIGNAL(triggered()), m_mainWidget, SLOT(doDisconnect()));
84 connect(m_mainWidget, SIGNAL(connected(bool)), disconnectAction, SLOT(setEnabled(bool)));
85
66 /* exit entry */ 86 /* exit entry */
67 fileMenu->addSeparator(); 87 fileMenu->addSeparator();
68 QAction *quitAction = new QAction("E&xit", this); 88 QAction *quitAction = new QAction("E&xit", this);
@@ -70,7 +90,6 @@ void Client::createMenu()
70 fileMenu->addAction(quitAction); 90 fileMenu->addAction(quitAction);
71 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); 91 connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
72 92
73
74 QAction *aboutAction= menuBar()->addAction("Ab&out"); 93 QAction *aboutAction= menuBar()->addAction("Ab&out");
75 connect(aboutAction, SIGNAL(triggered()), this, SLOT(showAbout())); 94 connect(aboutAction, SIGNAL(triggered()), this, SLOT(showAbout()));
76} 95}
@@ -114,11 +133,15 @@ QPixmap Client::soundIcon(bool enabled) const
114 133
115void Client::showAbout() 134void Client::showAbout()
116{ 135{
117 QDialog *about = new QDialog(this); 136 if (m_dialog != NULL)
118 about->setWindowTitle("About Pacman"); 137 {
119 about->setWindowFlags(about->windowFlags() & ~Qt::WindowContextHelpButtonHint); 138 delete m_dialog;
139 m_dialog = new QDialog(this);
140 }
141 m_dialog->setWindowTitle("About Pacman");
142 m_dialog->setWindowFlags(m_dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
120 143
121 QGridLayout *layout = new QGridLayout(about); 144 QGridLayout *layout = new QGridLayout(m_dialog);
122 layout->setSizeConstraint(QLayout::SetFixedSize); 145 layout->setSizeConstraint(QLayout::SetFixedSize);
123 146
124 QString actoricons; 147 QString actoricons;
@@ -135,19 +158,71 @@ void Client::showAbout()
135 "Developed using Qt %2 (%3 bit)<br/>") 158 "Developed using Qt %2 (%3 bit)<br/>")
136 .arg(actoricons, QLatin1String(QT_VERSION_STR), QString::number(QSysInfo::WordSize)); 159 .arg(actoricons, QLatin1String(QT_VERSION_STR), QString::number(QSysInfo::WordSize));
137 160
138 QLabel *label = new QLabel(text); 161 QLabel *label = new QLabel(text, m_dialog);
139 label->setWordWrap(true); 162 label->setWordWrap(true);
140 label->setOpenExternalLinks(true); 163 label->setOpenExternalLinks(true);
141 label->setTextInteractionFlags(Qt::TextBrowserInteraction); 164 label->setTextInteractionFlags(Qt::TextBrowserInteraction);
142 165
143 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); 166 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, m_dialog);
144 QPushButton *closeButton = buttonBox->button(QDialogButtonBox::Close); 167 QPushButton *closeButton = buttonBox->button(QDialogButtonBox::Close);
145 buttonBox->addButton(closeButton, QDialogButtonBox::ButtonRole(QDialogButtonBox::RejectRole | QDialogButtonBox::AcceptRole)); 168 buttonBox->addButton(closeButton, QDialogButtonBox::ButtonRole(QDialogButtonBox::RejectRole | QDialogButtonBox::AcceptRole));
146 connect(buttonBox , SIGNAL(rejected()), about, SLOT(reject())); 169 connect(buttonBox , SIGNAL(rejected()), m_dialog, SLOT(reject()));
147 170
148 layout->addWidget(label, 0, 1, 4, 4); 171 layout->addWidget(label, 0, 1, 4, 4);
149 layout->addWidget(buttonBox, 4, 0, 1, 5); 172 layout->addWidget(buttonBox, 4, 0, 1, 5);
150 about->show(); 173 m_dialog->show();
174}
175
176void Client::showConnectDialog()
177{
178 if (m_dialog != NULL)
179 {
180 delete m_dialog;
181 m_dialog = new QDialog(this);
182 }
183 m_dialog->setWindowTitle("Connect");
184
185 QGridLayout *layout = new QGridLayout(m_dialog);
186 layout->setSizeConstraint(QLayout::SetFixedSize);
187
188 QLabel *srvLabel = new QLabel("Address:", m_dialog);
189 QLineEdit *srv = new QLineEdit(m_settings->value("address", "127.0.0.1").toString(), m_dialog);
190 QLabel *portLabel = new QLabel("Port:", m_dialog);
191 QDoubleSpinBox *port = new QDoubleSpinBox(m_dialog);
192 port->setDecimals(0);
193 port->setMinimum(1);
194 port->setMaximum(65535);
195 port->setValue(m_settings->value("port", Constants::Networking::port).toUInt());
196
197 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
198 Qt::Horizontal, m_dialog);
199 QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
200 QPushButton *cancelButton = buttonBox->button(QDialogButtonBox::Cancel);
201 buttonBox->addButton(okButton, QDialogButtonBox::ButtonRole(QDialogButtonBox::AcceptRole));
202 buttonBox->addButton(cancelButton, QDialogButtonBox::ButtonRole(QDialogButtonBox::RejectRole));
203 connect(buttonBox, SIGNAL(rejected()), m_dialog, SLOT(reject()));
204 connect(buttonBox, SIGNAL(accepted()), m_dialog, SLOT(accept()));
205
206 layout->addWidget(srvLabel, 0, 0);
207 layout->addWidget(srv, 0, 1);
208 layout->addWidget(portLabel, 1, 0);
209 layout->addWidget(port, 1, 1);
210 layout->addWidget(buttonBox, 4, 0, 1, 5);
211
212 connect(m_dialog, SIGNAL(accepted()), this, SLOT(onAcceptConnectDialog()));
213 m_dialog->show();
214}
215
216void Client::onAcceptConnectDialog()
217{
218 if (m_dialog == NULL)
219 return;
220 QGridLayout *layout = static_cast<QGridLayout *>(m_dialog->layout());
221 QLineEdit *srv = static_cast<QLineEdit *>(layout->itemAtPosition(0, 1)->widget());
222 QDoubleSpinBox *port = static_cast<QDoubleSpinBox *>(layout->itemAtPosition(1, 1)->widget());
223 m_settings->setValue("address", srv->text());
224 m_settings->setValue("port", int(port->value()));
225 m_mainWidget->doConnect(srv->text(), int(port->value()));
151} 226}
152 227
153bool Constants::server = false; 228bool Constants::server = false;
@@ -159,6 +234,13 @@ int main(int argc, char **argv)
159 */ 234 */
160 GOOGLE_PROTOBUF_VERIFY_VERSION; 235 GOOGLE_PROTOBUF_VERIFY_VERSION;
161 236
237 if (enet_initialize () != 0)
238 {
239 qCritical() << "An error occurred while initializing ENet";
240 return EXIT_FAILURE;
241 }
242
243 Q_INIT_RESOURCE(pacman);
162 QApplication app(argc, argv, true); 244 QApplication app(argc, argv, true);
163 app.setOrganizationName("TU Wien FOOP"); 245 app.setOrganizationName("TU Wien FOOP");
164 app.setApplicationName("Pacman Client"); 246 app.setApplicationName("Pacman Client");
@@ -166,12 +248,16 @@ int main(int argc, char **argv)
166 248
167 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); 249 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
168 250
251 AudioManager::self();
252
169 Client client; 253 Client client;
170 client.show(); 254 client.show();
171 client.setWindowTitle(app.applicationName()); 255 client.setWindowTitle(app.applicationName());
172 256
173 int ret = app.exec(); 257 int ret = app.exec();
174 258
259 enet_deinitialize();
260
175 /* Delete all global objects allocated by libprotobuf */ 261 /* Delete all global objects allocated by libprotobuf */
176 google::protobuf::ShutdownProtobufLibrary(); 262 google::protobuf::ShutdownProtobufLibrary();
177 263
diff --git a/pacman-c++/client.h b/pacman-c++/client/client.h
index 7030683..9b231ca 100644
--- a/pacman-c++/client.h
+++ b/pacman-c++/client/client.h
@@ -24,6 +24,8 @@ private slots:
24 /* enable ambient (emitted by action) */ 24 /* enable ambient (emitted by action) */
25 void enableAmbientSound(bool); 25 void enableAmbientSound(bool);
26 void showAbout(); 26 void showAbout();
27 void showConnectDialog();
28 void onAcceptConnectDialog();
27 29
28private: 30private:
29 void createMenu(); 31 void createMenu();
@@ -31,6 +33,7 @@ private:
31 33
32private: 34private:
33 MainWidget *m_mainWidget; 35 MainWidget *m_mainWidget;
36 QDialog *m_dialog;
34 QSettings *m_settings; 37 QSettings *m_settings;
35 bool m_ambientMuted; 38 bool m_ambientMuted;
36}; 39};
diff --git a/pacman-c++/client/client.pro b/pacman-c++/client/client.pro
new file mode 100644
index 0000000..849cca2
--- /dev/null
+++ b/pacman-c++/client/client.pro
@@ -0,0 +1,12 @@
1TEMPLATE = app
2TARGET = pacman
3
4SOURCES += clicklabel.cpp \
5 client.cpp \
6 mainwidget.cpp
7HEADERS += clicklabel.h \
8 client.h \
9 mainwidget.h
10
11include(../common.pri)
12PRE_TARGETDEPS += ../common/libcommon.a
diff --git a/pacman-c++/mainwidget.cpp b/pacman-c++/client/mainwidget.cpp
index 49ddf7a..f6f088b 100644
--- a/pacman-c++/mainwidget.cpp
+++ b/pacman-c++/client/mainwidget.cpp
@@ -7,40 +7,89 @@
7#include <QStringBuilder> 7#include <QStringBuilder>
8 8
9MainWidget::MainWidget(QWidget *parent) 9MainWidget::MainWidget(QWidget *parent)
10 : QWidget(parent), m_currentKey(Transmission::none), m_running(false), m_scene(NULL), 10 : QWidget(parent), m_currentKey(Transmission::none), m_running(false),
11 m_maxplayers(0) 11 m_host(NULL), m_peer(NULL), m_scene(NULL), m_maxplayers(0)
12{ 12{
13 m_host = enet_host_create(NULL, 1, 1, 0, 0);
14 if (m_host == NULL)
15 {
16 QMessageBox::critical(this, "Error", "An error occurred while trying to create an ENet client host");
17 qCritical() << "An error occurred while trying to create an ENet client host";
18 return;
19 }
20
13 /* create audio player */ 21 /* create audio player */
14 m_ambientPlayer = new GaplessAudioPlayer(Sound::Ambient, 100, this); 22 m_ambientPlayer = new GaplessAudioPlayer(Sound::Ambient, 100, this);
15 23
16 Color::Color color = connectToServer(); 24 m_recvTimer = new QTimer(this);
25 m_recvTimer->setInterval(Constants::tick / 2);
26 connect(m_recvTimer, SIGNAL(timeout()), this, SLOT(tick()));
27}
28
29MainWidget::~MainWidget()
30{
31 doDisconnect();
32 if (m_host != NULL)
33 {
34 enet_host_destroy(m_host);
35 m_host = NULL;
36 }
37}
38
39void MainWidget::doConnect(QString srv, unsigned int port)
40{
41 Color::Color color = connectToServer(srv, port);
17 if (color == Color::none) 42 if (color == Color::none)
18 { 43 {
19 QMessageBox::critical(this, "Error", "Failed to connect to server, falling back to local test mode"); 44 QMessageBox::critical(this, "Error", "Failed to connect to server");
20 // TODO: quit application here or sth
21 return; 45 return;
22 } 46 }
23 47
24 /* create our scene */ 48 /* create our scene */
25 m_scene = new SceneHolder(this); 49 m_scene = new SceneHolder(this);
26 m_scene->setColor(color); 50 m_scene->setColor(color);
27 51 m_scene->showWaitingForPlayers(true);
28 /* call updateMap after m_color ist set! */
29 createGui(); 52 createGui();
30 53
31 /* wait for the server to send the first map update (initial map) 54 m_recvTimer->start();
32 * WARNING: this will block the gui 55 emit connected(true);
33 */
34 m_socket->waitForReadyRead(-1);
35 tick();
36
37 qDebug() << "[Connect] mycolor=" << m_scene->color(); 56 qDebug() << "[Connect] mycolor=" << m_scene->color();
38 connect(m_socket, SIGNAL(readyRead()), this, SLOT(tick())); 57}
58
59void MainWidget::deleteLayout(QLayout *layout)
60{
61 if (layout == NULL)
62 return;
63
64 foreach(QObject *obj, layout->children())
65 {
66 QLayout *inLayout = qobject_cast<QLayout*>(obj);
67 deleteLayout(inLayout);
68 }
69
70 QLayoutItem *child;
71 while ((child = layout->takeAt(0)) != NULL)
72 {
73 child->widget()->deleteLater();
74 delete child;
75 }
76
77 delete layout;
78}
79
80void MainWidget::doDisconnect()
81{
82 stopGame();
83 m_recvTimer->stop();
84 closeENetPeer();
85 deleteLayout(layout());
86 m_playerScoreLayouts.clear();
87 emit connected(false);
39} 88}
40 89
41bool MainWidget::connected() 90bool MainWidget::connected()
42{ 91{
43 return m_socket != NULL; 92 return m_peer != NULL;
44} 93}
45 94
46void MainWidget::createGui() 95void MainWidget::createGui()
@@ -135,54 +184,75 @@ Transmission::field_t MainWidget::translateKey(int key)
135 184
136void MainWidget::tick() 185void MainWidget::tick()
137{ 186{
138 while (m_socket->bytesAvailable() > (qint64)sizeof(qint64)) 187 ENetEvent event;
188 while (enet_host_service(m_host, &event, 1) > 0)
139 { 189 {
140 QSharedPointer<QByteArray> data = Util::receivePacket(m_socket); 190 switch (event.type)
141 bool worked = m_updatepacket.ParseFromArray(data->data(), data->size());
142 Q_ASSERT(worked);
143 Q_UNUSED(worked);
144
145 /* eating order data set indicates a new round */
146 if (m_updatepacket.eating_order_size() > 0)
147 { 191 {
148 Q_ASSERT(m_scene != NULL); 192 case ENET_EVENT_TYPE_DISCONNECT:
149 m_scene->reset(); 193 m_peer = NULL;
150 194 doDisconnect();
151 /* fetch eating order */ 195 break;
152 QList<Color::Color> order; 196 case ENET_EVENT_TYPE_RECEIVE:
153 for(int i = 0; i < m_updatepacket.eating_order_size(); ++i) 197 tick(&event);
154 order.append(static_cast<Color::Color>(m_updatepacket.eating_order(i) & Transmission::color_mask)); 198 enet_packet_destroy(event.packet);
155 m_scene->setEatingOrder(order); 199 break;
156 200 default:
157 /* stop game */ 201 break;
158 stopGame();
159
160 /* and restart game */
161 QTimer *timer = new QTimer(this);
162 timer->setSingleShot(true);
163 timer->setInterval(Sound::length[Sound::Intro] + Constants::tick);
164 connect(timer, SIGNAL(timeout()), this, SLOT(startGame()));
165 timer->start();
166 AudioManager::self()->play(Sound::Intro, true);
167 } 202 }
203 }
204}
205
206void MainWidget::tick(ENetEvent *event)
207{
208 QSharedPointer<QByteArray> data = Util::receivePacket(event->packet);
209 bool worked = m_updatepacket.ParseFromArray(data->data(), data->size());
210 Q_ASSERT(worked);
211 Q_UNUSED(worked);
168 212
169 Transmission::map_t map = Util::createUninitialisedMap(); 213 /* eating order data set indicates a new round */
170 Q_ASSERT(m_updatepacket.field_size() == (int) (Constants::map_size.width * Constants::map_size.height)); 214 if (m_updatepacket.eating_order_size() > 0)
171 int i = 0; 215 {
172 for (unsigned int x = 0; x < Constants::map_size.width; ++x) 216 Q_ASSERT(m_scene != NULL);
217 m_scene->reset();
218
219 /* fetch eating order */
220 QList<Color::Color> order;
221 for(int i = 0; i < m_updatepacket.eating_order_size(); ++i)
222 order.append(static_cast<Color::Color>(m_updatepacket.eating_order(i) & Transmission::color_mask));
223 m_scene->setEatingOrder(order);
224
225 /* stop game */
226 stopGame();
227
228 /* and restart game */
229 QTimer *timer = new QTimer(this);
230 timer->setSingleShot(true);
231 timer->setInterval(Sound::length[Sound::Intro] + Constants::tick);
232 connect(timer, SIGNAL(timeout()), this, SLOT(startGame()));
233 timer->start();
234 AudioManager::self()->play(Sound::Intro, true);
235 }
236
237 Transmission::map_t map = Util::createUninitialisedMap();
238 Q_ASSERT(m_updatepacket.field_size() == (int) (Constants::map_size.width * Constants::map_size.height));
239 int i = 0;
240 for (unsigned int x = 0; x < Constants::map_size.width; ++x)
241 {
242 for (unsigned int y = 0; y < Constants::map_size.height; ++y)
173 { 243 {
174 for (unsigned int y = 0; y < Constants::map_size.height; ++y) 244 map[x][y] = m_updatepacket.field(i);
175 { 245 ++i;
176 map[x][y] = m_updatepacket.field(i);
177 ++i;
178 }
179 } 246 }
180 m_scene->updateMap(map); 247 }
181 Util::deleteMap(map); 248 m_scene->updateMap(map);
182 updateScore(m_updatepacket); 249 Util::deleteMap(map);
250 updateScore(m_updatepacket);
183 251
184 if (m_updatepacket.eating_order_size() > 0) 252 if (m_updatepacket.eating_order_size() > 0)
185 m_scene->showEatingText(); 253 {
254 m_scene->showWaitingForPlayers(false);
255 m_scene->showEatingText();
186 } 256 }
187} 257}
188 258
@@ -208,7 +278,7 @@ void MainWidget::sendKeyUpdate()
208 qDebug() << "[SendKey] key=" << m_currentKey; 278 qDebug() << "[SendKey] key=" << m_currentKey;
209 ProtoBuf::KeyPressUpdate packet; 279 ProtoBuf::KeyPressUpdate packet;
210 packet.set_newkey(m_currentKey); 280 packet.set_newkey(m_currentKey);
211 Util::sendPacket(packet, m_socket); 281 Util::sendPacket(packet, m_peer, m_host);
212} 282}
213 283
214void MainWidget::keyReleaseEvent(QKeyEvent* event) 284void MainWidget::keyReleaseEvent(QKeyEvent* event)
@@ -248,32 +318,73 @@ void MainWidget::playerScoreClicked()
248 return; 318 return;
249} 319}
250 320
251Color::Color MainWidget::connectToServer() 321Color::Color MainWidget::connectToServer(QString srv, unsigned int port)
252{ 322{
253 /* TODO: check command line arguments for server port */ 323 qDebug() << "[Connect] server=" << srv << "port=" << port;
254 const QStringList &args = QCoreApplication::arguments();
255 QString srv = args.value(1, "127.0.0.1");
256 qDebug() << "[Connect] server=" << srv;
257 324
258 /* connect to server */ 325 /* connect to server */
259 m_socket = new QTcpSocket(this); 326 closeENetPeer();
260 m_socket->connectToHost(srv, Constants::Networking::port); 327 ENetAddress address;
261 bool worked = m_socket->waitForConnected(Constants::Networking::connection_timeout); 328 enet_address_set_host(&address, qPrintable(srv));
329 address.port = Constants::Networking::port;
330 m_peer = enet_host_connect(m_host, &address, 1, 0);
331 if (m_peer == NULL)
332 {
333 qCritical() << "No available peers for initiating an ENet connection";
334 return Color::none;
335 }
336
337 ENetEvent event;
338 bool worked = (enet_host_service(m_host, &event, Constants::Networking::connection_timeout) > 0
339 && event.type == ENET_EVENT_TYPE_CONNECT);
262 if (worked) 340 if (worked)
263 { 341 {
264 /* additional init: first packet is our color */ 342 /* additional init: first packet is our color */
265 worked = m_socket->waitForReadyRead(); 343 worked = (enet_host_service(m_host, &event, Constants::Networking::packet_timeout) > 0
344 && event.type == ENET_EVENT_TYPE_RECEIVE);
266 if (worked) 345 if (worked)
267 { 346 {
268 /* receive color */ 347 /* receive color */
269 QSharedPointer<QByteArray> data = Util::receivePacket(m_socket); 348 QSharedPointer<QByteArray> data = Util::receivePacket(event.packet);
349 enet_packet_destroy(event.packet);
270 ProtoBuf::Init packet; 350 ProtoBuf::Init packet;
271 bool worked = packet.ParseFromArray(data->data(), data->size()); 351 worked = packet.ParseFromArray(data->data(), data->size());
272 Q_ASSERT(worked); 352 Q_ASSERT(worked);
273 Q_UNUSED(worked); 353 Q_UNUSED(worked);
274 m_maxplayers = packet.maxplayers(); 354 m_maxplayers = packet.maxplayers();
275 return static_cast<Color::Color>(packet.color() & Transmission::color_mask); 355 return static_cast<Color::Color>(packet.color() & Transmission::color_mask);
276 } 356 }
277 } 357 }
358 enet_peer_reset(m_peer);
359 m_peer = NULL;
278 return Color::none; 360 return Color::none;
279} 361}
362
363void MainWidget::closeENetPeer()
364{
365 if (m_peer != NULL && m_peer->state != ENET_PEER_STATE_DISCONNECTED)
366 {
367 /* allow up to 3 seconds for the disconnect to succeed
368 * and drop any packets received packets
369 */
370 enet_peer_disconnect(m_peer, 0);
371 ENetEvent event;
372 while (enet_host_service(m_host, &event, 3000) > 0)
373 {
374 switch (event.type)
375 {
376 case ENET_EVENT_TYPE_RECEIVE:
377 enet_packet_destroy(event.packet);
378 break;
379 case ENET_EVENT_TYPE_DISCONNECT:
380 m_peer = NULL;
381 return;
382 default:
383 break;
384 }
385 }
386
387 enet_peer_reset(m_peer);
388 }
389 m_peer = NULL;
390}
diff --git a/pacman-c++/mainwidget.h b/pacman-c++/client/mainwidget.h
index d5695ed..99ff7d7 100644
--- a/pacman-c++/mainwidget.h
+++ b/pacman-c++/client/mainwidget.h
@@ -7,7 +7,10 @@
7#include "pacman.pb.h" 7#include "pacman.pb.h"
8#include <QtGui> 8#include <QtGui>
9#include <QtCore> 9#include <QtCore>
10#include <QTcpSocket> 10
11extern "C" {
12#include "enet/enet.h"
13}
11 14
12class Actor; 15class Actor;
13 16
@@ -18,19 +21,28 @@ class MainWidget
18 21
19public: 22public:
20 MainWidget(QWidget *parent = 0); 23 MainWidget(QWidget *parent = 0);
24 ~MainWidget();
21 bool connected(); 25 bool connected();
22 void setAmbientMuted(bool muted); 26 void setAmbientMuted(bool muted);
23 27
28public slots:
29 void doConnect(QString srv = "127.0.0.1", unsigned int port = Constants::Networking::port);
30 void doDisconnect();
31
24protected: 32protected:
25 /* handling of current key */ 33 /* handling of current key */
26 virtual void keyPressEvent(QKeyEvent *); 34 virtual void keyPressEvent(QKeyEvent *);
27 virtual void keyReleaseEvent(QKeyEvent *); 35 virtual void keyReleaseEvent(QKeyEvent *);
28 36
37signals:
38 void connected(bool connected);
39
29private slots: 40private slots:
30 void startGame(); 41 void startGame();
31 void stopGame(); 42 void stopGame();
32 void playerScoreClicked(); 43 void playerScoreClicked();
33 void tick(); 44 void tick();
45 void tick(ENetEvent *event);
34 void sendKeyUpdate(); 46 void sendKeyUpdate();
35 47
36private: 48private:
@@ -38,7 +50,9 @@ private:
38 void createMenu(); 50 void createMenu();
39 void updateScore(const ProtoBuf::MapUpdate&); 51 void updateScore(const ProtoBuf::MapUpdate&);
40 bool isRunning(); 52 bool isRunning();
41 Color::Color connectToServer(); 53 Color::Color connectToServer(QString srv = "127.0.0.1", unsigned int port = Constants::Networking::port);
54 void closeENetPeer();
55 void deleteLayout(QLayout *layout);
42 56
43 /* GUI elements needed in the progress of the game */ 57 /* GUI elements needed in the progress of the game */
44 QList<QGridLayout*> m_playerScoreLayouts; 58 QList<QGridLayout*> m_playerScoreLayouts;
@@ -53,9 +67,11 @@ private:
53 bool m_running; 67 bool m_running;
54 GaplessAudioPlayer *m_ambientPlayer; 68 GaplessAudioPlayer *m_ambientPlayer;
55 69
56 QTcpSocket *m_socket; 70 ENetHost *m_host;
71 ENetPeer *m_peer;
57 SceneHolder *m_scene; 72 SceneHolder *m_scene;
58 unsigned int m_maxplayers; 73 unsigned int m_maxplayers;
74 QTimer *m_recvTimer;
59 75
60 /* allocate as member variable as this packet is large and used often */ 76 /* allocate as member variable as this packet is large and used often */
61 ProtoBuf::MapUpdate m_updatepacket; 77 ProtoBuf::MapUpdate m_updatepacket;
diff --git a/pacman-c++/common.pri b/pacman-c++/common.pri
new file mode 100644
index 0000000..fed2973
--- /dev/null
+++ b/pacman-c++/common.pri
@@ -0,0 +1,21 @@
1LANGUAGE = C++
2VERSION = 0.1
3
4OBJECTS_DIR = .obj
5MOC_DIR = .moc
6
7QT += phonon network
8
9INCLUDEPATH += ../common
10DEPENDPATH += ../common
11LIBS += -L../common -lcommon
12
13INCLUDEPATH += $$OUT_PWD/../proto
14LIBS += -L../proto -lproto -lprotobuf
15
16INCLUDEPATH += ../enet/include
17LIBS += -L$$PWD/enet/.libs -lenet
18
19CONFIG(release, debug|release) {
20 DEFINES += QT_NO_DEBUG_OUTPUT
21}
diff --git a/pacman-c++/actor.cpp b/pacman-c++/common/actor.cpp
index de8d77e..de8d77e 100644
--- a/pacman-c++/actor.cpp
+++ b/pacman-c++/common/actor.cpp
diff --git a/pacman-c++/actor.h b/pacman-c++/common/actor.h
index c30c62a..c30c62a 100644
--- a/pacman-c++/actor.h
+++ b/pacman-c++/common/actor.h
diff --git a/pacman-c++/audio.cpp b/pacman-c++/common/audio.cpp
index 70cd37e..70cd37e 100644
--- a/pacman-c++/audio.cpp
+++ b/pacman-c++/common/audio.cpp
diff --git a/pacman-c++/audio.h b/pacman-c++/common/audio.h
index 6aec42d..6aec42d 100644
--- a/pacman-c++/audio.h
+++ b/pacman-c++/common/audio.h
diff --git a/pacman-c++/block.cpp b/pacman-c++/common/block.cpp
index 7f9dd14..7f9dd14 100644
--- a/pacman-c++/block.cpp
+++ b/pacman-c++/common/block.cpp
diff --git a/pacman-c++/block.h b/pacman-c++/common/block.h
index abfbc5a..abfbc5a 100644
--- a/pacman-c++/block.h
+++ b/pacman-c++/common/block.h
diff --git a/pacman-c++/bonuspoint.cpp b/pacman-c++/common/bonuspoint.cpp
index 033b7c8..033b7c8 100644
--- a/pacman-c++/bonuspoint.cpp
+++ b/pacman-c++/common/bonuspoint.cpp
diff --git a/pacman-c++/bonuspoint.h b/pacman-c++/common/bonuspoint.h
index a72a4db..a72a4db 100644
--- a/pacman-c++/bonuspoint.h
+++ b/pacman-c++/common/bonuspoint.h
diff --git a/pacman-c++/common/common.pro b/pacman-c++/common/common.pro
new file mode 100644
index 0000000..5903f9d
--- /dev/null
+++ b/pacman-c++/common/common.pro
@@ -0,0 +1,30 @@
1TEMPLATE = lib
2CONFIG += staticlib
3
4include(../common.pri)
5
6SOURCES += pixmapitem.cpp \
7 actor.cpp \
8 block.cpp \
9 bonuspoint.cpp \
10 point.cpp \
11 audio.cpp \
12 sceneholder.cpp \
13 util.cpp \
14 gameentity.cpp
15HEADERS += pixmapitem.h \
16 actor.h \
17 block.h \
18 bonuspoint.h \
19 constants.h \
20 point.h \
21 audio.h \
22 sceneholder.h \
23 util.h \
24 gameentity.h
25
26OTHER_FILES += style.qss \
27 pacman.rc
28
29RESOURCES += pacman.qrc
30RC_FILE = pacman.rc
diff --git a/pacman-c++/constants.h b/pacman-c++/common/constants.h
index e7dedbf..d40c39e 100644
--- a/pacman-c++/constants.h
+++ b/pacman-c++/common/constants.h
@@ -21,6 +21,7 @@ namespace Constants {
21 { 21 {
22 const unsigned int port = 7321; 22 const unsigned int port = 7321;
23 const unsigned int connection_timeout = 3000; 23 const unsigned int connection_timeout = 3000;
24 const unsigned int packet_timeout = 3000;
24 } 25 }
25 26
26 namespace Game 27 namespace Game
diff --git a/pacman-c++/gameentity.cpp b/pacman-c++/common/gameentity.cpp
index e73e759..e73e759 100644
--- a/pacman-c++/gameentity.cpp
+++ b/pacman-c++/common/gameentity.cpp
diff --git a/pacman-c++/gameentity.h b/pacman-c++/common/gameentity.h
index 116fae5..116fae5 100644
--- a/pacman-c++/gameentity.h
+++ b/pacman-c++/common/gameentity.h
diff --git a/pacman-c++/pacman.qrc b/pacman-c++/common/pacman.qrc
index 6654fd1..6654fd1 100644
--- a/pacman-c++/pacman.qrc
+++ b/pacman-c++/common/pacman.qrc
diff --git a/pacman-c++/pacman.rc b/pacman-c++/common/pacman.rc
index 8c9f03b..8c9f03b 100644
--- a/pacman-c++/pacman.rc
+++ b/pacman-c++/common/pacman.rc
diff --git a/pacman-c++/pics/actor1.png b/pacman-c++/common/pics/actor1.png
index 5a37b4f..5a37b4f 100644
--- a/pacman-c++/pics/actor1.png
+++ b/pacman-c++/common/pics/actor1.png
Binary files differ
diff --git a/pacman-c++/pics/actor1icon.png b/pacman-c++/common/pics/actor1icon.png
index 4407cef..4407cef 100644
--- a/pacman-c++/pics/actor1icon.png
+++ b/pacman-c++/common/pics/actor1icon.png
Binary files differ
diff --git a/pacman-c++/pics/actor2.png b/pacman-c++/common/pics/actor2.png
index 736a6e7..736a6e7 100644
--- a/pacman-c++/pics/actor2.png
+++ b/pacman-c++/common/pics/actor2.png
Binary files differ
diff --git a/pacman-c++/pics/actor2icon.png b/pacman-c++/common/pics/actor2icon.png
index eaf2a4c..eaf2a4c 100644
--- a/pacman-c++/pics/actor2icon.png
+++ b/pacman-c++/common/pics/actor2icon.png
Binary files differ
diff --git a/pacman-c++/pics/actor3.png b/pacman-c++/common/pics/actor3.png
index f963cff..f963cff 100644
--- a/pacman-c++/pics/actor3.png
+++ b/pacman-c++/common/pics/actor3.png
Binary files differ
diff --git a/pacman-c++/pics/actor3icon.png b/pacman-c++/common/pics/actor3icon.png
index 2558cbc..2558cbc 100644
--- a/pacman-c++/pics/actor3icon.png
+++ b/pacman-c++/common/pics/actor3icon.png
Binary files differ
diff --git a/pacman-c++/pics/actor4.png b/pacman-c++/common/pics/actor4.png
index e500dc5..e500dc5 100644
--- a/pacman-c++/pics/actor4.png
+++ b/pacman-c++/common/pics/actor4.png
Binary files differ
diff --git a/pacman-c++/pics/actor4icon.png b/pacman-c++/common/pics/actor4icon.png
index 82bf637..82bf637 100644
--- a/pacman-c++/pics/actor4icon.png
+++ b/pacman-c++/common/pics/actor4icon.png
Binary files differ
diff --git a/pacman-c++/pics/app.ico b/pacman-c++/common/pics/app.ico
index 4a73cd4..4a73cd4 100644
--- a/pacman-c++/pics/app.ico
+++ b/pacman-c++/common/pics/app.ico
Binary files differ
diff --git a/pacman-c++/pics/block0.png b/pacman-c++/common/pics/block0.png
index 76bc4b7..76bc4b7 100644
--- a/pacman-c++/pics/block0.png
+++ b/pacman-c++/common/pics/block0.png
Binary files differ
diff --git a/pacman-c++/pics/block1.png b/pacman-c++/common/pics/block1.png
index 99e8633..99e8633 100644
--- a/pacman-c++/pics/block1.png
+++ b/pacman-c++/common/pics/block1.png
Binary files differ
diff --git a/pacman-c++/pics/block2.png b/pacman-c++/common/pics/block2.png
index 963207e..963207e 100644
--- a/pacman-c++/pics/block2.png
+++ b/pacman-c++/common/pics/block2.png
Binary files differ
diff --git a/pacman-c++/pics/block3.png b/pacman-c++/common/pics/block3.png
index 6662de4..6662de4 100644
--- a/pacman-c++/pics/block3.png
+++ b/pacman-c++/common/pics/block3.png
Binary files differ
diff --git a/pacman-c++/pics/block4.png b/pacman-c++/common/pics/block4.png
index 00fbd74..00fbd74 100644
--- a/pacman-c++/pics/block4.png
+++ b/pacman-c++/common/pics/block4.png
Binary files differ
diff --git a/pacman-c++/pics/bonuspoints.png b/pacman-c++/common/pics/bonuspoints.png
index b5714c9..b5714c9 100644
--- a/pacman-c++/pics/bonuspoints.png
+++ b/pacman-c++/common/pics/bonuspoints.png
Binary files differ
diff --git a/pacman-c++/pics/pacman10-hp-sprite-2.png b/pacman-c++/common/pics/pacman10-hp-sprite-2.png
index 7354b9d..7354b9d 100644
--- a/pacman-c++/pics/pacman10-hp-sprite-2.png
+++ b/pacman-c++/common/pics/pacman10-hp-sprite-2.png
Binary files differ
diff --git a/pacman-c++/pics/points.png b/pacman-c++/common/pics/points.png
index 6ba4496..6ba4496 100644
--- a/pacman-c++/pics/points.png
+++ b/pacman-c++/common/pics/points.png
Binary files differ
diff --git a/pacman-c++/pics/soundoff.xpm b/pacman-c++/common/pics/soundoff.xpm
index ba33f5f..ba33f5f 100644
--- a/pacman-c++/pics/soundoff.xpm
+++ b/pacman-c++/common/pics/soundoff.xpm
diff --git a/pacman-c++/pics/soundon.xpm b/pacman-c++/common/pics/soundon.xpm
index e6ca41e..e6ca41e 100644
--- a/pacman-c++/pics/soundon.xpm
+++ b/pacman-c++/common/pics/soundon.xpm
diff --git a/pacman-c++/pixmapitem.cpp b/pacman-c++/common/pixmapitem.cpp
index 1ceeec1..1ceeec1 100644
--- a/pacman-c++/pixmapitem.cpp
+++ b/pacman-c++/common/pixmapitem.cpp
diff --git a/pacman-c++/pixmapitem.h b/pacman-c++/common/pixmapitem.h
index f57c22a..f57c22a 100644
--- a/pacman-c++/pixmapitem.h
+++ b/pacman-c++/common/pixmapitem.h
diff --git a/pacman-c++/point.cpp b/pacman-c++/common/point.cpp
index d7ebdb1..d7ebdb1 100644
--- a/pacman-c++/point.cpp
+++ b/pacman-c++/common/point.cpp
diff --git a/pacman-c++/point.h b/pacman-c++/common/point.h
index 7739554..7739554 100644
--- a/pacman-c++/point.h
+++ b/pacman-c++/common/point.h
diff --git a/pacman-c++/sceneholder.cpp b/pacman-c++/common/sceneholder.cpp
index 51496ca..bd9b01b 100644
--- a/pacman-c++/sceneholder.cpp
+++ b/pacman-c++/common/sceneholder.cpp
@@ -315,6 +315,34 @@ void SceneHolder::showEatingText(bool show)
315 addItem(m_overlayText); 315 addItem(m_overlayText);
316} 316}
317 317
318void SceneHolder::showWaitingForPlayers(bool show)
319{
320 if (!show)
321 {
322 if (m_overlayText->scene() == this)
323 removeItem(m_overlayText);
324 return;
325 }
326
327 m_overlayText->setDefaultTextColor(Qt::black);
328 QString text = QString(
329 "<div style=\"background-color: gray;\" align=\"center\">"
330 "<br />"
331 "Waiting for other Players...<br />"
332 "</div>"
333 );
334 unsigned int lines = 3;
335 m_overlayText->setHtml(text);
336 m_overlayText->setTextWidth(150);
337 m_overlayText->setOpacity(0.9);
338
339 QFontMetrics metrics(m_overlayText->font());
340 m_overlayText->setPos((width() - m_overlayText->textWidth()) / 2, (height() - metrics.height() * lines) / 2);
341 m_overlayText->setZValue(100);
342
343 addItem(m_overlayText);
344}
345
318QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y) 346QPoint SceneHolder::mapPositionToCoord(unsigned int x, unsigned int y)
319{ 347{
320 return QPoint(x * Constants::field_size.width, y * Constants::field_size.height); 348 return QPoint(x * Constants::field_size.width, y * Constants::field_size.height);
diff --git a/pacman-c++/sceneholder.h b/pacman-c++/common/sceneholder.h
index 7d6e556..0872837 100644
--- a/pacman-c++/sceneholder.h
+++ b/pacman-c++/common/sceneholder.h
@@ -25,6 +25,7 @@ public:
25 void setEatingOrder(QList<Color::Color> &order); 25 void setEatingOrder(QList<Color::Color> &order);
26 QList<Color::Color> &eatingOrder(); 26 QList<Color::Color> &eatingOrder();
27 void showEatingText(bool show = true); 27 void showEatingText(bool show = true);
28 void showWaitingForPlayers(bool show = true);
28 29
29signals: 30signals:
30 void allPointsRemoved(); 31 void allPointsRemoved();
diff --git a/pacman-c++/sound/ambient.ogg b/pacman-c++/common/sound/ambient.ogg
index 2919513..2919513 100644
--- a/pacman-c++/sound/ambient.ogg
+++ b/pacman-c++/common/sound/ambient.ogg
Binary files differ
diff --git a/pacman-c++/sound/die.ogg b/pacman-c++/common/sound/die.ogg
index f6af2e0..f6af2e0 100644
--- a/pacman-c++/sound/die.ogg
+++ b/pacman-c++/common/sound/die.ogg
Binary files differ
diff --git a/pacman-c++/sound/eating_fruit.ogg b/pacman-c++/common/sound/eating_fruit.ogg
index 752864a..752864a 100644
--- a/pacman-c++/sound/eating_fruit.ogg
+++ b/pacman-c++/common/sound/eating_fruit.ogg
Binary files differ
diff --git a/pacman-c++/sound/eating_ghost.ogg b/pacman-c++/common/sound/eating_ghost.ogg
index a204a2c..a204a2c 100644
--- a/pacman-c++/sound/eating_ghost.ogg
+++ b/pacman-c++/common/sound/eating_ghost.ogg
Binary files differ
diff --git a/pacman-c++/sound/intro.ogg b/pacman-c++/common/sound/intro.ogg
index d38f16b..d38f16b 100644
--- a/pacman-c++/sound/intro.ogg
+++ b/pacman-c++/common/sound/intro.ogg
Binary files differ
diff --git a/pacman-c++/sound/waka_waka.ogg b/pacman-c++/common/sound/waka_waka.ogg
index def0d96..def0d96 100644
--- a/pacman-c++/sound/waka_waka.ogg
+++ b/pacman-c++/common/sound/waka_waka.ogg
Binary files differ
diff --git a/pacman-c++/style.qss b/pacman-c++/common/style.qss
index 1a24459..1a24459 100644
--- a/pacman-c++/style.qss
+++ b/pacman-c++/common/style.qss
diff --git a/pacman-c++/util.cpp b/pacman-c++/common/util.cpp
index 09b2be1..a3426b6 100644
--- a/pacman-c++/util.cpp
+++ b/pacman-c++/common/util.cpp
@@ -1,5 +1,4 @@
1#include "util.h" 1#include "util.h"
2#include <QtNetwork/QTcpSocket>
3 2
4namespace Util 3namespace Util
5{ 4{
@@ -239,50 +238,36 @@ namespace Util
239 QSharedPointer<QByteArray> createPacket(const ::google::protobuf::MessageLite& packet) 238 QSharedPointer<QByteArray> createPacket(const ::google::protobuf::MessageLite& packet)
240 { 239 {
241 qint64 packetlen = packet.ByteSize(); 240 qint64 packetlen = packet.ByteSize();
242 /* datalen = packet with length prepended */
243 qint64 datalen = sizeof(qint64) + packetlen;
244
245 QSharedPointer<QByteArray> data = QSharedPointer<QByteArray>(new QByteArray); 241 QSharedPointer<QByteArray> data = QSharedPointer<QByteArray>(new QByteArray);
246 data->resize(datalen); 242 data->resize(packetlen);
247
248 /* use QDataStream for length to avoid endianess shit */
249 QDataStream out(data.data(), QIODevice::WriteOnly);
250 out << packetlen;
251 243
252 /* use protobuf.SerializeWithCachedSizesToArray() to avoid calling protobuf.ByteSize() again */ 244 /* use protobuf.SerializeWithCachedSizesToArray() to avoid calling protobuf.ByteSize() again */
253 ::google::protobuf::uint8 *dataptr = reinterpret_cast<google::protobuf::uint8 *>(data->data()); 245 ::google::protobuf::uint8 *dataptr = reinterpret_cast<google::protobuf::uint8 *>(data->data());
254 packet.SerializeWithCachedSizesToArray(dataptr + sizeof(qint64)); 246 packet.SerializeWithCachedSizesToArray(dataptr);
255
256 return data; 247 return data;
257 } 248 }
258 249
259 bool sendPacket(QByteArray *data, QTcpSocket *socket) 250 bool sendPacket(QByteArray *data, ENetPeer *peer, ENetHost *host)
260 { 251 {
261 int bytesWritten = socket->write(*data); 252 ENetPacket *packet = enet_packet_create(data->data(), data->length(), ENET_PACKET_FLAG_RELIABLE);
262 if (bytesWritten != data->size()) 253 if (enet_peer_send(peer, 0, packet) < 0)
263 { 254 {
264 qDebug() << "[sendPacket] Not all data has been sent:" 255 qDebug() << "[sendPacket] Error while sending packet";
265 << "written=" << bytesWritten << ", length=" << data->size();
266 return false; 256 return false;
267 } 257 }
268 socket->flush(); 258 enet_host_flush(host);
269 return true; 259 return true;
270 } 260 }
271 261
272 bool sendPacket(const ::google::protobuf::MessageLite& packet, QTcpSocket *socket) 262 bool sendPacket(const ::google::protobuf::MessageLite& packet, ENetPeer *peer, ENetHost *host)
273 { 263 {
274 return sendPacket(createPacket(packet).data(), socket); 264 return sendPacket(createPacket(packet).data(), peer, host);
275 } 265 }
276 266
277 QSharedPointer<QByteArray> receivePacket(QTcpSocket *socket) 267 QSharedPointer<QByteArray> receivePacket(ENetPacket *packet)
278 { 268 {
279 QDataStream in(socket); 269 const char *pdata = reinterpret_cast<const char *>(packet->data);
280 qint64 datalen; 270 QSharedPointer<QByteArray> data = QSharedPointer<QByteArray>(new QByteArray(pdata, packet->dataLength));
281 in >> datalen;
282
283 QSharedPointer<QByteArray> data = QSharedPointer<QByteArray>(new QByteArray);
284 data->resize(datalen);
285 socket->read(data->data(), data->size());
286 return data; 271 return data;
287 } 272 }
288 273
@@ -301,7 +286,7 @@ namespace Util
301 } 286 }
302 287
303#if 0 288#if 0
304 void hexdump(void *pAddressIn, long lSize) 289 void hexdump(void *pAddressIn, long lSize)
305 { 290 {
306 char szBuf[100]; 291 char szBuf[100];
307 long lIndent = 1; 292 long lIndent = 1;
diff --git a/pacman-c++/util.h b/pacman-c++/common/util.h
index d20eaa5..1ec82b3 100644
--- a/pacman-c++/util.h
+++ b/pacman-c++/common/util.h
@@ -5,7 +5,9 @@
5#include "actor.h" 5#include "actor.h"
6#include "pacman.pb.h" 6#include "pacman.pb.h"
7 7
8class QTcpSocket; 8extern "C" {
9#include "enet/enet.h"
10}
9 11
10namespace Util 12namespace Util
11{ 13{
@@ -24,9 +26,9 @@ namespace Util
24 26
25 /* send packet with error check and flush */ 27 /* send packet with error check and flush */
26 QSharedPointer<QByteArray> createPacket(const ::google::protobuf::MessageLite& packet); 28 QSharedPointer<QByteArray> createPacket(const ::google::protobuf::MessageLite& packet);
27 bool sendPacket(QByteArray *data, QTcpSocket *socket); 29 bool sendPacket(QByteArray *data, ENetPeer *peer, ENetHost *host);
28 bool sendPacket(const ::google::protobuf::MessageLite& packet, QTcpSocket *socket); 30 bool sendPacket(const ::google::protobuf::MessageLite& packet, ENetPeer *peer, ENetHost *host);
29 QSharedPointer<QByteArray> receivePacket(QTcpSocket *socket); 31 QSharedPointer<QByteArray> receivePacket(ENetPacket *packet);
30 32
31 int floorLog2(unsigned int n); 33 int floorLog2(unsigned int n);
32 34
diff --git a/pacman-c++/pacman.pro b/pacman-c++/pacman.pro
index f5187f9..ed5f303 100644
--- a/pacman-c++/pacman.pro
+++ b/pacman-c++/pacman.pro
@@ -1,48 +1,7 @@
1TEMPLATE = app 1TEMPLATE = subdirs
2LANGUAGE = C++ 2SUBDIRS = proto \
3VERSION = 0.1 3 common \
4 client \
5 server
6CONFIG += ordered
4 7
5QT += phonon network
6SOURCES += pixmapitem.cpp \
7 actor.cpp \
8 block.cpp \
9 client.cpp \
10 bonuspoint.cpp \
11 mainwidget.cpp \
12 point.cpp \
13 audio.cpp \
14 clicklabel.cpp \
15 sceneholder.cpp \
16 util.cpp \
17 gameentity.cpp
18HEADERS += pixmapitem.h \
19 actor.h \
20 block.h \
21 client.h \
22 bonuspoint.h \
23 mainwidget.h \
24 constants.h \
25 point.h \
26 audio.h \
27 clicklabel.h \
28 sceneholder.h \
29 util.h \
30 gameentity.h
31RESOURCES += pacman.qrc
32
33OBJECTS_DIR = .obj
34MOC_DIR = .moc
35RC_FILE = pacman.rc
36
37OTHER_FILES += \
38 style.qss \
39 pacman.rc \
40 pacman.proto
41
42PROTOS = pacman.proto
43include(protobuf.pri)
44LIBS += -lprotobuf
45
46CONFIG(release, debug|release) {
47 DEFINES += QT_NO_DEBUG_OUTPUT
48}
diff --git a/pacman-c++/pacman.server.pro b/pacman-c++/pacman.server.pro
deleted file mode 100644
index 0b4c568..0000000
--- a/pacman-c++/pacman.server.pro
+++ /dev/null
@@ -1,50 +0,0 @@
1TEMPLATE = app
2LANGUAGE = C++
3VERSION = 0.1
4DEFINES += SERVER
5
6TARGET = pacman-server
7
8QT += phonon network
9SOURCES += pixmapitem.cpp \
10 actor.cpp \
11 block.cpp \
12 server.cpp \
13 bonuspoint.cpp \
14 point.cpp \
15 audio.cpp \
16 sceneholder.cpp \
17 util.cpp \
18 clicklabel.cpp \
19 gameentity.cpp \
20 anyoption.cpp
21HEADERS += pixmapitem.h \
22 actor.h \
23 block.h \
24 server.h \
25 bonuspoint.h \
26 constants.h \
27 point.h \
28 audio.h \
29 sceneholder.h \
30 util.h \
31 clicklabel.h \
32 gameentity.h \
33 anyoption.h
34RESOURCES += pacman.qrc
35
36OBJECTS_DIR = .obj
37MOC_DIR = .moc
38RC_FILE = pacman.rc
39
40OTHER_FILES += \
41 style.qss \
42 pacman.rc
43
44PROTOS = pacman.proto
45include(protobuf.pri)
46LIBS += -lprotobuf
47
48CONFIG(release, debug|release) {
49 DEFINES += QT_NO_DEBUG_OUTPUT
50}
diff --git a/pacman-c++/pacman.proto b/pacman-c++/proto/pacman.proto
index 8e088e8..8e088e8 100644
--- a/pacman-c++/pacman.proto
+++ b/pacman-c++/proto/pacman.proto
diff --git a/pacman-c++/proto/proto.pro b/pacman-c++/proto/proto.pro
new file mode 100644
index 0000000..7c0b334
--- /dev/null
+++ b/pacman-c++/proto/proto.pro
@@ -0,0 +1,9 @@
1TEMPLATE = lib
2CONFIG += staticlib
3
4include(../common.pri)
5
6PROTOS = pacman.proto
7include(protobuf.pri)
8LIBS += -lprotobuf
9OTHER_FILES += $${PROTOS}
diff --git a/pacman-c++/protobuf.pri b/pacman-c++/proto/protobuf.pri
index 718cb70..718cb70 100644
--- a/pacman-c++/protobuf.pri
+++ b/pacman-c++/proto/protobuf.pri
diff --git a/pacman-c++/rebuild-server.sh b/pacman-c++/rebuild-server.sh
deleted file mode 100755
index 8d2adb9..0000000
--- a/pacman-c++/rebuild-server.sh
+++ /dev/null
@@ -1,4 +0,0 @@
1#!/bin/sh
2#make distclean
3qmake CONFIG+=DEBUG pacman.server.pro -o Makefile.server
4make -f Makefile.server -j2
diff --git a/pacman-c++/rebuild-client.sh b/pacman-c++/rebuild.sh
index 17cf206..58ec7c4 100755
--- a/pacman-c++/rebuild-client.sh
+++ b/pacman-c++/rebuild.sh
@@ -1,4 +1,4 @@
1#!/bin/sh 1#!/bin/sh
2#make distclean 2#make distclean
3qmake CONFIG+=DEBUG pacman.pro 3qmake CONFIG+=debug pacman.pro
4make -j2 4make -j2
diff --git a/pacman-c++/anyoption.cpp b/pacman-c++/server/anyoption.cpp
index 4e3828e..4e3828e 100644
--- a/pacman-c++/anyoption.cpp
+++ b/pacman-c++/server/anyoption.cpp
diff --git a/pacman-c++/anyoption.h b/pacman-c++/server/anyoption.h
index 3f7a5de..3f7a5de 100644
--- a/pacman-c++/anyoption.h
+++ b/pacman-c++/server/anyoption.h
diff --git a/pacman-c++/server.cpp b/pacman-c++/server/server.cpp
index 2311c81..c9e4fff 100644
--- a/pacman-c++/server.cpp
+++ b/pacman-c++/server/server.cpp
@@ -5,13 +5,11 @@
5#include "anyoption.h" 5#include "anyoption.h"
6#include "bonuspoint.h" 6#include "bonuspoint.h"
7#include "point.h" 7#include "point.h"
8#include <QtNetwork/QTcpServer>
9#include <QtNetwork/QTcpSocket>
10#include <QTextStream> 8#include <QTextStream>
11#include <sys/types.h> 9#include <algorithm>
12 10
13Server::Server(QWidget *parent) 11Server::Server(QWidget *parent)
14 : SceneHolder(parent), m_bindaddress(QHostAddress::Any), 12 : SceneHolder(parent), m_host(NULL), m_bindaddress(QHostAddress::Any),
15 m_port(Constants::Networking::port), m_numbots(0), 13 m_port(Constants::Networking::port), m_numbots(0),
16 m_rounds(3), m_curRound(0), m_running(false), m_finishRound(false) 14 m_rounds(3), m_curRound(0), m_running(false), m_finishRound(false)
17{ 15{
@@ -19,9 +17,40 @@ Server::Server(QWidget *parent)
19 for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers); 17 for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers);
20} 18}
21 19
20Server::~Server()
21{
22 if (m_host != NULL)
23 {
24 foreach(ENetPeer *peer, m_clientConnections.keys())
25 enet_peer_disconnect(peer, 0);
26
27 /* allow up to 3 seconds for the disconnect to succeed
28 * and drop any packets received packets
29 */
30 ENetEvent event;
31 while (m_clientConnections.count() > 0
32 && enet_host_service(m_host, &event, 3000) > 0)
33 {
34 switch (event.type)
35 {
36 case ENET_EVENT_TYPE_RECEIVE:
37 enet_packet_destroy(event.packet);
38 break;
39 case ENET_EVENT_TYPE_DISCONNECT:
40 m_clientConnections.remove(event.peer);
41 return;
42 default:
43 break;
44 }
45 }
46
47 enet_host_destroy(m_host);
48 }
49}
50
22bool Server::run() 51bool Server::run()
23{ 52{
24 /* create eating order list first - this can also be created dynamically per round (theoretically) */ 53 /* create eating order list first */
25 for(unsigned int i = 0; i < m_maxplayers; ++i) 54 for(unsigned int i = 0; i < m_maxplayers; ++i)
26 m_eatingorder.append(Color::order[i]); 55 m_eatingorder.append(Color::order[i]);
27 m_eatingorder.append(m_eatingorder.at(0)); 56 m_eatingorder.append(m_eatingorder.at(0));
@@ -55,6 +84,9 @@ void Server::tick()
55 return; 84 return;
56 } 85 }
57 86
87 /* fetch key updates */
88 keyPressUpdate();
89
58 /* let the bots move */ 90 /* let the bots move */
59 foreach (Color::Color color, m_bots) 91 foreach (Color::Color color, m_bots)
60 botCalculate(m_actors[color]); 92 botCalculate(m_actors[color]);
@@ -356,42 +388,64 @@ void Server::colorizeBlocks(Transmission::map_t map)
356bool Server::waitForClientConnections() 388bool Server::waitForClientConnections()
357{ 389{
358 // server must stay alive as long as sockets (qt parent mem mechanism) 390 // server must stay alive as long as sockets (qt parent mem mechanism)
359 QTcpServer *tcpSrv = new QTcpServer(this); 391 ENetAddress address;
360 tcpSrv->listen(m_bindaddress, m_port); 392 address.host = ENET_HOST_ANY;
361 if (!tcpSrv->isListening()) 393 if (m_bindaddress != QHostAddress::Any)
394 enet_address_set_host(&address, qPrintable(m_bindaddress.toString()));
395 address.port = m_port;
396
397 m_host = enet_host_create(&address, m_maxplayers - m_numbots, 1, 0, 0);
398 if (m_host == NULL)
362 { 399 {
363 qCritical() << "Error while creating socket:" << qPrintable(tcpSrv->errorString()); 400 qCritical() << "An error occurred while trying to create an ENet server host";
364 return false; 401 return false;
365 } 402 }
366 std::cout << "[Server] Listening on: "
367 << qPrintable(QString("%1:%2").arg(tcpSrv->serverAddress().toString())
368 .arg(tcpSrv->serverPort())) << std::endl;
369 403
370 std::cout << "[Server] Waiting for clients" << std::endl; 404 char buf[1024];
371 ProtoBuf::Init packet; 405 enet_address_get_host_ip(&m_host->address, buf, 1024);
372 packet.set_maxplayers(m_maxplayers); 406 std::cout << "[Server] Listening on: "
373 for (unsigned int i = 0; i < (m_maxplayers - m_numbots); ++i) 407 << qPrintable(QString("%1:%2").arg(buf).arg(m_host->address.port)) << std::endl;
374 {
375 bool connectionAvailable = tcpSrv->waitForNewConnection(-1);
376 Q_ASSERT(connectionAvailable);
377 Q_UNUSED(connectionAvailable);
378 QTcpSocket *socket = tcpSrv->nextPendingConnection();
379 connect(socket, SIGNAL(readyRead()), this, SLOT(keyPressUpdate()));
380
381 /* assign color and notify client */
382 Color::Color color = Color::order[i];
383 m_clientConnections[color] = socket;
384 packet.set_color(color);
385 Util::sendPacket(packet, socket);
386 std::cout << "[Connect] New Player: color=" << qPrintable(Util::colorToString(color)) << std::endl;
387 }
388 408
409 /* add bots first */
389 for (unsigned int i = (m_maxplayers - m_numbots); i < m_maxplayers; ++i) 410 for (unsigned int i = (m_maxplayers - m_numbots); i < m_maxplayers; ++i)
390 { 411 {
391 m_bots.append(Color::order[i]); 412 m_bots.append(Color::order[i]);
392 m_actorMovements[Color::order[i]] = Actor::None; 413 m_actorMovements[Color::order[i]] = Actor::None;
393 } 414 }
394 415
416 std::cout << "[Server] Waiting for clients" << std::endl;
417 ProtoBuf::Init packet;
418 packet.set_maxplayers(m_maxplayers);
419 unsigned int i = 0;
420 while(m_clientConnections.count() < int(m_maxplayers - m_numbots))
421 {
422 ENetEvent event;
423 if (enet_host_service(m_host, &event, 3000) > 0)
424 {
425 switch (event.type)
426 {
427 case ENET_EVENT_TYPE_CONNECT:
428 {
429 /* assign color and notify client */
430 Color::Color color = Color::order[i++];
431 m_clientConnections[event.peer] = color;
432 packet.set_color(color);
433 Util::sendPacket(packet, event.peer, m_host);
434 std::cout << "[Connect] New Player: color=" << qPrintable(Util::colorToString(color)) << std::endl;
435 }
436 break;
437 case ENET_EVENT_TYPE_RECEIVE:
438 keyPressUpdate(&event);
439 break;
440 case ENET_EVENT_TYPE_DISCONNECT:
441 keyPressUpdate(&event);
442 break;
443 default:
444 break;
445 }
446 }
447 }
448
395 qDebug() << "[Server] All Clients connected"; 449 qDebug() << "[Server] All Clients connected";
396 return true; 450 return true;
397} 451}
@@ -420,19 +474,18 @@ void Server::sendUpdate(Transmission::map_t map, bool firstPacket)
420 } 474 }
421 475
422 QSharedPointer<QByteArray> data = Util::createPacket(m_updatepacket); 476 QSharedPointer<QByteArray> data = Util::createPacket(m_updatepacket);
423 QMutableMapIterator<Color::Color, QTcpSocket *> i(m_clientConnections); 477 QMutableMapIterator<ENetPeer *, Color::Color> i(m_clientConnections);
424 while(i.hasNext()) 478 while(i.hasNext())
425 { 479 {
426 i.next(); 480 i.next();
427 QTcpSocket *socket = i.value(); 481 ENetPeer *peer = i.key();
428 482
429 if (!Util::sendPacket(data.data(), socket)) 483 if (!Util::sendPacket(data.data(), peer, m_host))
430 { 484 {
431 qWarning() << "[Connect] Error while sending data to client" << i.key() << "-> Disconnecting..."; 485 qWarning() << "[Connect] Error while sending data to client" << i.value() << "-> Disconnecting...";
432 socket->close(); 486 std::cout << "[Connect] Actor color=" << qPrintable(Util::colorToString(i.value()))
433 std::cout << "[Connect] Actor color=" << qPrintable(Util::colorToString(i.key()))
434 << " is now a bot" << std::endl; 487 << " is now a bot" << std::endl;
435 m_bots.append(i.key()); 488 m_bots.append(i.value());
436 ++m_numbots; 489 ++m_numbots;
437 i.remove(); 490 i.remove();
438 } 491 }
@@ -576,23 +629,41 @@ void Server::botCalculate(Actor *actor)
576void Server::keyPressUpdate() 629void Server::keyPressUpdate()
577{ 630{
578 ProtoBuf::KeyPressUpdate packet; 631 ProtoBuf::KeyPressUpdate packet;
579 QMapIterator<Color::Color, QTcpSocket *> i(m_clientConnections); 632 ENetEvent event;
580 while (i.hasNext()) 633 while (enet_host_service(m_host, &event, 1) > 0)
634 keyPressUpdate(&event);
635}
636
637void Server::keyPressUpdate(ENetEvent *event)
638{
639 ProtoBuf::KeyPressUpdate packet;
640 switch(event->type)
581 { 641 {
582 i.next(); 642 case ENET_EVENT_TYPE_RECEIVE:
583 Color::Color color = i.key();
584 QTcpSocket *socket = i.value();
585 QDataStream in(i.value());
586 while (socket->bytesAvailable() > (qint64)sizeof(qint64))
587 { 643 {
588 QSharedPointer<QByteArray> data = Util::receivePacket(socket); 644 QSharedPointer<QByteArray> data = Util::receivePacket(event->packet);
645 enet_packet_destroy(event->packet);
589 bool worked = packet.ParseFromArray(data->data(), data->size()); 646 bool worked = packet.ParseFromArray(data->data(), data->size());
590 Q_ASSERT(worked); 647 Q_ASSERT(worked);
591 Q_UNUSED(worked); 648 Q_UNUSED(worked);
592 Transmission::field_t direction = packet.newkey(); 649 Transmission::field_t direction = packet.newkey();
650 Color::Color color = m_clientConnections[event->peer];
593 qDebug() << "[KeyPress] actor=" << color << "direction=" << direction; 651 qDebug() << "[KeyPress] actor=" << color << "direction=" << direction;
594 m_actorMovements[color] = Util::transmissionMovementToActor(direction); 652 m_actorMovements[color] = Util::transmissionMovementToActor(direction);
595 } 653 }
654 break;
655 case ENET_EVENT_TYPE_DISCONNECT:
656 {
657 Color::Color color = m_clientConnections[event->peer];
658 std::cout << "[Connect] Actor color=" << qPrintable(Util::colorToString(color))
659 << " is now a bot" << std::endl;
660 m_bots.append(color);
661 ++m_numbots;
662 m_clientConnections.remove(event->peer);
663 }
664 break;
665 default:
666 break;
596 } 667 }
597} 668}
598 669
diff --git a/pacman-c++/server.h b/pacman-c++/server/server.h
index 41b800e..857f23d 100644
--- a/pacman-c++/server.h
+++ b/pacman-c++/server/server.h
@@ -5,7 +5,11 @@
5#include "actor.h" 5#include "actor.h"
6#include "pacman.pb.h" 6#include "pacman.pb.h"
7#include <QtGui> 7#include <QtGui>
8#include <QHostAddress> 8#include <QtNetwork/QHostAddress>
9
10extern "C" {
11#include "enet/enet.h"
12}
9 13
10class QTcpSocket; 14class QTcpSocket;
11 15
@@ -15,6 +19,7 @@ class Server
15 Q_OBJECT 19 Q_OBJECT
16public: 20public:
17 Server(QWidget *parent = 0); 21 Server(QWidget *parent = 0);
22 ~Server();
18 bool parseCommandline(); 23 bool parseCommandline();
19 bool run(); 24 bool run();
20 25
@@ -23,6 +28,7 @@ protected slots:
23 28
24 /* receive updates of client */ 29 /* receive updates of client */
25 void keyPressUpdate(); 30 void keyPressUpdate();
31 void keyPressUpdate(ENetEvent *event);
26 32
27protected: 33protected:
28 /* block until we have connections from all clients */ 34 /* block until we have connections from all clients */
@@ -46,7 +52,8 @@ protected slots:
46 void setFinishRound(); 52 void setFinishRound();
47 53
48protected: 54protected:
49 QMap<Color::Color, QTcpSocket *> m_clientConnections; 55 ENetHost *m_host;
56 QMap<ENetPeer *, Color::Color> m_clientConnections;
50 QList<Color::Color> m_bots; 57 QList<Color::Color> m_bots;
51 58
52 /* current movements. required to make pacmans continue their movement */ 59 /* current movements. required to make pacmans continue their movement */
diff --git a/pacman-c++/server/server.pro b/pacman-c++/server/server.pro
new file mode 100644
index 0000000..05d5c9d
--- /dev/null
+++ b/pacman-c++/server/server.pro
@@ -0,0 +1,10 @@
1TEMPLATE = app
2TARGET = pacman-server
3
4SOURCES += anyoption.cpp \
5 server.cpp
6HEADERS += anyoption.h \
7 server.h
8
9include(../common.pri)
10PRE_TARGETDEPS += ../common/libcommon.a