1 #include "pch.h"
2 #include "common/Def_Str.h"
3 #include "common/GuiCom.h"
4 #include "CGame.h"
5 #include "CGui.h"
6 #include "../vdrift/settings.h"
7 #include "../vdrift/game.h"
8 #include "../network/masterclient.hpp"
9 #include "../network/gameclient.hpp"
10 #include "common/MultiList2.h"
11 #include "common/Gui_Popup.h"
12 #include "common/MessageBox/MessageBox.h"
13 #include <boost/algorithm/string.hpp>
14 using namespace std;
15 using namespace MyGUI;
16 
17 
18 ///  Gui Events
19 
20 //  [Multiplayer]
21 //---------------------------------------------------------------------
22 
23 namespace
24 {
YesNo(bool cond)25 	UString YesNo(bool cond)
26 	{
27 		return cond ? TR("#{Yes}") : TR("#{No}");
28 	}
29 
MsgError(const UString & what,const UString & title=TR ("#{Error}"))30 	void inline MsgError(const UString& what, const UString& title = TR("#{Error}"))
31 	{
32 		Message::createMessageBox("Message", title, what, MessageBoxStyle::IconError | MessageBoxStyle::Ok);
33 	}
34 }
35 
36 
rebuildGameList()37 void CGui::rebuildGameList()
38 {
39 	if (!listServers || !app->mMasterClient)  return;
40 	Mli li = listServers;
41 	li->removeAllItems();
42 
43 	protocol::GameList list = app->mMasterClient->getList();
44 	const static char* sBoost[4] = {"#{Never}","#{FuelLap}","#{FuelTime}","#{Always}"};
45 
46 	for (protocol::GameList::const_iterator it = list.begin(); it != list.end(); ++it)
47 	{
48 		li->addItem("#C0FFC0"+UString(it->second.name));  int l = li->getItemCount()-1;
49 		li->setSubItemNameAt(1,l, "#50FF50"+ string(it->second.track));
50 		li->setSubItemNameAt(2,l, "#80FFC0"+ toStr((int)it->second.laps));
51 		li->setSubItemNameAt(3,l, "#FFFF00"+ toStr((int)it->second.players));
52 		li->setSubItemNameAt(4,l, "#80FFFF"+ YesNo((bool)it->second.collisions));
53 		li->setSubItemNameAt(5,l, "#D0D0FF"+ string(it->second.sim_mode));
54 		li->setSubItemNameAt(6,l, "#A0D0FF"+ TR(sBoost[it->second.boost_type]));
55 		li->setSubItemNameAt(iColLock,l, "#FF6060"+ YesNo((bool)it->second.locked));
56 		li->setSubItemNameAt(iColHost,l, "#FF9000"+ net::IPv4(it->second.address));
57 		li->setSubItemNameAt(iColPort,l, "#FFB000"+ toStr((int)it->second.port));
58 	}
59 }
60 
rebuildPlayerList()61 void CGui::rebuildPlayerList()
62 {
63 	if (!listPlayers || !app->mClient)  return;
64 	Mli li = listPlayers;
65 	li->removeAllItems();
66 
67 	//  Add self
68 	int peerCount = app->mClient->getPeerCount();
69 	li->addItem("#C0E0FF"+ pSet->nickname);
70 	li->setSubItemNameAt(1,0, "#80FFFF"+ sListCar);
71 	li->setSubItemNameAt(2,0, "#F0F060"+ toStr(peerCount));
72 	li->setSubItemNameAt(3,0, "#C0F0F0" "0");  bool rd = app->mClient->isReady();
73 	li->setSubItemNameAt(4,0, (rd?"#60FF60":"#FF8080")+ YesNo(rd));
74 
75 	//  Add others
76 	bool allReady = true;
77 	const PeerMap peers = app->mClient->getPeers();
78 	for (PeerMap::const_iterator it = peers.begin(); it != peers.end(); ++it)
79 	{
80 		if (it->second.name.empty() || it->second.connection == PeerInfo::DISCONNECTED)
81 			continue;
82 		// Determine if everyone is ready and connected
83 		if (it->second.peers != peerCount || !it->second.ready)
84 			allReady = false;
85 
86 		// Add list item
87 		li->addItem("#C0E0FF"+ it->second.name);  int l = li->getItemCount()-1;
88 		li->setSubItemNameAt(1,l, "#80FFFF"+ it->second.car);
89 		li->setSubItemNameAt(2,l, "#F0F060"+ toStr(it->second.peers));
90 		//static int pp=0;  pp+=50;  int p = (pp)%600;  //test clr
91 		int p = it->second.ping;
92 		li->setSubItemNameAt(3,l, CGuiCom::clrsDiff[std::min(7,1+p/100)]+ toStr(p));
93 		bool rd = it->second.ready;
94 		li->setSubItemNameAt(4,l, (rd?"#60FF60":"#FF8080")+ YesNo(rd));
95 	}
96 	//  Allow host to start the game
97 	if (app->mLobbyState == HOSTING)
98 		btnNetReady->setEnabled(allReady);
99 }
100 
updateGameInfo()101 void CGui::updateGameInfo()
102 {
103 	//  set game config
104 	if (netGameInfo.name && edNetGameName)
105 	{	string name(netGameInfo.name);
106 		edNetGameName->setCaption(name);
107 	}
108 	if (netGameInfo.track)
109 	{	string track(netGameInfo.track);
110 		gcom->sListTrack = track;
111 		gcom->bListTrackU = netGameInfo.track[31]==1;  //user
112 		gcom->ReadTrkStats();
113 	}
114 	updateGameSet();
115 	updateGameInfoGUI();
116 }
117 
118 ///  update game info
updateGameInfoGUI()119 void CGui::updateGameInfoGUI()
120 {
121 	if (!valNetGameInfo)  return;
122 	using Ogre::String;
123 
124 	String s;  const protocol::GameInfo& g = netGameInfo;
125 	s += TR("#40FF40#{Track}:      ") + gcom->sListTrack +"\n";
126 	s += TR("#60A060#{Reverse}:  ") + YesNo(g.reversed) +"\n";
127 	s += "\n";
128 	s += TR("#80F0F0#{Laps}:   ") + toStr(g.laps) +"\n";
129 	s += TR("#409090#{ReverseStartOrder}:  ") + YesNo(g.start_order) +"\n";
130 	s += TR("#F0F040#{Players}:  ") + toStr(g.players) +"\n";
131 	s += "\n";
132 	s += TR("#D090E0#{Game}") +"\n";
133 	s += TR("#90B0E0  #{Simulation}:  ") + String(g.sim_mode) +"\n";
134 	s += TR("#A0D0D0  #{CarCollis}:  ") + YesNo(g.collisions) +"\n";
135 	s += "\n";
136 	#define cmbs(cmb, i)  (i>=0 && i < cmb->getItemCount() ? cmb->getItemNameAt(i) : TR("#{Any}"))
137 	s += TR("#80C0FF  #{Boost}:  ") + "#90D0FF"+ cmbs(cmbBoost, g.boost_type) +"\n";
138 	s += TR("#6098A0  #{Flip}:  ") + "#7098A0"+ cmbs(cmbFlip, g.flip_type) +"\n";
139 	s += "\n";
140 	s += TR("#A090E0  #{Damage}:  ") + "#B090FF"+ cmbs(cmbDamage, g.damage_type) +"\n";
141 	s += TR("#A090C0  #{DamageDecLap}:  ") + "#B0A0F0"+ fToStr(g.damage_lap_dec,0,3) +" %\n\n";
142 	s += TR("#B080C0  #{InputMapRewind}:  ") + "#C090D0"+ cmbs(cmbRewind, g.rewind_type) +"\n";
143 	//float boost_power;
144 	//float boost_lap_inc, rewind_lap_inc;  //todo
145 	//uint8_t tree_collis;  float tree_mult;
146 
147 	valNetGameInfo->setCaption(s);
148 }
149 
150 
151 ///  Receive  set game from host
152 //---------------------------------------------------------------------
updateGameSet()153 void CGui::updateGameSet()
154 {
155 	pSet->game.sim_mode = netGameInfo.sim_mode;  LogO("== Netw sim mode: " + pSet->game.sim_mode);
156 
157 	pSet->game.collis_cars = netGameInfo.collisions>0;
158 	pSet->game.num_laps = netGameInfo.laps;		LogO("== Netw laps num: " + toStr(pSet->game.num_laps));
159 	pSet->game.trackreverse = netGameInfo.reversed>0;
160 
161 	pSet->game.start_order = netGameInfo.start_order;
162 	pSet->game.collis_veget = netGameInfo.tree_collis>0;
163 	pSet->game.trees = netGameInfo.tree_mult;
164 
165 	pSet->game.BoostDefault();  //
166 	pSet->game.boost_type = netGameInfo.boost_type;
167 	pSet->game.boost_power = netGameInfo.boost_power;
168 	pSet->game.flip_type = netGameInfo.flip_type;
169 
170 	pSet->game.damage_type = netGameInfo.damage_type;
171 	pSet->game.damage_dec = netGameInfo.damage_lap_dec;
172 	pSet->game.rewind_type = netGameInfo.rewind_type;
173 	//boost_lap_inc, rewind_lap_inc;  //todo
174 }
175 
176 ///  Send  upload to peers
177 //---------------------------------------------------------------------
uploadGameInfo()178 void CGui::uploadGameInfo()
179 {
180 	if (!app->mMasterClient || !app->mClient || !edNetGameName || !pSet)
181 		return;
182 	protocol::GameInfo game;
183 	string sGame = edNetGameName->getCaption();
184 	string sTrack = gcom->sListTrack, sSim = pSet->gui.sim_mode;
185 
186 	memset(game.name, 0, sizeof(game.name));
187 	memset(game.track, 0, sizeof(game.track));
188 	memset(game.sim_mode, 0, sizeof(game.sim_mode));
189 	strcpy(game.name, sGame.c_str());
190 	strcpy(game.track, sTrack.c_str());  game.track[31] = gcom->bListTrackU ? 1:0;  //user
191 	strcpy(game.sim_mode, sSim.c_str());
192 	game.players = app->mClient->getPeerCount()+1;
193 
194 	game.collisions = pSet->gui.collis_cars?1:0;
195 	game.laps = pSet->gui.num_laps;				LogO("== Netw laps num: " + toStr(pSet->gui.num_laps));
196 	game.reversed = pSet->gui.trackreverse?1:0;
197 
198 	game.start_order = pSet->gui.start_order;
199 	game.tree_collis = pSet->gui.collis_veget?1:0;
200 	game.tree_mult = pSet->gui.trees;
201 
202 	game.boost_type = pSet->gui.boost_type;
203 	game.boost_power = pSet->gui.boost_power;
204 	game.flip_type = pSet->gui.flip_type;
205 
206 	game.damage_type = pSet->gui.damage_type;
207 	game.damage_lap_dec = pSet->gui.damage_dec;
208 	game.rewind_type = pSet->gui.rewind_type;
209 	//boost_lap_inc, rewind_lap_inc;  //todo
210 
211 	game.port = pSet->local_port;
212 	game.locked = !edNetPassword->getCaption().empty();
213 	{
214 		//? boost::mutex::scoped_lock lock(netGuiMutex);
215 		netGameInfo = game;  // for host gui info
216 	}
217 	app->mMasterClient->updateGame(game); // Upload to master server
218 	if (app->mClient)  // Send to peers
219 		app->mClient->broadcastGameInfo(game);
220 }
221 //---------------------------------------------------------------------
222 
223 
setNetGuiHosting(bool enabled)224 void CGui::setNetGuiHosting(bool enabled)
225 {
226 	edNetGameName->setEnabled(enabled);
227 	edNetPassword->setEnabled(enabled);
228 	edNetPassword->setVisible(enabled);
229 	valNetPassword->setVisible(enabled);
230 	btnNetReady->setEnabled(!enabled);
231 	btnNetReady->setCaption(enabled ? TR("#{NetStart}") : TR("#{NetReady}"));
232 }
233 
gameListChanged(protocol::GameList list)234 void CGui::gameListChanged(protocol::GameList list)
235 {
236 	(void)list;
237 	boost::mutex::scoped_lock lock(netGuiMutex);
238 	bRebuildGameList = true;
239 }
240 
241 //  add new msg at end
AddChatMsg(const MyGUI::UString & clr,const MyGUI::UString & msg,bool add)242 void CGui::AddChatMsg(const MyGUI::UString& clr, const MyGUI::UString& msg, bool add)
243 {
244 	if (!app->isFocGui)  // if not in gui, show on hud
245 	{	sChatLast1 = sChatLast2;
246 		sChatLast2 = msg;
247 		iChatMove = 0;
248 	}
249 	sChatBuffer = add ? (sChatBuffer + clr + msg + "\n") : (clr + msg + "\n");
250 	bUpdChat = true;
251 }
252 
peerConnected(PeerInfo peer)253 void CGui::peerConnected(PeerInfo peer)
254 {
255 	// Master server player count update
256 	if (app->mLobbyState == HOSTING)  uploadGameInfo();
257 	// Schedule Gui updates
258 	boost::mutex::scoped_lock lock(netGuiMutex);
259 	AddChatMsg("#00FF00", TR("#{Connected}: ") + peer.name);
260 	bRebuildPlayerList = true;
261 }
262 
peerDisconnected(PeerInfo peer)263 void CGui::peerDisconnected(PeerInfo peer)
264 {
265 	if (peer.name.empty())  return;
266 	// Master server player count update
267 	if (app->mLobbyState == HOSTING)  uploadGameInfo();
268 	// Schedule Gui updates
269 	boost::mutex::scoped_lock lock(netGuiMutex);
270 	AddChatMsg("#FF8000", TR("#{Disconnected}: ") + peer.name);
271 	bRebuildPlayerList = true;
272 }
273 
peerInfo(PeerInfo peer)274 void CGui::peerInfo(PeerInfo peer)
275 {
276 	(void)peer;
277 	boost::mutex::scoped_lock lock(netGuiMutex);
278 	bRebuildPlayerList = true;
279 }
280 
peerMessage(PeerInfo peer,string msg)281 void CGui::peerMessage(PeerInfo peer, string msg)
282 {
283 	boost::mutex::scoped_lock lock(netGuiMutex);
284 
285 	int len = peer.name.length();
286 	if (len == 0)  return;
287 
288 	int hc = 16;  // color from name
289 	hc += len;  hc += peer.name[0];
290 	if (len > 3)  hc += peer.name[2];
291 
292 	const static int num = 24;
293 	const static char sclr[num][8] = {
294 		"#80FFC0","#C0FFC0","#B0FF40","#80C060",
295 		"#90E0E0","#40FFFF","#F0F0C0","#E0E040",
296 		"#FFC0FF","#FF80C0","#FFC040","#FF8080",
297 		"#FF4080","#FFA050","#FF8020","#C0C0C0",
298 		"#50B0E0","#C080FF","#C0C0FF","#8080FF",
299 		"#4080FF","#80C0FF","#E0F0FF","#F0F0F0"};
300 	/*for (int i=0; i<num; ++i)  //test clrs
301 		AddChatMsg(sclr[i], UString(peer.name) + ": " + msg);/**/
302 
303 	AddChatMsg(sclr[hc % num], UString(peer.name) + ": " + msg);
304 	bRebuildPlayerList = true; // For ping updates in the list
305 }
306 
peerState(PeerInfo peer,uint8_t state)307 void CGui::peerState(PeerInfo peer, uint8_t state)
308 {
309 	(void)peer;
310 	boost::mutex::scoped_lock lock(netGuiMutex);
311 	if (state == protocol::START_GAME)
312 	{
313 		bStartGame = true;
314 		bStartedGame = true;
315 	}
316 }
317 
gameInfo(protocol::GameInfo game)318 void CGui::gameInfo(protocol::GameInfo game)
319 {
320 	boost::mutex::scoped_lock lock(netGuiMutex);
321 	netGameInfo = game;
322 	bUpdateGameInfo = true;
323 }
324 
returnToLobby()325 void CGui::returnToLobby()
326 {
327 	btnNetReady->setCaption(TR("#{NetReady}"));
328 	app->isFocGui = true;  // show back gui
329 	toggleGui(false);
330 }
331 
startRace()332 void CGui::startRace()
333 {
334 	LogO("== Netw startRace +");
335 	pGame->timer.waiting = false;
336 	pGame->timer.end_sim = false;
337 }
338 
339 ///  Lap time got from network
timeInfo(ClientID id,uint8_t lap,double time)340 void CGui::timeInfo(ClientID id, uint8_t lap, double time)
341 {
342 	//if (!ap->mClient)  return;
343 	if (id == 0)  id = app->mClient->getId();
344 	int n = pGame->timer.netw_lap;
345 
346 	LogO("== Netw Lap " +toStr(lap) + "==" + toStr(n) + (lap == n ? "Good":"BAD!") +
347 		" finished by " +toStr(id) + " time:"+ toStr(float(time)));
348 	if (id >= app->carModels.size() || id < 0)
349 	{	LogO("== Netw Lap id wrong !" );  return;  }
350 
351 	//pGame->timer.Lap(id, 0,0, true, pSet->game.trackreverse/*<, pSet->boost_type*/);
352 	if (pGame->timer.LapNetworkTime(id, lap, time))  // is the same as above but sets client's time
353 	{}//LogO("== Netw Lap OK");
354 
355 	//carModels[id]->trackPercent = 0.f;
356 	//carPoses[id].percent = 0.f;
357 }
358 
error(string what)359 void CGui::error(string what)
360 {
361 	boost::mutex::scoped_lock lock(netGuiMutex);
362 	AddChatMsg("#FF3030", TR("#{Error}! ") + what);
363 }
364 
join(string host,string port,string password)365 void CGui::join(string host, string port, string password)
366 {
367 	try
368 	{	app->mClient.reset(new P2PGameClient(this, pSet->local_port));
369 		app->mClient->updatePlayerInfo(pSet->nickname, sListCar);
370 		app->mClient->connect(host, boost::lexical_cast<int>(port), password); // Lobby phase started automatically
371 		boost::mutex::scoped_lock lock(netGuiMutex);
372 		AddChatMsg("#00FFFF", TR("#{ConnectingTo} ") + host + ":" + port, false);  // clears chat
373 	}catch (...)
374 	{	MsgError(TR("#{NewtworkFailed}"), TR("NetworkError"));
375 		return;
376 	}
377 
378 	updateGameInfoGUI();
379 	rebuildPlayerList();
380 	setNetGuiHosting(false);
381 
382 	tabsNet->setIndexSelected(1);
383 	panNetServer->setVisible(true);  panNetGame->setVisible(false);
384 	panNetTrack->setVisible(true);   gcom->trkList->setVisible(false);
385 }
386 
evBtnNetRefresh(WP)387 void CGui::evBtnNetRefresh(WP)
388 {
389 	app->mMasterClient.reset(new MasterClient(this));
390 	app->mMasterClient->connect(pSet->master_server_address, pSet->master_server_port);
391 	// The actual refresh will be requested automatically when the connection is made
392 }
393 
evBtnNetJoin(WP)394 void CGui::evBtnNetJoin(WP)
395 {
396 	//  join selected game
397 	if (!listServers || !pSet)  return;
398 	size_t i = listServers->getIndexSelected();
399 	if (i == ITEM_NONE)  return;
400 
401 	//  TODO: Comparing against localized string is EVIL!
402 	if (listServers->getSubItemNameAt(iColLock, i).substr(7) == TR("#{No}"))
403 	{
404 		string host = listServers->getSubItemNameAt(iColHost, i).substr(7);
405 		string port = listServers->getSubItemNameAt(iColPort, i).substr(7);
406 
407 		join(host, port, "");
408 	}else
409 		popup->Show(newDelegate(this, &CGui::evBtnNetJoinLockedClose),
410 			TR("#{NetJoinLocked}"), true,
411 			TR("#{NetPassword}"), "", "", "",
412 			"", "", "","",
413 			TR("#{MessageBox_Ok}"), TR("#{MessageBox_Cancel}"), "", "");
414 }
415 
evBtnNetJoinLockedClose()416 void CGui::evBtnNetJoinLockedClose()
417 {
418 	popup->Hide();
419 	if (popup->btnResult != 0 || !listServers || !pSet)  return;
420 	size_t i = listServers->getIndexSelected();  if (i == ITEM_NONE)  return;
421 
422 	string host = listServers->getSubItemNameAt(iColHost, i).substr(7);
423 	string port = listServers->getSubItemNameAt(iColPort, i).substr(7);
424 
425 	join(host, port, popup->edit0);  // host, port, password
426 }
427 
evBtnNetCreate(WP)428 void CGui::evBtnNetCreate(WP)
429 {
430 	//  create game ..
431 	if (app->mLobbyState == DISCONNECTED)
432 	{	try
433 		{
434 			app->mClient.reset(new P2PGameClient(this, pSet->local_port));
435 			app->mClient->updatePlayerInfo(pSet->nickname, sListCar);
436 			app->mClient->startLobby();
437 		}
438 		catch (...)
439 		{	MsgError(TR("#{NewtworkFailed}"), TR("NetworkError"));
440 			return;
441 		}
442 		app->mLobbyState = HOSTING;
443 		if (!app->mMasterClient)
444 		{
445 			app->mMasterClient.reset(new MasterClient(this));
446 			app->mMasterClient->connect(pSet->master_server_address, pSet->master_server_port);
447 		}
448 		uploadGameInfo();
449 		updateGameInfoGUI();
450 
451 		rebuildPlayerList();
452 		setNetGuiHosting(true);
453 
454 		tabsNet->setIndexSelected(1);
455 		panNetServer->setVisible(true);  panNetGame->setVisible(false);
456 		panNetTrack->setVisible(false);  gcom->trkList->setVisible(true);
457 
458 		boost::mutex::scoped_lock lock(netGuiMutex);
459 		AddChatMsg("#00FFC0", TR("#{ListeningOnPort} ")  + toStr(pSet->local_port) + "...", false);  //clears chat
460 	}
461 }
462 
evBtnNetLeave(WP)463 void CGui::evBtnNetLeave(WP)
464 {
465 	//  leave current game
466 	app->mLobbyState = DISCONNECTED;
467 	app->mClient.reset();
468 	app->mMasterClient.reset();
469 	setNetGuiHosting(false);
470 
471 	tabsNet->setIndexSelected(0);
472 	panNetServer->setVisible(false);  panNetGame->setVisible(true);
473 	panNetTrack->setVisible(false);   gcom->trkList->setVisible(true);
474 }
475 
evBtnNetDirect(WP)476 void CGui::evBtnNetDirect(WP)
477 {
478 	popup->Show(newDelegate(this, &CGui::evBtnNetDirectClose),
479 		TR("#{NetDirectConnect}"), true,
480 		TR("#{NetAddress}"), TR("#{NetPort}"), TR("#{NetPassword}"), "",
481 		"localhost", toStr(protocol::DEFAULT_PORT), "","",
482 		TR("#{MessageBox_Ok}"), TR("#{MessageBox_Cancel}"), "", "");
483 }
484 
evBtnNetDirectClose()485 void CGui::evBtnNetDirectClose()
486 {
487 	popup->Hide();
488 	if (popup->btnResult != 0)  return;
489 
490 	join(popup->edit0, popup->edit1, popup->edit2);  // host, port, password
491 }
492 
evBtnNetReady(WP)493 void CGui::evBtnNetReady(WP)
494 {
495 	if (!app->mClient)  return;
496 
497 	app->mClient->toggleReady();
498 	if (app->mLobbyState == HOSTING)
499 	{
500 		LogO("== Netw Ready, hosting...");
501 		if (!bStartedGame)
502 		{
503 			if (app->mMasterClient)  app->mMasterClient->signalStart();
504 			boost::mutex::scoped_lock lock(netGuiMutex);
505 			bStartGame = true;
506 			bStartedGame = true;
507 			btnNetReady->setCaption( TR("#{NetNew}") );
508 		}else{
509 			app->mClient->returnToLobby();
510 			boost::mutex::scoped_lock lock(netGuiMutex);
511 			bStartGame = false;
512 			bStartedGame = false;
513 			btnNetReady->setCaption( TR("#{NetStart}") );
514 		}
515 	}else
516 	{
517 		if (app->mClient->isReady())
518 			btnNetReady->setCaption( TR("#{NetWaiting}") );
519 		else btnNetReady->setCaption( TR("#{NetReady}") );
520 	}
521 
522 	rebuildPlayerList();
523 }
524 
525 
chatSendMsg()526 void CGui::chatSendMsg()
527 {
528 	if (!app->mClient || !edNetChatMsg)  return;
529 	if (edNetChatMsg->getCaption().empty())  return;
530 
531 	app->mClient->sendMessage(edNetChatMsg->getCaption());
532 	edNetChatMsg->setCaption("");
533 }
534 
evEdNetGameName(EditPtr ed)535 void CGui::evEdNetGameName(EditPtr ed)
536 {
537 	//  game name text changed
538 	pSet->netGameName = ed->getCaption();
539 	if (app->mLobbyState != HOSTING || !app->mMasterClient || !app->mClient)  return;
540 	uploadGameInfo();
541 }
542 
evEdNetPassword(EditPtr)543 void CGui::evEdNetPassword(EditPtr)
544 {
545 	//  password changed
546 	if (app->mLobbyState != HOSTING || !app->mMasterClient || !app->mClient)  return;
547 
548 	app->mClient->setPassword(edNetPassword->getCaption());
549 	uploadGameInfo();
550 }
551 
552 //  net settings
553 
evEdNetNick(EditPtr ed)554 void CGui::evEdNetNick(EditPtr ed)
555 {
556 	pSet->nickname = ed->getCaption();
557 	if (app->mClient)  app->mClient->updatePlayerInfo(pSet->nickname, sListCar);
558 }
559 
evEdNetServerIP(EditPtr ed)560 void CGui::evEdNetServerIP(EditPtr ed)
561 {
562 	pSet->master_server_address = ed->getCaption();
563 }
564 
evEdNetServerPort(EditPtr ed)565 void CGui::evEdNetServerPort(EditPtr ed)
566 {
567 	pSet->master_server_port = s2i(ed->getCaption());
568 }
569 
evEdNetLocalPort(EditPtr ed)570 void CGui::evEdNetLocalPort(EditPtr ed)
571 {
572 	pSet->local_port = s2i(ed->getCaption());
573 }
574 
575 
576 ///  Gui updates from networking
577 //  handled in ogre thread as MyGUI is not thread-safe
UpdGuiNetw()578 void CGui::UpdGuiNetw()
579 {
580 	if (app->isFocGui)
581 	{
582 		if (app->mMasterClient) {
583 			std::string error = app->mMasterClient->getError();
584 			if (!error.empty())
585 				Message::createMessageBox("Message", TR("#{Error}"), error,
586 					MessageBoxStyle::IconError | MessageBoxStyle::Ok);
587 		}
588 		boost::mutex::scoped_lock lock(netGuiMutex);
589 		if (bRebuildGameList) {
590 			bRebuildGameList = false;  rebuildGameList();  }
591 		if (bRebuildPlayerList) {
592 			bRebuildPlayerList = false;  rebuildPlayerList();  }
593 		if (bUpdateGameInfo) {
594 			bUpdateGameInfo = false;  updateGameInfo();  }
595 		if (bUpdChat) {
596 			bUpdChat = false;  edNetChat->setCaption(sChatBuffer);  }
597 		if (bStartGame) {
598 			bStartGame = false;  app->mClient->startGame();  btnNewGameStart(NULL);  }
599 	}
600 }
601