1 /////////////////////////////////////////
2 //
3 //             OpenLieroX
4 //
5 // code under LGPL, based on JasonBs work,
6 // enhanced by Dark Charlie and Albert Zeyer
7 //
8 //
9 /////////////////////////////////////////
10 
11 
12 // Net menu - Joining
13 // Created 25/8/02
14 // Jason Boettcher
15 
16 
17 
18 
19 #include "LieroX.h"
20 #include "Sounds.h"
21 #include "CClient.h"
22 #include "DeprecatedGUI/Graphics.h"
23 #include "DeprecatedGUI/Menu.h"
24 #include "GfxPrimitives.h"
25 #include "StringUtils.h"
26 #include "CWorm.h"
27 #include "Protocol.h"
28 #include "DeprecatedGUI/CButton.h"
29 #include "DeprecatedGUI/CTextbox.h"
30 #include "DeprecatedGUI/CImage.h"
31 #include "DeprecatedGUI/CCheckbox.h"
32 #include "DeprecatedGUI/CLabel.h"
33 #include "DeprecatedGUI/CTextButton.h"
34 #include "DeprecatedGUI/CProgressbar.h"
35 #include "DeprecatedGUI/CBrowser.h"
36 #include "AuxLib.h"
37 #include "CClientNetEngine.h"
38 #include "Debug.h"
39 #include "console.h"
40 #include "DeprecatedGUI/CChatWidget.h"
41 
42 
43 namespace DeprecatedGUI {
44 
45 /*
46    Joining is broken into 2 parts:
47    1) Joining the server
48    2) If we succeeded in join, the lobby
49 */
50 
51 
52 // Joining menu's
53 enum {
54 	//join_players=0,
55 	join_connecting=0,
56 	join_lobby
57 };
58 
59 int		iJoinMenu = join_connecting;
60 std::string	sJoinAddress;
61 
62 
63 ///////////////////
64 // Join a server
Menu_Net_JoinInitialize(const std::string & sAddress)65 bool Menu_Net_JoinInitialize(const std::string& sAddress)
66 {
67 	iNetMode = net_join;
68 	iJoinMenu = join_connecting;
69 	sJoinAddress = sAddress;
70 
71 	if(!Menu_Net_JoinConnectionInitialize(sAddress)) {
72 		// Error
73 		return false;
74 	}
75 
76 
77 	return true;
78 }
79 
80 
81 ///////////////////
82 // Main join frame
Menu_Net_JoinFrame(int mouse)83 void Menu_Net_JoinFrame(int mouse)
84 {
85 	switch(iJoinMenu) {
86 
87 		// Select players
88 /*		case join_players:
89 			Menu_Net_JoinPlayersFrame(mouse);
90 			break;*/
91 
92 		// Connecting
93 		case join_connecting:
94 			Menu_Net_JoinConnectionFrame(mouse);
95 			break;
96 
97 		// Lobby
98 		case join_lobby:
99 			Menu_Net_JoinLobbyFrame(mouse);
100 			break;
101 	}
102 }
103 
Menu_Net_JoinShutdown()104 void Menu_Net_JoinShutdown()
105 {
106 	Menu_Net_JoinConnectionShutdown();
107 	Menu_Net_JoinLobbyShutdown();
108 }
109 
110 
111 
112 
113 
114 
115 /*
116 
117    Connect to the server
118 
119 */
120 
121 
122 static CGuiLayout cConnecting;
123 static Timer *cConnectingScreenUpdate = NULL;
124 
125 enum {
126 	cm_Cancel=0
127 };
128 
129 
130 ///////////////////
131 // Initialize the connection menu
Menu_Net_JoinConnectionInitialize(const std::string & sAddress)132 bool Menu_Net_JoinConnectionInitialize(const std::string& sAddress)
133 {
134 	iJoinMenu = join_connecting;
135 	tLX->iGameType = GME_JOIN;
136 	sJoinAddress = sAddress;
137 	cConnecting.Shutdown();
138 	cConnecting.Initialize();
139 
140 	cConnecting.Add( new CButton(BUT_CANCEL, tMenu->bmpButtons),	cm_Cancel, 	25, 440, 75,15);
141 
142     Menu_redrawBufferRect(0, 0, 640, 480);
143 	if (!cConnectingScreenUpdate)
144 		cConnectingScreenUpdate = new Timer("Connecting...", null, NULL, 250, false);
145 	cConnectingScreenUpdate->start();
146 
147 	return true;
148 }
149 
Menu_Net_JoinConnectionShutdown()150 void Menu_Net_JoinConnectionShutdown()
151 {
152 	cConnectingScreenUpdate->stop();
153 	cConnecting.Shutdown();
154 }
155 
156 
157 ///////////////////
158 // Connection frame
Menu_Net_JoinConnectionFrame(int mouse)159 void Menu_Net_JoinConnectionFrame(int mouse)
160 {
161 	gui_event_t *ev = NULL;
162 
163 	Menu_redrawBufferRect(0,180,640,tLX->cFont.GetHeight());
164 
165 	// Process the client frame
166 	tLX->cFont.DrawCentre(VideoPostProcessor::videoSurface(), 320, 180, tLX->clNormalLabel, "Connecting to " + cClient->getServerAddr_HumanReadable());
167 	cClient->Frame();
168 
169 
170 	// Connected??
171 	if(cClient->getStatus() == NET_CONNECTED) {
172 
173 		// Leave this connection screen & go to the lobby
174 		Menu_Net_JoinConnectionShutdown();
175 
176 		if(!Menu_Net_JoinLobbyInitialize()) {
177 			// Error
178 			Menu_Net_MainInitialize();
179 		}
180 		return;
181 	}
182 
183 	// Check for a bad connection
184 	if(cClient->getBadConnection()) {
185 		warnings << "Bad connection: " << cClient->getBadConnectionMsg() << endl;
186 		Menu_MessageBox("Connection Error", cClient->getBadConnectionMsg(), LMB_OK);
187 
188 		cClient->Shutdown();
189 
190 		// Shutdown
191 		Menu_Net_JoinConnectionShutdown();
192 		Menu_NetInitialize();
193 		return;
194 	}
195 
196 
197 	// Process & Draw the gui
198 	ev = cConnecting.Process();
199 	cConnecting.Draw( VideoPostProcessor::videoSurface() );
200 
201 
202 	// Process any events
203 	if(ev) {
204 
205 		switch(ev->iControlID) {
206 
207 			// Cancel
208 			case cm_Cancel:
209 				if(ev->iEventMsg == BTN_CLICKED) {
210 
211 					// Click!
212 					PlaySoundSample(sfxGeneral.smpClick);
213 
214 					// Shutdown
215 					Menu_Net_JoinConnectionShutdown();
216 
217 					Menu_NetInitialize();
218 				}
219 				break;
220 		}
221 	}
222 
223 
224 	// Draw the mouse
225 	DrawCursor(VideoPostProcessor::videoSurface());
226 }
227 
228 
229 
230 
231 
232 
233 
234 /*
235 
236    Join lobby
237 
238 */
239 
240 CGuiLayout	cJoinLobby;
241 int			iJoinSpeaking = 0;
242 bool		bJoin_Update = true;
243 enum {
244 	jl_Back=0,
245 	jl_Ready,
246 	jl_ChatText,
247 	jl_ChatList,
248 	jl_Favourites,
249 	jl_PlayerList,
250 	jl_Details,
251 	jl_CancelDownload,
252 	jl_DownloadProgress,
253 	jl_DownloadMap,
254 	jl_DownloadMod,
255 	jl_More,
256 	jl_Less
257 };
258 
259 
260 
261 ///////////////////
262 // Initialize the joining lobby
Menu_Net_JoinLobbyInitialize()263 bool Menu_Net_JoinLobbyInitialize()
264 {
265     Menu_Net_JoinDrawLobby();
266 
267     Menu_Net_JoinLobbyCreateGui();
268 
269 	// Add the chat
270 	CBrowser *lv = (CBrowser *)cJoinLobby.getWidget(jl_ChatList);
271 	if (lv)  {
272 		lv->InitializeChatBox();
273 		CChatBox *Chatbox = cClient->getChatbox();
274 		lines_iterator it = Chatbox->Begin();
275 
276 		// Copy the chat text
277 		for ( ; it != Chatbox->End(); it++ )  {
278 			lv->AddChatBoxLine(it->strLine, it->iColour, it->iTextType);
279 		}
280 	}
281 
282 	iNetMode = net_join;
283 	iJoinMenu = join_lobby;
284 
285 	cClient->getChatbox()->Clear();
286 	iJoinSpeaking = 0; // The first player is always speaking
287 	tMenu->sSavedChatText = "";
288 
289 	tLX->iGameType = GME_JOIN;
290 
291 	return true;
292 }
293 
294 ////////////////////
295 // Shutdown the join lobby
Menu_Net_JoinLobbyShutdown()296 void Menu_Net_JoinLobbyShutdown()
297 {
298 	if (cClient)
299 		cClient->Disconnect();
300 
301 	cJoinLobby.Shutdown();
302 
303 	if (cClient)
304 		cClient->Shutdown();
305 
306 	tMenu->sSavedChatText = "";
307 }
308 
309 
310 ///////////////////
311 // Draw the join lobby
Menu_Net_JoinDrawLobby()312 void Menu_Net_JoinDrawLobby()
313 {
314 	// Create the buffer
315 	DrawImage(tMenu->bmpBuffer.get(),tMenu->bmpMainBack_common,0,0);
316 	if (tMenu->tFrontendInfo.bPageBoxes)
317 		Menu_DrawBox(tMenu->bmpBuffer.get(), 5,5, 635, 475);
318 
319     // Title
320     DrawImageAdv(tMenu->bmpBuffer.get(), tMenu->bmpMainBack_common, 281,0, 281,0, 79,20);
321     tLX->cFont.DrawCentre(tMenu->bmpBuffer.get(), 320, -1, tLX->clNormalLabel, "[  Lobby  ]");
322 
323 	// Chat box
324     DrawRectFill(tMenu->bmpBuffer.get(), 16, 270, 624, 417, tLX->clChatBoxBackground);
325 
326 	Menu_RedrawMouse(true);
327 }
328 
329 static void updateDetailsList(CListview* l);
330 
initDetailsList(CListview * l)331 static void initDetailsList(CListview* l) {
332 #define SUBS(title)	l->AddSubitem(LVS_TEXT, title, (DynDrawIntf*)NULL, NULL); l->AddSubitem(LVS_TEXT, "", (DynDrawIntf*)NULL, NULL);
333 	int index = 0;
334 	l->Clear();
335 	l->AddItem("servername", index++, tLX->clNormalLabel); SUBS("Server name:");
336 	l->AddItem("level", index++, tLX->clNormalLabel); SUBS("Level:");
337 	if (tMenu->bmpDownload.get())  {
338 		CImage *img = new CImage(tMenu->bmpDownload);
339 		img->Setup(jl_DownloadMap, 0, 0, img->getWidth(), img->getHeight());
340 		l->AddSubitem(LVS_WIDGET, "", (DynDrawIntf*)NULL, img);
341 	}
342 	l->AddItem("gamemode", index++, tLX->clNormalLabel); SUBS("Game Mode:");
343 	l->AddItem("mod", index++, tLX->clNormalLabel); SUBS("Mod:");
344 	if (tMenu->bmpDownload.get())  {
345 		CImage *img = new CImage(tMenu->bmpDownload);
346 		img->Setup(jl_DownloadMod, 0, 0, img->getWidth(), img->getHeight());
347 		l->AddSubitem(LVS_WIDGET, "", (DynDrawIntf*)NULL, img);
348 	}
349 	l->AddItem("lives", index++, tLX->clNormalLabel); SUBS("Lives:");
350 	l->AddItem("maxkills", index++, tLX->clNormalLabel); SUBS("Max Kills:");
351 	l->AddItem("timelimit", index++, tLX->clNormalLabel); SUBS("Timelimit:");
352 	l->AddItem("loadingtime", index++, tLX->clNormalLabel); SUBS("Loading time:");
353 	l->AddItem("bonuses", index++, tLX->clNormalLabel); SUBS("Bonuses:");
354 
355 	if (tLXOptions->bAdvancedLobby)  {
356 		l->AddItem("serverversion", index++, tLX->clNormalLabel); SUBS("Server version:");
357 	} else {
358 		// More button
359 		lv_item_t *it = l->AddItem("more", index++, tLX->clNormalLabel);
360 		l->AddSubitem(LVS_TEXT, "", (DynDrawIntf*)NULL, NULL);
361 		CButton *more = new CButton(BUT_MORE, tMenu->bmpButtons);
362 		more->setID(jl_More);
363 		more->Create();
364 		it->iHeight = more->getHeight() + 10;
365 		l->AddSubitem(LVS_WIDGET, "", (DynDrawIntf*)NULL, more);
366 	}
367 #undef SUBS
368 	updateDetailsList(l);
369 }
370 
updateDetailsList(CListview * l)371 static void updateDetailsList(CListview* l) {
372 #define SETI	{ i = l->getItem(index++); si = i->tSubitems->tNext; si->iColour = defaultColor; }
373 	int index = 0;
374 	lv_item_t* i;
375 	lv_subitem_t* si;
376 	l->SaveScrollbarPos();
377 	Color defaultColor = tLX->clPrivateText;
378 	SETI; si->sText = cClient->getServerName(); // servername
379 	SETI;
380 	if(cClient->getHaveMap()) {
381 		si->sText = cClient->getGameLobby()->sMapName;
382 		if (si->tNext)
383 			si->tNext->bVisible = false;  // Hide the download button
384 	} else {  // Don't have the map
385 		si->sText = cClient->getGameLobby()->sMapFile;
386 		si->iColour = tLX->clError;
387 		if (si->tNext)  {
388 			// not downloading the map, display an option for doing so
389 			si->tNext->bVisible = !cClient->getDownloadingMap();
390 		}
391 	}
392 
393 	const std::string gamemodes[] = {"Death Match","Team Death Match", "Tag", "Demolitions"};
394 	SETI;
395 	if(cClient->getGameLobby()->sGameMode == "") {
396 		int generalType = cClient->getGameLobby()->iGeneralGameType;
397 		si->sText = (generalType < 0 || (uint)generalType >= sizeof(gamemodes)/sizeof(std::string)) ? "Invalid" : gamemodes[generalType];
398 	} else
399 		si->sText = cClient->getGameLobby()->sGameMode;
400 	SETI;
401 	if(cClient->getHaveMod()) {
402 		si->sText = cClient->getGameLobby()->sModName;
403 		if (si->tNext)
404 			si->tNext->bVisible = false;  // Hide the download button
405 	} else {
406 		si->sText = cClient->getGameLobby()->sModName;
407 		si->iColour = tLX->clError;
408 		if (si->tNext)
409 			si->tNext->bVisible = !cClient->getDownloadingMod();
410 	}
411 
412 	SETI;
413 	if(cClient->getGameLobby()->iLives >= 0) {
414 		si->sText = itoa(cClient->getGameLobby()->iLives);
415 	} else {
416 		si->sText = "infinity";
417 		si->iColour = tLX->clDisabled;
418 	}
419 
420 	SETI;
421 	if(cClient->getGameLobby()->iKillLimit >= 0) {
422 		si->sText = itoa(cClient->getGameLobby()->iKillLimit);
423 	} else {
424 		si->sText = "infinity";
425 		si->iColour = tLX->clDisabled;
426 	}
427 
428 	SETI;
429 	if(cClient->getGameLobby()->fTimeLimit >= 0) {
430 		si->sText = ftoa(cClient->getGameLobby()->fTimeLimit) + " min";
431 	} else if(cClient->getGameLobby()->fTimeLimit <= -100) {
432 		si->sText = "unknown";
433 		si->iColour = tLX->clDisabled;
434 	} else {
435 		si->sText = "disabled";
436 		si->iColour = tLX->clDisabled;
437 	}
438 
439 	SETI; si->sText = itoa(cClient->getGameLobby()->iLoadingTime) + "%";
440 	SETI; si->sText = cClient->getGameLobby()->bBonusesOn ? "On" : "Off";
441 
442 	// Advanced info
443 	if (tLXOptions->bAdvancedLobby)  {
444 		SETI; si->sText = cClient->getServerVersion().asString(); // serverversion
445 
446 		int numItems = l->getNumItems();
447 		for( int rm = index; rm < numItems; rm++ )
448 			l->RemoveItem(rm);
449 
450 		foreach( Feature*, f, Array(featureArray,featureArrayLen()) ) {
451 			if( cClient->getGameLobby()->features[f->get()] == f->get()->unsetValue )
452 				continue;
453 			i = l->AddItem("feature:" + f->get()->name, index++, tLX->clNormalLabel);
454 			l->AddSubitem(LVS_TEXT, f->get()->humanReadableName + ":", (DynDrawIntf*)NULL, NULL);
455 			l->AddSubitem(LVS_TEXT, "", (DynDrawIntf*)NULL, NULL);
456 			si = i->tSubitems->tNext;
457 
458 			si->iColour = defaultColor;
459 			si->sText = cClient->getGameLobby()->features[f->get()].toString();
460 		}
461 
462 		foreach( FeatureCompatibleSettingList::Feature&, f, cClient->getUnknownFeatures().list ) {
463 			i = l->AddItem("feature:" + f->get().name, index++, tLX->clNormalLabel);
464 			l->AddSubitem(LVS_TEXT, f->get().humanName + ":", (DynDrawIntf*)NULL, NULL);
465 			l->AddSubitem(LVS_TEXT, "", (DynDrawIntf*)NULL, NULL);
466 
467 			si = i->tSubitems->tNext;
468 			Color col;
469 			switch(f->get().type) {
470 				case FeatureCompatibleSettingList::Feature::FCSL_JUSTUNKNOWN: col = tLX->clDisabled; break;
471 				case FeatureCompatibleSettingList::Feature::FCSL_INCOMPATIBLE: col = tLX->clError; break;
472 				default: col = defaultColor;
473 			}
474 			si->iColour = col;
475 			si->sText = f->get().var.toString();
476 		}
477 
478 		// Less button
479 		lv_item_t *it = l->AddItem("less", index++, tLX->clNormalLabel);
480 		l->AddSubitem(LVS_TEXT, "", (DynDrawIntf*)NULL, NULL);
481 		CButton *less = new CButton(BUT_LESS, tMenu->bmpButtons);
482 		less->setID(jl_Less);
483 		less->Create();
484 		it->iHeight = less->getHeight() + 10;
485 		l->AddSubitem(LVS_WIDGET, "", (DynDrawIntf*)NULL, less);
486 	}
487 
488 	l->RestoreScrollbarPos();
489 
490 #undef SETI
491 }
492 
493 ////////////////////
494 // Finished the mod/map download (callback)
Menu_Net_JoinDlFinished()495 void Menu_Net_JoinDlFinished()
496 {
497 	CButton *cancel = (CButton *)cJoinLobby.getWidget(jl_CancelDownload);
498 	CProgressBar *progress = (CProgressBar *)cJoinLobby.getWidget(jl_DownloadProgress);
499 	CListview *details = (CListview *)cJoinLobby.getWidget(jl_Details);
500 	if (!cancel || !progress || !details)
501 		return;
502 
503 	updateDetailsList(details);
504 
505 	// If we are still downloading, don't hide the progress
506 	if (cClient->getDownloadingMap() || cClient->getDownloadingMod())
507 		return;
508 
509 	// Hide the progress
510 	details->Setup(details->getID(), details->getX(), details->getY(), details->getWidth(), 250);
511 	details->ReadjustScrollbar();
512 
513 	progress->setEnabled(false);
514 	cancel->setEnabled(false);
515 }
516 
517 ////////////////////
518 // Changes the GUI to display downloading things
Menu_Net_JoinStartDownload()519 void Menu_Net_JoinStartDownload()
520 {
521 	CButton *cancel = (CButton *)cJoinLobby.getWidget(jl_CancelDownload);
522 	CProgressBar *progress = (CProgressBar *)cJoinLobby.getWidget(jl_DownloadProgress);
523 	CListview *details = (CListview *)cJoinLobby.getWidget(jl_Details);
524 	if (!cancel || !progress || !details)
525 		return;
526 
527 	// Show the progress
528 	details->Setup(details->getID(), details->getX(), details->getY(), details->getWidth(), 210);
529 	details->ReadjustScrollbar();
530 
531 	progress->setEnabled(true);
532 	cancel->setEnabled(true);
533 }
534 
535 
536 ///////////////////
537 // Create the lobby gui stuff
Menu_Net_JoinLobbyCreateGui()538 void Menu_Net_JoinLobbyCreateGui()
539 {
540     cJoinLobby.Shutdown();
541 	cJoinLobby.Initialize();
542 
543 	cJoinLobby.Add( new CButton(BUT_LEAVE, tMenu->bmpButtons),jl_Back,	15,  450, 60,  15);
544     cJoinLobby.Add( new CButton(BUT_READY, tMenu->bmpButtons),jl_Ready,	560, 450, 65,  15);
545 	cJoinLobby.Add( new CButton(BUT_ADDTOFAVOURITES, tMenu->bmpButtons), jl_Favourites, 230,450,150,15);
546 	cJoinLobby.Add( new CTextbox(),							  jl_ChatText, 15,  421, 610, tLX->cFont.GetHeight());
547     cJoinLobby.Add( new CBrowser(),                           jl_ChatList, 15,  268, 610, 150);
548 	cJoinLobby.Add( new CListview(),						  jl_PlayerList, 15, 15, 325, 220);
549 	cJoinLobby.Add( new CListview(),						  jl_Details, 350, 15, 290, 250);
550 
551 	// Downloading stuff
552 	CProgressBar *dl = new CProgressBar(LoadGameImage("data/frontend/downloadbar_lobby.png", true), 0, 0, false, 1);
553 	CButton *cancel = new CButton(BUT_CANCEL, tMenu->bmpButtons);
554 	cJoinLobby.Add( dl, jl_DownloadProgress, 360, 245, 0, 0);
555 	cJoinLobby.Add( cancel, jl_CancelDownload, 360 + dl->getWidth() + 5, 245 + (dl->getHeight() - 20)/2, 0, 0);
556 	dl->setEnabled(false);
557 	cancel->setEnabled(false);
558 	cClient->setOnMapDlFinished(&Menu_Net_JoinDlFinished);
559 	cClient->setOnModDlFinished(&Menu_Net_JoinDlFinished);
560 
561 	// Setup the player list
562 	CListview *player_list = (CListview *)cJoinLobby.getWidget(jl_PlayerList);
563 	if (player_list)  {
564 		player_list->setShowSelect(false);
565 		player_list->setOldStyle(true);
566 		player_list->AddColumn("Players", tMenu->bmpLobbyReady.get()->w + 2, tLX->clHeading);  // Lobby ready/Players label
567 		player_list->AddColumn("", 30);  // Skin
568 		player_list->AddColumn("", 220); // Name
569 		player_list->AddColumn("", -1); // Team
570 	}
571 
572 
573 	CListview* details = (CListview *)cJoinLobby.getWidget(jl_Details);
574 	//details->Setup(0, x + 15, y+5, w - 30, h - 25); // is this done already in .Add(...) above?
575 	details->setDrawBorder(false);
576 	details->setRedrawMenu(false);
577 	details->setShowSelect(false);
578 	details->setOldStyle(true);
579 	details->subItemsAreAligned() = true;
580 
581 	// like in Menu_SvrList_DrawInfo
582 	int first_column_width = tLX->cFont.GetWidth("Loading Times:") + 30; // Width of the widest item in this column + some space
583 	int last_column_width = tLX->cFont.GetWidth("999"); // Kills width
584 	details->AddColumn("", first_column_width);
585 	details->AddColumn("", details->getWidth() - first_column_width - (last_column_width*2) - gfxGUI.bmpScrollbar.get()->w); // The rest
586 	details->AddColumn("", last_column_width);
587 	details->AddColumn("", last_column_width);
588 
589 	initDetailsList(details);
590 
591 	iJoinSpeaking = 0; // The first client is always speaking
592 
593 	cJoinLobby.FocusWidget(jl_ChatText);
594 #ifdef __ANDROID__
595 	Menu_WarpMouse(cJoinLobby.getWidget(jl_ChatText)->getX() + cJoinLobby.getWidget(jl_ChatText)->getWidth() - 2,
596 					cJoinLobby.getWidget(jl_ChatText)->getY() + cJoinLobby.getWidget(jl_ChatText)->getHeight() - 2);
597 #endif
598 }
599 
600 
601 ///////////////////
602 // Go straight back to the join lobby
603 // TODO: please comment the difference between Menu_Net_JoinGotoLobby and GotoJoinLobby
Menu_Net_JoinGotoLobby()604 void Menu_Net_JoinGotoLobby()
605 {
606     Menu_Net_JoinDrawLobby();
607 
608     Menu_Net_JoinLobbyCreateGui();
609 
610 	iNetMode = net_join;
611 	iJoinMenu = join_lobby;
612 
613 	// Add the chat
614 	CBrowser *lv = (CBrowser *)cJoinLobby.getWidget(jl_ChatList);
615 	if (lv)  {
616 		lv->InitializeChatBox();
617 		CChatBox *Chatbox = cClient->getChatbox();
618 		lines_iterator it = Chatbox->At((int)Chatbox->getNumLines()-256); // If there's more than 256 messages, we start not from beginning but from end()-256
619 		//int id = (lv->getLastItem() && lv->getItems()) ? lv->getLastItem()->iIndex + 1 : 0;
620 
621 		// Copy the chat text
622 		for (; it != Chatbox->End(); it++)  {
623 			if (it->iTextType == TXT_CHAT || it->iTextType == TXT_PRIVATE || it->iTextType == TXT_TEAMPM)  {  // Add only chat messages
624 				lv->AddChatBoxLine(it->strLine, it->iColour, it->iTextType);
625 			}
626 		}
627 	}
628 
629 	// Add the ingame chatter text to lobby chatter
630 	Menu_Net_JoinLobbySetText(cClient->chatterText());
631 
632 	iJoinSpeaking = 0; // The first player is always speaking
633 	tMenu->sSavedChatText = "";
634 }
635 
636 //////////////////////
637 // Get the content of the chatbox
Menu_Net_JoinLobbyGetText()638 std::string Menu_Net_JoinLobbyGetText()
639 {
640 	if (tMenu->bMenuRunning)  {
641 		std::string buf;
642 		cJoinLobby.SendMessage(jl_ChatText, TXS_GETTEXT, &buf, 256);
643 		return buf;
644 	} else {
645 		return tMenu->sSavedChatText;
646 	}
647 }
648 
Menu_Net_JoinLobbySetText(const std::string & str)649 void Menu_Net_JoinLobbySetText(const std::string& str) {
650 	cJoinLobby.SendMessage(jl_ChatText, TXS_SETTEXT, str, 0);
651 }
652 
653 
654 ///////////////////
655 // Join lobby frame
Menu_Net_JoinLobbyFrame(int mouse)656 void Menu_Net_JoinLobbyFrame(int mouse)
657 {
658 	gui_event_t *ev = NULL;
659 	int			i,y;
660 
661 	// Process the client
662 	cClient->Frame();
663 
664     // If there is a client error, leave
665     if(cClient->getClientError()) {
666 
667 		Menu_Net_JoinShutdown();
668         Menu_NetInitialize();
669 		bJoin_Update = true;
670 		return;
671     }
672 
673 
674 	// If we have started, leave the frontend
675 	if(cClient->getGameReady()) {
676 
677 		cJoinLobby.Shutdown();
678 
679         // Setup the client
680         cClient->SetupViewports();
681 
682 		// Leave the frontend
683 		*bGame = true;
684 		tMenu->bMenuRunning = false;
685 		tLX->iGameType = GME_JOIN;
686 
687 		// Save the chat text
688 		cJoinLobby.SendMessage(jl_ChatText, TXS_GETTEXT, &tMenu->sSavedChatText, 256);
689 
690 		bJoin_Update = true;
691 
692 		return;
693 	}
694 
695 
696 	// Check if the communication link between us & server is still ok
697 	if(cClient->getServerError()) {
698 		// Create the buffer
699 		DrawImage(tMenu->bmpBuffer.get(),tMenu->bmpMainBack_common,0,0);
700 		Menu_DrawSubTitle(tMenu->bmpBuffer.get(),SUB_LOBBY);
701 
702 		Menu_MessageBox("Communication", cClient->getServerErrorMsg(), LMB_OK);
703 
704         cJoinLobby.Shutdown();
705 
706 		Menu_NetInitialize();
707 
708 		bJoin_Update = true;
709 		return;
710 	}
711 
712 
713     // Clear the player list and game settings
714     Menu_redrawBufferRect(15, 15,  400, 230);
715     Menu_redrawBufferRect(360,15,  280, 200);
716 
717 
718 	// Add chat to the listbox
719 	CBrowser *lv = (CBrowser *)cJoinLobby.getWidget(jl_ChatList);
720     line_t ln;
721 	while(cClient->getChatbox()->GetNewLine(ln)) {
722 		lv->AddChatBoxLine(ln.strLine, ln.iColour, ln.iTextType);
723 	}
724 
725 
726 	// Downloading progress
727 	if (cClient->getDownloadingMap() || cClient->getDownloadingMod())  {
728 		CProgressBar *bar = (CProgressBar *)cJoinLobby.getWidget(jl_DownloadProgress);
729 		if (bar)
730 			bar->SetPosition(cClient->getDlProgress());
731 	}
732 
733 
734 	// Draw the connected players
735 	if (bJoin_Update)  {
736 		CListview *player_list = (CListview *)cJoinLobby.getWidget(jl_PlayerList);
737 		if (!player_list) { // Weird, shouldn't happen
738 			warnings << "Menu_Net_JoinLobbyFrame: player_list unset" << endl;
739 			return;
740 		}
741 		player_list->SaveScrollbarPos();
742 		player_list->Clear();  // Clear first
743 
744 		CWorm *w = cClient->getRemoteWorms();
745 		CImage *team_img = NULL;
746 
747 		for (i=0; i < MAX_PLAYERS; i++, w++)  {
748 			if (!w->isUsed())  // Don't bother with unused worms
749 				continue;
750 
751 			w->ChangeGraphics(cClient->getGameLobby()->iGeneralGameType);
752 
753 			// Add the item
754 			player_list->AddItem(w->getName(), i, tLX->clNormalLabel);
755 			if (w->getLobbyReady())  // Ready control
756 				player_list->AddSubitem(LVS_IMAGE, "", tMenu->bmpLobbyReady, NULL);
757 			else
758 				player_list->AddSubitem(LVS_IMAGE, "", tMenu->bmpLobbyNotReady, NULL);
759 			player_list->AddSubitem(LVS_IMAGE, "", w->getPicimg(), NULL);  // Skin
760 			player_list->AddSubitem(LVS_TEXT, "#"+itoa(w->getID())+" "+w->getName(), (DynDrawIntf*)NULL, NULL);  // Name
761 
762 			// Display the team mark if TDM
763 			if (cClient->getGameLobby()->iGeneralGameType == GMT_TEAMS)  {
764 				team_img = new CImage(gfxGame.bmpTeamColours[w->getTeam()]);
765 				if (!team_img)
766 					continue;
767 				team_img->setID(w->getID());
768 				team_img->setRedrawMenu(false);
769 
770 				player_list->AddSubitem(LVS_WIDGET, "", (DynDrawIntf*)NULL, team_img); // Team
771 			}
772 		}
773 
774 		player_list->RestoreScrollbarPos();  // Scroll back to where we were before the update
775 
776 		CListview* details = (CListview *)cJoinLobby.getWidget(jl_Details);
777 		updateDetailsList(details);
778 
779 		bJoin_Update = false;
780 	}
781 
782 	// Draw the game info
783 	if(true) {	//if(GameLobby->bSet) {
784 		CFont *f = &tLX->cFont;
785         int x = 360;
786         y = 15;
787 
788 		f->Draw(VideoPostProcessor::videoSurface(), x, y,  tLX->clHeading, "Game Details");
789 	}
790 
791 	// If any textbox is selected, forbid to show the console
792 	if (cJoinLobby.getFocusedWidget() && !Con_IsVisible())  {
793 		tMenu->bForbidConsole = cJoinLobby.getFocusedWidget()->getType() == wid_Textbox;
794 	}
795 
796 	// Process & Draw the gui
797 	if (!Con_IsVisible() && !CChatWidget::GlobalEnabled())  // Don't process when the console is opened
798 		ev = cJoinLobby.Process();
799 
800 	cJoinLobby.Draw( VideoPostProcessor::videoSurface() );
801 
802 	if(CChatWidget::GlobalEnabled())
803 	{
804 		CChatWidget::GlobalProcessAndDraw(VideoPostProcessor::videoSurface());
805 		return;
806 	}
807 
808 	// Process any events
809 	if(ev) {
810 		switch(ev->iControlID) {
811 
812 			// Back
813 			case jl_Back:
814 				if(ev->iEventMsg == BTN_CLICKED) {
815 					// Click
816 					PlaySoundSample(sfxGeneral.smpClick);
817 
818 					Menu_Net_JoinLobbyShutdown();
819 
820 					// Back to net menu
821 					Menu_NetInitialize();
822 				}
823 				break;
824 
825 			// Ready
826 			case jl_Ready:
827 				if(ev->iEventMsg == BTN_CLICKED) {
828 					// Let the server know that my worms are now ready
829 					bool ready = true;
830 					if( cClient->getNumWorms() > 0 )
831 						ready = ! cClient->getWorm(0)->getLobbyReady();
832 					cClient->getNetEngine()->SendUpdateLobby(ready);
833 
834 					// Hide the ready button
835 					/*
836 					CButton *btn = (CButton *)cJoinLobby.getWidget(jl_Ready);
837 					btn->setEnabled(false);
838                     btn->redrawBuffer();
839                     */
840 				}
841 				break;
842 
843 			// Add to favourites
844 			case jl_Favourites:
845 				if (ev->iEventMsg == BTN_CLICKED) {
846 					Menu_SvrList_AddFavourite(cClient->getServerName(),cClient->getServerAddress());
847 				}
848 				break;
849 
850 			// Cancel file transfers
851 			case jl_CancelDownload:
852 				if (ev->iEventMsg == BTN_CLICKED)  {
853 					cClient->AbortDownloads();
854 				}
855 				break;
856 
857 			// Chat box
858 			case jl_ChatList:
859 				if (ev->iEventMsg == BRW_KEY_NOT_PROCESSED)  {
860 					// Activate the textbox automatically
861 					cJoinLobby.FocusWidget(jl_ChatText);
862 					tMenu->bForbidConsole = true;
863 
864 					// Hack: add the just-pressed key to the textbox
865 					CTextbox *txt = (CTextbox *)cJoinLobby.getWidget(jl_ChatText);
866 					if (txt && GetKeyboard()->queueLength > 0)  {
867 						KeyboardEvent kbev = GetKeyboard()->keyQueue[GetKeyboard()->queueLength - 1];
868 						txt->KeyDown(kbev.ch, kbev.sym, *GetCurrentModstate());
869 					}
870 				}
871 				break;
872 
873 
874 			// Chat textbox
875 			case jl_ChatText:
876 				if(ev->iEventMsg == TXT_ENTER && iJoinSpeaking >= 0) {
877 					// Send the msg to the server
878 
879 					// Get the text
880 					std::string text;
881 					cJoinLobby.SendMessage(jl_ChatText, TXS_GETTEXT, &text, 0);
882 
883                     // Don't send empty messages
884                     if(text.size() == 0)
885                         break;
886 
887 					// Clear the text box
888 					cJoinLobby.SendMessage(jl_ChatText, TXS_SETTEXT, "",0);
889 
890 					// Send
891 					cClient->getNetEngine()->SendText(text, cClient->getWorm(0)->getName());
892 				} else
893 				if(ev->iEventMsg == TXT_TAB) {
894 					if(strSeemsLikeChatCommand(Menu_Net_JoinLobbyGetText())) {
895 						cClient->getNetEngine()->SendChatCommandCompletionRequest(Menu_Net_JoinLobbyGetText().substr(1));
896 						return;
897 					}
898 				}
899 				break;
900 
901 			case jl_Details:
902 				if (ev->iEventMsg == LV_WIDGETEVENT)  {
903 					CListview *details = (CListview *)cJoinLobby.getWidget(jl_Details);
904 					gui_event_t *ev2 = details->getWidgetEvent();
905 					if (ev2)  {
906 						switch (ev2->iControlID)  {
907 						case jl_DownloadMap:
908 							if (ev2->iEventMsg == IMG_CLICK)  {
909 								cClient->DownloadMap(cClient->getGameLobby()->sMapFile);  // Download the map
910 								Menu_Net_JoinStartDownload();
911 								updateDetailsList(details);
912 							}
913 						break;
914 						case jl_DownloadMod:
915 							if (ev2->iEventMsg == IMG_CLICK)  {
916 								cClient->DownloadMod(cClient->getGameLobby()->sModDir); // Download the mod
917 								Menu_Net_JoinStartDownload();
918 								updateDetailsList(details);
919 							}
920 						break;
921 						case jl_Less:
922 							if (ev2->iEventMsg == BTN_CLICKED)  {
923 								tLXOptions->bAdvancedLobby = false;
924 								initDetailsList(details);
925 							}
926 						break;
927 						case jl_More:
928 							if (ev2->iEventMsg == BTN_CLICKED)  {
929 								tLXOptions->bAdvancedLobby = true;
930 								initDetailsList(details);
931 							}
932 						break;
933 						}
934 					}
935 				}
936 			break;
937 
938 			/*case jl_StartStopUdpFileDownload:
939 				if(ev->iEventMsg == TXB_MOUSEUP) {
940 					if( cClient->getUdpFileDownloader()->getFilesPendingAmount() > 0 )
941 					{
942 						cClient->AbortMapDownloads();
943 						if( ! cClient->getUdpFileDownloader()->isFinished() ||
944 							cClient->getUdpFileDownloader()->getFilesPendingAmount() > 0 )
945 						{
946 							cClient->getUdpFileDownloader()->abortDownload();
947 							cClient->getNetEngine()->SendFileData();
948 							cClient->setLastFileRequest( tLX->currentTime + 10000.0f ); // Disable file download for current session
949 						}
950 					}
951 					else
952 					{
953 						cClient->setLastFileRequest( tLX->currentTime - 10.0f ); // Re-enable file requests
954 						if( ! cClient->getGameLobby()->bHaveMod && cClient->getGameLobby()->szModDir != "" )
955 							cClient->getUdpFileDownloader()->requestFileInfo(cClient->getGameLobby()->szModDir, true);
956 						if( ! cClient->getGameLobby()->bHaveMap && cClient->getGameLobby()->szMapFile != "" )
957 							cClient->DownloadMap(cClient->getGameLobby()->szMapFile);	// Download map with HTTP, then try UDP
958 					}
959 				}
960 				break;*/
961 		}
962 	}
963 
964 	// Draw the mouse
965 	DrawCursor(VideoPostProcessor::videoSurface());
966 }
967 
968 }; // namespace DeprecatedGUI
969