00001 #include <stdlib.h>
00002 #include <vector>
00003 #include <iostream>
00004 #include <assert.h>
00005
00006 #include "menu/widgets.h"
00007
00008 #include <time.h>
00009
00010 #include "opengl.h"
00011 #include "input/Input.h"
00012 #include "resources/resources.h"
00013 #include "textures.h"
00014
00015 #include "math/random.h"
00016 #include "client.h"
00017
00018 #include "connectmenu.h"
00019
00020 #include "net/MMNet.h"
00021 #include "LobbyGS.h"
00022
00023
00024 using namespace MMGUI;
00025 using namespace MMNet;
00026 using namespace TNL;
00027 using namespace std;
00028
00029
00030
00031
00032 static GameState *thisGS;
00033 static ConnectMenu *CM;
00034 static bool connecting;
00035
00036 static char *Names[] = { "Prince John",
00037 "King Richard",
00038 "Blinkin",
00039 "Ahchoo",
00040 "Will Scarlet",
00041 "Dirty Ezio",
00042 "Rabbi Tuckman",
00043 NULL };
00044 #define NAME_COUNT 11
00045
00046 static void joinGameManually(const char *);
00047 static void joinButtonServer(const char *);
00048 static void findServers(const char *);
00049
00050 static void toMainMenu(const char *) {
00051 setGameState(MAIN_MENU);
00052 }
00053
00054 static void enterLobby() {
00055
00056 setGameState(new LobbyGS(thisGS->client));
00057 }
00058
00059 static ConnectMenu * cm;
00060 static ConnectMenuCallback *cb;
00061
00062 ConnectMenu::ConnectMenu(NetClient *client) : GameState(client) {
00063
00064
00065
00066
00067 cb = new ConnectMenuCallback(cm);
00068
00069 assert(client != NULL);
00070
00071 }
00072
00073
00074 bool ConnectMenu::findingServers() {
00075 return canFindAgain >= time(NULL);
00076 }
00077
00078 void ConnectMenu::init() {
00079 thisGS = this;
00080 CM = this;
00081 client->setNetCallback(cb);
00082
00083 canFindAgain = 0;
00084
00085 menuInit();
00086 Frame *pane = new Frame(WidgetAlignCenter, 800, 600);
00087 getRoot()->addChild(pane);
00088
00089
00090 Button *button = new Button(WidgetAlignBottomLeft, 100, 50);
00091 button->setUpImage(TEXTURE_EXIT_BUTTON);
00092 button->setDownImage(TEXTURE_EXIT_BUTTON_ON);
00093 button->setOverImage(TEXTURE_EXIT_BUTTON_OVER);
00094 button->setClickFunction(toMainMenu);
00095 pane->addChild(button);
00096
00097
00098 Frame *frame = new Frame(WidgetAlignTop, 150, 70);
00099 frame->setBorderColor(0.25, 0.1, 0);
00100 frame->setBorder(1);
00101 pane->addChild(frame);
00102
00103
00104 Textfield *label = new Textfield(0, 30, 150, 20);
00105 label->setText("Player Name");
00106 label->setFontColor(0, 1, 0);
00107 label->alignCenter();
00108 frame->addChild(label);
00109
00110
00111 nameField = new Textbox(0, 50, 150, 20);
00112 nameField->alignCenter();
00113 nameField->setBGColor(0, 0.2, 0);
00114 frame->addChild(nameField);
00115
00116
00117 mmsrand(time(NULL));
00118 char *name = Names[mmrand() % sizeof(NAME_COUNT)];
00119 nameField->setText(name);
00120
00121
00122 frame = new Frame(WidgetAlignCenter, 700, 300);
00123 frame->setMargin(5);
00124 pane->addChild(frame);
00125
00126 frame->addChild(initServerListFrame(WidgetAlignTopRight));
00127 frame->addChild(initFindServersFrame(WidgetAlignTopLeft));
00128 frame->addChild(initManualConnectFrame(WidgetAlignBottomLeft));
00129 frame->addChild(initMessageFrame(WidgetAlignBottomRight));
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 glutPostRedisplay();
00178 }
00179
00180 void ConnectMenu::serverListClear() {
00181 serverFrame->clearChildren();
00182 serverFrame->setBorderColor(0.1, 0.1, 0.1);
00183
00184 Textfield *label = new Textfield(WidgetAlignTop, serverFrame->content_width(), 20);
00185 label->alignCenter();
00186 label->setText("Servers Located");
00187 label->setFontColor(0.4, 0.4, 0.4);
00188 serverFrame->addChild(label);
00189
00190 glutPostRedisplay();
00191
00192 }
00193
00194 void ConnectMenu::serverListAdd(Address addr) {
00195 int count = serverFrame->numChildren();
00196
00197
00198 if(count == 1) {
00199 serverFrame->setBorderColor(0, 0.5, 0);
00200 }
00201
00202
00203 if(count > 5) {
00204 return;
00205 }
00206
00207 TextButton *button = new TextButton(addr.toString(), 0, 15 + (25 * count), serverFrame->content_width(), 22);
00208 button->setClickFunction(joinButtonServer);
00209
00210 button->setColorUp(0, 0.2, 0);
00211 button->setColorDown(0, 1, 0);
00212 button->setColorOver(0, 0.6, 0);
00213
00214 serverFrame->addChild(button);
00215 glutPostRedisplay();
00216 }
00217
00218 void ConnectMenu::setMessage(const char *text) {
00219 messages->setText(text);
00220 glutPostRedisplay();
00221 }
00222
00223 void clearMessage() {
00224
00225 glutPostRedisplay();
00226 }
00227
00228 Frame *ConnectMenu::initServerListFrame(enum WidgetAlign align) {
00229 int width = 330;
00230 int height = 140;
00231
00232 serverFrame = new Frame(align, width, height);
00233 serverFrame->setBorderColor(0.25, 0.1, 0);
00234 serverFrame->setMargin(4);
00235 serverFrame->setBorder(2);
00236
00237 serverListClear();
00238
00239 return serverFrame;
00240 }
00241
00242 Frame *ConnectMenu::initMessageFrame(enum WidgetAlign align) {
00243 int width = 330;
00244 int height = 140;
00245
00246 Frame *frame = new Frame(align, width, height);
00247 frame->setBorderColor(0.25, 0.1, 0);
00248 frame->setMargin(4);
00249 frame->setBorder(2);
00250
00251 Textfield *label = new Textfield(WidgetAlignTop, width, 15);
00252 label->alignCenter();
00253 label->setText("Messages:");
00254 label->setFontColor(0,1,0);
00255 frame->addChild(label);
00256
00257 messages = new Textfield(0, 20, width, height);
00258 messages->alignLeft();
00259 messages->setBGColor(0, 0.3, 0);
00260 messages->setFontColor(1,1,1);
00261 frame->addChild(messages);
00262
00263 return frame;
00264 }
00265
00266 Frame *ConnectMenu::initFindServersFrame(enum WidgetAlign align) {
00267 int width = 330;
00268 int height = 140;
00269
00270 Frame *frame = new Frame(align, width, height);
00271 frame->setBorderColor(0.25, 0.1, 0);
00272 frame->setMargin(4);
00273 frame->setBorder(2);
00274
00275 Textfield *label = new Textfield(WidgetAlignTop, width, 15);
00276 label->alignCenter();
00277 label->setText("Locate Servers");
00278 label->setFontColor(0,1,0);
00279 frame->addChild(label);
00280
00281 findButton = new Button(WidgetAlignCenter, 100, 50);
00282 findButton->setUpImage(TEXTURE_FIND_BUTTON);
00283 findButton->setDownImage(TEXTURE_FIND_BUTTON_ON);
00284 findButton->setOverImage(TEXTURE_FIND_BUTTON_OVER);
00285 findButton->setClickFunction(findServers);
00286 frame->addChild(findButton);
00287
00288 return frame;
00289 }
00290
00291 Frame *ConnectMenu::initManualConnectFrame(enum WidgetAlign align) {
00292 int width = 330;
00293 int height = 140;
00294
00295 Frame *frame = new Frame(align, width, height);
00296 frame->setBorderColor(0.25, 0.1, 0);
00297 frame->setMargin(4);
00298 frame->setBorder(2);
00299
00300 Textfield *label = new Textfield(WidgetAlignTop, width, 20);
00301 label->alignCenter();
00302 label->setText("Manual Connect");
00303 label->setFontColor(0,1,0);
00304 frame->addChild(label);
00305
00306 label = new Textfield(0, 40, 80, 20);
00307 label->alignRight();
00308 label->setText("Address: ");
00309 frame->addChild(label);
00310
00311 manualField = new Textbox(80, 40, 200, 20);
00312 manualField->setBGColor(0, 0.2, 0);
00313 manualField->alignLeft();
00314 manualField->setText("127.0.0.1:28000");
00315 frame->addChild(manualField);
00316
00317 Button *button = new Button(WidgetAlignBottom, 100, 50);
00318 button->setUpImage(TEXTURE_CONNECT_BUTTON);
00319 button->setDownImage(TEXTURE_CONNECT_BUTTON_ON);
00320 button->setOverImage(TEXTURE_CONNECT_BUTTON_OVER);
00321 button->setClickFunction(joinGameManually);
00322 frame->addChild(button);
00323
00324 return frame;
00325 }
00326
00327
00328 void ConnectMenu::display(void) {
00329 glClearColor(0,0,0,0);
00330 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00331
00332 MMGUI::menuDraw();
00333
00334 glutSwapBuffers();
00335 }
00336
00337 void ConnectMenu::update(void) {
00338 if(findButton->isDisabled() && findingServers() == false) {
00339 findButton->setDisabled(false);
00340 setMessage("Done.");
00341 glutPostRedisplay();
00342 }
00343 }
00344
00345 void ConnectMenu::exit() {
00346 client->setNetCallback(NULL);
00347 MMGUI::menuClear();
00348 }
00349
00350 static void findServers(const char *text) {
00351 if(CM->findingServers()) {
00352 CM->setMessage("Already locating servers...");
00353 return;
00354 }
00355 CM->canFindAgain = time(NULL) + 5;
00356 CM->serverListClear();
00357 CM->setMessage("Locating servers...");
00358 CM->findButton->setDisabled(true);
00359
00360 thisGS->client->setNetCallback(cb);
00361 thisGS->client->findServers(Address(IPProtocol, Address::Broadcast, 28000));
00362 }
00363
00364
00365
00366 void ConnectMenu::createServerList(const char * serverName) {
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 }
00380
00381
00382 void ConnectMenu::joinGame(Address addr) {
00383
00384 if(connecting) {
00385
00386 return;
00387 }
00388 connecting = true;
00389
00390
00391
00392
00393
00394
00395
00396
00397 string playername = nameField->getText(0);
00398 if (playername.length() <= 0) {
00399 playername = "Little John";
00400 }
00401
00402
00403
00404 client->connectToServer(addr, playername.c_str());
00405
00406 }
00407
00408 static void joinGameManually(const char *) {
00409
00410 string addr = "IP:" + CM->manualField->getText(0);
00411
00412 CM->joinGame(Address(addr.c_str()));
00413 }
00414
00415 static void joinButtonServer(const char *str) {
00416 TNL::Address addr(str);
00417 CM->serverListClear();
00418 CM->joinGame(addr);
00419 CM->setMessage("Joining game. Please be patient.");
00420 }
00421
00422
00424
00425 static string status;
00426 ConnectMenuCallback::ConnectMenuCallback(ConnectMenu * cm) {
00427 this->cm = cm;
00428 }
00429
00430 void ConnectMenuCallback::ServerDiscovered(TNL::Address serverAddress, TNL::BitStream *stream) {
00431 cout << "Server discovered at " << serverAddress.toString() << endl;
00432 CM->serverListAdd(serverAddress);
00433 }
00434
00435 void ConnectMenuCallback::JoinApproved(TNL::Address serverAddress, TNL::BitStream *stream) {
00436 cout << "Server at " << serverAddress.toString() << " approved join attempt." << endl;
00437 status = "Server at ";
00438 status += serverAddress.toString();
00439 status += " approved join attempt.";
00440
00441
00442 connecting = false;
00443 }
00444
00445 void ConnectMenuCallback::JoinDenied(TNL::Address serverAddress, TNL::BitStream *stream) {
00446 cout << "Server at " << serverAddress.toString() << " denied join attempt." << endl;
00447 status = "Server at " +(string)serverAddress.toString() +" denied join attempt.";
00448
00449 connecting = false;
00450 }
00451
00452 void ConnectMenuCallback::GameConnectionFailed(const char *errmsg) {
00453 cout << "Attempt to establish connection failed - " << errmsg << endl;
00454 status = "Attempt to establish connection failed - " + (string)errmsg;
00455 CM->setMessage( (char*)status.c_str());
00456 connecting = false;
00457 }
00458
00459 void ConnectMenuCallback::GameConnectionEstablished(TNL::Address serverAddress) {
00460 cout << "Connection to " << serverAddress.toString() << " established." << endl;
00461 status = "Connection to " +(string)serverAddress.toString() + " established.";
00462 CM->setMessage( status.c_str());
00463 enterLobby();
00464 }
00465
00466 void ConnectMenuCallback::GameDisconnected(TNL::NetConnection::TerminationReason reason, const char *edString) {
00467 cout << "Game over - " << reason << ": " << edString << endl;
00468 status = "Game over - " + (string)edString;
00469 CM->setMessage(status.c_str());
00470 }