1 //	This file is part of Glest (www.glest.org)
2 //
3 //	Copyright (C) 2001-2008 Martiño Figueroa
4 //
5 //	You can redistribute this code and/or modify it under
6 //	the terms of the GNU General Public License as published
7 //	by the Free Software Foundation; either version 2 of the
8 //	License, or (at your option) any later version
9 // ==============================================================
10 
11 #include "game.h"
12 
13 #include "config.h"
14 #include "renderer.h"
15 #include "particle_renderer.h"
16 #include "commander.h"
17 #include "battle_end.h"
18 #include "sound_renderer.h"
19 #include "profiler.h"
20 #include "core_data.h"
21 #include "metrics.h"
22 #include "faction.h"
23 #include "network_manager.h"
24 #include "checksum.h"
25 #include "auto_test.h"
26 #include "menu_state_keysetup.h"
27 #include "video_player.h"
28 #include "compression_utils.h"
29 #include "cache_manager.h"
30 
31 #include "leak_dumper.h"
32 
33 using namespace Shared::Graphics;
34 using namespace Shared::Util;
35 using namespace Shared::Platform;
36 using namespace Shared::CompressionUtil;
37 
38 namespace Glest{ namespace Game{
39 
40 string GameSettings::playerDisconnectedText = "";
41 Game *thisGamePtr = NULL;
42 
43 // =====================================================
44 // 	class Game
45 // =====================================================
46 
47 // ===================== PUBLIC ========================
48 
49 const float PHOTO_MODE_MAXHEIGHT = 500.0;
50 
51 const int CREATE_NEW_TEAM = -100;
52 const int CANCEL_SWITCH_TEAM = -1;
53 
54 const int CANCEL_DISCONNECT_PLAYER = -1;
55 
56 const float Game::highlightTime= 0.5f;
57 
58 int fadeMusicMilliseconds = 3500;
59 
60 // Check every x seconds if we should switch disconnected players to AI
61 const int NETWORK_PLAYER_CONNECTION_CHECK_SECONDS = 5;
62 
63 int GAME_STATS_DUMP_INTERVAL = 60 * 10;
64 
Game()65 Game::Game() : ProgramState(NULL) {
66 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
67 
68 	originalDisplayMsgCallback = NULL;
69 	aiInterfaces.clear();
70 	videoPlayer = NULL;
71 	playingStaticVideo = false;
72 
73 	mouse2d=0;
74 	mouseX=0;
75 	mouseY=0;
76 	updateFps=0;
77 	lastUpdateFps=0;
78 	avgUpdateFps=0;
79 	framesToCatchUpAsClient=0;
80 	framesToSlowDownAsClient=0;
81 	totalRenderFps=0;
82 	renderFps=0;
83 	lastRenderFps=0;
84 	avgRenderFps=0;
85 	currentAvgRenderFpsTotal=0;
86 	paused=false;
87 	networkPauseGameForLaggedClientsRequested=false;
88 	networkResumeGameForLaggedClientsRequested=false;
89 	pausedForJoinGame=false;
90 	pausedBeforeJoinGame=false;
91 	pauseRequestSent=false;
92 	resumeRequestSent=false;
93 	pauseStateChanged=false;
94 	gameOver=false;
95 	renderNetworkStatus=false;
96 	renderInGamePerformance=false;
97 	showFullConsole=false;
98 	setMarker=false;
99 	cameraDragAllowed=false;
100 	mouseMoved=false;
101 	scrollSpeed=0;
102 	camLeftButtonDown=false;
103 	camRightButtonDown=false;
104 	camUpButtonDown=false;
105 	camDownButtonDown=false;
106 	this->speed=1;
107 	weatherParticleSystem=NULL;
108 	isFirstRender=false;
109 	quitTriggeredIndicator=false;
110 	quitPendingIndicator=false;
111 	original_updateFps=0;
112 	original_cameraFps=0;
113 	captureAvgTestStatus=false;
114 	updateFpsAvgTest=0;
115 	renderFpsAvgTest=0;
116 	renderExtraTeamColor=0;
117 	photoModeEnabled=false;
118 	healthbarMode=hbvUndefined;
119 	visibleHUD=false;
120 	timeDisplay=false;
121 	withRainEffect=false;
122 	program=NULL;
123 	gameStarted=false;
124 	this->initialResumeSpeedLoops=false;
125 
126 	highlightCellTexture=NULL;
127 	lastMasterServerGameStatsDump=0;
128 	lastMaxUnitCalcTime=0;
129 	lastRenderLog2d=0;
130 	playerIndexDisconnect=0;
131 	tickCount=0;
132 	currentCameraFollowUnit=NULL;
133 
134 	popupMenu.setEnabled(false);
135 	popupMenu.setVisible(false);
136 
137 	popupMenuSwitchTeams.setEnabled(false);
138 	popupMenuSwitchTeams.setVisible(false);
139 
140 	popupMenuDisconnectPlayer.setEnabled(false);
141 	popupMenuDisconnectPlayer.setVisible(false);
142 
143 	switchTeamConfirmMessageBox.setEnabled(false);
144 	disconnectPlayerConfirmMessageBox.setEnabled(false);
145 
146 	disconnectPlayerIndexMap.clear();
147 
148 	exitGamePopupMenuIndex = -1;
149 	joinTeamPopupMenuIndex = -1;
150 	pauseGamePopupMenuIndex = -1;
151 	saveGamePopupMenuIndex = -1;
152 	loadGamePopupMenuIndex = -1;
153 	keyboardSetupPopupMenuIndex = -1;
154 	disconnectPlayerPopupMenuIndex = -1;
155 
156 	isMarkCellEnabled = false;
157 	isMarkCellTextEnabled = false;
158 
159 	markCellTexture = NULL;
160 	isUnMarkCellEnabled = false;
161 	unmarkCellTexture = NULL;
162 
163 	masterserverMode = false;
164 	currentUIState=NULL;
165 	currentAmbientSound=NULL;
166 	//printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound);
167 
168 	loadGameNode = NULL;
169 	lastworldFrameCountForReplay = -1;
170 	lastNetworkPlayerConnectionCheck = time(NULL);
171 	inJoinGameLoading = false;
172 	quitGameCalled = false;
173 	disableSpeedChange = false;
174 
175 	for( int i=0;i<GameConstants::networkSmoothInterval;i++){
176 		receivedTooEarlyInFrames[i]=-1;
177 		framesNeededToWaitForServerMessage[i]=-1;
178 	}
179 
180 	fadeMusicMilliseconds = Config::getInstance().getInt("GameStartStopFadeSoundMilliseconds",intToStr(fadeMusicMilliseconds).c_str());
181 	GAME_STATS_DUMP_INTERVAL = Config::getInstance().getInt("GameStatsDumpIntervalSeconds",intToStr(GAME_STATS_DUMP_INTERVAL).c_str());
182 }
183 
resetMembers()184 void Game::resetMembers() {
185 	Unit::setGame(this);
186 	gameStarted = false;
187 	this->initialResumeSpeedLoops = false;
188 
189 	original_updateFps = GameConstants::updateFps;
190 	original_cameraFps = GameConstants::cameraFps;
191 	GameConstants::updateFps= 40;
192 	GameConstants::cameraFps= 100;
193 	captureAvgTestStatus = false;
194 	updateFpsAvgTest=0;
195 	renderFpsAvgTest=0;
196 	lastRenderLog2d		 = 0;
197 	playerIndexDisconnect=0;
198 	lastMasterServerGameStatsDump=0;
199 	highlightCellTexture=NULL;
200 	totalRenderFps       =0;
201 	lastMaxUnitCalcTime  =0;
202 	renderExtraTeamColor =0;
203 
204 	mouseMoved= false;
205 	quitTriggeredIndicator = false;
206 	quitPendingIndicator=false;
207 	originalDisplayMsgCallback = NULL;
208 	thisGamePtr = this;
209 
210 	popupMenu.setEnabled(false);
211 	popupMenu.setVisible(false);
212 
213 	popupMenuSwitchTeams.setEnabled(false);
214 	popupMenuSwitchTeams.setVisible(false);
215 
216 	popupMenuDisconnectPlayer.setEnabled(false);
217 	popupMenuDisconnectPlayer.setVisible(false);
218 
219 	switchTeamConfirmMessageBox.setEnabled(false);
220 	disconnectPlayerConfirmMessageBox.setEnabled(false);
221 
222 	disconnectPlayerIndexMap.clear();
223 
224 	exitGamePopupMenuIndex = -1;
225 	joinTeamPopupMenuIndex = -1;
226 	pauseGamePopupMenuIndex = -1;
227 	saveGamePopupMenuIndex = -1;
228 	loadGamePopupMenuIndex = -1;
229 	keyboardSetupPopupMenuIndex = -1;
230 	disconnectPlayerPopupMenuIndex = -1;
231 
232 	isMarkCellEnabled = false;
233 	isMarkCellTextEnabled = false;
234 
235 	markCellTexture = NULL;
236 	isUnMarkCellEnabled = false;
237 	unmarkCellTexture = NULL;
238 
239 	currentUIState = NULL;
240 
241 	scrollSpeed = Config::getInstance().getFloat("UiScrollSpeed","1.5");
242 	photoModeEnabled = Config::getInstance().getBool("PhotoMode","false");
243 	healthbarMode = Config::getInstance().getInt("HealthBarMode","4");
244 	visibleHUD = Config::getInstance().getBool("VisibleHud","true");
245 	timeDisplay = Config::getInstance().getBool("TimeDisplay","true");
246 	withRainEffect = Config::getInstance().getBool("RainEffect","true");
247 	//MIN_RENDER_FPS_ALLOWED = Config::getInstance().getInt("MIN_RENDER_FPS_ALLOWED",intToStr(MIN_RENDER_FPS_ALLOWED).c_str());
248 
249 	mouseX=0;
250 	mouseY=0;
251 	mouse2d= 0;
252 	loadingText="";
253 	weatherParticleSystem= NULL;
254 	updateFps=0;
255 	renderFps=0;
256 	lastUpdateFps=0;
257 	framesToCatchUpAsClient=0;
258 	framesToSlowDownAsClient=0;
259 	lastRenderFps=-1;
260 	avgUpdateFps=-1;
261 	avgRenderFps=-1;
262 	currentAvgRenderFpsTotal=0;
263 	tickCount=0;
264 	paused= false;
265 	networkPauseGameForLaggedClientsRequested=false;
266 	networkResumeGameForLaggedClientsRequested=false;
267 	pausedForJoinGame=false;
268 	pausedBeforeJoinGame=false;
269 	resumeRequestSent=false;
270 	pauseRequestSent=false;
271 	pauseStateChanged=false;
272 	gameOver= false;
273 	renderNetworkStatus= false;
274 	renderInGamePerformance=false;
275 	this->speed= 1;
276 	showFullConsole= false;
277 	setMarker = false;
278 	cameraDragAllowed=false;
279 	camLeftButtonDown=false;
280 	camRightButtonDown=false;
281 	camUpButtonDown=false;
282 	camDownButtonDown=false;
283 
284 	currentCameraFollowUnit=NULL;
285 	currentAmbientSound=NULL;
286 	//printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound);
287 
288 	loadGameNode = NULL;
289 	lastworldFrameCountForReplay = -1;
290 
291 	lastNetworkPlayerConnectionCheck = time(NULL);
292 
293 	inJoinGameLoading = false;
294 	quitGameCalled = false;
295 	disableSpeedChange = false;
296 
297 	for( int i=0;i<GameConstants::networkSmoothInterval;i++){
298 		receivedTooEarlyInFrames[i]=-1;
299 		framesNeededToWaitForServerMessage[i]=-1;
300 	}
301 
302 
303 	fadeMusicMilliseconds = Config::getInstance().getInt("GameStartStopFadeSoundMilliseconds",intToStr(fadeMusicMilliseconds).c_str());
304 	GAME_STATS_DUMP_INTERVAL = Config::getInstance().getInt("GameStatsDumpIntervalSeconds",intToStr(GAME_STATS_DUMP_INTERVAL).c_str());
305 
306     Logger &logger= Logger::getInstance();
307 	logger.showProgress();
308 }
309 
Game(Program * program,const GameSettings * gameSettings,bool masterserverMode)310 Game::Game(Program *program, const GameSettings *gameSettings,bool masterserverMode):
311 	ProgramState(program), lastMousePos(0), isFirstRender(true)
312 {
313 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
314 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
315 
316 	this->masterserverMode = masterserverMode;
317 	videoPlayer = NULL;
318 	playingStaticVideo = false;
319 	highlightCellTexture = NULL;
320 	playerIndexDisconnect=0;
321 	updateFpsAvgTest=0;
322 	renderFpsAvgTest=0;
323 	cameraDragAllowed=false;
324 
325 	if(this->masterserverMode == true) {
326 		printf("Starting a new game...\n");
327 	}
328 
329 	this->program = program;
330 	resetMembers();
331 	this->gameSettings= *gameSettings;
332 
333 	Lang::getInstance().setAllowNativeLanguageTechtree(this->gameSettings.getNetworkAllowNativeLanguageTechtree());
334 
335 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
336 }
337 
endGame()338 void Game::endGame() {
339 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
340 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
341 
342 	quitGame();
343 	sleep(0);
344 
345 	Object::setStateCallback(NULL);
346 	thisGamePtr = NULL;
347 	if(originalDisplayMsgCallback != NULL) {
348 		NetworkInterface::setDisplayMessageFunction(originalDisplayMsgCallback);
349 	}
350 
351 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
352 
353     Logger &logger= Logger::getInstance();
354 	Renderer &renderer= Renderer::getInstance();
355 
356 	logger.clearHints();
357 	logger.loadLoadingScreen("");
358 	logger.setState(Lang::getInstance().getString("Deleting"));
359 	//logger.add("Game", true);
360 	logger.add(Lang::getInstance().getString("LogScreenGameLoading","",true), false);
361 	logger.hideProgress();
362 
363 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
364 
365 	// Cannot Fade because sound files will be deleted below
366 	SoundRenderer::getInstance().stopAllSounds(fadeMusicMilliseconds);
367 
368 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
369 
370 //	deleteValues(aiInterfaces.begin(), aiInterfaces.end());
371 //	aiInterfaces.clear();
372 
373 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
374 
375 	gui.end();		//selection must be cleared before deleting units
376 
377 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
378 
379 //	world.end();	//must die before selection because of referencers
380 
381 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] aiInterfaces.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,aiInterfaces.size());
382 
383 	// MUST DO THIS LAST!!!! Because objects above have pointers to things like
384 	// unit particles and fade them out etc and this end method deletes the original
385 	// object pointers.
386 	renderer.endGame(false);
387 
388 	GameConstants::updateFps = original_updateFps;
389 	GameConstants::cameraFps = original_cameraFps;
390 
391 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
392 
393 	Unit::setGame(NULL);
394 
395 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] ==== END GAME ==== getCurrentPixelByteCount() = " MG_SIZE_T_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderer.getCurrentPixelByteCount());
396 	if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"==== END GAME ====\n");
397 
398 	FileCRCPreCacheThread * &preCacheCRCThreadPtr = CacheManager::getCachedItem< FileCRCPreCacheThread * >(GameConstants::preCacheThreadCacheLookupKey);
399 	if(preCacheCRCThreadPtr != NULL) {
400 		preCacheCRCThreadPtr->setPauseForGame(false);
401 	}
402 
403 	//this->program->reInitGl();
404 	//renderer.reinitAll();
405 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
406 }
407 
~Game()408 Game::~Game() {
409 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
410 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
411 
412 	quitGame();
413 
414 	Object::setStateCallback(NULL);
415 	thisGamePtr = NULL;
416 	if(originalDisplayMsgCallback != NULL) {
417 		NetworkInterface::setDisplayMessageFunction(originalDisplayMsgCallback);
418 	}
419 
420 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
421 
422     Logger &logger= Logger::getInstance();
423 	Renderer &renderer= Renderer::getInstance();
424 
425 	logger.loadLoadingScreen("");
426 	logger.setState(Lang::getInstance().getString("Deleting"));
427 	//logger.add("Game", true);
428 	logger.add(Lang::getInstance().getString("LogScreenGameLoading","",true), false);
429 	logger.hideProgress();
430 
431 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
432 
433 	// Cannot Fade because sound files will be deleted below
434 	SoundRenderer::getInstance().stopAllSounds();
435 
436 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
437 
438 	masterController.clearSlaves(true);
439 	deleteValues(aiInterfaces.begin(), aiInterfaces.end());
440 	aiInterfaces.clear();
441 
442 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
443 
444 	gui.end();		//selection must be cleared before deleting units
445 
446 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
447 
448 	world.end();	//must die before selection because of referencers
449 
450 	BaseColorPickEntity::resetUniqueColors();
451 
452 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] aiInterfaces.size() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,aiInterfaces.size());
453 
454 	delete videoPlayer;
455 	videoPlayer = NULL;
456 	playingStaticVideo = false;
457 
458 	// MUST DO THIS LAST!!!! Because objects above have pointers to things like
459 	// unit particles and fade them out etc and this end method deletes the original
460 	// object pointers.
461 	renderer.endGame(true);
462 	BaseColorPickEntity::cleanupPBO();
463 
464 	GameConstants::updateFps = original_updateFps;
465 	GameConstants::cameraFps = original_cameraFps;
466 
467 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
468 
469 	Unit::setGame(NULL);
470 
471 	Lang::getInstance().setAllowNativeLanguageTechtree(true);
472 
473 	FileCRCPreCacheThread * &preCacheCRCThreadPtr = CacheManager::getCachedItem< FileCRCPreCacheThread * >(GameConstants::preCacheThreadCacheLookupKey);
474 	if(preCacheCRCThreadPtr != NULL) {
475 		preCacheCRCThreadPtr->setPauseForGame(false);
476 	}
477 
478 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] ==== END GAME ==== getCurrentPixelByteCount() = " MG_SIZE_T_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderer.getCurrentPixelByteCount());
479 	if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"==== END GAME ====\n");
480 
481 	//this->program->reInitGl();
482 	//renderer.reinitAll();
483 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
484 }
485 
showTranslatedTechTree() const486 bool Game::showTranslatedTechTree() const {
487 	return this->gameSettings.getNetworkAllowNativeLanguageTechtree();
488 }
489 
quitTriggered()490 bool Game::quitTriggered() {
491 	return quitTriggeredIndicator;
492 }
493 
quitAndToggleState()494 Stats Game::quitAndToggleState() {
495 	//quitGame();
496 	//Program *program = game->getProgram();
497 	return quitGame();
498 	//Game::exitGameState(program, endStats);
499 }
500 
501 // ==================== init and load ====================
502 
ErrorDisplayMessage(const char * msg,bool exitApp)503 int Game::ErrorDisplayMessage(const char *msg, bool exitApp) {
504 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] %s\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,msg);
505 
506 	if(thisGamePtr != NULL) {
507 		string text = msg;
508 		thisGamePtr->showErrorMessageBox(text, "Error detected", false);
509 	}
510 
511     return 0;
512 }
513 
findFactionLogoTexture(const GameSettings * settings,Logger * logger,string factionLogoFilter,bool useTechDefaultIfFilterNotFound)514 Texture2D * Game::findFactionLogoTexture(const GameSettings *settings, Logger *logger,string factionLogoFilter, bool useTechDefaultIfFilterNotFound) {
515 	Texture2D *result = NULL;
516 	string logoFilename = Game::findFactionLogoFile(settings, logger,factionLogoFilter);
517 	if(logoFilename == "" && factionLogoFilter != "" && useTechDefaultIfFilterNotFound == true) {
518 		logoFilename = Game::findFactionLogoFile(settings, logger);
519 	}
520 
521 	result = Renderer::findTexture(logoFilename);
522 
523 	return result;
524 }
525 
extractScenarioLogoFile(const GameSettings * settings,string & result,bool & loadingImageUsed,Logger * logger,string factionLogoFilter)526 string Game::extractScenarioLogoFile(const GameSettings *settings, string &result,
527 		bool &loadingImageUsed, Logger *logger, string factionLogoFilter) {
528     string scenarioDir = "";
529     if(settings->getScenarioDir() != "") {
530 		scenarioDir = settings->getScenarioDir();
531 		if(EndsWith(scenarioDir, ".xml") == true) {
532 			scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4);
533 			scenarioDir = scenarioDir.erase(scenarioDir.size() - settings->getScenario().size(), settings->getScenario().size() + 1);
534 		}
535 
536 		//printf("!!! extractScenarioLogoFile scenarioDir [%s] factionLogoFilter [%s]\n",scenarioDir.c_str(),factionLogoFilter.c_str());
537 
538 		vector<string> loadScreenList;
539 		string logoFullPathFilter = scenarioDir + factionLogoFilter;
540 		findAll(logoFullPathFilter, loadScreenList, false, false);
541 		if(loadScreenList.empty() == false) {
542 			int bestLogoIndex = 0;
543 
544 			if(loadScreenList.size() > 1 && EndsWith(factionLogoFilter, ".xml") == false) {
545 				if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nLooking for best logo from a list of: " MG_SIZE_T_SPECIFIER " using filter: [%s]\n",loadScreenList.size(),logoFullPathFilter.c_str());
546 
547 				int bestMinWidthDiff = INT_MAX;
548 				int bestMinHeightDiff = INT_MAX;
549 				// Now find the best texture for our screen
550 				// Texture2D *result = preloadTexture(logoFilename);
551 				for(unsigned int logoIndex = 0; logoIndex < loadScreenList.size(); ++logoIndex) {
552 					string senarioLogo = scenarioDir + loadScreenList[bestLogoIndex];
553 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,senarioLogo.c_str());
554 
555 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Looking for best logo: %u [%s]\n",logoIndex,senarioLogo.c_str());
556 
557 					if(fileExists(senarioLogo) == true) {
558 						if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,senarioLogo.c_str());
559 
560 						Texture2D *checkLogo = Renderer::preloadTexture(senarioLogo);
561 						if(checkLogo != NULL) {
562 							const Metrics &metrics= Metrics::getInstance();
563 							int minWidthDifference = abs(metrics.getScreenW() - checkLogo->getPixmapConst()->getW());
564 							int minHeightDifference = abs(metrics.getScreenH() - checkLogo->getPixmapConst()->getH());
565 
566 							if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Logo info: %d x %d (%d,%d)\n",checkLogo->getPixmapConst()->getW(),checkLogo->getPixmapConst()->getH(),minWidthDifference,minHeightDifference);
567 
568 							if(minWidthDifference < bestMinWidthDiff) {
569 								bestMinWidthDiff = minWidthDifference;
570 
571 								bestLogoIndex = logoIndex;
572 								if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#1 New best logo is [%s]\n",senarioLogo.c_str());
573 							}
574 							else if(minWidthDifference == bestMinWidthDiff &&
575 									minHeightDifference < bestMinHeightDiff) {
576 								bestMinHeightDiff = minHeightDifference;
577 
578 								bestLogoIndex = logoIndex;
579 								if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#2 New best logo is [%s]\n",senarioLogo.c_str());
580 							}
581 						}
582 					}
583 				}
584 			}
585 
586 			string senarioLogo = scenarioDir + loadScreenList[bestLogoIndex];
587 			if(fileExists(senarioLogo) == true) {
588 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] found scenario loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,senarioLogo.c_str());
589 
590 				result = senarioLogo;
591 				if(logger != NULL) {
592 					logger->loadLoadingScreen(result);
593 				}
594 				loadingImageUsed=true;
595 			}
596 		}
597 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameSettings.getScenarioDir() = [%s] gameSettings.getScenario() = [%s] scenarioDir = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,settings->getScenarioDir().c_str(),settings->getScenario().c_str(),scenarioDir.c_str());
598 	}
599     return scenarioDir;
600 }
601 
extractFactionLogoFile(bool & loadingImageUsed,string factionName,string scenarioDir,string techName,Logger * logger,string factionLogoFilter)602 string Game::extractFactionLogoFile(bool &loadingImageUsed, string factionName,
603 		string scenarioDir, string techName, Logger *logger, string factionLogoFilter) {
604 	string result = "";
605 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Searching for faction loading screen\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
606 
607 	if(factionName == formatString(GameConstants::OBSERVER_SLOTNAME)) {
608 		string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
609 		const string factionLogo = data_path + "data/core/misc_textures/observer.jpg";
610 		//printf("In [%s::%s Line: %d] looking for loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
611 
612 		if(fileExists(factionLogo) == true) {
613 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
614 
615 			result = factionLogo;
616 			if(logger != NULL) {
617 				logger->loadLoadingScreen(result);
618 			}
619 			loadingImageUsed = true;
620 		}
621 	}
622 	//else if(settings->getFactionTypeName(i) == formatString(GameConstants::RANDOMFACTION_SLOTNAME)) {
623 	else if(factionName == formatString(GameConstants::RANDOMFACTION_SLOTNAME)) {
624 		string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
625 		const string factionLogo = data_path + "data/core/misc_textures/random.jpg";
626 
627 		if(fileExists(factionLogo) == true) {
628 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
629 
630 			result = factionLogo;
631 			if(logger != NULL) {
632 				logger->loadLoadingScreen(result);
633 			}
634 			loadingImageUsed = true;
635 		}
636 	}
637 	else {
638 		Config &config = Config::getInstance();
639 		vector<string> pathList = config.getPathListForType(ptTechs,scenarioDir);
640 		for(int idx = 0; idx < (int)pathList.size(); idx++) {
641 			string currentPath = pathList[idx];
642 			endPathWithSlash(currentPath);
643 			//string path = currentPath + techName + "/" + "factions" + "/" + settings->getFactionTypeName(i);
644 			string path = currentPath + techName + "/" + "factions" + "/" + factionName;
645 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] possible loading screen dir '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str());
646 			if(isdir(path.c_str()) == true) {
647 				endPathWithSlash(path);
648 
649 				vector<string> loadScreenList;
650 				string logoFullPathFilter = path + factionLogoFilter;
651 				findAll(logoFullPathFilter, loadScreenList, false, false);
652 				if(loadScreenList.empty() == false) {
653 					int bestLogoIndex = 0;
654 
655 					if(loadScreenList.size() > 1 && EndsWith(factionLogoFilter, ".xml") == false) {
656 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nLooking for best logo from a list of: " MG_SIZE_T_SPECIFIER " using filter: [%s]\n",loadScreenList.size(),logoFullPathFilter.c_str());
657 
658 
659 						int bestMinWidthDiff = INT_MAX;
660 						int bestMinHeightDiff = INT_MAX;
661 						// Now find the best texture for our screen
662 						// Texture2D *result = preloadTexture(logoFilename);
663 						for(unsigned int logoIndex = 0; logoIndex < (unsigned int)loadScreenList.size(); ++logoIndex) {
664 							string factionLogo = path + loadScreenList[logoIndex];
665 							if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
666 
667 							if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Looking for best logo: %u [%s]\n",logoIndex,factionLogo.c_str());
668 
669 							if(fileExists(factionLogo) == true) {
670 								if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
671 
672 								Texture2D *checkLogo = Renderer::preloadTexture(factionLogo);
673 								if(checkLogo != NULL) {
674 									const Metrics &metrics= Metrics::getInstance();
675 									int minWidthDifference = abs(metrics.getScreenW() - checkLogo->getPixmapConst()->getW());
676 									int minHeightDifference = abs(metrics.getScreenH() - checkLogo->getPixmapConst()->getH());
677 
678 									if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Logo info: %d x %d (%d,%d)\n",checkLogo->getPixmapConst()->getW(),checkLogo->getPixmapConst()->getH(),minWidthDifference,minHeightDifference);
679 
680 									if(minWidthDifference < bestMinWidthDiff) {
681 										bestMinWidthDiff = minWidthDifference;
682 
683 										bestLogoIndex = logoIndex;
684 										if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#1 New best logo is [%s]\n",factionLogo.c_str());
685 									}
686 									else if(minWidthDifference == bestMinWidthDiff &&
687 											minHeightDifference < bestMinHeightDiff) {
688 										bestMinHeightDiff = minHeightDifference;
689 
690 										bestLogoIndex = logoIndex;
691 										if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#2 New best logo is [%s]\n",factionLogo.c_str());
692 									}
693 								}
694 							}
695 						}
696 					}
697 
698 					string factionLogo = path + loadScreenList[bestLogoIndex];
699 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
700 
701 					if(fileExists(factionLogo) == true) {
702 						if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
703 
704 						result = factionLogo;
705 						if(logger != NULL) {
706 							logger->loadLoadingScreen(result);
707 						}
708 						loadingImageUsed = true;
709 						break;
710 					}
711 				}
712 				// Check if this is a linked faction
713 				else {
714 					//!!!
715 					string factionXMLFile = path + factionName + ".xml";
716 
717 					//printf("A factionXMLFile [%s]\n",factionXMLFile.c_str());
718 
719 					if(fileExists(factionXMLFile) == true) {
720 						XmlTree	xmlTreeFaction(XML_RAPIDXML_ENGINE);
721 						std::map<string,string> mapExtraTagReplacementValues;
722 						xmlTreeFaction.load(factionXMLFile, Properties::getTagReplacementValues(&mapExtraTagReplacementValues),true,true);
723 
724 						const XmlNode *rootNode= xmlTreeFaction.getRootNode();
725 
726 						//printf("B factionXMLFile [%s] root name [%s] root first child name [%s]\n",factionXMLFile.c_str(),rootNode->getName().c_str(),rootNode->getChild(0)->getName().c_str());
727 						//printf("B factionXMLFile [%s] root name [%s]\n",factionXMLFile.c_str(),rootNode->getName().c_str());
728 						if(rootNode->hasChild("link") == true) {
729 							rootNode = rootNode->getChild("link");
730 						}
731 						if(rootNode->getName() == "link" && rootNode->hasChild("techtree") == true) {
732 							const XmlNode *linkNode = rootNode;
733 
734 							//printf("C factionXMLFile [%s]\n",factionXMLFile.c_str());
735 
736 							//if(linkNode->hasChild("techtree") == true) {
737 							const XmlNode *techtreeNode = linkNode->getChild("techtree");
738 
739 							string linkedTechTreeName = techtreeNode->getAttribute("name")->getValue();
740 
741 							//printf("D factionXMLFile [%s] linkedTechTreeName [%s]\n",factionXMLFile.c_str(),linkedTechTreeName.c_str());
742 
743 							if(linkedTechTreeName != "") {
744 
745 								string linkedTechTreePath=TechTree::findPath(linkedTechTreeName,pathList);
746 								string techTreePath=linkedTechTreePath;
747 								endPathWithSlash(techTreePath);
748 
749 								string linkedCurrentPath = techTreePath + "factions/" + factionName;
750 								endPathWithSlash(linkedCurrentPath);
751 								//string linkedTmppath= linkedCurrentPath + factionName +".xml";
752 
753 								path = linkedCurrentPath;
754 								if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] possible loading screen dir '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str());
755 
756 								//printf("D1 idx = %d\ncurrentPath [%s]\npath [%s]\npathList[idx] [%s]\n",idx,currentPath.c_str(),path.c_str(),pathList[idx].c_str());
757 
758 								if(isdir(path.c_str()) == true) {
759 									endPathWithSlash(path);
760 
761 									//printf("E path [%s]\n",path.c_str());
762 
763 									loadScreenList.clear();
764 									findAll(path + factionLogoFilter, loadScreenList, false, false);
765 									if(loadScreenList.empty() == false) {
766 										string factionLogo = path + loadScreenList[0];
767 										if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
768 
769 										//printf("F factionLogo [%s]\n",factionLogo.c_str());
770 
771 										if(fileExists(factionLogo) == true) {
772 											if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
773 
774 											result = factionLogo;
775 											if(logger != NULL) {
776 												logger->loadLoadingScreen(result);
777 											}
778 											loadingImageUsed = true;
779 											break;
780 										}
781 									}
782 								}
783 							}
784 							//}
785 						}
786 					}
787 				}
788 			}
789 
790 			if(loadingImageUsed == true) {
791 				break;
792 			}
793 		}
794 	}
795 		//break;
796 		//}
797 	//}
798 	return result;
799 }
800 
extractTechLogoFile(string scenarioDir,string techName,bool & loadingImageUsed,Logger * logger,string factionLogoFilter)801 string Game::extractTechLogoFile(string scenarioDir, string techName,
802 		bool &loadingImageUsed, Logger *logger,string factionLogoFilter) {
803 	string result = "";
804 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Searching for tech loading screen\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
805     Config &config = Config::getInstance();
806     vector<string> pathList = config.getPathListForType(ptTechs, scenarioDir);
807     for(int idx = 0; idx < (int)pathList.size(); idx++) {
808 		string currentPath = pathList[idx];
809 		endPathWithSlash(currentPath);
810 		string path = currentPath + techName;
811 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] possible loading screen dir '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,path.c_str());
812 		if(isdir(path.c_str()) == true) {
813 			endPathWithSlash(path);
814 
815 			vector<string> loadScreenList;
816 			findAll(path + factionLogoFilter, loadScreenList, false, false);
817 			if(loadScreenList.empty() == false) {
818 				string factionLogo = path + loadScreenList[0];
819 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
820 
821 				if(fileExists(factionLogo) == true) {
822 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found loading screen '%s'\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,factionLogo.c_str());
823 
824 					result = factionLogo;
825 					if(logger != NULL) {
826 						logger->loadLoadingScreen(result);
827 					}
828 					loadingImageUsed = true;
829 					break;
830 				}
831 			}
832 		}
833 		if(loadingImageUsed == true) {
834 			break;
835 		}
836 	}
837 
838     return result;
839 }
840 
loadHudTexture(const GameSettings * settings)841 void Game::loadHudTexture(const GameSettings *settings)
842 {
843 	string factionName = "";
844 	string techName			= settings->getTech();
845 	string scenarioDir 		= extractDirectoryPathFromFile(settings->getScenarioDir());
846 	//printf("In loadHudTexture, scenarioDir [%s]\n",scenarioDir.c_str());
847 
848 	for(int i=0; i < settings->getFactionCount(); ++i ) {
849 		if((settings->getFactionControl(i) == ctHuman) || (settings->getFactionControl(i) == ctNetwork
850 		        && settings->getThisFactionIndex() == i)){
851 			factionName= settings->getFactionTypeName(i);
852 			break;
853 		}
854 	}
855 	if(factionName != "") {
856 		bool hudFound = false;
857 		Config &config= Config::getInstance();
858 		vector<string> pathList= config.getPathListForType(ptTechs, scenarioDir);
859 		for(int idx= 0; hudFound == false && idx < (int)pathList.size(); idx++){
860 			string currentPath= pathList[idx];
861 			endPathWithSlash(currentPath);
862 
863 			vector<string> hudList;
864 			string path= currentPath + techName + "/" + "factions" + "/" + factionName;
865 			endPathWithSlash(path);
866 			findAll(path + GameConstants::HUD_SCREEN_FILE_FILTER, hudList, false, false);
867 			if(hudList.empty() == false){
868 				for(unsigned int hudIdx = 0; hudFound == false && hudIdx < (unsigned int)hudList.size(); ++hudIdx) {
869 					string hudImageFileName= path + hudList[hudIdx];
870 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] looking for a HUD [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,hudImageFileName.c_str());
871 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled)
872 						SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] looking for a HUD [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,hudImageFileName.c_str());
873 
874 					if(fileExists(hudImageFileName) == true){
875 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] found HUD image [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,hudImageFileName.c_str());
876 						if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled)
877 							SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found HUD image [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,hudImageFileName.c_str());
878 
879 						Texture2D* texture= Renderer::findTexture(hudImageFileName);
880 						gui.setHudTexture(texture);
881 						hudFound = true;
882 						//printf("Hud texture found! \n");
883 						break;
884 					}
885 				}
886 			}
887 		}
888 	}
889 }
890 
findFactionLogoFile(const GameSettings * settings,Logger * logger,string factionLogoFilter)891 string Game::findFactionLogoFile(const GameSettings *settings, Logger *logger,
892 		string factionLogoFilter) {
893 	string result = "";
894 	if(settings == NULL) {
895 		result = "";
896 	}
897 	else {
898 		string mapName			= settings->getMap();
899 		string tilesetName		= settings->getTileset();
900 		string techName			= settings->getTech();
901 		string scenarioName		= settings->getScenario();
902 		bool loadingImageUsed	= false;
903 
904 		if(logger != NULL) {
905 			logger->setState(Lang::getInstance().getString("Loading"));
906 
907 			if(scenarioName.empty()) {
908 				string scenarioDir = extractDirectoryPathFromFile(settings->getScenarioDir());
909 				TechTree techTree(Config::getInstance().getPathListForType(ptTechs,scenarioDir));
910 
911 				logger->setSubtitle(formatString(mapName) + " - " +
912 						formatString(tilesetName) + " - " + formatString(techTree.getTranslatedName(techName)));
913 			}
914 			else {
915 				logger->setSubtitle(formatString(scenarioName));
916 			}
917 		}
918 
919 		string scenarioDir = "";
920 		bool skipCustomLoadScreen = false;
921 		if(skipCustomLoadScreen == false) {
922 			scenarioDir = extractScenarioLogoFile(settings, result, loadingImageUsed,
923 					logger, factionLogoFilter);
924 		}
925 		// try to use a faction related loading screen
926 		if(skipCustomLoadScreen == false && loadingImageUsed == false) {
927 			for(int i=0; i < settings->getFactionCount(); ++i ) {
928 				if( settings->getFactionControl(i) == ctHuman ||
929 					(settings->getFactionControl(i) == ctNetwork && settings->getThisFactionIndex() == i)) {
930 
931 					result = extractFactionLogoFile(loadingImageUsed, settings->getFactionTypeName(i),
932 						scenarioDir, techName, logger, factionLogoFilter);
933 					break;
934 				}
935 			}
936 		}
937 
938 		// try to use a tech related loading screen
939 		if(skipCustomLoadScreen == false && loadingImageUsed == false){
940 			result = extractTechLogoFile(scenarioDir, techName,
941 					loadingImageUsed, logger, factionLogoFilter);
942 		}
943 	}
944 	return result;
945 }
946 
processTech(string techName)947 vector<Texture2D *> Game::processTech(string techName) {
948 	vector<Texture2D *> logoFiles;
949 	bool enableFactionTexturePreview = Config::getInstance().getBool("FactionPreview","true");
950 	if(enableFactionTexturePreview) {
951 		//string currentTechName_factionPreview = techName;
952 
953 		vector<string> factions;
954 		vector<string> techPaths = Config::getInstance().getPathListForType(ptTechs);
955 		for(int idx = 0; idx < (int)techPaths.size(); idx++) {
956 			string &techPath = techPaths[idx];
957 			endPathWithSlash(techPath);
958 			findAll(techPath + techName + "/factions/*.", factions, false, false);
959 
960 			if(factions.empty() == false) {
961 				for(unsigned int factionIdx = 0; factionIdx < (unsigned int)factions.size(); ++factionIdx) {
962 					bool loadingImageUsed = false;
963 					string currentFactionName_factionPreview = factions[factionIdx];
964 
965 					string factionLogo = Game::extractFactionLogoFile(
966 							loadingImageUsed,
967 							currentFactionName_factionPreview,
968 							"",
969 							techName,
970 							NULL,
971 							GameConstants::PREVIEW_SCREEN_FILE_FILTER);
972 
973 					if(factionLogo == "") {
974 						factionLogo = Game::extractFactionLogoFile(
975 								loadingImageUsed,
976 								currentFactionName_factionPreview,
977 								"",
978 								techName,
979 								NULL,
980 								GameConstants::LOADING_SCREEN_FILE_FILTER);
981 					}
982 					if(factionLogo != "") {
983 						Texture2D *texture = Renderer::preloadTexture(factionLogo);
984 						logoFiles.push_back(texture);
985 					}
986 				}
987 			}
988 		}
989 	}
990 
991 	return logoFiles;
992 }
993 
load()994 void Game::load() {
995 	load(lgt_All);
996 }
997 
load(int loadTypes)998 void Game::load(int loadTypes) {
999 	bool showPerfStats = Config::getInstance().getBool("ShowPerfStats","false");
1000 	Chrono chronoPerf;
1001 	if(showPerfStats) chronoPerf.start();
1002 	char perfBuf[8096]="";
1003 	std::vector<string> perfList;
1004 
1005 	if(showPerfStats) {
1006 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1007 		perfList.push_back(perfBuf);
1008 	}
1009 
1010 	FileCRCPreCacheThread * &preCacheCRCThreadPtr = CacheManager::getCachedItem< FileCRCPreCacheThread * >(GameConstants::preCacheThreadCacheLookupKey);
1011 	if(preCacheCRCThreadPtr != NULL) {
1012 		preCacheCRCThreadPtr->setPauseForGame(true);
1013 	}
1014 
1015 	std::map<string,vector<pair<string, string> > > loadedFileList;
1016 	originalDisplayMsgCallback = NetworkInterface::getDisplayMessageFunction();
1017 	NetworkInterface::setDisplayMessageFunction(ErrorDisplayMessage);
1018 
1019 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] loadTypes = %d, gameSettings = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,loadTypes,this->gameSettings.toString().c_str());
1020 
1021 	SoundRenderer &soundRenderer= SoundRenderer::getInstance();
1022 	soundRenderer.stopAllSounds(fadeMusicMilliseconds);
1023 
1024 	BaseColorPickEntity::resetUniqueColors();
1025 
1026 	Config &config = Config::getInstance();
1027 	Logger &logger= Logger::getInstance();
1028 
1029 	string mapName= gameSettings.getMap();
1030 	string tilesetName= gameSettings.getTileset();
1031 	string techName= gameSettings.getTech();
1032 	string scenarioName= gameSettings.getScenario();
1033 	string data_path= getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
1034 	// loadHints
1035 
1036 	if(data_path != ""){
1037 		endPathWithSlash(data_path);
1038 	}
1039 
1040 	string user_data_path = config.getString("UserData_Root","");
1041 	if(user_data_path != "") {
1042 		endPathWithSlash(user_data_path);
1043 	}
1044 
1045 	string englishFile=getGameCustomCoreDataPath(data_path, "data/lang/hint/hint_"+Lang::getInstance().getDefaultLanguage()+".lng");
1046 	string languageFile=getGameCustomCoreDataPath(data_path, "data/lang/hint/hint_"+ Lang::getInstance().getLanguage() +".lng");
1047 	string languageFileUserData=user_data_path + "data/lang/hint/hint_"+ Lang::getInstance().getLanguage() +".lng";
1048 
1049 	if(fileExists(languageFileUserData) == true){
1050 		languageFile=languageFileUserData;
1051 	}
1052 	if(fileExists(languageFile) == false){
1053 		// if there is no language specific file use english instead
1054 		languageFile=englishFile;
1055 	}
1056 	if(fileExists(englishFile) == false){
1057 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] file [%s] not found\n",__FILE__,__FUNCTION__,__LINE__,englishFile.c_str());
1058 	}
1059 	else {
1060 		logger.loadGameHints(englishFile,languageFile,true);
1061 
1062 		::Shared::Platform::Window::handleEvent();
1063 		SDL_PumpEvents();
1064 	}
1065 
1066 	if((loadTypes & lgt_FactionPreview) == lgt_FactionPreview) {
1067 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1068 		Game::findFactionLogoFile(&gameSettings, &logger);
1069 
1070 		::Shared::Platform::Window::handleEvent();
1071 		SDL_PumpEvents();
1072 	}
1073 
1074 	if(showPerfStats) {
1075 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1076 		perfList.push_back(perfBuf);
1077 	}
1078 
1079 	loadHudTexture(&gameSettings);
1080 
1081 	const string markCellTextureFilename = data_path + "data/core/misc_textures/mark_cell.png";
1082 	markCellTexture = Renderer::findTexture(markCellTextureFilename);
1083 	const string unmarkCellTextureFilename = data_path + "data/core/misc_textures/unmark_cell.png";
1084 	unmarkCellTexture = Renderer::findTexture(unmarkCellTextureFilename);
1085 	const string highlightCellTextureFilename = data_path + "data/core/misc_textures/pointer.png";
1086 	highlightCellTexture = Renderer::findTexture(highlightCellTextureFilename);
1087 
1088     string scenarioDir = "";
1089     if(gameSettings.getScenarioDir() != "") {
1090     	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1091         scenarioDir = gameSettings.getScenarioDir();
1092         if(EndsWith(scenarioDir, ".xml") == true) {
1093             scenarioDir = scenarioDir.erase(scenarioDir.size() - 4, 4);
1094             scenarioDir = scenarioDir.erase(scenarioDir.size() - gameSettings.getScenario().size(), gameSettings.getScenario().size() + 1);
1095         }
1096     }
1097 
1098 	if(showPerfStats) {
1099 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1100 		perfList.push_back(perfBuf);
1101 	}
1102 
1103     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1104 
1105 	//tileset
1106 	if((loadTypes & lgt_TileSet) == lgt_TileSet) {
1107 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1108 		world.loadTileset(	config.getPathListForType(ptTilesets,scenarioDir),
1109     						tilesetName, &checksum, loadedFileList);
1110 	}
1111 
1112 	if(showPerfStats) {
1113 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1114 		perfList.push_back(perfBuf);
1115 	}
1116 
1117     // give CPU time to update other things to avoid apperance of hanging
1118     sleep(0);
1119     ::Shared::Platform::Window::handleEvent();
1120 	SDL_PumpEvents();
1121 
1122 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1123 
1124     set<string> factions;
1125 	for ( int i=0; i < gameSettings.getFactionCount(); ++i ) {
1126 		factions.insert(gameSettings.getFactionTypeName(i));
1127 	}
1128 
1129 	if(showPerfStats) {
1130 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1131 		perfList.push_back(perfBuf);
1132 	}
1133 
1134     if((loadTypes & lgt_TechTree) == lgt_TechTree) {
1135     	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1136 
1137 		//tech, load before map because of resources
1138 		world.loadTech(	config.getPathListForType(ptTechs,scenarioDir), techName,
1139 						factions, &checksum,loadedFileList);
1140 
1141 		if(world.getTechTree() == NULL || world.getTechTree()->getNameUntranslated() == "") {
1142 			char szBuf[8096]="";
1143 			snprintf(szBuf,8096,"Line ref: %d, ERROR: Cannot find techtree: [%s]",__LINE__,techName.c_str());
1144 
1145 			throw megaglest_runtime_error(szBuf, true);
1146 		}
1147     }
1148 
1149 	if(showPerfStats) {
1150 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1151 		perfList.push_back(perfBuf);
1152 	}
1153 
1154     // give CPU time to update other things to avoid apperance of hanging
1155     sleep(0);
1156     ::Shared::Platform::Window::handleEvent();
1157 	SDL_PumpEvents();
1158 
1159 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1160 
1161     //map
1162     if((loadTypes & lgt_Map) == lgt_Map) {
1163     	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1164     	world.loadMap(Config::getMapPath(mapName,scenarioDir), &checksum);
1165     }
1166 
1167 	if(showPerfStats) {
1168 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1169 		perfList.push_back(perfBuf);
1170 	}
1171 
1172     // give CPU time to update other things to avoid apperance of hanging
1173     sleep(0);
1174     ::Shared::Platform::Window::handleEvent();
1175 	SDL_PumpEvents();
1176 
1177 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1178 
1179     //scenario
1180     if((loadTypes & lgt_Scenario) == lgt_Scenario) {
1181     	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1182 		if(scenarioName.empty() == false) {
1183 
1184 			bool isTutorial = Scenario::isGameTutorial(gameSettings.getScenarioDir());
1185 			//printf("Loading scenario gameSettings.getScenarioDir() [%s] scenarioName [%s] isTutorial: %d\n",gameSettings.getScenarioDir().c_str(),scenarioName.c_str(),isTutorial);
1186 
1187 			Lang::getInstance().loadScenarioStrings(gameSettings.getScenarioDir(), scenarioName, isTutorial);
1188 
1189 			//printf("In [%s::%s Line: %d] rootNode [%p][%s]\n",__FILE__,__FUNCTION__,__LINE__,loadGameNode,(loadGameNode != NULL ? loadGameNode->getName().c_str() : "none"));
1190 			world.loadScenario(gameSettings.getScenarioDir(), &checksum, false,loadGameNode);
1191 		}
1192     }
1193 
1194 	if(showPerfStats) {
1195 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1196 		perfList.push_back(perfBuf);
1197 	}
1198 
1199     // give CPU time to update other things to avoid apperance of hanging
1200     sleep(0);
1201 	SDL_PumpEvents();
1202 
1203 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1204     //good_fpu_control_registers(NULL,extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1205 
1206 	if(showPerfStats && chronoPerf.getMillis() >= 50) {
1207 		for(unsigned int x = 0; x < perfList.size(); ++x) {
1208 			printf("%s",perfList[x].c_str());
1209 		}
1210 	}
1211 }
1212 
init()1213 void Game::init() {
1214 	init(false);
1215 }
1216 
init(bool initForPreviewOnly)1217 void Game::init(bool initForPreviewOnly) {
1218 	bool showPerfStats = Config::getInstance().getBool("ShowPerfStats","false");
1219 	Chrono chronoPerf;
1220 	if(showPerfStats) chronoPerf.start();
1221 	char perfBuf[8096]="";
1222 	std::vector<string> perfList;
1223 
1224 	if(showPerfStats) {
1225 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1226 		perfList.push_back(perfBuf);
1227 	}
1228 
1229 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] initForPreviewOnly = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,initForPreviewOnly);
1230 
1231 	Lang &lang= Lang::getInstance();
1232 	Logger &logger= Logger::getInstance();
1233 	CoreData &coreData= CoreData::getInstance();
1234 	Renderer &renderer= Renderer::getInstance();
1235 	Map *map= world.getMap();
1236 	NetworkManager &networkManager= NetworkManager::getInstance();
1237 
1238 	GameSettings::playerDisconnectedText = "*" + lang.getString("AI") + "* ";
1239 
1240 	if(map == NULL) {
1241 		throw megaglest_runtime_error("map == NULL");
1242 	}
1243 
1244 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1245 
1246 	if(initForPreviewOnly == false) {
1247 		logger.setState(lang.getString("Initializing"));
1248 
1249 		//message box
1250 		mainMessageBox.init(lang.getString("Yes"), lang.getString("No"));
1251 		mainMessageBox.setEnabled(false);
1252 
1253 		//message box
1254 		errorMessageBox.init(lang.getString("Ok"));
1255 		errorMessageBox.setEnabled(false);
1256 		errorMessageBox.setY(20);
1257 
1258 
1259 		//init world, and place camera
1260 		commander.init(&world);
1261 
1262 		// give CPU time to update other things to avoid apperance of hanging
1263 		sleep(0);
1264 		::Shared::Platform::Window::handleEvent();
1265 		SDL_PumpEvents();
1266 	}
1267 
1268 	try {
1269 		world.init(this, gameSettings.getDefaultUnits());
1270 	}
1271 	catch(const megaglest_runtime_error &ex) {
1272 		string sErrBuf = "";
1273 		if(ex.wantStackTrace() == true) {
1274 			char szErrBuf[8096]="";
1275 			snprintf(szErrBuf,8096,"In [%s::%s %d]",__FILE__,__FUNCTION__,__LINE__);
1276 			sErrBuf = string(szErrBuf) + string("\nerror [") + string(ex.what()) + string("]\n");
1277 		}
1278 		else {
1279 			sErrBuf = ex.what();
1280 		}
1281 		SystemFlags::OutputDebug(SystemFlags::debugError,sErrBuf.c_str());
1282 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,sErrBuf.c_str());
1283 
1284 		if(errorMessageBox.getEnabled() == false) {
1285 			ErrorDisplayMessage(ex.what(),true);
1286 		}
1287 	}
1288 	catch(const exception &ex) {
1289 		char szErrBuf[8096]="";
1290 		snprintf(szErrBuf,8096,"In [%s::%s %d]",__FILE__,__FUNCTION__,__LINE__);
1291 		string sErrBuf = string(szErrBuf) + string("\nerror [") + string(ex.what()) + string("]\n");
1292 		SystemFlags::OutputDebug(SystemFlags::debugError,sErrBuf.c_str());
1293 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,sErrBuf.c_str());
1294 
1295 		if(errorMessageBox.getEnabled() == false) {
1296 			ErrorDisplayMessage(ex.what(),true);
1297 		}
1298 	}
1299 
1300 	if(showPerfStats) {
1301 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1302 		perfList.push_back(perfBuf);
1303 	}
1304 
1305 	if(loadGameNode != NULL) {
1306 		//world.getMapPtr()->loadGame(loadGameNode,&world);
1307 	}
1308 
1309 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1310 
1311 	if(initForPreviewOnly == false) {
1312 		// give CPU time to update other things to avoid apperance of hanging
1313 		sleep(0);
1314 		::Shared::Platform::Window::handleEvent();
1315 		SDL_PumpEvents();
1316 
1317 		gui.init(this);
1318 
1319 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1320 
1321 		// give CPU time to update other things to avoid apperance of hanging
1322 		sleep(0);
1323 		//SDL_PumpEvents();
1324 
1325 		chatManager.init(&console, world.getThisTeamIndex());
1326 		console.clearStoredLines();
1327 	}
1328 
1329 	if(showPerfStats) {
1330 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1331 		perfList.push_back(perfBuf);
1332 	}
1333 
1334 	if(this->loadGameNode == NULL) {
1335 		initCamera(map);
1336 	}
1337 	else {
1338 		gui.loadGame(loadGameNode,&world);
1339 
1340 		if(inJoinGameLoading == true) {
1341 			initCamera(map);
1342 		}
1343 	}
1344 
1345 	if(showPerfStats) {
1346 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1347 		perfList.push_back(perfBuf);
1348 	}
1349 
1350 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1351 
1352 	NetworkRole role = nrIdle;
1353 	if(initForPreviewOnly == false) {
1354 		// give CPU time to update other things to avoid apperance of hanging
1355 		sleep(0);
1356 		::Shared::Platform::Window::handleEvent();
1357 		SDL_PumpEvents();
1358 
1359 		scriptManager.init(&world, &gameCamera,loadGameNode);
1360 
1361 		//good_fpu_control_registers(NULL,extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1362 
1363 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] creating AI's\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1364 
1365 		//create AIs
1366 
1367 		bool enableServerControlledAI 	= this->gameSettings.getEnableServerControlledAI();
1368 		bool isNetworkGame 				= this->gameSettings.isNetworkGame();
1369 		role 							= networkManager.getNetworkRole();
1370 
1371 		masterController.clearSlaves(true);
1372 		deleteValues(aiInterfaces.begin(), aiInterfaces.end());
1373 
1374 		std::vector<SlaveThreadControllerInterface *> slaveThreadList;
1375 		aiInterfaces.resize(world.getFactionCount());
1376 		for(int i=0; i < world.getFactionCount(); ++i) {
1377 			Faction *faction= world.getFaction(i);
1378 
1379 			//printf("Controltype = %d for index = %d\n",faction->getControlType(),i);
1380 
1381 			if(faction->getCpuControl(enableServerControlledAI,isNetworkGame,role) == true) {
1382 				//printf("** Loading AI player for Controltype = %d for index = %d\n",faction->getControlType(),i);
1383 
1384 				aiInterfaces[i]= new AiInterface(*this, i, faction->getTeam());
1385 				if(loadGameNode != NULL) {
1386 					aiInterfaces[i]->loadGame(loadGameNode,faction);
1387 				}
1388 				char szBuf[8096]="";
1389 				snprintf(szBuf,8096,Lang::getInstance().getString("LogScreenGameLoadingCreatingAIFaction","",true).c_str(),i);
1390 				logger.add(szBuf, true);
1391 
1392 				slaveThreadList.push_back(aiInterfaces[i]->getWorkerThread());
1393 			}
1394 			else {
1395 				aiInterfaces[i]= NULL;
1396 			}
1397 		}
1398 		if(Config::getInstance().getBool("EnableNewThreadManager","false") == true) {
1399 			masterController.setSlaves(slaveThreadList);
1400 		}
1401 
1402 		if(showPerfStats) {
1403 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1404 			perfList.push_back(perfBuf);
1405 		}
1406 
1407 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1408 
1409 		// give CPU time to update other things to avoid apperance of hanging
1410 		sleep(0);
1411 		::Shared::Platform::Window::handleEvent();
1412 		SDL_PumpEvents();
1413 
1414 		if(world.getFactionCount() == 1 && world.getFaction(0)->getPersonalityType() == fpt_Observer) {
1415 			withRainEffect = false;
1416 		}
1417 
1418 		if(withRainEffect) {
1419 			//weather particle systems
1420 			if(world.getTileset()->getWeather() == wRainy) {
1421 				logger.add(Lang::getInstance().getString("LogScreenGameLoadingCreatingRainParticles","",true), true);
1422 				weatherParticleSystem= new RainParticleSystem();
1423 				weatherParticleSystem->setSpeed(12.f / GameConstants::updateFps);
1424 				weatherParticleSystem->setPos(gameCamera.getPos());
1425 				renderer.manageParticleSystem(weatherParticleSystem, rsGame);
1426 			}
1427 			else if(world.getTileset()->getWeather() == wSnowy) {
1428 				logger.add(Lang::getInstance().getString("LogScreenGameLoadingCreatingSnowParticles","",true), true);
1429 				weatherParticleSystem= new SnowParticleSystem(1200);
1430 				weatherParticleSystem->setSpeed(1.5f / GameConstants::updateFps);
1431 				weatherParticleSystem->setPos(gameCamera.getPos());
1432 				weatherParticleSystem->setTexture(coreData.getSnowTexture());
1433 				renderer.manageParticleSystem(weatherParticleSystem, rsGame);
1434 			}
1435 		}
1436 		else if(world.getTileset()->getWeather() == wRainy) {
1437 			world.getTileset()->setWeather(wSunny);
1438 		}
1439 
1440 		renderer.manageDeferredParticleSystems();
1441     }
1442 
1443 	if(showPerfStats) {
1444 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1445 		perfList.push_back(perfBuf);
1446 	}
1447 
1448 	//init renderer state
1449 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Initializing renderer\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
1450 	logger.add(Lang::getInstance().getString("LogScreenGameLoadingInitRenderer","",true), true);
1451 
1452 	//printf("Before renderer.initGame\n");
1453 	renderer.initGame(this,this->getGameCameraPtr());
1454 	//printf("After renderer.initGame\n");
1455 
1456 	if(showPerfStats) {
1457 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1458 		perfList.push_back(perfBuf);
1459 	}
1460 
1461 	for(int i=0; i < world.getFactionCount(); ++i) {
1462 		Faction *faction= world.getFaction(i);
1463 		if(faction != NULL) {
1464 			faction->deletePixels();
1465 		}
1466 	}
1467 
1468 	if(showPerfStats) {
1469 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1470 		perfList.push_back(perfBuf);
1471 	}
1472 
1473 	if(initForPreviewOnly == false) {
1474 		//good_fpu_control_registers(NULL,extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1475 
1476 		// give CPU time to update other things to avoid apperance of hanging
1477 		sleep(0);
1478 		::Shared::Platform::Window::handleEvent();
1479 		SDL_PumpEvents();
1480 
1481 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Waiting for network\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__);
1482 		logger.add(Lang::getInstance().getString("LogScreenGameLoadingWaitForNetworkPlayers","",true), true);
1483 		networkManager.getGameNetworkInterface()->waitUntilReady(&checksum);
1484 
1485 		//std::string worldLog = world.DumpWorldToLog(true);
1486 
1487 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Starting music stream\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1488 		logger.add(Lang::getInstance().getString("LogScreenGameLoadingStartingMusic","",true), true);
1489 
1490 		if(this->masterserverMode == false) {
1491 			if(world.getThisFaction() == NULL) {
1492 				throw megaglest_runtime_error("world.getThisFaction() == NULL");
1493 			}
1494 			if(world.getThisFaction()->getType() == NULL) {
1495 				throw megaglest_runtime_error("world.getThisFaction()->getType() == NULL");
1496 			}
1497 			//if(world.getThisFaction()->getType()->getMusic() == NULL) {
1498 			//	throw megaglest_runtime_error("world.getThisFaction()->getType()->getMusic() == NULL");
1499 			//}
1500 		}
1501 
1502 		//sounds
1503 		SoundRenderer &soundRenderer= SoundRenderer::getInstance();
1504 		soundRenderer.stopAllSounds(fadeMusicMilliseconds);
1505 		soundRenderer= SoundRenderer::getInstance();
1506 
1507 		Tileset *tileset= world.getTileset();
1508 		AmbientSounds *ambientSounds= tileset->getAmbientSounds();
1509 
1510 		//rain
1511 		if(tileset->getWeather() == wRainy && ambientSounds->isEnabledRain()) {
1512 			logger.add(Lang::getInstance().getString("LogScreenGameLoadingStartingAmbient","",true), true);
1513 			currentAmbientSound = ambientSounds->getRain();
1514 			//printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound);
1515 			soundRenderer.playAmbient(currentAmbientSound);
1516 		}
1517 
1518 		//snow
1519 		if(tileset->getWeather() == wSnowy && ambientSounds->isEnabledSnow()) {
1520 			logger.add(Lang::getInstance().getString("LogScreenGameLoadingStartingAmbient","",true), true);
1521 			currentAmbientSound = ambientSounds->getSnow();
1522 			//printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound);
1523 			soundRenderer.playAmbient(currentAmbientSound);
1524 		}
1525 
1526 		if(this->masterserverMode == false) {
1527 			StrSound *gameMusic= world.getThisFaction()->getType()->getMusic();
1528 			soundRenderer.playMusic(gameMusic);
1529 		}
1530 
1531 		logger.add(Lang::getInstance().getString("LogScreenGameLoadingLaunchGame","",true));
1532 	}
1533 
1534 	if(showPerfStats) {
1535 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1536 		perfList.push_back(perfBuf);
1537 	}
1538 
1539 	//throw "test";
1540 
1541 	logger.setCancelLoadingEnabled(false);
1542 
1543 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"================ STARTING GAME ================\n");
1544 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled) SystemFlags::OutputDebug(SystemFlags::debugPathFinder,"================ STARTING GAME ================\n");
1545 	setupPopupMenus(false);
1546 
1547 	for(int i=0; i < world.getFactionCount(); ++i) {
1548 		Faction *faction= world.getFaction(i);
1549 
1550 		//printf("Check for team switch to observer i = %d, team = %d [%d]\n",i,faction->getTeam(),(GameConstants::maxPlayers -1 + fpt_Observer));
1551 		if(faction != NULL && faction->getTeam() == GameConstants::maxPlayers -1 + fpt_Observer) {
1552 			faction->setPersonalityType(fpt_Observer);
1553 			world.getStats()->setPersonalityType(i, faction->getPersonalityType());
1554 		}
1555 	}
1556 
1557 	if(showPerfStats) {
1558 		sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1559 		perfList.push_back(perfBuf);
1560 	}
1561 
1562 	if(role == nrClient) {
1563 		ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
1564 		if(clientInterface != NULL && clientInterface->getResumeInGameJoin() == true) {
1565 
1566 			//printf("Client sending resume message to server...\n");
1567 
1568 			clientInterface->sendResumeGameMessage();
1569 			//this->initialResumeSpeedLoops = true;
1570 		}
1571 	}
1572 
1573 	printf("Game unique identifier is: %s\n",this->gameSettings.getGameUUID().c_str());
1574 
1575 	gameStarted = true;
1576 
1577 	if(this->masterserverMode == true) {
1578 		world.getStats()->setIsMasterserverMode(true);
1579 
1580 		printf("New game has started...\n");
1581 	}
1582 
1583 	if(isFlagType1BitEnabled(ft1_network_synch_checks_verbose) == true) {
1584 		printf("*Note: Monitoring Network CRC VERBOSE synchronization...\n");
1585 	}
1586 	else if(isFlagType1BitEnabled(ft1_network_synch_checks) == true) {
1587 		printf("*Note: Monitoring Network CRC NORMAL synchronization...\n");
1588 	}
1589 
1590 	//NetworkRole role = networkManager.getNetworkRole();
1591 	if(role == nrServer) {
1592 		networkManager.initServerInterfaces(this);
1593 	}
1594 
1595 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] ==== START GAME ==== getCurrentPixelByteCount() = " MG_SIZE_T_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderer.getCurrentPixelByteCount());
1596 
1597 	if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"=============================================\n");
1598 	if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"==== START GAME ====\n");
1599 	if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"=============================================\n");
1600 	if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"Starting framecount: %d\n",world.getFrameCount());
1601 
1602 	if(showPerfStats && chronoPerf.getMillis() >= 50) {
1603 		for(unsigned int x = 0; x < perfList.size(); ++x) {
1604 			printf("%s",perfList[x].c_str());
1605 		}
1606 	}
1607 }
1608 
initCamera(Map * map)1609 void Game::initCamera(Map *map){
1610 	gameCamera.init(map->getW(), map->getH());
1611 
1612 	// camera default height calculation
1613 	if(map->getCameraHeight()>0 && gameCamera.getCalculatedDefault()<map->getCameraHeight()){
1614 		gameCamera.setCalculatedDefault(map->getCameraHeight());
1615 	}
1616 	else if(gameCamera.getCalculatedDefault()<map->getMaxMapHeight()+13.0f){
1617 		gameCamera.setCalculatedDefault(map->getMaxMapHeight()+13.0f);
1618 	}
1619 
1620 	if(world.getThisFaction() != NULL) {
1621 		const Vec2i &v= map->getStartLocation(world.getThisFaction()->getStartLocationIndex());
1622 		gameCamera.setPos(Vec2f(v.x, v.y+gameCamera.getCalculatedDefault()/2));
1623 	}
1624 }
1625 
1626 // ==================== update ====================
1627 
reInitGUI()1628 void Game::reInitGUI() {
1629 	gui.init(this);
1630 }
1631 
setupPopupMenus(bool checkClientAdminOverrideOnly)1632 void Game::setupPopupMenus(bool checkClientAdminOverrideOnly) {
1633 	Lang &lang= Lang::getInstance();
1634 	NetworkManager &networkManager= NetworkManager::getInstance();
1635 	NetworkRole role = networkManager.getNetworkRole();
1636 	ClientInterface *clientInterface = NULL;
1637 	ServerInterface *serverInterface = NULL;
1638 
1639 	bool allowAdminMenuItems = false;
1640 	bool forceJoinInProgressUpdate = false;
1641 	if(role == nrServer) {
1642 		allowAdminMenuItems = true;
1643 
1644 		if(disconnectPlayerPopupMenuIndex == -1) {
1645 			serverInterface = dynamic_cast<ServerInterface *>(networkManager.getServerInterface());
1646 			if(serverInterface != NULL && checkClientAdminOverrideOnly == true) {
1647 				for(int i = 0; i < world.getFactionCount(); ++i) {
1648 					Faction *faction = world.getFaction(i);
1649 
1650 					MutexSafeWrapper safeMutex(serverInterface->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
1651 					ConnectionSlot *slot =  serverInterface->getSlot(faction->getStartLocationIndex(),false);
1652 					if(slot != NULL && slot->getConnectHasHandshaked() == true &&
1653 							slot->getCurrentFrameCount() <= 0) {
1654 						//printf("Connected slot can be disconnected: %d\n",slot->getPlayerIndex());
1655 
1656 						forceJoinInProgressUpdate = true;
1657 						break;
1658 					}
1659 				}
1660 			}
1661 		}
1662 	}
1663 	else if(role == nrClient) {
1664 		clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
1665 
1666 		if(clientInterface != NULL &&
1667 			(gameSettings.getMasterserver_admin() == clientInterface->getSessionKey() ||
1668 					clientInterface->isMasterServerAdminOverride() == true)) {
1669 			allowAdminMenuItems = true;
1670 		}
1671 	}
1672 
1673 	if(checkClientAdminOverrideOnly == false ||
1674 			forceJoinInProgressUpdate == true ||
1675 			(clientInterface != NULL &&
1676 			 (gameSettings.getMasterserver_admin() != clientInterface->getSessionKey() &&
1677 					clientInterface->isMasterServerAdminOverride() == true))) {
1678 		exitGamePopupMenuIndex = -1;
1679 		joinTeamPopupMenuIndex = -1;
1680 		pauseGamePopupMenuIndex = -1;
1681 		saveGamePopupMenuIndex = -1;
1682 		loadGamePopupMenuIndex = -1;
1683 		keyboardSetupPopupMenuIndex = -1;
1684 		disconnectPlayerPopupMenuIndex = -1;
1685 
1686 		if(checkClientAdminOverrideOnly == true && clientInterface != NULL) {
1687 			gameSettings.setMasterserver_admin(clientInterface->getSessionKey());
1688 			gameSettings.setMasterserver_admin_faction_index(clientInterface->getPlayerIndex());
1689 		}
1690 		//PopupMenu popupMenu;
1691 		std::vector<string> menuItems;
1692 		menuItems.push_back("  " + lang.getString("ExitGameMenu") + "  ");
1693 		exitGamePopupMenuIndex = (int)menuItems.size()-1;
1694 
1695 		if((gameSettings.getFlagTypes1() & ft1_allow_team_switching) == ft1_allow_team_switching &&
1696 			world.getThisFaction() != NULL && world.getThisFaction()->getPersonalityType() != fpt_Observer) {
1697 			menuItems.push_back("  " + lang.getString("JoinOtherTeam") + "  ");
1698 			joinTeamPopupMenuIndex = (int)menuItems.size()-1;
1699 		}
1700 
1701 		if(allowAdminMenuItems == true){
1702 			menuItems.push_back("  " + lang.getString("PauseResumeGame") + "  ");
1703 			pauseGamePopupMenuIndex= (int)menuItems.size() - 1;
1704 
1705 			if(gameSettings.isNetworkGame() == false || gameSettings.getScenario() != "") {
1706 				menuItems.push_back("  " + lang.getString("SaveGame") + "  ");
1707 				saveGamePopupMenuIndex= (int)menuItems.size() - 1;
1708 			}
1709 
1710 			if(gameSettings.isNetworkGame() == true) {
1711 				menuItems.push_back("  " + lang.getString("DisconnectNetorkPlayer") + "  ");
1712 				disconnectPlayerPopupMenuIndex= (int)menuItems.size() - 1;
1713 			}
1714 		}
1715 		menuItems.push_back("  " + lang.getString("KeyboardsetupL") + "  ");
1716 		keyboardSetupPopupMenuIndex = (int)menuItems.size()-1;
1717 
1718 		menuItems.push_back("  " + lang.getString("Cancel") + "  ");
1719 
1720 		popupMenu.setW(100);
1721 		popupMenu.setH(100);
1722 		popupMenu.init("  " + lang.getString("GameMenuTitle") + "  ",menuItems);
1723 		popupMenu.setEnabled(false);
1724 		popupMenu.setVisible(false);
1725 
1726 		popupMenuSwitchTeams.setEnabled(false);
1727 		popupMenuSwitchTeams.setVisible(false);
1728 
1729 		popupMenuDisconnectPlayer.setEnabled(false);
1730 		popupMenuDisconnectPlayer.setVisible(false);
1731 	}
1732 }
1733 
processNetworkSynchChecksIfRequired()1734 void Game::processNetworkSynchChecksIfRequired() {
1735 	bool isNetworkGame = this->gameSettings.isNetworkGame();
1736 	if (isNetworkGame == true && NetworkManager::getInstance().getGameNetworkInterface() != NULL) {
1737 		GameSettings *settings = world.getGameSettingsPtr();
1738 		if(settings != NULL) {
1739 			bool calculateNetworkCRC = false;
1740 
1741 			if(isFlagType1BitEnabled(ft1_network_synch_checks) == true ||
1742 				isFlagType1BitEnabled(ft1_network_synch_checks_verbose) == true) {
1743 				calculateNetworkCRC = true;
1744 			}
1745 
1746 			if(calculateNetworkCRC == true) {
1747 				NetworkManager &networkManager = NetworkManager::getInstance();
1748 				NetworkRole role = networkManager.getNetworkRole();
1749 
1750 				NetworkInterface *netIntf = networkManager.getGameNetworkInterface();
1751 				for(int index = 0; index < GameConstants::maxPlayers; ++index) {
1752 					if(index < world.getFactionCount()) {
1753 						Faction *faction = world.getFaction(index);
1754 						netIntf->setNetworkPlayerFactionCRC(index,faction->getCRC().getSum());
1755 
1756 						if(settings != NULL) {
1757 							if(isFlagType1BitEnabled(ft1_network_synch_checks_verbose) == true) {
1758 								faction->addCRC_DetailsForWorldFrame(world.getFrameCount(),role == nrServer);
1759 							}
1760 							else if(isFlagType1BitEnabled(ft1_network_synch_checks) == true &&
1761 									world.getFrameCount() % 20 == 0) {
1762 								faction->addCRC_DetailsForWorldFrame(world.getFrameCount(),role == nrServer);
1763 							}
1764 						}
1765 					}
1766 					else {
1767 						netIntf->setNetworkPlayerFactionCRC(index,0);
1768 					}
1769 				}
1770 			}
1771 		}
1772 	}
1773 }
1774 
1775 //update
update()1776 void Game::update() {
1777 	try {
1778 		if(currentUIState != NULL) {
1779 			currentUIState->update();
1780 		}
1781 
1782 		bool showPerfStats = Config::getInstance().getBool("ShowPerfStats","false");
1783 		Chrono chronoPerf;
1784 		char perfBuf[8096]="";
1785 		std::vector<string> perfList;
1786 		if(showPerfStats) chronoPerf.start();
1787 
1788 		if(showPerfStats) {
1789 			sprintf(perfBuf,"=============== FRAME: %d In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",world.getFrameCount(),extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1790 			perfList.push_back(perfBuf);
1791 		}
1792 
1793 		Chrono chronoGamePerformanceCounts;
1794 		Chrono chrono;
1795 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
1796 
1797 		// a) Updates non dependent on speed
1798 
1799 		// set game stats for host
1800 		NetworkManager &networkManager	= NetworkManager::getInstance();
1801 		NetworkRole role 				= networkManager.getNetworkRole();
1802 		if(role == nrServer) {
1803 			ServerInterface *server = NetworkManager::getInstance().getServerInterface(false);
1804 			if(server != NULL) {
1805 				server->setGameStats(world.getStats());
1806 			}
1807 		}
1808 
1809 		bool pendingQuitError = (quitPendingIndicator == true ||
1810 								 (NetworkManager::getInstance().getGameNetworkInterface() != NULL &&
1811 								  NetworkManager::getInstance().getGameNetworkInterface()->getQuit()));
1812 
1813 		if(pendingQuitError == true &&
1814 		   (this->masterserverMode == true ||
1815 		    (mainMessageBox.getEnabled() == false && errorMessageBox.getEnabled() == false))) {
1816 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1817 
1818 			quitTriggeredIndicator = true;
1819 			return;
1820 		}
1821 
1822 		if(this->masterserverMode == false) {
1823 			if(world.getFactionCount() > 0 && world.getThisFaction()->getFirstSwitchTeamVote() != NULL) {
1824 				const SwitchTeamVote *vote = world.getThisFaction()->getFirstSwitchTeamVote();
1825 				GameSettings *settings = world.getGameSettingsPtr();
1826 
1827 				Lang &lang= Lang::getInstance();
1828 
1829 				char szBuf[8096]="";
1830 				if(lang.hasString("AllowPlayerJoinTeam") == true) {
1831 					snprintf(szBuf,8096,lang.getString("AllowPlayerJoinTeam").c_str(),settings->getNetworkPlayerName(vote->factionIndex).c_str(),vote->oldTeam,vote->newTeam);
1832 				}
1833 				else {
1834 					snprintf(szBuf,8096,"Allow player [%s] to join your team\n(changing from team# %d to team# %d)?",settings->getNetworkPlayerName(vote->factionIndex).c_str(),vote->oldTeam,vote->newTeam);
1835 				}
1836 
1837 				switchTeamConfirmMessageBox.setText(szBuf);
1838 				switchTeamConfirmMessageBox.init(lang.getString("Yes"), lang.getString("No"));
1839 				switchTeamConfirmMessageBox.setEnabled(true);
1840 
1841 				world.getThisFactionPtr()->setCurrentSwitchTeamVoteFactionIndex(vote->factionIndex);
1842 			}
1843 		}
1844 
1845 		//misc
1846 		updateFps++;
1847 		mouse2d= (mouse2d+1) % Renderer::maxMouse2dAnim;
1848 
1849 		//console
1850 		console.update();
1851 
1852 		// b) Updates depandant on speed
1853 		int updateLoops= getUpdateLoops();
1854 
1855 		// Temp speed boost when player first joins an in progress game
1856 		if(this->initialResumeSpeedLoops == true) {
1857 			printf("Resume In Progress Game: %d\n",__LINE__);
1858 
1859 			this->initialResumeSpeedLoops = false;
1860 			//updateLoops = 80;
1861 		}
1862 
1863 		chronoGamePerformanceCounts.start();
1864 		bool enableServerControlledAI 	= this->gameSettings.getEnableServerControlledAI();
1865 
1866 		if(role == nrClient && updateLoops == 1 && world.getFrameCount() >= (gameSettings.getNetworkFramePeriod() * 2) ) {
1867 			ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
1868 			if(clientInterface != NULL) {
1869 				uint64 lastNetworkFrameFromServer = clientInterface->getCachedLastPendingFrameCount();
1870 
1871 				/////////////////////////////////
1872 				// TTTT new attempt to make things smoother:
1873 				///////////////
1874 
1875 				////////////////////////////////////////////
1876 				//get stats of received/waiting for packages
1877 				////////////////////////////////////////////
1878 				// calculate current receive Index slot:
1879 				int index = ((world.getFrameCount()
1880 						- (world.getFrameCount()
1881 								% gameSettings.getNetworkFramePeriod()))
1882 								/ gameSettings.getNetworkFramePeriod())
1883 						% GameConstants::networkSmoothInterval;
1884 
1885 				// clean the next frame slot
1886 				receivedTooEarlyInFrames[(index+1)%GameConstants::networkSmoothInterval]=-1;
1887 				framesNeededToWaitForServerMessage[(index+1)%GameConstants::networkSmoothInterval]=-1;
1888 
1889 				if(receivedTooEarlyInFrames[index]==-1){
1890 					// we need to check if we already received something for next frame
1891 					if(lastNetworkFrameFromServer > 0 && lastNetworkFrameFromServer > (uint64)world.getFrameCount()) {
1892 						receivedTooEarlyInFrames[index]= lastNetworkFrameFromServer-world.getFrameCount();
1893 					}
1894 				}
1895 				if(framesNeededToWaitForServerMessage[index]==-1){
1896 					// calc time waiting for message in milliseconds to frames
1897 					int64 timeClientWaitedForLastMessage=clientInterface->getTimeClientWaitedForLastMessage();
1898 					if(timeClientWaitedForLastMessage>0){
1899 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("world.getFrameCount():%d index %d Client waited:%d ms\n",world.getFrameCount(),index,(int)timeClientWaitedForLastMessage);
1900 						framesNeededToWaitForServerMessage[index]=timeClientWaitedForLastMessage*GameConstants::updateFps/1000;
1901 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("ClienttimeClientWaitedForLastMessage:%d ms  which is %d frames \n",(int)timeClientWaitedForLastMessage,framesNeededToWaitForServerMessage[index]);
1902 					}
1903 					else {
1904 						framesNeededToWaitForServerMessage[index]=0;
1905 					}
1906 				}
1907 
1908 				////////////////////////////////////////////
1909 				//use the recorded stats of received/waiting for packages
1910 				////////////////////////////////////////////
1911 				//lets see if the client is in front and had to wait for messages ...
1912 
1913 				//lets see if all last recorded frames where received too early
1914 				int minimum=0;
1915 				int allowedMaxFallback=5;
1916 				int countOfMessagesReceivedTooEarly=0;
1917 				int countOfMessagesReceivedTooLate=0;
1918 				int sumOfTooLateFrames=0;
1919 				bool cleanupStats=false;
1920 
1921 				for( int i=0;i<GameConstants::networkSmoothInterval;i++){
1922 					if(receivedTooEarlyInFrames[i]>allowedMaxFallback){
1923 						countOfMessagesReceivedTooEarly++;
1924 						if ( minimum == 0 || minimum > receivedTooEarlyInFrames[i]  ){
1925 							minimum=receivedTooEarlyInFrames[i];
1926 						}
1927 					}
1928 					if(framesNeededToWaitForServerMessage[i]>0){
1929 						countOfMessagesReceivedTooLate++;
1930 						sumOfTooLateFrames+=framesNeededToWaitForServerMessage[i];
1931 					}
1932 				}
1933 
1934 				if( countOfMessagesReceivedTooEarly==GameConstants::networkSmoothInterval-1 ) // -1 because slot for next frame is already initialized
1935 				{// all packages where too early
1936 					// we catch up the minimum-catchupInterval of what we recorded
1937 					framesToCatchUpAsClient=minimum-allowedMaxFallback;
1938 					framesToSlowDownAsClient=0;
1939 					cleanupStats=true;
1940 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Worldframe %d : Client will speed up: %d frames\n",world.getFrameCount(),framesToCatchUpAsClient);
1941 				}
1942 				else if(countOfMessagesReceivedTooLate>3){
1943 					framesToSlowDownAsClient=sumOfTooLateFrames/countOfMessagesReceivedTooLate;
1944 					framesToCatchUpAsClient=0;
1945 					cleanupStats=true;
1946 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Worldframe %d : Client will slow down: %d frames\n",world.getFrameCount(),framesToSlowDownAsClient);
1947 				}
1948 
1949 				if(cleanupStats==true) {
1950 					// Once we decided to use the stats to do some correction, we reset/cleanup our recorded stats
1951 					for( int i=0;i<GameConstants::networkSmoothInterval;i++){
1952 						receivedTooEarlyInFrames[i]=-1;
1953 						framesNeededToWaitForServerMessage[i]=-1;
1954 					}
1955 				}
1956 			}
1957 		}
1958 		// if game is paused don't try to catch up
1959 		if(updateLoops > 0) {
1960 			// we catch up a bit smoother with updateLoops = 2
1961 			if(framesToCatchUpAsClient>0)
1962 			{
1963 					updateLoops = 2;
1964 					framesToCatchUpAsClient=framesToCatchUpAsClient-1;
1965 			}
1966 			if(framesToSlowDownAsClient>0)
1967 			{// slowdown still the hard way.
1968 				updateLoops = 0;
1969 				framesToSlowDownAsClient=framesToSlowDownAsClient-1;
1970 			}
1971 		}
1972 
1973 		addPerformanceCount("CalculateNetworkUpdateLoops",chronoGamePerformanceCounts.getMillis());
1974 
1975 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
1976 		if(showPerfStats) {
1977 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1978 			perfList.push_back(perfBuf);
1979 		}
1980 
1981 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [before ReplaceDisconnectedNetworkPlayersWithAI]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
1982 		if(showPerfStats) {
1983 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
1984 			perfList.push_back(perfBuf);
1985 		}
1986 
1987 		// Check to see if we are playing a network game and if any players
1988 		// have disconnected?
1989 		bool isNetworkGame = this->gameSettings.isNetworkGame();
1990 
1991 		chronoGamePerformanceCounts.start();
1992 
1993 		ReplaceDisconnectedNetworkPlayersWithAI(isNetworkGame, role);
1994 
1995 		addPerformanceCount("ReplaceDisconnectedNetworkPlayersWithAI",chronoGamePerformanceCounts.getMillis());
1996 
1997 		setupPopupMenus(true);
1998 
1999 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after ReplaceDisconnectedNetworkPlayersWithAI]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
2000 		if(showPerfStats) {
2001 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2002 			perfList.push_back(perfBuf);
2003 		}
2004 
2005 		if(updateLoops > 0) {
2006 			// update the frame based timer in the stats with at least one step
2007 			world.getStats()->addFramesToCalculatePlaytime();
2008 
2009 			//update
2010 			Chrono chronoReplay;
2011 			int64 lastReplaySecond = -1;
2012 			int replayCommandsPlayed = 0;
2013 			int replayTotal = commander.getReplayCommandListForFrameCount();
2014 			if(replayTotal > 0) {
2015 				chronoReplay.start();
2016 			}
2017 
2018 			do {
2019 				if(replayTotal > 0) {
2020 					replayCommandsPlayed = (replayTotal - commander.getReplayCommandListForFrameCount());
2021 				}
2022 				for(int i = 0; i < updateLoops; ++i) {
2023 					//if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
2024 					if(showPerfStats) {
2025 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2026 						perfList.push_back(perfBuf);
2027 					}
2028 
2029 					//AiInterface
2030 					if(commander.hasReplayCommandListForFrame() == false) {
2031 						chronoGamePerformanceCounts.start();
2032 
2033 						processNetworkSynchChecksIfRequired();
2034 
2035 						addPerformanceCount("CalculateNetworkCRCSynchChecks",chronoGamePerformanceCounts.getMillis());
2036 
2037 						const bool newThreadManager = Config::getInstance().getBool("EnableNewThreadManager","false");
2038 						if(newThreadManager == true) {
2039 							int currentFrameCount = world.getFrameCount();
2040 							masterController.signalSlaves(&currentFrameCount);
2041 							//bool slavesCompleted = masterController.waitTillSlavesTrigger(20000);
2042 							masterController.waitTillSlavesTrigger(20000);
2043 						}
2044 						else {
2045 							// Signal the faction threads to do any pre-processing
2046 							chronoGamePerformanceCounts.start();
2047 
2048 							bool hasAIPlayer = false;
2049 							for(int j = 0; j < world.getFactionCount(); ++j) {
2050 								Faction *faction = world.getFaction(j);
2051 
2052 								//printf("Faction Index = %d enableServerControlledAI = %d, isNetworkGame = %d, role = %d isCPU player = %d scriptManager.getPlayerModifiers(j)->getAiEnabled() = %d\n",j,enableServerControlledAI,isNetworkGame,role,faction->getCpuControl(enableServerControlledAI,isNetworkGame,role),scriptManager.getPlayerModifiers(j)->getAiEnabled());
2053 
2054 								if(	faction->getCpuControl(enableServerControlledAI,isNetworkGame,role) == true &&
2055 									scriptManager.getPlayerModifiers(j)->getAiEnabled() == true) {
2056 
2057 									if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] [i = %d] faction = %d, factionCount = %d, took msecs: %lld [before AI updates]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,j,world.getFactionCount(),chrono.getMillis());
2058 									aiInterfaces[j]->signalWorkerThread(world.getFrameCount());
2059 									hasAIPlayer = true;
2060 								}
2061 							}
2062 
2063 							if(showPerfStats) {
2064 								sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2065 								perfList.push_back(perfBuf);
2066 							}
2067 
2068 							if(hasAIPlayer == true) {
2069 								//sleep(0);
2070 
2071 								Chrono chronoAI;
2072 								chronoAI.start();
2073 
2074 								const int MAX_FACTION_THREAD_WAIT_MILLISECONDS = 20000;
2075 								for(;chronoAI.getMillis() < MAX_FACTION_THREAD_WAIT_MILLISECONDS;) {
2076 									bool workThreadsFinished = true;
2077 									for(int j = 0; j < world.getFactionCount(); ++j) {
2078 										Faction *faction = world.getFaction(j);
2079 										if(faction == NULL) {
2080 											throw megaglest_runtime_error("faction == NULL");
2081 										}
2082 										if(	faction->getCpuControl(enableServerControlledAI,isNetworkGame,role) == true &&
2083 											scriptManager.getPlayerModifiers(j)->getAiEnabled() == true) {
2084 											if(aiInterfaces[j]->isWorkerThreadSignalCompleted(world.getFrameCount()) == false) {
2085 												workThreadsFinished = false;
2086 												break;
2087 											}
2088 										}
2089 									}
2090 									if(workThreadsFinished == false) {
2091 										//sleep(0);
2092 									}
2093 									else {
2094 										break;
2095 									}
2096 								}
2097 							}
2098 
2099 							addPerformanceCount("ProcessAIWorkerThreads",chronoGamePerformanceCounts.getMillis());
2100 						}
2101 
2102 						if(showPerfStats) {
2103 							sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2104 							perfList.push_back(perfBuf);
2105 						}
2106 
2107 					}
2108 					else {
2109 						// Simply show a progress message while replaying commands
2110 						if(lastReplaySecond < chronoReplay.getSeconds()) {
2111 							lastReplaySecond = chronoReplay.getSeconds();
2112 							Renderer &renderer= Renderer::getInstance();
2113 							renderer.clearBuffers();
2114 							renderer.clearZBuffer();
2115 							renderer.reset2d();
2116 
2117 							char szBuf[8096]="";
2118 							snprintf(szBuf,8096,"Please wait, loading game with replay [%d / %d]...",replayCommandsPlayed,replayTotal);
2119 							string text = szBuf;
2120 							if(Renderer::renderText3DEnabled) {
2121 								Font3D *font = CoreData::getInstance().getMenuFontBig3D();
2122 								const Metrics &metrics= Metrics::getInstance();
2123 								int w= metrics.getVirtualW();
2124 								int renderX = (w / 2) - (font->getMetrics()->getTextWidth(text) / 2);
2125 								int h= metrics.getVirtualH();
2126 								int renderY = (h / 2) + (font->getMetrics()->getHeight(text) / 2);
2127 
2128 								renderer.renderText3D(
2129 									text, font,
2130 									Vec3f(1.f, 1.f, 0.f),
2131 									renderX, renderY, false);
2132 							}
2133 							else {
2134 								Font2D *font = CoreData::getInstance().getMenuFontBig();
2135 								const Metrics &metrics= Metrics::getInstance();
2136 								int w= metrics.getVirtualW();
2137 								int renderX = (w / 2);
2138 								int h= metrics.getVirtualH();
2139 								int renderY = (h / 2);
2140 
2141 								renderer.renderText(
2142 									text, font,
2143 									Vec3f(1.f, 1.f, 0.f),
2144 									renderX, renderY, true);
2145 							}
2146 
2147 							renderer.swapBuffers();
2148 						}
2149 					}
2150 
2151 					if(showPerfStats) {
2152 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2153 						perfList.push_back(perfBuf);
2154 					}
2155 
2156 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [AI updates]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
2157 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
2158 
2159 					//World
2160 					chronoGamePerformanceCounts.start();
2161 
2162 					if(pendingQuitError == false) world.update();
2163 
2164 					addPerformanceCount("ProcessWorldUpdate",chronoGamePerformanceCounts.getMillis());
2165 
2166 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [world update i = %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),i);
2167 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
2168 
2169 					if(showPerfStats) {
2170 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2171 						perfList.push_back(perfBuf);
2172 					}
2173 
2174 					if(currentCameraFollowUnit != NULL) {
2175 						Vec3f c=currentCameraFollowUnit->getCurrMidHeightVector();
2176 						int rotation=currentCameraFollowUnit->getRotation();
2177 						float angle=rotation+180;
2178 
2179 						c.z=c.z+4*std::cos(degToRad(angle));
2180 						c.x=c.x+4*std::sin(degToRad(angle));
2181 
2182 						c.y=c.y+currentCameraFollowUnit->getType()->getHeight()/2.f+2.0f;
2183 
2184 						getGameCameraPtr()->setPos(c);
2185 
2186 						rotation=(540-rotation)%360;
2187 						getGameCameraPtr()->rotateToVH(18.0f,rotation);
2188 
2189 						if(currentCameraFollowUnit->isAlive()==false){
2190 							currentCameraFollowUnit=NULL;
2191 							getGameCameraPtr()->setState(GameCamera::sGame);
2192 						}
2193 					}
2194 
2195 					if(showPerfStats) {
2196 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2197 						perfList.push_back(perfBuf);
2198 					}
2199 
2200 					// Commander
2201 					chronoGamePerformanceCounts.start();
2202 
2203 					if(pendingQuitError == false) {
2204 						commander.signalNetworkUpdate(this);
2205 					}
2206 
2207 					addPerformanceCount("ProcessNetworkUpdate",chronoGamePerformanceCounts.getMillis());
2208 
2209 					if(showPerfStats) {
2210 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2211 						perfList.push_back(perfBuf);
2212 					}
2213 
2214 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [commander updateNetwork i = %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),i);
2215 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
2216 
2217 					//Gui
2218 					chronoGamePerformanceCounts.start();
2219 
2220 					gui.update();
2221 
2222 					addPerformanceCount("ProcessGUIUpdate",chronoGamePerformanceCounts.getMillis());
2223 
2224 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [gui updating i = %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),i);
2225 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
2226 
2227 					if(showPerfStats) {
2228 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2229 						perfList.push_back(perfBuf);
2230 					}
2231 
2232 					//Particle systems
2233 					if(weatherParticleSystem != NULL) {
2234 						weatherParticleSystem->setPos(gameCamera.getPos());
2235 					}
2236 
2237 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [weather particle updating i = %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),i);
2238 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
2239 
2240 					if(showPerfStats) {
2241 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2242 						perfList.push_back(perfBuf);
2243 					}
2244 
2245 					Renderer &renderer= Renderer::getInstance();
2246 
2247 					chronoGamePerformanceCounts.start();
2248 
2249 					renderer.updateParticleManager(rsGame,avgRenderFps);
2250 
2251 					addPerformanceCount("ProcessParticleManager",chronoGamePerformanceCounts.getMillis());
2252 
2253 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [particle manager updating i = %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis(),i);
2254 					if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
2255 
2256 					if(showPerfStats) {
2257 						sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2258 						perfList.push_back(perfBuf);
2259 					}
2260 
2261 					//good_fpu_control_registers(NULL,extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2262 				}
2263 			}
2264 			while (commander.hasReplayCommandListForFrame() == true);
2265 		}
2266 		//else if(role == nrClient) {
2267 		else {
2268 			if(pendingQuitError == false) {
2269 				commander.signalNetworkUpdate(this);
2270 			}
2271 
2272 			if(playingStaticVideo == true) {
2273 				if(videoPlayer->isPlaying() == false) {
2274 					playingStaticVideo = false;
2275 					tryPauseToggle(false);
2276 				}
2277 			}
2278 		}
2279 
2280 		if(showPerfStats) {
2281 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2282 			perfList.push_back(perfBuf);
2283 		}
2284 
2285 		chronoGamePerformanceCounts.start();
2286 
2287 		//call the chat manager
2288 		chatManager.updateNetwork();
2289 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [chatManager.updateNetwork]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chrono.getMillis());
2290 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
2291 
2292 		if(showPerfStats) {
2293 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2294 			perfList.push_back(perfBuf);
2295 		}
2296 
2297 		updateNetworkMarkedCells();
2298 		updateNetworkUnMarkedCells();
2299 		updateNetworkHighligtedCells();
2300 
2301 		if(showPerfStats) {
2302 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2303 			perfList.push_back(perfBuf);
2304 		}
2305 
2306 		//check for quiting status
2307 		if(NetworkManager::getInstance().getGameNetworkInterface() != NULL &&
2308 			NetworkManager::getInstance().getGameNetworkInterface()->getQuit() &&
2309 		   mainMessageBox.getEnabled() == false &&
2310 		   errorMessageBox.getEnabled() == false) {
2311 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2312 			quitTriggeredIndicator = true;
2313 			return;
2314 		}
2315 
2316 		if(showPerfStats) {
2317 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2318 			perfList.push_back(perfBuf);
2319 		}
2320 
2321 		addPerformanceCount("ProcessMiscNetwork",chronoGamePerformanceCounts.getMillis());
2322 
2323 		// START - Handle joining in progress games
2324 		if(role == nrServer) {
2325 
2326 			if(this->networkPauseGameForLaggedClientsRequested == true) {
2327 				this->networkPauseGameForLaggedClientsRequested = false;
2328 
2329 				if(getPaused() == false) {
2330 
2331 					printf("[CMDR] Pausing game for lagging client(s), current world frame [%d]\n",world.getFrameCount());
2332 					commander.tryPauseGame(false,false);
2333 				}
2334 			}
2335 			else if(this->networkResumeGameForLaggedClientsRequested == true) {
2336 				this->networkResumeGameForLaggedClientsRequested = false;
2337 
2338 				if(getPaused() == true) {
2339 
2340 					printf("[CMDR] Resuming game after Pause for lagging client(s), current world frame [%d]\n",world.getFrameCount());
2341 					commander.tryResumeGame(false,false);
2342 				}
2343 			}
2344 
2345 			ServerInterface *server = NetworkManager::getInstance().getServerInterface();
2346 			if(server->getPauseForInGameConnection() == true) {
2347 
2348 				bool clientNeedsGameSetup = false;
2349 				for(int i = 0; i < world.getFactionCount(); ++i) {
2350 					Faction *faction = world.getFaction(i);
2351 
2352 					MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
2353 					ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
2354 					if(slot != NULL && slot->getPauseForInGameConnection() == true) {
2355 						clientNeedsGameSetup = true;
2356 						break;
2357 					}
2358 				}
2359 
2360 				if(pausedForJoinGame == false || clientNeedsGameSetup == true) {
2361 					//printf("================= Switching player pausing game\n");
2362 
2363 					for(int i = 0; i < world.getFactionCount(); ++i) {
2364 						Faction *faction = world.getFaction(i);
2365 
2366 						//printf("Switching player check %d from: %d connected: %d, startindex = %d, connected #2: %d\n",i,faction->getControlType(),server->isClientConnected(faction->getStartLocationIndex()),faction->getStartLocationIndex(),server->isClientConnected(i));
2367 						//printf("Slot: %d faction name: %s\n",i,faction->getType()->getName().c_str());
2368 
2369 						if(	faction->getControlType() != ctNetwork &&
2370 							faction->getControlType() != ctHuman &&
2371 							server->isClientConnected(faction->getStartLocationIndex()) == true) {
2372 
2373 							//printf("Switching player %d from: %d to %d\n",i,faction->getControlType(),ctNetwork);
2374 							//printf("Slot: %d faction name: %s GS faction: %s\n",i,faction->getType()->getName().c_str(),server->gameSettings.getFactionTypeName(i).c_str());
2375 
2376 							server->gameSettings.setFactionControl(i,ctNetwork);
2377 
2378 							MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
2379 							ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
2380 							server->gameSettings.setNetworkPlayerName(i,slot->getName());
2381 							server->gameSettings.setNetworkPlayerUUID(i,slot->getUUID());
2382 							server->gameSettings.setNetworkPlayerPlatform(i,slot->getPlatform());
2383 							safeMutex.ReleaseLock();
2384 							server->gameSettings.setNetworkPlayerStatuses(i,npst_None);
2385 
2386 							this->gameSettings.setFactionControl(i,ctNetwork);
2387 							this->gameSettings.setNetworkPlayerName(i,server->gameSettings.getNetworkPlayerName(i));
2388 							this->gameSettings.setNetworkPlayerUUID(i,server->gameSettings.getNetworkPlayerUUID(i));
2389 							this->gameSettings.setNetworkPlayerPlatform(i,server->gameSettings.getNetworkPlayerPlatform(i));
2390 							this->gameSettings.setNetworkPlayerStatuses(i,npst_None);
2391 						}
2392 					}
2393 					//printf("#1 Data synch: lmap %u ltile: %d ltech: %u\n",gameSettings.getMapCRC(),gameSettings.getTilesetCRC(),gameSettings.getTechCRC());
2394 					//printf("#2 Data synch: lmap %u ltile: %d ltech: %u\n",server->gameSettings.getMapCRC(),server->gameSettings.getTilesetCRC(),server->gameSettings.getTechCRC());
2395 					server->broadcastGameSetup(&server->gameSettings,true);
2396 				}
2397 
2398 				for(int i = 0; i < world.getFactionCount(); ++i) {
2399 					Faction *faction = world.getFaction(i);
2400 					MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
2401 					ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
2402 					if(slot != NULL && slot->getPauseForInGameConnection() == true) {
2403 						slot->setPauseForInGameConnection(false);
2404 					}
2405 				}
2406 			}
2407 			else if(server->getStartInGameConnectionLaunch() == true) {
2408 				//printf("^^^ getStartInGameConnectionLaunch triggered!\n");
2409 
2410 				//server->setStartInGameConnectionLaunch(false);
2411 
2412 				//this->speed = 1;
2413 
2414 				//Lang &lang= Lang::getInstance();
2415 				bool pauseAndSaveGameForNewClient = false;
2416 				for(int i = 0; i < world.getFactionCount(); ++i) {
2417 					Faction *faction = world.getFaction(i);
2418 
2419 					MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
2420 					ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
2421 
2422 					if(slot != NULL && slot->getStartInGameConnectionLaunch() == true) {
2423 						//slot->setStartInGameConnectionLaunch(false);
2424 						pauseAndSaveGameForNewClient = true;
2425 					}
2426 					if(slot != NULL && slot->getJoinGameInProgress() == true) {
2427 						//printf("$$$ signalling client to start game [deleting AI player] factionIndex: %d slot: %d startlocation: %d!\n",i,slot->getPlayerIndex(),faction->getStartLocationIndex());
2428 						safeMutex.ReleaseLock();
2429 
2430 						this->gameSettings.setFactionControl(i,ctNetwork);
2431 						this->gameSettings.setNetworkPlayerName(i,server->gameSettings.getNetworkPlayerName(i));
2432 						this->gameSettings.setNetworkPlayerUUID(i,server->gameSettings.getNetworkPlayerUUID(i));
2433 						this->gameSettings.setNetworkPlayerPlatform(i,server->gameSettings.getNetworkPlayerPlatform(i));
2434 
2435 						if(this->gameSettings.getNetworkPlayerStatuses(i) == npst_Disconnected) {
2436 							this->gameSettings.setNetworkPlayerStatuses(i,npst_None);
2437 						}
2438 
2439 						//printf("START Purging AI player for index: %d\n",i);
2440 						masterController.clearSlaves(true);
2441 						delete aiInterfaces[i];
2442 						aiInterfaces[i] = NULL;
2443 						//printf("END Purging AI player for index: %d\n",i);
2444 
2445 						Faction *faction = world.getFaction(i);
2446 						faction->setControlType(ctNetwork);
2447 						//pauseAndSaveGameForNewClient = true;
2448 					}
2449 					else if((slot == NULL || slot->isConnected() == false) &&
2450 							this->gameSettings.getFactionControl(i) == ctNetwork &&
2451 							aiInterfaces[i] == NULL) {
2452 
2453 						safeMutex.ReleaseLock();
2454 						faction->setFactionDisconnectHandled(false);
2455 						//this->gameSettings.setNetworkPlayerName(i,lang.getString("AI") + intToStr(i+1));
2456 						//server->gameSettings.setNetworkPlayerName(i,lang.getString("AI") + intToStr(i+1));
2457 					}
2458 					else {
2459 						safeMutex.ReleaseLock();
2460 					}
2461 				}
2462 
2463 				if(pauseAndSaveGameForNewClient == true && pausedForJoinGame == false &&
2464 						pauseRequestSent == false) {
2465 					//printf("Pausing game for join in progress game...\n");
2466 
2467 					commander.tryPauseGame(true,true);
2468 					pauseRequestSent = true;
2469 					return;
2470 				}
2471 			}
2472 			//else if(server->getPauseForInGameConnection() == true && paused == true &&
2473 			if(pausedForJoinGame == true) {
2474 				if(pauseStateChanged == true) {
2475 					pauseStateChanged = false;
2476 				}
2477 
2478 				if(server->getUnPauseForInGameConnection() == true) {
2479 					//printf("^^^ getUnPauseForInGameConnection triggered!\n");
2480 
2481 					for(int i = 0; i < world.getFactionCount(); ++i) {
2482 						Faction *faction = world.getFaction(i);
2483 
2484 						MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
2485 						ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
2486 						if(slot != NULL && slot->getUnPauseForInGameConnection() == true) {
2487 							slot->setUnPauseForInGameConnection(false);
2488 							faction->setFactionDisconnectHandled(false);
2489 						}
2490 					}
2491 					//printf("Resuming game for join in progress game resumeRequestSent: %d...\n",resumeRequestSent);
2492 
2493 					if(pausedBeforeJoinGame == false && resumeRequestSent == false) {
2494 						commander.tryResumeGame(true,true);
2495 						resumeRequestSent = true;
2496 					}
2497 				}
2498 				else if(server->getStartInGameConnectionLaunch() == true) {
2499 					bool saveNetworkGame = false;
2500 
2501 					ServerInterface *server = NetworkManager::getInstance().getServerInterface();
2502 					for(int i = 0; i < world.getFactionCount(); ++i) {
2503 						Faction *faction = world.getFaction(i);
2504 
2505 						MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
2506 						ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
2507 						if(slot != NULL && slot->getJoinGameInProgress() == true &&
2508 							slot->getStartInGameConnectionLaunch() == true &&
2509 							slot->getSentSavedGameInfo() == false) {
2510 							slot->setStartInGameConnectionLaunch(false);
2511 
2512 							saveNetworkGame = true;
2513 							break;
2514 						}
2515 					}
2516 
2517 					if(saveNetworkGame == true) {
2518 						//printf("Saved network game to disk\n");
2519 
2520 						string file = this->saveGame(GameConstants::saveNetworkGameFileServer,"temp/");
2521 
2522 						string saveGameFilePath = "temp/";
2523 						string saveGameFileCompressed = saveGameFilePath + string(GameConstants::saveNetworkGameFileServerCompressed);
2524 						if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
2525 							saveGameFilePath = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + saveGameFilePath;
2526 							saveGameFileCompressed = saveGameFilePath + string(GameConstants::saveNetworkGameFileServerCompressed);
2527 						}
2528 						else {
2529 							string userData = Config::getInstance().getString("UserData_Root","");
2530 							if(userData != "") {
2531 								endPathWithSlash(userData);
2532 							}
2533 							saveGameFilePath = userData + saveGameFilePath;
2534 							saveGameFileCompressed = saveGameFilePath + string(GameConstants::saveNetworkGameFileServerCompressed);
2535 						}
2536 
2537 						bool compressed_result = compressFileToZIPFile(
2538 								file, saveGameFileCompressed);
2539 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Saved game [%s] compressed to [%s] returned: %d\n",file.c_str(),saveGameFileCompressed.c_str(), compressed_result);
2540 
2541 						char szBuf[8096]="";
2542 						Lang &lang= Lang::getInstance();
2543 						snprintf(szBuf,8096,lang.getString("GameSaved","",true).c_str(),file.c_str());
2544 						console.addLine(szBuf);
2545 
2546 						for(int i = 0; i < world.getFactionCount(); ++i) {
2547 							Faction *faction = world.getFaction(i);
2548 
2549 							MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
2550 							ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
2551 							if(slot != NULL && slot->getJoinGameInProgress() == true &&
2552 									slot->getSentSavedGameInfo() == false) {
2553 
2554 								safeMutex.ReleaseLock();
2555 							    NetworkMessageReady networkMessageReady(0);
2556 								slot->sendMessage(&networkMessageReady);
2557 
2558 								slot =  server->getSlot(faction->getStartLocationIndex(),false);
2559 								if(slot != NULL) {
2560 									slot->setSentSavedGameInfo(true);
2561 								}
2562 							}
2563 						}
2564 					}
2565 				}
2566 			}
2567 			//else {
2568 			// handle setting changes from clients
2569 			Map *map= world.getMap();
2570 			//printf("switchSetupRequests != NULL\n");
2571 
2572 			bool switchRequested = switchSetupForSlots(server, 0, map->getMaxPlayers(), false);
2573 			switchRequested = switchRequested || switchSetupForSlots(server, map->getMaxPlayers(), GameConstants::maxPlayers, true);
2574 
2575 			if(switchRequested == true) {
2576 				//printf("Send new game setup from switch: %d\n",switchRequested);
2577 
2578 				//for(int i= 0; i < gameSettings.getFactionCount(); ++i) {
2579 					//printf("#1 Faction Index: %d control: %d startlocation: %d\n",i,gameSettings.getFactionControl(i),gameSettings.getStartLocationIndex(i));
2580 
2581 					//printf("#2 Faction Index: %d control: %d startlocation: %d\n",i,server->gameSettings.getFactionControl(i),server->gameSettings.getStartLocationIndex(i));
2582 				//}
2583 
2584 				server->broadcastGameSetup(&server->gameSettings,true);
2585 				}
2586 			//}
2587 
2588 			// Make the server wait a bit for clients to start.
2589 			if(pausedForJoinGame == false && resumeRequestSent == true) {
2590 				resumeRequestSent = false;
2591 				//sleep(500);
2592 			}
2593 		}
2594 		// END - Handle joining in progress games
2595 
2596 		//update auto test
2597 		if(Config::getInstance().getBool("AutoTest")){
2598 			AutoTest::getInstance().updateGame(this);
2599 			return;
2600 		}
2601 
2602 		if(showPerfStats) {
2603 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2604 			perfList.push_back(perfBuf);
2605 		}
2606 
2607 		if(world.getQueuedScenario() != "") {
2608 			string name = world.getQueuedScenario();
2609 			bool keepFactions = world.getQueuedScenarioKeepFactions();
2610 			world.setQueuedScenario("",false);
2611 
2612 			//vector<string> results;
2613 			const vector<string> &dirList = Config::getInstance().getPathListForType(ptScenarios);
2614 			string scenarioFile = Scenario::getScenarioPath(dirList, name);
2615 
2616 
2617 			try {
2618 				gameStarted = false;
2619 
2620 			//printf("\nname [%s] scenarioFile [%s] results.size() = " MG_SIZE_T_SPECIFIER "\n",name.c_str(),scenarioFile.c_str(),results.size());
2621 			//printf("[%s:%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2622 
2623 			bool isTutorial = Scenario::isGameTutorial(scenarioFile);
2624 			ScenarioInfo scenarioInfo;
2625 			Scenario::loadScenarioInfo(scenarioFile, &scenarioInfo, isTutorial);
2626 
2627 			//printf("[%s:%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2628 			GameSettings gameSettings;
2629 			Scenario::loadGameSettings(dirList,&scenarioInfo, &gameSettings, scenarioFile);
2630 
2631 			//Program *program = world->getGame()->getProgram();
2632 			//program->setState(new Game(program, &gameSettings, false));
2633 
2634 			//world->end();
2635 
2636 			//world->getMapPtr()->end();
2637 			//world.end();
2638 
2639 			if(keepFactions == false) {
2640 				world.end();
2641 
2642 				world.cleanup();
2643 				world.clearTileset();
2644 
2645 				SoundRenderer::getInstance().stopAllSounds();
2646 
2647 				masterController.clearSlaves(true);
2648 				deleteValues(aiInterfaces.begin(), aiInterfaces.end());
2649 				aiInterfaces.clear();
2650 				gui.end();		//selection must be cleared before deleting units
2651 				world.end();	//must die before selection because of referencers
2652 
2653 				BaseColorPickEntity::resetUniqueColors();
2654 				// MUST DO THIS LAST!!!! Because objects above have pointers to things like
2655 				// unit particles and fade them out etc and this end method deletes the original
2656 				// object pointers.
2657 				Renderer &renderer= Renderer::getInstance();
2658 				renderer.endGame(true);
2659 
2660 				GameConstants::updateFps = original_updateFps;
2661 				GameConstants::cameraFps = original_cameraFps;
2662 
2663 				this->setGameSettings(&gameSettings);
2664 				this->resetMembers();
2665 				this->load();
2666 				this->init();
2667 			}
2668 			else {
2669 				SoundRenderer &soundRenderer= SoundRenderer::getInstance();
2670 				//printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound);
2671 				if(currentAmbientSound) {
2672 					soundRenderer.stopAmbient(currentAmbientSound);
2673 				}
2674 				//soundRenderer.stopAllSounds();
2675 				soundRenderer.stopAllSounds(fadeMusicMilliseconds);
2676 
2677 				world.endScenario();
2678 				BaseColorPickEntity::resetUniqueColors();
2679 
2680 				Renderer &renderer= Renderer::getInstance();
2681 				renderer.endScenario();
2682 				world.clearTileset();
2683 				this->setGameSettings(&gameSettings);
2684 				this->load(lgt_FactionPreview | lgt_TileSet | lgt_Map | lgt_Scenario);
2685 				try {
2686 					world.init(this, gameSettings.getDefaultUnits(),false);
2687 				}
2688 				catch(const exception &ex) {
2689 					char szBuf[8096]="";
2690 					snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
2691 
2692 					SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
2693 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
2694 
2695 					if(errorMessageBox.getEnabled() == false) {
2696 						ErrorDisplayMessage(ex.what(),true);
2697 					}
2698 				}
2699 
2700 				world.initUnitsForScenario();
2701 				Map *map= world.getMap();
2702 				gameCamera.init(map->getW(), map->getH());
2703 
2704 				// camera default height calculation
2705 				if(map->getCameraHeight()>0 && gameCamera.getCalculatedDefault()<map->getCameraHeight()){
2706 					gameCamera.setCalculatedDefault(map->getCameraHeight());
2707 				}
2708 				else if(gameCamera.getCalculatedDefault()<map->getMaxMapHeight()+13.0f){
2709 					gameCamera.setCalculatedDefault(map->getMaxMapHeight()+13.0f);
2710 				}
2711 
2712 				scriptManager.init(&world, &gameCamera,loadGameNode);
2713 				renderer.initGame(this,this->getGameCameraPtr());
2714 
2715 				//sounds
2716 				//soundRenderer.stopAllSounds(fadeMusicMilliseconds);
2717 				//soundRenderer.stopAllSounds();
2718 				//soundRenderer= SoundRenderer::getInstance();
2719 
2720 				Tileset *tileset= world.getTileset();
2721 				AmbientSounds *ambientSounds= tileset->getAmbientSounds();
2722 
2723 				//rain
2724 				if(tileset->getWeather() == wRainy && ambientSounds->isEnabledRain()) {
2725 					//logger.add("Starting ambient stream", true);
2726 					currentAmbientSound = ambientSounds->getRain();
2727 					//printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound);
2728 					soundRenderer.playAmbient(currentAmbientSound);
2729 				}
2730 
2731 				//snow
2732 				if(tileset->getWeather() == wSnowy && ambientSounds->isEnabledSnow()) {
2733 					//logger.add("Starting ambient stream", true);
2734 					currentAmbientSound = ambientSounds->getSnow();
2735 					//printf("In [%s:%s] Line: %d currentAmbientSound = [%p]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,currentAmbientSound);
2736 					soundRenderer.playAmbient(currentAmbientSound);
2737 				}
2738 
2739 				if(this->masterserverMode == false) {
2740 					StrSound *gameMusic= world.getThisFaction()->getType()->getMusic();
2741 					soundRenderer.playMusic(gameMusic);
2742 				}
2743 
2744 				gameStarted = true;
2745 			}
2746 			//this->init();
2747 
2748 			//printf("[%s:%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2749 			//Checksum checksum;
2750 			//world->loadScenario(scenarioFile, &checksum, true);
2751 			}
2752 #if defined(WIN32)
2753 			catch(const exception) {
2754 #else
2755 			catch(const exception &ex) {
2756 #endif
2757 				gameStarted = true;
2758 				totalRenderFps++;
2759 
2760 				throw;
2761 			}
2762 		}
2763 
2764 		if(showPerfStats) {
2765 			sprintf(perfBuf,"In [%s::%s] Line: %d took msecs: " MG_I64_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,chronoPerf.getMillis());
2766 			perfList.push_back(perfBuf);
2767 		}
2768 
2769 		if(showPerfStats && chronoPerf.getMillis() >= 50) {
2770 			for(unsigned int x = 0; x < (unsigned int)perfList.size(); ++x) {
2771 				printf("%s",perfList[x].c_str());
2772 			}
2773 		}
2774 	}
2775 	catch(const exception &ex) {
2776 		quitPendingIndicator = true;
2777 
2778 		char szBuf[8096]="";
2779 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
2780 
2781 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
2782 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
2783 
2784 		//printf("#100 quitPendingIndicator = %d, errorMessageBox.getEnabled() = %d\n",quitPendingIndicator,errorMessageBox.getEnabled());
2785 
2786 		NetworkManager &networkManager= NetworkManager::getInstance();
2787 		if(networkManager.getGameNetworkInterface() != NULL) {
2788 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
2789 			networkInterface->sendTextMessage(szBuf,-1,true,"");
2790 			sleep(10);
2791 			networkManager.getGameNetworkInterface()->quitGame(true);
2792 		}
2793 		if(errorMessageBox.getEnabled() == false) {
2794             ErrorDisplayMessage(ex.what(),true);
2795 		}
2796 	}
2797 }
2798 
2799 void Game::addPerformanceCount(string key,int64 value) {
2800 	gamePerformanceCounts[key] = value + gamePerformanceCounts[key] / 2;
2801 }
2802 
2803 string Game::getGamePerformanceCounts(bool displayWarnings) const {
2804 	if(gamePerformanceCounts.empty() == true) {
2805 		return "";
2806 	}
2807 
2808 	bool displayWarningHeader 	= true;
2809 	bool WARN_TO_CONSOLE 		= Config::getInstance().getBool("PerformanceWarningEnabled","false");
2810 	int WARNING_MILLIS 			= Config::getInstance().getInt("PerformanceWarningMillis","7");
2811 	int WARNING_RENDER_MILLIS 	= Config::getInstance().getInt("PerformanceWarningRenderMillis","40");
2812 
2813 	string result = "";
2814 	for(std::map<string,int64>::const_iterator iterMap = gamePerformanceCounts.begin();
2815 			iterMap != gamePerformanceCounts.end(); ++iterMap) {
2816 		if(iterMap->first == ProgramState::MAIN_PROGRAM_RENDER_KEY) {
2817 			if(iterMap->second < WARNING_RENDER_MILLIS) {
2818 				continue;
2819 			}
2820 			//else {
2821 			//	printf("iterMap->second: " MG_I64_SPECIFIER " WARNING_RENDER_MILLIS = %d\n",iterMap->second,WARNING_RENDER_MILLIS);
2822 			//}
2823 		}
2824 		else if(iterMap->second < WARNING_MILLIS) {
2825 			continue;
2826 		}
2827 
2828 		if(result != "") {
2829 			result += "\n";
2830 		}
2831 		string perfStat = iterMap->first + " = avg millis: " + intToStr(iterMap->second);
2832 
2833 		if(displayWarnings == true && WARN_TO_CONSOLE == true) {
2834 			if(displayWarningHeader == true) {
2835 				displayWarningHeader = false;
2836 				printf("=====================================\nPERFORMANCE WARNINGS for World Frame: %d\n",world.getFrameCount());
2837 			}
2838 
2839 			printf("*PERFORMANCE WARNING* %s\n",perfStat.c_str());
2840 		}
2841 
2842 		result += perfStat;
2843 	}
2844 
2845 	return result;
2846 }
2847 
2848 bool Game::switchSetupForSlots(ServerInterface *& serverInterface,
2849 		int startIndex, int endIndex, bool onlyNetworkUnassigned) {
2850 	bool switchRequested = false;
2851 	if(serverInterface == NULL) {
2852 		return switchRequested;
2853 	}
2854 
2855 	MutexSafeWrapper safeMutex(serverInterface->getSwitchSetupRequestsMutex(),CODE_AT_LINE);
2856 	SwitchSetupRequest ** switchSetupRequests = serverInterface->getSwitchSetupRequests();
2857 	if(switchSetupRequests == NULL) {
2858 		return switchRequested;
2859 	}
2860 
2861 	Map *map= world.getMap();
2862 	for(int i= startIndex; i < endIndex; ++i) {
2863 		if(switchSetupRequests[i] != NULL) {
2864 			//printf("Faction Index: %d Switch slot = %d to = %d current control = %d\n",i,switchSetupRequests[i]->getCurrentSlotIndex(),switchSetupRequests[i]->getToSlotIndex(),gameSettings.getFactionControl(i));
2865 
2866 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] switchSetupRequests[i]->getSwitchFlags() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,switchSetupRequests[i]->getSwitchFlags());
2867 
2868 			if(onlyNetworkUnassigned == true && gameSettings.getFactionControl(i) != ctNetworkUnassigned) {
2869 				if(i < map->getMaxPlayers() || (i >= map->getMaxPlayers() && gameSettings.getFactionControl(i) != ctNetwork)) {
2870 					continue;
2871 				}
2872 			}
2873 
2874 			if(gameSettings.getFactionControl(i) == ctNetwork ||
2875 				gameSettings.getFactionControl(i) == ctNetworkUnassigned ||
2876 				//(gameSettings.getFactionControl(i) != ctClosed && gameSettings.getFactionControl(i) != ctHuman)) {
2877 				(gameSettings.getFactionControl(i) != ctHuman)) {
2878 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] switchSetupRequests[i]->getToFactionIndex() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,switchSetupRequests[i]->getToSlotIndex());
2879 
2880 				if(switchSetupRequests[i]->getToSlotIndex() != -1) {
2881 					int newSlotIdx = switchSetupRequests[i]->getToSlotIndex();
2882 
2883 					//printf("switchSlot request from %d to %d\n",switchSetupRequests[i]->getCurrentSlotIndex(),switchSetupRequests[i]->getToSlotIndex());
2884 
2885 					int switchSlotIdx = switchSetupRequests[i]->getCurrentSlotIndex();
2886 					if(serverInterface->switchSlot(switchSlotIdx,newSlotIdx)) {
2887 						//printf("switchSlot returned true\n");
2888 						switchRequested = true;
2889 
2890 						int oldFactionIndex = gameSettings.getFactionIndexForStartLocation(switchSlotIdx);
2891 						int newFactionIndex = gameSettings.getFactionIndexForStartLocation(newSlotIdx);
2892 
2893 						//printf("Switching faction for index %d [%d] to %d\n",newSlotIdx,switchSlotIdx,gameSettings.getFactionControl(newFactionIndex));
2894 
2895 						gameSettings.setNetworkPlayerName(oldFactionIndex, "");
2896 						serverInterface->gameSettings.setNetworkPlayerName(oldFactionIndex, "");
2897 						gameSettings.setNetworkPlayerUUID(oldFactionIndex, "");
2898 						serverInterface->gameSettings.setNetworkPlayerUUID(oldFactionIndex, "");
2899 
2900 						gameSettings.setNetworkPlayerPlatform(oldFactionIndex, "");
2901 						serverInterface->gameSettings.setNetworkPlayerPlatform(oldFactionIndex, "");
2902 
2903 						gameSettings.setFactionControl(newFactionIndex,ctNetwork);
2904 						serverInterface->gameSettings.setFactionControl(newFactionIndex,ctNetwork);
2905 
2906 						//printf("#1a Faction Index: %d control: %d startlocation: %d\n",newFactionIndex,gameSettings.getFactionControl(newFactionIndex),gameSettings.getStartLocationIndex(newFactionIndex));
2907 						//printf("#2a Faction Index: %d control: %d startlocation: %d\n",newFactionIndex,serverInterface->gameSettings.getFactionControl(newFactionIndex),serverInterface->gameSettings.getStartLocationIndex(newFactionIndex));
2908 
2909 						try {
2910 							//if(switchSetupRequests[i]->getSelectedFactionName() != "") {
2911 							//	listBoxFactions[newFactionIdx].setSelectedItem(switchSetupRequests[i]->getSelectedFactionName());
2912 							//}
2913 							//if(switchSetupRequests[i]->getToTeam() != -1) {
2914 							//	listBoxTeams[newFactionIdx].setSelectedItemIndex(switchSetupRequests[i]->getToTeam());
2915 							//}
2916 							if(switchSetupRequests[i]->getNetworkPlayerName() != "") {
2917 								//if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d] i = %d, labelPlayerNames[newFactionIdx].getText() [%s] switchSetupRequests[i]->getNetworkPlayerName() [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,labelPlayerNames[newFactionIdx].getText().c_str(),switchSetupRequests[i]->getNetworkPlayerName().c_str());
2918 								gameSettings.setNetworkPlayerName(newFactionIndex,switchSetupRequests[i]->getNetworkPlayerName());
2919 								serverInterface->gameSettings.setNetworkPlayerName(newFactionIndex,switchSetupRequests[i]->getNetworkPlayerName());
2920 							}
2921 
2922 //							if(gameSettings.getFactionControl(switchFactionIdx) == ctNetworkUnassigned) {
2923 //								serverInterface->removeSlot(switchFactionIdx);
2924 //								//listBoxControls[switchFactionIdx].setSelectedItemIndex(ctClosed);
2925 //								gameSettings.getFactionControl(switchFactionIdx)
2926 //
2927 //								labelPlayers[switchFactionIdx].setVisible(switchFactionIdx+1 <= mapInfo.players);
2928 //								labelPlayerNames[switchFactionIdx].setVisible(switchFactionIdx+1 <= mapInfo.players);
2929 //								listBoxControls[switchFactionIdx].setVisible(switchFactionIdx+1 <= mapInfo.players);
2930 //								listBoxFactions[switchFactionIdx].setVisible(switchFactionIdx+1 <= mapInfo.players);
2931 //								listBoxTeams[switchFactionIdx].setVisible(switchFactionIdx+1 <= mapInfo.players);
2932 //								labelNetStatus[switchSlotIdx].setVisible(switchSlotIdx+1 <= mapInfo.players);
2933 //							}
2934 						}
2935 						catch(const runtime_error &e) {
2936 							SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what());
2937 							if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] caught exception error = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what());
2938 						}
2939 					}
2940 					//printf("AFTER switchSlot returned\n");
2941 				}
2942 				else {
2943 					try {
2944 						//if(switchSetupRequests[i]->getSelectedFactionName() != "") {
2945 						//	listBoxFactions[i].setSelectedItem(switchSetupRequests[i]->getSelectedFactionName());
2946 						//}
2947 						//if(switchSetupRequests[i]->getToTeam() != -1) {
2948 						//	listBoxTeams[i].setSelectedItemIndex(switchSetupRequests[i]->getToTeam());
2949 						//}
2950 
2951 						if((switchSetupRequests[i]->getSwitchFlags() & ssrft_NetworkPlayerName) == ssrft_NetworkPlayerName) {
2952 							//if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] i = %d, switchSetupRequests[i]->getSwitchFlags() = %d, switchSetupRequests[i]->getNetworkPlayerName() [%s], labelPlayerNames[i].getText() [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,switchSetupRequests[i]->getSwitchFlags(),switchSetupRequests[i]->getNetworkPlayerName().c_str(),labelPlayerNames[i].getText().c_str());
2953 
2954 							if(switchSetupRequests[i]->getNetworkPlayerName() != GameConstants::NETWORK_SLOT_UNCONNECTED_SLOTNAME) {
2955 								//labelPlayerNames[i].setText(switchSetupRequests[i]->getNetworkPlayerName());
2956 								gameSettings.setNetworkPlayerName(i,switchSetupRequests[i]->getNetworkPlayerName());
2957 								serverInterface->gameSettings.setNetworkPlayerName(i,switchSetupRequests[i]->getNetworkPlayerName());
2958 								switchRequested = true;
2959 							}
2960 							else {
2961 								//labelPlayerNames[i].setText("");
2962 								gameSettings.setNetworkPlayerName(i,"");
2963 								serverInterface->gameSettings.setNetworkPlayerName(i,"");
2964 								switchRequested = true;
2965 							}
2966 							//SetActivePlayerNameEditor();
2967 							//switchSetupRequests[i]->clearSwitchFlag(ssrft_NetworkPlayerName);
2968 						}
2969 					}
2970 					catch(const runtime_error &e) {
2971 						SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what());
2972 						if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] caught exception error = [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what());
2973 					}
2974 				}
2975 			}
2976 
2977 			delete switchSetupRequests[i];
2978 			switchSetupRequests[i]=NULL;
2979 		}
2980 	}
2981 
2982 	return switchRequested;
2983 }
2984 
2985 void Game::updateNetworkMarkedCells() {
2986 	try {
2987 		GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
2988 
2989 		if(gameNetworkInterface != NULL &&
2990 			gameNetworkInterface->getMarkedCellList(false).empty() == false) {
2991 
2992 			std::vector<MarkedCell> chatList = gameNetworkInterface->getMarkedCellList(true);
2993 			for(int idx = 0; idx < (int)chatList.size(); idx++) {
2994 				MarkedCell mc = chatList[idx];
2995 				if(mc.getFactionIndex() >= 0) {
2996 					mc.setFaction((const Faction *)world.getFaction(mc.getFactionIndex()));
2997 				}
2998 
2999 				Map *map= world.getMap();
3000 				Vec2i surfaceCellPos = map->toSurfCoords(mc.getTargetPos());
3001 				mapMarkedCellList[surfaceCellPos] = mc;
3002 			}
3003 		}
3004 	}
3005 	catch(const std::exception &ex) {
3006 		char szBuf[8096]="";
3007 		snprintf(szBuf,8096,"In [%s::%s %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
3008 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3009 		throw megaglest_runtime_error(szBuf);
3010 	}
3011 }
3012 
3013 void Game::updateNetworkUnMarkedCells() {
3014 	try {
3015 		GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
3016 
3017 		if(gameNetworkInterface != NULL &&
3018 				gameNetworkInterface->getUnMarkedCellList(false).empty() == false) {
3019 			//Lang &lang= Lang::getInstance();
3020 
3021 			std::vector<UnMarkedCell> chatList = gameNetworkInterface->getUnMarkedCellList(true);
3022 			for(int idx = 0; idx < (int)chatList.size(); idx++) {
3023 				UnMarkedCell mc = chatList[idx];
3024 				mc.setFaction((const Faction *)world.getFaction(mc.getFactionIndex()));
3025 
3026 				Map *map= world.getMap();
3027 				Vec2i surfaceCellPos = map->toSurfCoords(mc.getTargetPos());
3028 				mapMarkedCellList.erase(surfaceCellPos);
3029 			}
3030 		}
3031 	}
3032 	catch(const std::exception &ex) {
3033 		char szBuf[8096]="";
3034 		snprintf(szBuf,8096,"In [%s::%s %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
3035 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3036 		throw megaglest_runtime_error(szBuf);
3037 	}
3038 }
3039 
3040 
3041 void Game::updateNetworkHighligtedCells() {
3042 	try {
3043 		GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
3044 
3045 		//update the current entries
3046 		for(int idx = (int)highlightedCells.size()-1; idx >= 0; idx--) {
3047 			MarkedCell *mc = &highlightedCells[idx];
3048 			mc->decrementAliveCount();
3049 			if(mc->getAliveCount() < 0) {
3050 				highlightedCells.erase(highlightedCells.begin()+idx);
3051 			}
3052 		}
3053 
3054 		if(gameNetworkInterface != NULL &&
3055 				gameNetworkInterface->getHighlightedCellList(false).empty() == false) {
3056 			//Lang &lang= Lang::getInstance();
3057 			std::vector<MarkedCell> highlighList = gameNetworkInterface->getHighlightedCellList(true);
3058 			for(int idx = 0; idx < (int)highlighList.size(); idx++) {
3059 				MarkedCell mc = highlighList[idx]; // I want a copy here
3060 				if(mc.getFactionIndex() >= 0) {
3061 					mc.setFaction((const Faction *)world.getFaction(mc.getFactionIndex())); // set faction pointer
3062 				}
3063 				addOrReplaceInHighlightedCells(mc);
3064 			}
3065 		}
3066 	}
3067 	catch(const std::exception &ex) {
3068 		char szBuf[8096]="";
3069 		snprintf(szBuf,8096,"In [%s::%s %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
3070 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3071 		throw megaglest_runtime_error(szBuf);
3072 	}
3073 }
3074 
3075 void Game::addOrReplaceInHighlightedCells(MarkedCell mc){
3076 	if(mc.getFactionIndex() >= 0) {
3077 		for(int i = (int)highlightedCells.size()-1; i >= 0; i--) {
3078 			MarkedCell *currentMc = &highlightedCells[i];
3079 			if(currentMc->getFactionIndex() == mc.getFactionIndex()) {
3080 				highlightedCells.erase(highlightedCells.begin()+i);
3081 			}
3082 		}
3083 	}
3084 	if(mc.getAliveCount() <= 0) {
3085 		mc.setAliveCount(200);
3086 	}
3087 	highlightedCells.push_back(mc);
3088 
3089 	if (this->masterserverMode == false) {
3090 		CoreData &coreData= CoreData::getInstance();
3091 		SoundRenderer &soundRenderer= SoundRenderer::getInstance();
3092 
3093 		const Faction *faction = mc.getFaction();
3094 		if(getWorld()->getThisFaction() == NULL) {
3095 			throw megaglest_runtime_error("getWorld()->getThisFaction() == NULL");
3096 		}
3097 		//printf("faction [%p][%s]\n",faction,(faction != NULL ? faction->getType()->getName().c_str() : ""));
3098 		if((faction == NULL) ||
3099 				(faction->getTeam() == getWorld()->getThisFaction()->getTeam())) {
3100 			soundRenderer.playFx(coreData.getMarkerSound(),true);
3101 		}
3102 	}
3103 }
3104 
3105 void Game::ReplaceDisconnectedNetworkPlayersWithAI(bool isNetworkGame, NetworkRole role) {
3106 	if(role == nrServer && isNetworkGame == true &&
3107 			difftime((long int)time(NULL),lastNetworkPlayerConnectionCheck) >= NETWORK_PLAYER_CONNECTION_CHECK_SECONDS) {
3108 		lastNetworkPlayerConnectionCheck = time(NULL);
3109 		Logger &logger= Logger::getInstance();
3110 		ServerInterface *server = NetworkManager::getInstance().getServerInterface();
3111 
3112 		bool newAIPlayerCreated = false;
3113 		for(int i = 0; i < world.getFactionCount(); ++i) {
3114 			Faction *faction = world.getFaction(i);
3115 			if(	faction->getFactionDisconnectHandled() == false &&
3116 				(faction->getControlType() == ctNetwork ||
3117 				faction->getControlType() == ctNetworkCpuEasy ||
3118 				faction->getControlType() == ctNetworkCpu ||
3119 				faction->getControlType() == ctNetworkCpuUltra ||
3120 				faction->getControlType() == ctNetworkCpuMega)) {
3121 
3122 				if(aiInterfaces[i] == NULL &&
3123 						server->isClientConnected(faction->getStartLocationIndex()) == false) {
3124 
3125 					if(faction->getPersonalityType() != fpt_Observer) {
3126 						DumpCRCWorldLogIfRequired("_faction_" + intToStr(i));
3127 					}
3128 
3129 					faction->setFactionDisconnectHandled(true);
3130 
3131 					Lang &lang= Lang::getInstance();
3132 
3133 					bool isPlayerObserver = false;
3134 					char szBuf[8096]="";
3135 					if(faction->getPersonalityType() != fpt_Observer) {
3136 						aiInterfaces[i] = new AiInterface(*this, i, faction->getTeam(), faction->getStartLocationIndex());
3137 
3138 						snprintf(szBuf,8096,Lang::getInstance().getString("LogScreenGameLoadingCreatingAIFaction","",true).c_str(),i);
3139 						logger.add(szBuf, true);
3140 
3141 						commander.tryNetworkPlayerDisconnected(i);
3142 
3143 						newAIPlayerCreated = true;
3144 					}
3145 					else {
3146 						isPlayerObserver = true;
3147 
3148 					}
3149 
3150 					const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
3151 					for(unsigned int j = 0; j < (unsigned int)languageList.size(); ++j) {
3152 						if(isPlayerObserver == false) {
3153 							string msg = "Player #%d [%s] has disconnected, switching player to AI mode!";
3154 							if(lang.hasString("GameSwitchPlayerToAI",languageList[j],true)) {
3155 								msg = lang.getString("GameSwitchPlayerToAI",languageList[j],true);
3156 							}
3157 							snprintf(szBuf,8096,msg.c_str(),i+1,this->gameSettings.getNetworkPlayerName(i).c_str());
3158 						}
3159 						else {
3160 							string msg = "Player #%d [%s] has disconnected, but player was only an observer!";
3161 							if(lang.hasString("GameSwitchPlayerObserverToAI",languageList[j],true)) {
3162 								msg = lang.getString("GameSwitchPlayerObserverToAI",languageList[j],true);
3163 							}
3164 							snprintf(szBuf,8096,msg.c_str(),i+1,this->gameSettings.getNetworkPlayerName(i).c_str());
3165 						}
3166 						bool localEcho = (languageList[j] == lang.getLanguage());
3167 						server->sendTextMessage(szBuf,-1,localEcho,languageList[j]);
3168 					}
3169 				}
3170 			}
3171 		}
3172 
3173 		if(newAIPlayerCreated == true && Config::getInstance().getBool("EnableNewThreadManager","false") == true) {
3174 			bool enableServerControlledAI 	= this->gameSettings.getEnableServerControlledAI();
3175 
3176 			masterController.clearSlaves(true);
3177 
3178 			std::vector<SlaveThreadControllerInterface *> slaveThreadList;
3179 			for(int i=0; i < world.getFactionCount(); ++i) {
3180 				Faction *faction= world.getFaction(i);
3181 				if(faction->getCpuControl(enableServerControlledAI,isNetworkGame,role) == true) {
3182 					slaveThreadList.push_back(aiInterfaces[i]->getWorkerThread());
3183 				}
3184 			}
3185 			masterController.setSlaves(slaveThreadList);
3186 		}
3187 	}
3188 }
3189 
3190 void Game::updateCamera(){
3191 	if(currentUIState != NULL) {
3192 		currentUIState->updateCamera();
3193 		return;
3194 	}
3195 	gameCamera.update();
3196 }
3197 
3198 
3199 // ==================== render ====================
3200 
3201 //render
3202 void Game::render() {
3203 	// Ensure the camera starts in the right position
3204 	if(isFirstRender == true) {
3205 		isFirstRender = false;
3206 
3207 		if(this->loadGameNode == NULL) {
3208 			gameCamera.setState(GameCamera::sGame);
3209 			this->restoreToStartXY();
3210 		}
3211 	}
3212 
3213 	canRender();
3214 	incrementFps();
3215 
3216 	renderFps++;
3217 	totalRenderFps++;
3218 
3219 	updateWorldStats();
3220 
3221 	//NetworkManager &networkManager= NetworkManager::getInstance();
3222 	if(this->masterserverMode == false) {
3223 		renderWorker();
3224 	}
3225 	else {
3226 		// Titi, uncomment this to watch the game on the masterserver
3227 		//renderWorker();
3228 
3229 		// In masterserver mode quit game if no network players left
3230 		ServerInterface *server = NetworkManager::getInstance().getServerInterface();
3231 		int connectedClients=0;
3232 		for(int i = 0; i < world.getFactionCount(); ++i) {
3233 			Faction *faction = world.getFaction(i);
3234 			if(server->isClientConnected(faction->getStartLocationIndex()) == true) {
3235 				connectedClients++;
3236 			}
3237 		}
3238 
3239 		if(connectedClients == 0) {
3240 			quitTriggeredIndicator = true;
3241 		}
3242 		else {
3243 		    string str="";
3244 		    std::map<int,string> factionDebugInfo;
3245 
3246 			if( difftime((long int)time(NULL),lastMasterServerGameStatsDump) >= GAME_STATS_DUMP_INTERVAL) {
3247 				lastMasterServerGameStatsDump = time(NULL);
3248 				str = getDebugStats(factionDebugInfo);
3249 
3250 				printf("== Current in-game stats (interval %d) ==\n%s\n",GAME_STATS_DUMP_INTERVAL,str.c_str());
3251 			}
3252 		}
3253 	}
3254 }
3255 
3256 void Game::renderWorker() {
3257 	if(currentUIState != NULL) {
3258 //		Renderer &renderer= Renderer::getInstance();
3259 //		renderer.clearBuffers();
3260 //
3261 //		//3d
3262 //		renderer.reset3dMenu();
3263 //
3264 //		renderer.clearZBuffer();
3265 //		//renderer.loadCameraMatrix(menuBackground.getCamera());
3266 //		//renderer.renderMenuBackground(&menuBackground);
3267 //		renderer.renderParticleManager(rsMenu);
3268 //
3269 //		//2d
3270 //		renderer.reset2d();
3271 //
3272 //		currentUIState->render();
3273 //
3274 //		if(renderer.isMasterserverMode() == false) {
3275 //			renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim);
3276 //			renderer.renderFPSWhenEnabled(lastFps);
3277 //			renderer.swapBuffers();
3278 //		}
3279 
3280 		currentUIState->render();
3281 		return;
3282 	}
3283 	else {
3284 		Renderer &renderer= Renderer::getInstance();
3285 		if(renderer.getCustom3dMenu() != NULL) {
3286 			renderer.setCustom3dMenu(NULL);
3287 		}
3288 	}
3289 
3290 	Chrono chrono;
3291 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
3292 
3293 	render3d();
3294 
3295 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %d [render3d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
3296 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
3297 
3298 	render2d();
3299 
3300 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %d [render2d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
3301 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
3302 
3303 	Renderer::getInstance().swapBuffers();
3304 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %d [swap buffers]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
3305 }
3306 
3307 // ==================== tick ====================
3308 
3309 void Game::removeUnitFromSelection(const Unit *unit) {
3310 	try {
3311 		Selection *selection= gui.getSelectionPtr();
3312 		for(int i=0; i < selection->getCount(); ++i) {
3313 			const Unit *currentUnit = selection->getUnit(i);
3314 			if(currentUnit == unit) {
3315 				selection->unSelect(i);
3316 				break;
3317 			}
3318 		}
3319 	}
3320 	catch(const exception &ex) {
3321 		char szBuf[8096]="";
3322 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
3323 
3324 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3325 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
3326 
3327 		if(errorMessageBox.getEnabled() == false) {
3328             ErrorDisplayMessage(ex.what(),true);
3329 		}
3330 
3331 		//abort();
3332 	}
3333 }
3334 
3335 bool Game::addUnitToSelection(Unit *unit) {
3336 	bool result = false;
3337 	try {
3338 		Selection *selection= gui.getSelectionPtr();
3339 		if(selection != NULL) {
3340 			result = selection->select(unit,true);
3341 		}
3342 	}
3343 	catch(const exception &ex) {
3344 		char szBuf[8096]="";
3345 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
3346 
3347 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3348 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
3349 
3350 		if(errorMessageBox.getEnabled() == false) {
3351             ErrorDisplayMessage(ex.what(),true);
3352 		}
3353 
3354 		//abort();
3355 	}
3356 
3357 	return result;
3358 }
3359 
3360 void Game::addUnitToGroupSelection(Unit *unit,int groupIndex) {
3361 	try {
3362 		Selection *selection= gui.getSelectionPtr();
3363 		if(selection != NULL) {
3364 			selection->addUnitToGroup(groupIndex,unit);
3365 		}
3366 	}
3367 	catch(const exception &ex) {
3368 		char szBuf[8096]="";
3369 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
3370 
3371 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3372 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
3373 
3374 		if(errorMessageBox.getEnabled() == false) {
3375             ErrorDisplayMessage(ex.what(),true);
3376 		}
3377 
3378 		//abort();
3379 	}
3380 }
3381 
3382 void Game::removeUnitFromGroupSelection(int unitId,int groupIndex) {
3383 	try {
3384 		Selection *selection= gui.getSelectionPtr();
3385 		if(selection != NULL) {
3386 			selection->removeUnitFromGroup(groupIndex,unitId);
3387 		}
3388 	}
3389 	catch(const exception &ex) {
3390 		char szBuf[8096]="";
3391 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
3392 
3393 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3394 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
3395 
3396 		if(errorMessageBox.getEnabled() == false) {
3397             ErrorDisplayMessage(ex.what(),true);
3398 		}
3399 
3400 		//abort();
3401 	}
3402 }
3403 
3404 void Game::recallGroupSelection(int groupIndex) {
3405 	try {
3406 		Selection *selection= gui.getSelectionPtr();
3407 		if(selection != NULL) {
3408 			selection->recallGroup(groupIndex);
3409 		}
3410 	}
3411 	catch(const exception &ex) {
3412 		char szBuf[8096]="";
3413 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
3414 
3415 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
3416 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
3417 
3418 		if(errorMessageBox.getEnabled() == false) {
3419             ErrorDisplayMessage(ex.what(),true);
3420 		}
3421 
3422 		//abort();
3423 	}
3424 }
3425 
3426 void Game::tick() {
3427 	ProgramState::tick();
3428 
3429 	tickCount++;
3430 
3431 	if(avgUpdateFps == -1) {
3432 		avgUpdateFps = updateFps;
3433 	}
3434 	else {
3435 		avgUpdateFps = (avgUpdateFps + updateFps) / 2;
3436 	}
3437 	currentAvgRenderFpsTotal += renderFps;
3438 
3439 	if(avgRenderFps == -1) {
3440 		avgRenderFps = renderFps;
3441 	}
3442 	// Update the average every x game ticks
3443 	const int CHECK_AVG_FPS_EVERY_X_TICKS = 15;
3444 	if(tickCount % CHECK_AVG_FPS_EVERY_X_TICKS == 0) {
3445 		avgRenderFps = currentAvgRenderFpsTotal / CHECK_AVG_FPS_EVERY_X_TICKS;
3446 		currentAvgRenderFpsTotal = 0;
3447 	}
3448 
3449 	if(captureAvgTestStatus == true) {
3450 		if(updateFpsAvgTest == -1) {
3451 			updateFpsAvgTest = updateFps;
3452 		}
3453 		else {
3454 			updateFpsAvgTest = (updateFpsAvgTest + updateFps) / 2;
3455 		}
3456 		if(renderFpsAvgTest == -1) {
3457 			renderFpsAvgTest = renderFps;
3458 		}
3459 		else {
3460 			renderFpsAvgTest = (renderFpsAvgTest + renderFps) / 2;
3461 		}
3462 	}
3463 
3464 	lastUpdateFps= updateFps;
3465 	lastRenderFps= renderFps;
3466 	updateFps= 0;
3467 	renderFps= 0;
3468 
3469 	//Win/lose check
3470 	checkWinner();
3471 	gui.tick();
3472 }
3473 
3474 
3475 // ==================== events ====================
3476 
3477 int Game::getFirstUnusedTeamNumber() {
3478 	std::map<int,bool> uniqueTeamNumbersUsed;
3479 	for(unsigned int i = 0; i < (unsigned int)world.getFactionCount(); ++i) {
3480 		Faction *faction = world.getFaction(i);
3481 		uniqueTeamNumbersUsed[faction->getTeam()]=true;
3482 	}
3483 
3484 	int result = -1;
3485 	for(int i = 0; i < GameConstants::maxPlayers; ++i) {
3486 		if(uniqueTeamNumbersUsed.find(i) == uniqueTeamNumbersUsed.end()) {
3487 			result = i;
3488 			break;
3489 		}
3490 	}
3491 
3492 	return result;
3493 }
3494 
3495 void Game::setupRenderForVideo() {
3496 	Renderer &renderer= Renderer::getInstance();
3497 	//renderer.clearBuffers();
3498 	//3d
3499 	//renderer.reset3dMenu();
3500 	//renderer.clearZBuffer();
3501 	//2d
3502 	//renderer.reset2d();
3503 	renderer.setupRenderForVideo();
3504 }
3505 
3506 void Game::tryPauseToggle(bool pauseValue) {
3507 	bool allowAdminMenuItems = false;
3508 	NetworkManager &networkManager= NetworkManager::getInstance();
3509 	NetworkRole role = networkManager.getNetworkRole();
3510 	if(role == nrServer) {
3511 		allowAdminMenuItems = true;
3512 	}
3513 	else if(role == nrClient) {
3514 		ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
3515 
3516 		if(clientInterface != NULL &&
3517 			gameSettings.getMasterserver_admin() == clientInterface->getSessionKey()) {
3518 			allowAdminMenuItems = true;
3519 		}
3520 	}
3521 
3522 	bool isNetworkGame 				= this->gameSettings.isNetworkGame();
3523 	//printf("Try Pause allowAdminMenuItems = %d, pauseValue = %d\n",allowAdminMenuItems,pauseValue);
3524 
3525 	if(allowAdminMenuItems) {
3526 		if(pauseValue == true) {
3527 			commander.tryPauseGame(false,false);
3528 		}
3529 		else {
3530 			if(isNetworkGame == false) {
3531 				setPaused(pauseValue, true,false,false);
3532 			}
3533 			else {
3534 				commander.tryResumeGame(false,false);
3535 			}
3536 		}
3537 	}
3538 }
3539 
3540 void Game::startMarkCell() {
3541 	int totalMarkedCellsForPlayer = 0;
3542 	if(world.getThisFaction() != NULL) {
3543 		for(std::map<Vec2i, MarkedCell>::iterator iterMap = mapMarkedCellList.begin();
3544 				iterMap != mapMarkedCellList.end(); ++iterMap) {
3545 			MarkedCell &bm = iterMap->second;
3546 			if(bm.getPlayerIndex() == world.getThisFaction()->getStartLocationIndex()) {
3547 				totalMarkedCellsForPlayer++;
3548 			}
3549 		}
3550 	}
3551 
3552 	const int MAX_MARKER_COUNT = 5;
3553 	if(totalMarkedCellsForPlayer < MAX_MARKER_COUNT) {
3554 		isMarkCellEnabled = true;
3555 	}
3556 	else {
3557 		Lang &lang= Lang::getInstance();
3558 		console.addLine(lang.getString("MaxMarkerCount") + " " + intToStr(MAX_MARKER_COUNT));
3559 	}
3560 }
3561 
3562 void Game::processInputText(string text, bool cancelled) {
3563 	isMarkCellTextEnabled = false;
3564 
3565 	if(cancelled == false) {
3566 		//printf("Note [%s]\n",text.c_str());
3567 
3568 		cellMarkedData.setNote(text);
3569 		addCellMarker(cellMarkedPos, cellMarkedData);
3570 
3571 //		if(text.find("\\n") != text.npos) {
3572 //			replaceAll(text, "\\n", "\n");
3573 //		}
3574 //		if(text.find("\\t") != text.npos) {
3575 //			replaceAll(text, "\\t", "\t");
3576 //		}
3577 //
3578 //		cellMarkedData.setNote(text);
3579 //		mapMarkedCellList[cellMarkedPos] = cellMarkedData;
3580 //
3581 //		GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
3582 //
3583 //		int factionIndex = -1;
3584 //		int playerIndex = -1;
3585 //		if(cellMarkedData.getFaction() != NULL) {
3586 //			factionIndex = cellMarkedData.getFaction()->getIndex();
3587 //			playerIndex = cellMarkedData.getFaction()->getStartLocationIndex();
3588 //		}
3589 //		gameNetworkInterface->sendMarkCellMessage(
3590 //				cellMarkedData.getTargetPos(),
3591 //				factionIndex,
3592 //				cellMarkedData.getNote(),
3593 //				playerIndex);
3594 //
3595 //		Renderer &renderer= Renderer::getInstance();
3596 //		renderer.forceQuadCacheUpdate();
3597 	}
3598 }
3599 
3600 void Game::addCellMarker(Vec2i cellPos, MarkedCell cellData) {
3601 	//printf("Note [%s]\n",text.c_str());
3602 
3603 	string text = cellData.getNote();
3604 	if(text.find("\\n") != text.npos) {
3605 		replaceAll(text, "\\n", "\n");
3606 	}
3607 	if(text.find("\\t") != text.npos) {
3608 		replaceAll(text, "\\t", "\t");
3609 	}
3610 
3611 	cellData.setNote(text);
3612 	mapMarkedCellList[cellPos] = cellData;
3613 
3614 	GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
3615 
3616 	int factionIndex = -1;
3617 	int playerIndex = -1;
3618 	if(cellData.getFaction() != NULL) {
3619 		factionIndex = cellData.getFaction()->getIndex();
3620 		playerIndex = cellData.getFaction()->getStartLocationIndex();
3621 	}
3622 
3623 	//printf("Adding Cell marker pos [%s] factionIndex [%d] note [%s] playerIndex = %d\n",cellData.getTargetPos().getString().c_str(),factionIndex,cellData.getNote().c_str(),playerIndex);
3624 
3625 	gameNetworkInterface->sendMarkCellMessage(
3626 			cellData.getTargetPos(),
3627 			factionIndex,
3628 			cellData.getNote(),
3629 			playerIndex);
3630 
3631 	Renderer &renderer= Renderer::getInstance();
3632 	renderer.forceQuadCacheUpdate();
3633 }
3634 
3635 void Game::removeCellMarker(Vec2i surfaceCellPos, const Faction *faction) {
3636 	//Vec2i surfaceCellPos = map->toSurfCoords(Vec2i(xCell,yCell));
3637 	Map *map= world.getMap();
3638 	SurfaceCell *sc = map->getSurfaceCell(surfaceCellPos);
3639 	Vec3f vertex = sc->getVertex();
3640 	Vec2i targetPos(vertex.x,vertex.z);
3641 
3642 	//printf("Remove Cell marker lookup pos [%s] factionIndex [%d]\n",surfaceCellPos.getString().c_str(),(faction != NULL ? faction->getIndex() : -1));
3643 
3644 	if(mapMarkedCellList.find(surfaceCellPos) != mapMarkedCellList.end()) {
3645 		MarkedCell mc = mapMarkedCellList[surfaceCellPos];
3646 		if(mc.getFaction() == faction) {
3647 			mapMarkedCellList.erase(surfaceCellPos);
3648 			GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
3649 
3650 			int factionIndex = (faction != NULL ? faction->getIndex() : -1);
3651 
3652 			//printf("Remvoing Cell marker pos [%s] factionIndex [%d] note [%s]\n",mc.getTargetPos().getString().c_str(),factionIndex,mc.getNote().c_str());
3653 
3654 			gameNetworkInterface->sendUnMarkCellMessage(mc.getTargetPos(),factionIndex);
3655 		}
3656 	}
3657 	//printf("#1 ADDED in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",surfaceCellPos.getString().c_str(),mapMarkedCellList.size());
3658 
3659 	//isUnMarkCellEnabled = false;
3660 
3661 	Renderer &renderer= Renderer::getInstance();
3662 	//renderer.updateMarkedCellScreenPosQuadCache(surfaceCellPos);
3663 	renderer.forceQuadCacheUpdate();
3664 }
3665 void Game::showMarker(Vec2i cellPos, MarkedCell cellData) {
3666 	//setMarker = true;
3667 	//if(setMarker) {
3668 		//Vec2i targetPos = cellData.targetPos;
3669 		//Vec2i screenPos(x,y-60);
3670 		//Renderer &renderer= Renderer::getInstance();
3671 		//renderer.computePosition(screenPos, targetPos);
3672 		//Vec2i surfaceCellPos = map->toSurfCoords(targetPos);
3673 
3674 		//MarkedCell mc(targetPos,world.getThisFaction(),"none",world.getThisFaction()->getStartLocationIndex());
3675 		addOrReplaceInHighlightedCells(cellData);
3676 
3677 		GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
3678 		gameNetworkInterface->sendHighlightCellMessage(cellData.getTargetPos(),cellData.getFactionIndex());
3679 	//}
3680 }
3681 
3682 void Game::mouseDownLeft(int x, int y) {
3683 	if(this->masterserverMode == true) {
3684 		return;
3685 	}
3686 	cameraDragAllowed=false;
3687 	if(currentUIState != NULL) {
3688 		currentUIState->mouseDownLeft(x, y);
3689 		return;
3690 	}
3691 
3692 	try {
3693 		if(gameStarted == false || totalRenderFps <= 0) {
3694 			Logger::getInstance().handleMouseClick(x, y);
3695 			return;
3696 		}
3697 
3698 		Map *map= world.getMap();
3699 		const Metrics &metrics= Metrics::getInstance();
3700 		NetworkManager &networkManager= NetworkManager::getInstance();
3701 		bool messageBoxClick= false;
3702 		bool originalIsMarkCellEnabled = isMarkCellEnabled;
3703 		bool originalIsUnMarkCellEnabled = isUnMarkCellEnabled;
3704 
3705 		if(popupMenu.mouseClick(x, y)) {
3706 			std::pair<int,string> result = popupMenu.mouseClickedMenuItem(x, y);
3707 			//printf("In popup callback menuItemSelected [%s] menuIndexSelected = %d\n",result.second.c_str(),result.first);
3708 
3709 			//printf("popupMenu.mouseClick == true result.first = %d disconnectPlayerPopupMenuIndex = %d\n",result.first,disconnectPlayerPopupMenuIndex);
3710 
3711 			popupMenu.setEnabled(false);
3712 			popupMenu.setVisible(false);
3713 
3714 			// Exit game
3715 			if(result.first == exitGamePopupMenuIndex) {
3716 				showMessageBox(Lang::getInstance().getString("ExitBattleQuestion"), "", true);
3717 			}
3718 			else if(result.first == joinTeamPopupMenuIndex) {
3719 
3720 				Lang &lang= Lang::getInstance();
3721 				switchTeamIndexMap.clear();
3722 				std::map<int,bool> uniqueTeamNumbersUsed;
3723 				std::vector<string> menuItems;
3724 				for(unsigned int i = 0; i < (unsigned int)world.getFactionCount(); ++i) {
3725 					Faction *faction = world.getFaction(i);
3726 
3727 					if(faction->getPersonalityType() != fpt_Observer &&
3728 						uniqueTeamNumbersUsed.find(faction->getTeam()) == uniqueTeamNumbersUsed.end()) {
3729 						uniqueTeamNumbersUsed[faction->getTeam()] = true;
3730 					}
3731 
3732 					if(faction->getPersonalityType() != fpt_Observer &&
3733 						world.getThisFaction()->getIndex() != faction->getIndex() &&
3734 						world.getThisFaction()->getTeam() != faction->getTeam()) {
3735 						char szBuf[8096]="";
3736 						if(lang.hasString("JoinPlayerTeam") == true) {
3737 							snprintf(szBuf,8096,("  " + lang.getString("JoinPlayerTeam") + "  ").c_str(),faction->getIndex(),this->gameSettings.getNetworkPlayerName(i).c_str(),faction->getTeam());
3738 						}
3739 						else {
3740 							snprintf(szBuf,8096,"  Join player #%d - %s on Team: %d  ",faction->getIndex(),this->gameSettings.getNetworkPlayerName(i).c_str(),faction->getTeam());
3741 						}
3742 
3743 						menuItems.push_back(szBuf);
3744 
3745 						switchTeamIndexMap[(int)menuItems.size()-1] = faction->getTeam();
3746 					}
3747 				}
3748 
3749 				if((int)uniqueTeamNumbersUsed.size() < 8) {
3750 					menuItems.push_back("  " + lang.getString("CreateNewTeam") + "  ");
3751 					switchTeamIndexMap[(int)menuItems.size()-1] = CREATE_NEW_TEAM;
3752 				}
3753 				menuItems.push_back("  " + lang.getString("Cancel") + "  ");
3754 				switchTeamIndexMap[(int)menuItems.size()-1] = CANCEL_SWITCH_TEAM;
3755 
3756 				popupMenuSwitchTeams.setW(100);
3757 				popupMenuSwitchTeams.setH(100);
3758 				popupMenuSwitchTeams.init("  " + lang.getString("SwitchTeams") + "  ",menuItems);
3759 				popupMenuSwitchTeams.setEnabled(true);
3760 				popupMenuSwitchTeams.setVisible(true);
3761 			}
3762 			else if(result.first == disconnectPlayerPopupMenuIndex) {
3763 				Lang &lang= Lang::getInstance();
3764 
3765 				NetworkManager &networkManager= NetworkManager::getInstance();
3766 				NetworkRole role = networkManager.getNetworkRole();
3767 				ServerInterface *serverInterface = NULL;
3768 				if(role == nrServer) {
3769 					serverInterface = dynamic_cast<ServerInterface *>(networkManager.getServerInterface());
3770 				}
3771 				disconnectPlayerIndexMap.clear();
3772 				std::vector<string> menuItems;
3773 				for(unsigned int i = 0; i < (unsigned int)world.getFactionCount(); ++i) {
3774 					Faction *faction = world.getFaction(i);
3775 
3776 					//printf("faction->getPersonalityType() = %d index [%d,%d] control [%d] networkstatus [%d]\n",faction->getPersonalityType(),world.getThisFaction()->getIndex(),faction->getIndex(),faction->getControlType(),this->gameSettings.getNetworkPlayerStatuses(i));
3777 
3778 					bool isSlotJoinInProgressClient = false;
3779 					if(serverInterface != NULL) {
3780 
3781 						MutexSafeWrapper safeMutex(serverInterface->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
3782 						ConnectionSlot *slot =  serverInterface->getSlot(faction->getStartLocationIndex(),false);
3783 						if(slot != NULL && slot->getConnectHasHandshaked() == true &&
3784 								slot->getCurrentFrameCount() <= 0) {
3785 							isSlotJoinInProgressClient = true;
3786 						}
3787 					}
3788 
3789 					//printf("isSlotJoinInProgressClient: %d [%d] [%d][%d] [%d] [%d] [%d]\n",
3790 					//		isSlotJoinInProgressClient,faction->getPersonalityType(),faction->getIndex(),world.getThisFaction()->getIndex(),faction->getControlType(),this->gameSettings.getNetworkPlayerStatuses(i),i);
3791 
3792 					if(isSlotJoinInProgressClient == true ||
3793 						(faction->getPersonalityType() != fpt_Observer &&
3794 						world.getThisFaction()->getIndex() != faction->getIndex() &&
3795 						faction->getControlType() == ctNetwork &&
3796 						this->gameSettings.getNetworkPlayerStatuses(i) != npst_Disconnected)) {
3797 
3798 						char szBuf[8096]="";
3799 						if(lang.hasString("DisconnectNetorkPlayerIndex") == true) {
3800 							snprintf(szBuf,8096,("  " + lang.getString("DisconnectNetorkPlayerIndex") + "  ").c_str(),faction->getIndex()+1,this->gameSettings.getNetworkPlayerName(i).c_str());
3801 						}
3802 						else {
3803 							snprintf(szBuf,8096,"  Disconnect player #%d - %s:  ",faction->getIndex()+1,this->gameSettings.getNetworkPlayerName(i).c_str());
3804 						}
3805 
3806 						menuItems.push_back(szBuf);
3807 
3808 						//disconnectPlayerIndexMap[menuItems.size()-1] = faction->getStartLocationIndex();
3809 						disconnectPlayerIndexMap[(int)menuItems.size()-1] = faction->getIndex();
3810 					}
3811 				}
3812 
3813 				menuItems.push_back("  " + lang.getString("Cancel") + "  ");
3814 				disconnectPlayerIndexMap[(int)menuItems.size()-1] = CANCEL_DISCONNECT_PLAYER;
3815 
3816 				popupMenuDisconnectPlayer.setW(100);
3817 				popupMenuDisconnectPlayer.setH(100);
3818 				popupMenuDisconnectPlayer.init("  " + lang.getString("DisconnectNetorkPlayer") + "  ",menuItems);
3819 				popupMenuDisconnectPlayer.setEnabled(true);
3820 				popupMenuDisconnectPlayer.setVisible(true);
3821 			}
3822 			else if(result.first == keyboardSetupPopupMenuIndex) {
3823 				MainMenu *newMenu = new MainMenu(program); // open keyboard shortcuts setup screen
3824 				currentUIState = newMenu;
3825 				Renderer &renderer= Renderer::getInstance();
3826 				renderer.setCustom3dMenu(newMenu);
3827 				//currentUIState->load();
3828 				currentUIState->init();
3829 
3830 				// open keyboard shortcuts setup screen
3831 				newMenu->setState(new MenuStateKeysetup(program, newMenu, &currentUIState));
3832 			}
3833 			else if(result.first == pauseGamePopupMenuIndex) {
3834 				//this->setPaused(!paused);
3835 				//printf("popup paused = %d\n",paused);
3836 
3837 				bool allowAdminMenuItems = false;
3838 				NetworkRole role = networkManager.getNetworkRole();
3839 				if(role == nrServer) {
3840 					allowAdminMenuItems = true;
3841 				}
3842 				else if(role == nrClient) {
3843 					ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
3844 
3845 					if(clientInterface != NULL &&
3846 						gameSettings.getMasterserver_admin() == clientInterface->getSessionKey()) {
3847 						allowAdminMenuItems = true;
3848 					}
3849 				}
3850 
3851 				if(allowAdminMenuItems) {
3852 					if(getPaused() == false) {
3853 						commander.tryPauseGame(false,false);
3854 					}
3855 					else {
3856 						commander.tryResumeGame(false,false);
3857 					}
3858 				}
3859 			}
3860 			else if(result.first == saveGamePopupMenuIndex){
3861 				saveGame();
3862 			}
3863 			//else if(result.first == markCellPopupMenuIndex) {
3864 			//	startMarkCell();
3865 			//}
3866 			//else if(result.first == unmarkCellPopupMenuIndex) {
3867 			//	isUnMarkCellEnabled = true;
3868 			//}
3869 		}
3870 		else if(popupMenuSwitchTeams.mouseClick(x, y)) {
3871 			//popupMenuSwitchTeams
3872 			std::pair<int,string> result = popupMenuSwitchTeams.mouseClickedMenuItem(x, y);
3873 			//printf("In popup callback menuItemSelected [%s] menuIndexSelected = %d\n",result.second.c_str(),result.first);
3874 
3875 			popupMenuSwitchTeams.setEnabled(false);
3876 			popupMenuSwitchTeams.setVisible(false);
3877 
3878 			//bool isNetworkGame = this->gameSettings.isNetworkGame();
3879 
3880 			int teamIndex = switchTeamIndexMap[result.first];
3881 			switch(teamIndex) {
3882 				case CREATE_NEW_TEAM:
3883 					{
3884 					int newTeam = getFirstUnusedTeamNumber();
3885 					//if(isNetworkGame == true) {
3886 						const Faction *faction = world.getThisFaction();
3887 						commander.trySwitchTeam(faction,newTeam);
3888 					//}
3889 					//else {
3890 					//	const Faction *faction = world.getThisFaction();
3891 					//	commander.trySwitchTeam(faction,newTeam);
3892 					//}
3893 					}
3894 					break;
3895 				case CANCEL_SWITCH_TEAM:
3896 					break;
3897 				default:
3898 					//if(isNetworkGame == true) {
3899 						const Faction *faction = world.getThisFaction();
3900 						commander.trySwitchTeam(faction,teamIndex);
3901 					//}
3902 					//else {
3903 					//	const Faction *faction = world.getThisFaction();
3904 					//	commander.trySwitchTeam(faction,teamIndex);
3905 					//}
3906 
3907 					break;
3908 			}
3909 		}
3910 		else if(popupMenuDisconnectPlayer.mouseClick(x, y)) {
3911 			//popupMenuSwitchTeams
3912 			std::pair<int,string> result = popupMenuDisconnectPlayer.mouseClickedMenuItem(x, y);
3913 			//printf("In popup callback menuItemSelected [%s] menuIndexSelected = %d\n",result.second.c_str(),result.first);
3914 
3915 			popupMenuDisconnectPlayer.setEnabled(false);
3916 			popupMenuDisconnectPlayer.setVisible(false);
3917 
3918 			//bool isNetworkGame = this->gameSettings.isNetworkGame();
3919 
3920 			//int playerIndex = disconnectPlayerIndexMap[result.first];
3921 			int factionIndex = disconnectPlayerIndexMap[result.first];
3922 			switch(factionIndex) {
3923 				case CANCEL_DISCONNECT_PLAYER:
3924 					break;
3925 				default:
3926 //					if(isNetworkGame == true) {
3927 //						const Faction *faction = world.getThisFaction();
3928 //						commander.trySwitchTeam(faction,teamIndex);
3929 //					}
3930 //					else {
3931 //						const Faction *faction = world.getThisFaction();
3932 //						commander.trySwitchTeam(faction,teamIndex);
3933 //					}
3934 
3935 
3936 					GameSettings *settings = world.getGameSettingsPtr();
3937 					Lang &lang= Lang::getInstance();
3938 
3939 					char szBuf[8096]="";
3940 					if(lang.hasString("DisconnectNetorkPlayerIndexConfirm") == true) {
3941 						snprintf(szBuf,8096,("  " + lang.getString("DisconnectNetorkPlayerIndexConfirm") + "  ").c_str(),factionIndex+1,settings->getNetworkPlayerName(factionIndex).c_str());
3942 					}
3943 					else {
3944 						snprintf(szBuf,8096,"  Confirm disconnection for player #%d - %s?  ",factionIndex+1,settings->getNetworkPlayerName(factionIndex).c_str());
3945 					}
3946 
3947 					disconnectPlayerConfirmMessageBox.setText(szBuf);
3948 					disconnectPlayerConfirmMessageBox.init(lang.getString("Yes"), lang.getString("No"));
3949 					disconnectPlayerConfirmMessageBox.setEnabled(true);
3950 
3951 					playerIndexDisconnect = world.getFaction(factionIndex)->getStartLocationIndex();
3952 
3953 					GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
3954 					if(gameNetworkInterface != NULL) {
3955 						Lang &lang= Lang::getInstance();
3956 						const vector<string> languageList = settings->getUniqueNetworkPlayerLanguages();
3957 						for(unsigned int i = 0; i < (unsigned int)languageList.size(); ++i) {
3958 							char szMsg[8096]="";
3959 							if(lang.hasString("DisconnectNetorkPlayerIndexConfirmed",languageList[i]) == true) {
3960 								snprintf(szMsg,8096,lang.getString("DisconnectNetorkPlayerIndexConfirmed",languageList[i]).c_str(),factionIndex+1,settings->getNetworkPlayerName(factionIndex).c_str());
3961 							}
3962 							else {
3963 								snprintf(szMsg,8096,"Notice - Admin is warning to disconnect player #%d - %s!",factionIndex+1,settings->getNetworkPlayerName(factionIndex).c_str());
3964 							}
3965 							bool localEcho = lang.isLanguageLocal(languageList[i]);
3966 							gameNetworkInterface->sendTextMessage(szMsg,-1, localEcho,languageList[i]);
3967 						}
3968 
3969 						sleep(10);
3970 					}
3971 
3972 					break;
3973 			}
3974 		}
3975 
3976 		if(switchTeamConfirmMessageBox.getEnabled() == true) {
3977 			int button= -1;
3978 			if(switchTeamConfirmMessageBox.mouseClick(x,y,button)) {
3979 				switchTeamConfirmMessageBox.setEnabled(false);
3980 
3981 				SwitchTeamVote *vote = world.getThisFactionPtr()->getSwitchTeamVote(world.getThisFaction()->getCurrentSwitchTeamVoteFactionIndex());
3982 				vote->voted = true;
3983 				vote->allowSwitchTeam = (button == 0);
3984 
3985 				const Faction *faction = world.getThisFaction();
3986 				commander.trySwitchTeamVote(faction,vote);
3987 			}
3988 		}
3989 		else if(disconnectPlayerConfirmMessageBox.getEnabled() == true) {
3990 			int button= -1;
3991 			if(disconnectPlayerConfirmMessageBox.mouseClick(x,y,button)) {
3992 				disconnectPlayerConfirmMessageBox.setEnabled(false);
3993 
3994 				if(button == 0) {
3995 					const Faction *faction = world.getThisFaction();
3996 					commander.tryDisconnectNetworkPlayer(faction,playerIndexDisconnect);
3997 				}
3998 			}
3999 		}
4000 
4001 		//scrip message box, only if the exit box is not enabled
4002 		if( mainMessageBox.getEnabled() == false &&
4003 			errorMessageBox.getEnabled() == false &&
4004 			scriptManager.getMessageBox()->getEnabled()) {
4005 			int button= 0;
4006 			if(scriptManager.getMessageBox()->mouseClick(x, y, button)){
4007 				scriptManager.onMessageBoxOk();
4008 				messageBoxClick= true;
4009 			}
4010 		}
4011 
4012 		//minimap panel
4013 		if(messageBoxClick == false) {
4014 			if(metrics.isInMinimap(x, y)){
4015 				int xm= x - metrics.getMinimapX();
4016 				int ym= y - metrics.getMinimapY();
4017 				int xCell= static_cast<int>(xm * (static_cast<float>(map->getW()) / metrics.getMinimapW()));
4018 				int yCell= static_cast<int>(map->getH() - ym * (static_cast<float>(map->getH()) / metrics.getMinimapH()));
4019 
4020 				if(map->isInside(xCell, yCell) && map->isInsideSurface(map->toSurfCoords(Vec2i(xCell,yCell)))) {
4021 					if(gui.isSelectingPos()){
4022 						gui.mouseDownLeftGraphics(xCell, yCell, true);
4023 					}
4024 					else
4025 					{
4026 						if(!setMarker) {
4027 							cameraDragAllowed=true;
4028 							gameCamera.setPos(Vec2f(static_cast<float>(xCell), static_cast<float>(yCell)));
4029 						}
4030 					}
4031 
4032 					if(setMarker) {
4033 						Vec2i surfaceCellPos = map->toSurfCoords(Vec2i(xCell,yCell));
4034 						SurfaceCell *sc = map->getSurfaceCell(surfaceCellPos);
4035 						Vec3f vertex = sc->getVertex();
4036 						Vec2i targetPos(vertex.x,vertex.z);
4037 
4038 						MarkedCell mc(targetPos,world.getThisFaction(),"none",world.getThisFaction()->getStartLocationIndex());
4039 						addOrReplaceInHighlightedCells(mc);
4040 
4041 						GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
4042 						gameNetworkInterface->sendHighlightCellMessage(mc.getTargetPos(),mc.getFaction()->getIndex());
4043 					}
4044 
4045 
4046 					if(originalIsMarkCellEnabled == true && isMarkCellEnabled == true) {
4047 						Vec2i surfaceCellPos = map->toSurfCoords(Vec2i(xCell,yCell));
4048 						SurfaceCell *sc = map->getSurfaceCell(surfaceCellPos);
4049 						Vec3f vertex = sc->getVertex();
4050 						Vec2i targetPos(vertex.x,vertex.z);
4051 
4052 						MarkedCell mc(targetPos,world.getThisFaction(),"placeholder for note",world.getThisFaction()->getStartLocationIndex());
4053 
4054 						//GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
4055 						//gameNetworkInterface->sendMarkCellMessage(mc.getTargetPos(),mc.getFaction()->getIndex(),mc.getNote());
4056 
4057 						//printf("#1 ADDED in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",surfaceCellPos.getString().c_str(),mapMarkedCellList.size());
4058 
4059 						isMarkCellEnabled = false;
4060 						cellMarkedData = mc;
4061 						cellMarkedPos = surfaceCellPos;
4062 						isMarkCellTextEnabled = true;
4063 						chatManager.switchOnEdit(this,500);
4064 
4065 						Renderer &renderer= Renderer::getInstance();
4066 						//renderer.updateMarkedCellScreenPosQuadCache(surfaceCellPos);
4067 						renderer.forceQuadCacheUpdate();
4068 					}
4069 					if(originalIsUnMarkCellEnabled == true && isUnMarkCellEnabled == true) {
4070 						Vec2i surfaceCellPos = map->toSurfCoords(Vec2i(xCell,yCell));
4071 						SurfaceCell *sc = map->getSurfaceCell(surfaceCellPos);
4072 						Vec3f vertex = sc->getVertex();
4073 						Vec2i targetPos(vertex.x,vertex.z);
4074 
4075 //						if(mapMarkedCellList.find(surfaceCellPos) != mapMarkedCellList.end()) {
4076 //							MarkedCell mc = mapMarkedCellList[surfaceCellPos];
4077 //							if(mc.getFaction() == world.getThisFaction()) {
4078 //								mapMarkedCellList.erase(surfaceCellPos);
4079 //								GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
4080 //								gameNetworkInterface->sendUnMarkCellMessage(mc.getTargetPos(),mc.getFaction()->getIndex());
4081 //							}
4082 //						}
4083 
4084 						isUnMarkCellEnabled = false;
4085 
4086 						removeCellMarker(surfaceCellPos, world.getThisFaction());
4087 						//printf("#1 ADDED in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",surfaceCellPos.getString().c_str(),mapMarkedCellList.size());
4088 
4089 						Renderer &renderer= Renderer::getInstance();
4090 						//renderer.updateMarkedCellScreenPosQuadCache(surfaceCellPos);
4091 						renderer.forceQuadCacheUpdate();
4092 					}
4093 				}
4094 			}
4095 			//display panel
4096 			else if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()) {
4097 				int xd= x - metrics.getDisplayX();
4098 				int yd= y - metrics.getDisplayY();
4099 				if(gui.mouseValid(xd, yd)) {
4100 					gui.mouseDownLeftDisplay(xd, yd);
4101 				}
4102 				else {
4103 					gui.mouseDownLeftGraphics(x, y, false);
4104 				}
4105 			}
4106 			//graphics panel
4107 			else {
4108 				gui.mouseDownLeftGraphics(x, y, false);
4109 
4110 				if(setMarker) {
4111 					Vec2i targetPos;
4112 					Vec2i screenPos(x,y-60);
4113 					targetPos=getMouseCellPos();
4114 					//Vec2i surfaceCellPos = map->toSurfCoords(targetPos);
4115 
4116 
4117 					MarkedCell mc(targetPos,world.getThisFaction(),"none",world.getThisFaction()->getStartLocationIndex());
4118 					addOrReplaceInHighlightedCells(mc);
4119 
4120 					GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
4121 					gameNetworkInterface->sendHighlightCellMessage(mc.getTargetPos(),mc.getFaction()->getIndex());
4122 				}
4123 
4124 				if(originalIsMarkCellEnabled == true && isMarkCellEnabled == true) {
4125 					Vec2i targetPos;
4126 					Vec2i screenPos(x,y-60);
4127 					targetPos=getMouseCellPos();
4128 					Vec2i surfaceCellPos = map->toSurfCoords(targetPos);
4129 
4130 					MarkedCell mc(targetPos,world.getThisFaction(),"placeholder for note",world.getThisFaction()->getStartLocationIndex());
4131 
4132 					//printf("#2 ADDED in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",surfaceCellPos.getString().c_str(),mapMarkedCellList.size());
4133 
4134 					isMarkCellEnabled = false;
4135 					cellMarkedData = mc;
4136 					cellMarkedPos = surfaceCellPos;
4137 					isMarkCellTextEnabled = true;
4138 					chatManager.switchOnEdit(this,500);
4139 
4140 					//renderer.updateMarkedCellScreenPosQuadCache(surfaceCellPos);
4141 					Renderer::getInstance().forceQuadCacheUpdate();
4142 				}
4143 
4144 				if(originalIsUnMarkCellEnabled == true && isUnMarkCellEnabled == true) {
4145 					Vec2i targetPos;
4146 					Vec2i screenPos(x,y-35);
4147 					targetPos=getMouseCellPos();
4148 					Vec2i surfaceCellPos = map->toSurfCoords(targetPos);
4149 
4150 //					if(mapMarkedCellList.find(surfaceCellPos) != mapMarkedCellList.end()) {
4151 //						MarkedCell mc = mapMarkedCellList[surfaceCellPos];
4152 //						if(mc.getFaction() == world.getThisFaction()) {
4153 //							mapMarkedCellList.erase(surfaceCellPos);
4154 //							GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
4155 //							gameNetworkInterface->sendUnMarkCellMessage(mc.getTargetPos(),mc.getFaction()->getIndex());
4156 //						}
4157 //					}
4158 
4159 					isUnMarkCellEnabled = false;
4160 					removeCellMarker(surfaceCellPos, world.getThisFaction());
4161 					//printf("#1 ADDED in marked list pos [%s] markedCells.size() = " MG_SIZE_T_SPECIFIER "\n",surfaceCellPos.getString().c_str(),mapMarkedCellList.size());
4162 
4163 					//Renderer &renderer= Renderer::getInstance();
4164 					//renderer.updateMarkedCellScreenPosQuadCache(surfaceCellPos);
4165 					Renderer::getInstance().forceQuadCacheUpdate();
4166 				}
4167 			}
4168 		}
4169 
4170 		//exit message box, has to be the last thing to do in this function
4171 		if(errorMessageBox.getEnabled() == true) {
4172 			if(errorMessageBox.mouseClick(x, y)) {
4173 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
4174 				//close message box
4175 				errorMessageBox.setEnabled(false);
4176 			}
4177 		}
4178 		if(mainMessageBox.getEnabled()){
4179 			int button= 0;
4180 			if(mainMessageBox.mouseClick(x, y, button)) {
4181 				if(button==0) {
4182 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
4183 					if(networkManager.getGameNetworkInterface() != NULL) {
4184 						networkManager.getGameNetworkInterface()->quitGame(true);
4185 					}
4186 					quitTriggeredIndicator = true;
4187 					return;
4188 				}
4189 				else {
4190 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
4191 					//close message box
4192 					mainMessageBox.setEnabled(false);
4193 				}
4194 			}
4195 		}
4196 	}
4197 	catch(const exception &ex) {
4198 		char szBuf[8096]="";
4199 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
4200 
4201 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
4202 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
4203 
4204 		NetworkManager &networkManager= NetworkManager::getInstance();
4205 		if(networkManager.getGameNetworkInterface() != NULL) {
4206 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
4207 			networkInterface->sendTextMessage(szBuf,-1,true,"");
4208 			sleep(10);
4209 			networkManager.getGameNetworkInterface()->quitGame(true);
4210 		}
4211 		ErrorDisplayMessage(ex.what(),true);
4212 	}
4213 }
4214 
4215 void Game::mouseDownRight(int x, int y) {
4216 	if(this->masterserverMode == true) {
4217 		return;
4218 	}
4219 
4220 	if(currentUIState != NULL) {
4221 		currentUIState->mouseDownRight(x, y);
4222 		return;
4223 	}
4224 
4225 	try {
4226 		if(gameStarted == false || totalRenderFps <= 0) {
4227 			Logger::getInstance().handleMouseClick(x, y);
4228 			return;
4229 		}
4230 
4231 		Map *map= world.getMap();
4232 		const Metrics &metrics= Metrics::getInstance();
4233 
4234 		if(metrics.isInMinimap(x, y) ){
4235 			int xm= x - metrics.getMinimapX();
4236 			int ym= y - metrics.getMinimapY();
4237 			int xCell= static_cast<int>(xm * (static_cast<float>(map->getW()) / metrics.getMinimapW()));
4238 			int yCell= static_cast<int>(map->getH() - ym * (static_cast<float>(map->getH()) / metrics.getMinimapH()));
4239 
4240 			if(map->isInside(xCell, yCell) && map->isInsideSurface(map->toSurfCoords(Vec2i(xCell,yCell)))) {
4241 				gui.mouseDownRightGraphics(xCell, yCell,true);
4242 			}
4243 		}
4244 		else {
4245 			Vec2i targetPos;
4246 			Vec2i screenPos(x,y);
4247 			targetPos=getMouseCellPos();
4248 			if(isValidMouseCellPos() == true &&
4249 				map->isInsideSurface(map->toSurfCoords(targetPos)) == true) {
4250 				gui.mouseDownRightGraphics(x, y,false);
4251 			}
4252 		}
4253 	}
4254 	catch(const exception &ex) {
4255 		char szBuf[8096]="";
4256 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s] x = %d y = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what(),x,y);
4257 
4258 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
4259 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
4260 
4261 		NetworkManager &networkManager= NetworkManager::getInstance();
4262 		if(networkManager.getGameNetworkInterface() != NULL) {
4263 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
4264 			networkInterface->sendTextMessage(szBuf,-1,true,"");
4265 			sleep(10);
4266 			networkManager.getGameNetworkInterface()->quitGame(true);
4267 		}
4268 		ErrorDisplayMessage(ex.what(),true);
4269 	}
4270 }
4271 
4272  void Game::mouseUpCenter(int x, int y) {
4273 	if(this->masterserverMode == true) {
4274 		return;
4275 	}
4276 
4277 	if(gameStarted == false || totalRenderFps <= 0) {
4278 		return;
4279 	}
4280 
4281 	if(currentUIState != NULL) {
4282 		currentUIState->mouseUpCenter(x, y);
4283 		return;
4284 	}
4285 
4286  	if(mouseMoved == false) {
4287  		gameCamera.setState(GameCamera::sGame);
4288  	}
4289  	else {
4290  		mouseMoved = false;
4291  	}
4292 }
4293 
4294 void Game::mouseUpLeft(int x, int y) {
4295 	if(this->masterserverMode == true) {
4296 		return;
4297 	}
4298 
4299 	try {
4300 		if(gameStarted == false || totalRenderFps <= 0) {
4301 			return;
4302 		}
4303 
4304 		if(currentUIState != NULL) {
4305 			currentUIState->mouseUpLeft(x, y);
4306 			return;
4307 		}
4308 
4309 		gui.mouseUpLeftGraphics(x, y);
4310 	}
4311 	catch(const exception &ex) {
4312 		char szBuf[8096]="";
4313 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
4314 
4315 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
4316 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
4317 
4318 		NetworkManager &networkManager= NetworkManager::getInstance();
4319 		if(networkManager.getGameNetworkInterface() != NULL) {
4320 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
4321 			networkInterface->sendTextMessage(szBuf,-1,true,"");
4322 			sleep(10);
4323 			networkManager.getGameNetworkInterface()->quitGame(true);
4324 		}
4325 		ErrorDisplayMessage(ex.what(),true);
4326 	}
4327 }
4328 
4329 void Game::mouseDoubleClickLeft(int x, int y) {
4330 	if(this->masterserverMode == true) {
4331 		return;
4332 	}
4333 
4334 	try {
4335 		if(gameStarted == false || totalRenderFps <= 0) {
4336 			return;
4337 		}
4338 		if(currentUIState != NULL) {
4339 			currentUIState->mouseDoubleClickLeft(x, y);
4340 			return;
4341 		}
4342 
4343 		const Metrics &metrics= Metrics::getInstance();
4344 
4345 		if(metrics.isInMinimap(x, y)){
4346 			// no double click on minimap
4347 		}
4348 		else {
4349 			//display panel
4350 			if(metrics.isInDisplay(x, y) && !gui.isSelectingPos()) {
4351 				int xd= x - metrics.getDisplayX();
4352 				int yd= y - metrics.getDisplayY();
4353 				if(gui.mouseValid(xd, yd)){
4354 					return;
4355 				}
4356 			}
4357 			//graphics panel
4358 			gui.mouseDoubleClickLeftGraphics(x, y);
4359 		}
4360 	}
4361 	catch(const exception &ex) {
4362 		char szBuf[8096]="";
4363 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
4364 
4365 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
4366 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
4367 
4368 		NetworkManager &networkManager= NetworkManager::getInstance();
4369 		if(networkManager.getGameNetworkInterface() != NULL) {
4370 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
4371 			networkInterface->sendTextMessage(szBuf,-1,true,"");
4372 			sleep(10);
4373 			networkManager.getGameNetworkInterface()->quitGame(true);
4374 		}
4375 		ErrorDisplayMessage(ex.what(),true);
4376 	}
4377 }
4378 
4379 void Game::mouseMove(int x, int y, const MouseState *ms) {
4380 	if(this->masterserverMode == true) {
4381 		return;
4382 	}
4383 
4384 	try {
4385 		if(gameStarted == false || totalRenderFps <= 0) {
4386 			return;
4387 		}
4388 		if(currentUIState != NULL) {
4389 			currentUIState->mouseMove(x, y, ms);
4390 			return;
4391 		}
4392 
4393 		popupMenu.mouseMove(x, y);
4394 		popupMenuSwitchTeams.mouseMove(x, y);
4395 		popupMenuDisconnectPlayer.mouseMove(x, y);
4396 
4397 		const Metrics &metrics = Metrics::getInstance();
4398 
4399 		mouseX = x;
4400 		mouseY = y;
4401 
4402 		if (ms->get(mbCenter)) {
4403 			mouseMoved = true;
4404 			if(currentCameraFollowUnit == NULL) {
4405 				float ymult = 0.2f;
4406 				float xmult = 0.2f;
4407 
4408 				Vec2i oldPos = ::Shared::Platform::Window::getOldMousePos();
4409 				int oldx= (oldPos.x * metrics.getVirtualW() / metrics.getScreenW());
4410 				int oldy= ((metrics.getScreenH()-oldPos.y) * metrics.getVirtualH()  /  metrics.getScreenH());
4411 				lastMousePos.x=oldx;
4412 				lastMousePos.y=oldy;
4413 				gameCamera.transitionVH(-(y - oldy) * ymult, (oldx - x) * xmult);
4414 			}
4415 			mouseX=lastMousePos.x;
4416 			mouseY=lastMousePos.y;
4417 			::Shared::Platform::Window::revertMousePos();
4418 
4419 			return;
4420 		}
4421 		else if(currentCameraFollowUnit==NULL) {
4422 			//if(Window::isKeyDown() == false)
4423 			if(!camLeftButtonDown && !camRightButtonDown && !camUpButtonDown && !camDownButtonDown)
4424 			{
4425 				if(ms->get(mbLeft) && metrics.isInMinimap(x, y)) {
4426 					int xm= x - metrics.getMinimapX();
4427 					int ym= y - metrics.getMinimapY();
4428 
4429 					Map *map= world.getMap();
4430 					int xCell= static_cast<int>(xm * (static_cast<float>(map->getW()) / metrics.getMinimapW()));
4431 					int yCell= static_cast<int>(map->getH() - ym * (static_cast<float>(map->getH()) / metrics.getMinimapH()));
4432 
4433 					if(map->isInside(xCell, yCell) && map->isInsideSurface(map->toSurfCoords(Vec2i(xCell,yCell)))) {
4434 						if(gui.isSelectingPos()){
4435 							gui.mouseDownLeftGraphics(xCell, yCell, true);
4436 						}
4437 						else
4438 						{
4439 							if(cameraDragAllowed == true) {
4440 								gameCamera.setPos(Vec2f(static_cast<float>(xCell), static_cast<float>(yCell)));
4441 							}
4442 						}
4443 					}
4444 				}
4445 				else {
4446 					bool mouseMoveScrollsWorld = Config::getInstance().getBool("MouseMoveScrollsWorld","true");
4447 					if(mouseMoveScrollsWorld == true) {
4448 						if (y < 10) {
4449 							gameCamera.setMoveZ(-scrollSpeed);
4450 						}
4451 						else if (y > metrics.getVirtualH() - 10) {
4452 							gameCamera.setMoveZ(scrollSpeed);
4453 						}
4454 						else {
4455 							gameCamera.setMoveZ(0);
4456 						}
4457 
4458 						if (x < 10) {
4459 							gameCamera.setMoveX(-scrollSpeed);
4460 						}
4461 						else if (x > metrics.getVirtualW() - 10) {
4462 							gameCamera.setMoveX(scrollSpeed);
4463 						}
4464 						else {
4465 							gameCamera.setMoveX(0);
4466 						}
4467 					}
4468 				}
4469 			}
4470 
4471 			if(switchTeamConfirmMessageBox.getEnabled() == true) {
4472 				switchTeamConfirmMessageBox.mouseMove(x,y);
4473 			}
4474 
4475 			if(disconnectPlayerConfirmMessageBox.getEnabled() == true) {
4476 				disconnectPlayerConfirmMessageBox.mouseMove(x,y);
4477 			}
4478 
4479 			if (mainMessageBox.getEnabled()) {
4480 				mainMessageBox.mouseMove(x, y);
4481 			}
4482 			if (errorMessageBox.getEnabled()) {
4483 				errorMessageBox.mouseMove(x, y);
4484 			}
4485 			if (scriptManager.getMessageBox()->getEnabled()) {
4486 				scriptManager.getMessageBox()->mouseMove(x, y);
4487 			}
4488 			//else if (saveBox) {
4489 			//	saveBox->mouseMove(x, y);
4490 			//} else {
4491 			//	//graphics
4492 			gui.mouseMoveGraphics(x, y);
4493 			//}
4494 		}
4495 
4496 		//display
4497 		if ( !gui.isSelecting() && !gui.isSelectingPos()) {
4498 			if (!gui.isSelectingPos()) {
4499 				if(metrics.isInDisplay(x, y)){
4500 					gui.mouseMoveDisplay(x - metrics.getDisplayX(), y - metrics.getDisplayY());
4501 				}
4502 				else {
4503 					gui.mouseMoveOutsideDisplay();
4504 				}
4505 			}
4506 		}
4507 
4508 		lastMousePos.x = mouseX;
4509 		lastMousePos.y = mouseY;
4510 
4511 		Renderer &renderer= Renderer::getInstance();
4512 		renderer.ccomputePosition(Vec2i(mouseX, mouseY), mouseCellPos);
4513 	}
4514 	catch(const exception &ex) {
4515 		char szBuf[8096]="";
4516 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
4517 
4518 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
4519 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
4520 
4521 		NetworkManager &networkManager= NetworkManager::getInstance();
4522 		if(networkManager.getGameNetworkInterface() != NULL) {
4523 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
4524 			networkInterface->sendTextMessage(szBuf,-1,true,"");
4525 			sleep(10);
4526 			networkManager.getGameNetworkInterface()->quitGame(true);
4527 		}
4528 		ErrorDisplayMessage(ex.what(),true);
4529 	}
4530 }
4531 
4532 bool Game::isValidMouseCellPos() const{
4533 	if(world.getMap() == NULL){
4534 		return false;
4535 	}
4536 	else {
4537 		return world.getMap()->isInside(mouseCellPos);
4538 	}
4539 }
4540 
4541 void Game::eventMouseWheel(int x, int y, int zDelta) {
4542 	if(this->masterserverMode == true) {
4543 		return;
4544 	}
4545 
4546 	if(currentUIState != NULL) {
4547 		currentUIState->eventMouseWheel(x, y, zDelta);
4548 		return;
4549 	}
4550 
4551 	try {
4552 		gameCamera.zoom((float)zDelta / 60.0f);
4553 	}
4554 	catch(const exception &ex) {
4555 		char szBuf[8096]="";
4556 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
4557 
4558 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
4559 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
4560 
4561 		NetworkManager &networkManager= NetworkManager::getInstance();
4562 		if(networkManager.getGameNetworkInterface() != NULL) {
4563 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
4564 			networkInterface->sendTextMessage(szBuf,-1,true,"");
4565 			sleep(10);
4566 			networkManager.getGameNetworkInterface()->quitGame(true);
4567 		}
4568 		ErrorDisplayMessage(ex.what(),true);
4569 	}
4570 }
4571 
4572 void Game::startCameraFollowUnit() {
4573 	Selection *selection= gui.getSelectionPtr();
4574 	if(selection->getCount() == 1) {
4575 		Unit *currentUnit = selection->getUnitPtr(0);
4576 		if(currentUnit != NULL) {
4577 			currentCameraFollowUnit = currentUnit;
4578 			getGameCameraPtr()->setState(GameCamera::sUnit);
4579 			getGameCameraPtr()->setPos(currentCameraFollowUnit->getCurrMidHeightVector());
4580 
4581 			int rotation=currentCameraFollowUnit->getRotation();
4582 			getGameCameraPtr()->stop();
4583 			getGameCameraPtr()->rotateToVH(0.0f,(540-rotation)%360);
4584 			getGameCameraPtr()->setHAng((540-rotation)%360);
4585 			getGameCameraPtr()->setVAng(0.0f);
4586 		}
4587 	}
4588 	else {
4589 		if(currentCameraFollowUnit != NULL) {
4590 			currentCameraFollowUnit = NULL;
4591 		}
4592 	}
4593 }
4594 
4595 bool Game::textInput(std::string text) {
4596 	if(chatManager.getEditEnabled() == true) {
4597 		return chatManager.textInput(text);
4598 	}
4599 	return false;
4600 }
4601 
4602 bool Game::sdlKeyDown(SDL_KeyboardEvent key) {
4603 	if(this->masterserverMode == true) {
4604 		return false;
4605 	}
4606 	if(gameStarted == false || totalRenderFps <= 0) {
4607 		return false;
4608 	}
4609 
4610 	if(chatManager.getEditEnabled() == true) {
4611 		return false;
4612 	}
4613 	Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
4614 	//group
4615 	for(int idx = 1; idx <= Selection::maxGroups; idx++) {
4616 		string keyName = "GroupUnitsKey" + intToStr(idx);
4617 
4618 		SDL_Keycode groupHotKey = configKeys.getSDLKey(keyName.c_str());
4619 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] keyName [%s] group index = %d, key = [%c] [%d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,keyName.c_str(),idx,groupHotKey,groupHotKey);
4620 
4621 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("input.keysym.mod = %d groupHotKey = %d key = %d (%d) [%s] isgroup = %d\n",key.keysym.mod,groupHotKey,key.keysym.sym,key.keysym.unicode,keyName.c_str(),isKeyPressed(groupHotKey,key));
4622 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("input.keysym.mod = %d groupHotKey = %d key = (%d) [%s] isgroup = %d\n",key.keysym.mod,groupHotKey,key.keysym.sym,keyName.c_str(),isKeyPressed(groupHotKey,key));
4623 		//printf(" group key check %d   scancode:%d sym:%d groupHotKey=%d  \n",idx,key.keysym.scancode,key.keysym.sym,groupHotKey);
4624 		if(key.keysym.sym==groupHotKey){
4625 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
4626 			//printf("IS GROUP KEY %d   scancode:%d sym:%d groupHotKey=%d  \n",idx,key.keysym.scancode,key.keysym.sym,groupHotKey);
4627 			gui.groupKey(idx-1);
4628 			return true;
4629 		}
4630 	}
4631 	return false;
4632 }
4633 
4634 void Game::keyDown(SDL_KeyboardEvent key) {
4635 	if(this->masterserverMode == true) {
4636 		return;
4637 	}
4638 
4639 	//printf("In game checking keypress for key [%d]\n",key.keysym.sym);
4640 
4641 	try {
4642 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d] gameStarted [%d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym, gameStarted);
4643 		if(gameStarted == false || totalRenderFps <= 0) {
4644 			return;
4645 		}
4646 		if(currentUIState != NULL) {
4647 			currentUIState->keyDown(key);
4648 			return;
4649 		}
4650 
4651 		Lang &lang= Lang::getInstance();
4652 		bool formerChatState=chatManager.getEditEnabled();
4653 		//send key to the chat manager
4654 		chatManager.keyDown(key);
4655 
4656 		if( formerChatState==false && chatManager.getEditEnabled()) {
4657 				camUpButtonDown= false;
4658 				camDownButtonDown = false;
4659 				camLeftButtonDown = false;
4660 				camRightButtonDown = false;
4661 
4662 				gameCamera.stopMove();
4663 		}
4664 
4665 		//printf("GAME KEYDOWN #1\n");
4666 
4667 		if(chatManager.getEditEnabled() == false) {
4668 			//printf("GAME KEYDOWN #2\n");
4669 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%d - %c]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);
4670 
4671 			Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
4672 			//if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("In [%s::%s Line: %d] key = [%d - %c] pausegame [%d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,key,key,configKeys.getCharKey("PauseGame"));
4673 
4674 			//printf("SDL [%d] key [%d][%d]\n",configKeys.getSDLKey("SetMarker"),key.keysym.unicode,key.keysym.sym);
4675 			bool setMarkerKeyAllowsModifier = false;
4676 			if( configKeys.getSDLKey("SetMarker") == SDLK_RALT ||
4677 				configKeys.getSDLKey("SetMarker") == SDLK_LALT) {
4678 				setMarkerKeyAllowsModifier = true;
4679 			}
4680 
4681 			//printf("In game checking keypress for key [%d] camera left [%d]\n",key.keysym.sym,configKeys.getSDLKey("CameraModeLeft"));
4682 
4683 			if(isKeyPressed(configKeys.getSDLKey("RenderInGamePerformance"),key, false) == true) {
4684 				renderInGamePerformance = !renderInGamePerformance;
4685 
4686 				Config::getInstance().setBool("PerformanceWarningEnabled",renderInGamePerformance, true);
4687 			}
4688 			//if(key == configKeys.getCharKey("RenderNetworkStatus")) {
4689 			else if(isKeyPressed(configKeys.getSDLKey("RenderNetworkStatus"),key, false) == true) {
4690 				renderNetworkStatus= !renderNetworkStatus;
4691 			}
4692 			//else if(key == configKeys.getCharKey("ShowFullConsole")) {
4693 			else if(isKeyPressed(configKeys.getSDLKey("ShowFullConsole"),key, false) == true) {
4694 				showFullConsole= true;
4695 			}
4696 			else if(isKeyPressed(configKeys.getSDLKey("SetMarker"),key, setMarkerKeyAllowsModifier) == true) {
4697 				setMarker= true;
4698 			}
4699 			//else if(key == configKeys.getCharKey("TogglePhotoMode")) {
4700 			else if(isKeyPressed(configKeys.getSDLKey("TogglePhotoMode"),key, false) == true) {
4701 				photoModeEnabled = !photoModeEnabled;
4702 				if(	photoModeEnabled == true &&
4703 					this->gameSettings.isNetworkGame() == false) {
4704 					gameCamera.setMaxHeight(PHOTO_MODE_MAXHEIGHT);
4705 				}
4706 				else if(photoModeEnabled == false) {
4707 					gameCamera.setMaxHeight(-1);
4708 				}
4709 
4710 			}
4711 			//Toggle Healthbars
4712 			else if(isKeyPressed(configKeys.getSDLKey("ToggleHealthbars"),key, false) == true) {
4713 				switch (healthbarMode) {
4714 					case hbvUndefined:
4715 						healthbarMode=hbvOff;
4716 						console.addLine(lang.getString("Healthbar2")+": "+lang.getString("HealthbarsOff"));
4717 						break;
4718 					case hbvOff:
4719 						healthbarMode=hbvAlways;
4720 						console.addLine(lang.getString("Healthbar2")+": "+lang.getString("HealthbarsAlways"));
4721 						break;
4722 					case hbvAlways:
4723 						healthbarMode=hbvIfNeeded;
4724 						console.addLine(lang.getString("Healthbar2")+": "+lang.getString("HealthbarsIfNeeded"));
4725 						break;
4726 					case hbvIfNeeded:
4727 						healthbarMode=hbvSelected;
4728 						console.addLine(lang.getString("Healthbar2")+": "+lang.getString("HealthbarsSelected"));
4729 						break;
4730 					case hbvSelected:
4731 						healthbarMode=hbvSelected | hbvIfNeeded;
4732 						console.addLine(lang.getString("Healthbar2")+": "+lang.getString("HealthbarsSelectedOrNeeded"));
4733 						break;
4734 					case (hbvSelected | hbvIfNeeded):
4735 						healthbarMode=hbvUndefined;
4736 						console.addLine(lang.getString("Healthbar2")+": "+lang.getString("HealthbarsFactionDefault"));
4737 						break;
4738 					default:
4739 						printf("In [%s::%s Line: %d] Toggle Healthbars Hotkey - Invalid Value. Setting to default.\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
4740 						healthbarMode=hbvUndefined;
4741 						break;
4742 				}
4743 			}
4744 			//Toggle music
4745 			//else if(key == configKeys.getCharKey("ToggleMusic")) {
4746 			else if(isKeyPressed(configKeys.getSDLKey("ToggleMusic"),key, false) == true) {
4747 
4748 				if(this->masterserverMode == false) {
4749 					Config &config = Config::getInstance();
4750 					StrSound *gameMusic = world.getThisFaction()->getType()->getMusic();
4751 					if(gameMusic != NULL) {
4752 						float configVolume = (config.getInt("SoundVolumeMusic") / 100.f);
4753 						float currentVolume = gameMusic->getVolume();
4754 						if(currentVolume > 0) {
4755 							gameMusic->setVolume(0);
4756 							console.addLine(lang.getString("GameMusic") + " " + lang.getString("Off"));
4757 						}
4758 						else {
4759 							//If the config says zero, use the default music volume
4760 							gameMusic->setVolume(configVolume ? configVolume : 0.9);
4761 							console.addLine(lang.getString("GameMusic"));
4762 						}
4763 					}
4764 				}
4765 			}
4766 			//move camera left
4767 			//else if(key == configKeys.getCharKey("CameraModeLeft")) {
4768 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeLeft"),key, false) == true) {
4769 				gameCamera.setMoveX(-1);
4770 				camLeftButtonDown=true;
4771 			}
4772 			//move camera right
4773 			//else if(key == configKeys.getCharKey("CameraModeRight")) {
4774 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeRight"),key, false) == true) {
4775 				gameCamera.setMoveX(1);
4776 				camRightButtonDown=true;
4777 			}
4778 			//move camera up
4779 			//else if(key == configKeys.getCharKey("CameraModeUp")) {
4780 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeUp"),key, false) == true) {
4781 				gameCamera.setMoveZ(1);
4782 				camUpButtonDown=true;
4783 			}
4784 			//move camera down
4785 			//else if(key == configKeys.getCharKey("CameraModeDown")) {
4786 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeDown"),key, false) == true) {
4787 				gameCamera.setMoveZ(-1);
4788 				camDownButtonDown=true;
4789 			}
4790 			//change camera mode
4791 			//else if(key == configKeys.getCharKey("FreeCameraMode")) {
4792 			else if(isKeyPressed(configKeys.getSDLKey("FreeCameraMode"),key, false) == true) {
4793 				if(gameCamera.getState()==GameCamera::sFree)
4794 				{
4795 					gameCamera.setState(GameCamera::sGame);
4796 					string stateString= gameCamera.getState()==GameCamera::sGame? lang.getString("GameCamera"): lang.getString("FreeCamera");
4797 					console.addLine(lang.getString("CameraModeSet")+" "+ stateString);
4798 				}
4799 				else if(gameCamera.getState()==GameCamera::sGame)
4800 				{
4801 					gameCamera.setState(GameCamera::sFree);
4802 					string stateString= gameCamera.getState()==GameCamera::sGame? lang.getString("GameCamera"): lang.getString("FreeCamera");
4803 					console.addLine(lang.getString("CameraModeSet")+" "+ stateString);
4804 				}
4805 				//else ignore!
4806 			}
4807 			//reset camera mode to normal
4808 			//else if(key == configKeys.getCharKey("ResetCameraMode")) {
4809 			else if(isKeyPressed(configKeys.getSDLKey("ResetCameraMode"),key, false) == true) {
4810 				if(currentCameraFollowUnit != NULL) {
4811 					currentCameraFollowUnit = NULL;
4812 				}
4813 				gameCamera.setState(GameCamera::sGame);
4814 			}
4815 			//pause
4816 			//else if(key == configKeys.getCharKey("PauseGame")) {
4817 			else if(isKeyPressed(configKeys.getSDLKey("PauseGame"),key, false) == true) {
4818 				//printf("Toggle pause paused = %d\n",paused);
4819 				//setPaused(!paused);
4820 
4821 				bool allowAdminMenuItems = false;
4822 				NetworkManager &networkManager= NetworkManager::getInstance();
4823 				NetworkRole role = networkManager.getNetworkRole();
4824 				if(role == nrServer) {
4825 					allowAdminMenuItems = true;
4826 				}
4827 				else if(role == nrClient) {
4828 					ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
4829 
4830 					if(clientInterface != NULL &&
4831 						gameSettings.getMasterserver_admin() == clientInterface->getSessionKey()) {
4832 						allowAdminMenuItems = true;
4833 					}
4834 				}
4835 
4836 				if(allowAdminMenuItems) {
4837 					if(getPaused() == false) {
4838 						commander.tryPauseGame(false,false);
4839 					}
4840 					else {
4841 						commander.tryResumeGame(false,false);
4842 					}
4843 				}
4844 			}
4845 			else if(isKeyPressed(configKeys.getSDLKey("ExtraTeamColorMarker"),key, false) == true) {
4846 				//printf("Toggle ExtraTeamColorMarker\n");
4847 				toggleTeamColorMarker();
4848 			}
4849 			//switch display color
4850 			//else if(key == configKeys.getCharKey("ChangeFontColor")) {
4851 			else if(isKeyPressed(configKeys.getSDLKey("ChangeFontColor"),key, false) == true) {
4852 				gui.switchToNextDisplayColor();
4853 			}
4854 			//increment speed
4855 			//else if(key == configKeys.getCharKey("GameSpeedIncrease")) {
4856 			else if(isKeyPressed(configKeys.getSDLKey("GameSpeedIncrease"),key, false) == true) {
4857 				bool speedChangesAllowed= !NetworkManager::getInstance().isNetworkGameWithConnectedClients();
4858 				if(speedChangesAllowed){
4859 					incSpeed();
4860 				}
4861 			}
4862 			//decrement speed
4863 			//else if(key == configKeys.getCharKey("GameSpeedDecrease")) {
4864 			else if(isKeyPressed(configKeys.getSDLKey("GameSpeedDecrease"),key, false) == true) {
4865 				bool speedChangesAllowed= !NetworkManager::getInstance().isNetworkGameWithConnectedClients();
4866 				if(speedChangesAllowed){
4867 					decSpeed();
4868 				}
4869 			}
4870 			else if(isKeyPressed(configKeys.getSDLKey("BookmarkAdd"),key, false) == true) {
4871 				startMarkCell();
4872 			}
4873 			else if(isKeyPressed(configKeys.getSDLKey("BookmarkRemove"),key, false) == true) {
4874 				isUnMarkCellEnabled = true;
4875 			}
4876 			else if(isKeyPressed(configKeys.getSDLKey("CameraFollowSelectedUnit"),key, false) == true) {
4877 				startCameraFollowUnit();
4878 			}
4879 			//exit
4880 			else if(isKeyPressed(configKeys.getSDLKey("ExitKey"),key, false) == true) {
4881 				popupMenu.setEnabled(!popupMenu.getEnabled());
4882 				popupMenu.setVisible(popupMenu.getEnabled());
4883 			}
4884 
4885 			//hotkeys
4886 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] gameCamera.getState() = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,gameCamera.getState());
4887 
4888 			if(gameCamera.getState() != GameCamera::sFree){
4889 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,key);
4890 
4891 				gui.hotKey(key);
4892 			}
4893 			else {
4894 				//rotate camera leftt
4895 				//if(key == configKeys.getCharKey("CameraRotateLeft")) {
4896 				if(isKeyPressed(configKeys.getSDLKey("CameraRotateLeft"),key) == true) {
4897 					gameCamera.setRotate(-1);
4898 				}
4899 				//rotate camera right
4900 				//else if(key == configKeys.getCharKey("CameraRotateRight")){
4901 				else if(isKeyPressed(configKeys.getSDLKey("CameraRotateRight"),key) == true) {
4902 					gameCamera.setRotate(1);
4903 				}
4904 				//camera up
4905 				//else if(key == configKeys.getCharKey("CameraRotateUp")) {
4906 				else if(isKeyPressed(configKeys.getSDLKey("CameraRotateUp"),key) == true) {
4907 					gameCamera.setMoveY(1);
4908 				}
4909 				//camera down
4910 				//else if(key == configKeys.getCharKey("CameraRotateDown")) {
4911 				else if(isKeyPressed(configKeys.getSDLKey("CameraRotateDown"),key) == true) {
4912 					gameCamera.setMoveY(-1);
4913 				}
4914 			}
4915 
4916 			if(isKeyPressed(configKeys.getSDLKey("SaveGame"),key) == true) {
4917 				saveGame();
4918 			}
4919 		}
4920 	}
4921 	catch(const exception &ex) {
4922 		char szBuf[8096]="";
4923 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
4924 
4925 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
4926 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
4927 
4928 		NetworkManager &networkManager= NetworkManager::getInstance();
4929 		if(networkManager.getGameNetworkInterface() != NULL) {
4930 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
4931 			networkInterface->sendTextMessage(szBuf,-1,true,"");
4932 			sleep(10);
4933 			networkManager.getGameNetworkInterface()->quitGame(true);
4934 		}
4935 		ErrorDisplayMessage(ex.what(),true);
4936 	}
4937 }
4938 
4939 void Game::keyUp(SDL_KeyboardEvent key) {
4940 	if(this->masterserverMode == true) {
4941 		return;
4942 	}
4943 
4944 	try {
4945 		if(gameStarted == false || totalRenderFps <= 0) {
4946 			return;
4947 		}
4948 		if(currentUIState != NULL) {
4949 			currentUIState->keyUp(key);
4950 			return;
4951 		}
4952 
4953 		if(chatManager.getEditEnabled()) {
4954 			//send key to the chat manager
4955 			chatManager.keyUp(key);
4956 		}
4957 		else {
4958 			Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
4959 
4960 			//if(key == configKeys.getCharKey("ShowFullConsole")) {
4961 			if(isKeyPressed(configKeys.getSDLKey("ShowFullConsole"),key) == true) {
4962 				showFullConsole= false;
4963 			}
4964 			else if(isKeyPressed(configKeys.getSDLKey("SetMarker"),key) == true) {
4965 				setMarker= false;
4966 			}
4967 			//else if(key == configKeys.getCharKey("CameraRotateLeft") ||
4968 			//		key == configKeys.getCharKey("CameraRotateRight")) {
4969 			else if(isKeyPressed(configKeys.getSDLKey("CameraRotateLeft"),key) == true ||
4970 					isKeyPressed(configKeys.getSDLKey("CameraRotateRight"),key) == true) {
4971 				gameCamera.setRotate(0);
4972 			}
4973 			//else if(key == configKeys.getCharKey("CameraRotateDown") ||
4974 			//		key == configKeys.getCharKey("CameraRotateUp")) {
4975 			else if(isKeyPressed(configKeys.getSDLKey("CameraRotateDown"),key) == true ||
4976 					isKeyPressed(configKeys.getSDLKey("CameraRotateUp"),key) == true) {
4977 
4978 				gameCamera.setMoveY(0);
4979 			}
4980 			//else if(key == configKeys.getCharKey("CameraModeUp")){
4981 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeUp"),key) == true) {
4982 				gameCamera.setMoveZ(0);
4983 				camUpButtonDown= false;
4984 				calcCameraMoveZ();
4985 			}
4986 			//else if(key == configKeys.getCharKey("CameraModeDown")){
4987 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeDown"),key) == true) {
4988 				gameCamera.setMoveZ(0);
4989 				camDownButtonDown= false;
4990 				calcCameraMoveZ();
4991 			}
4992 			//else if(key == configKeys.getCharKey("CameraModeLeft")){
4993 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeLeft"),key) == true) {
4994 				gameCamera.setMoveX(0);
4995 				camLeftButtonDown= false;
4996 				calcCameraMoveX();
4997 			}
4998 			//else if(key == configKeys.getCharKey("CameraModeRight")){
4999 			else if(isKeyPressed(configKeys.getSDLKey("CameraModeRight"),key) == true) {
5000 				gameCamera.setMoveX(0);
5001 				camRightButtonDown= false;
5002 				calcCameraMoveX();
5003 			}
5004 		}
5005 	}
5006 	catch(const exception &ex) {
5007 		char szBuf[8096]="";
5008 		snprintf(szBuf,8096,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
5009 
5010 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
5011 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
5012 
5013 		NetworkManager &networkManager= NetworkManager::getInstance();
5014 		if(networkManager.getGameNetworkInterface() != NULL) {
5015 			GameNetworkInterface *networkInterface = NetworkManager::getInstance().getGameNetworkInterface();
5016 			networkInterface->sendTextMessage(szBuf,-1,true,"");
5017 			sleep(10);
5018 			networkManager.getGameNetworkInterface()->quitGame(true);
5019 		}
5020 		ErrorDisplayMessage(ex.what(),true);
5021 	}
5022 }
5023 
5024 void Game::calcCameraMoveX(){
5025 	//move camera left
5026 	if(camLeftButtonDown == true){
5027 		gameCamera.setMoveX(-1);
5028 	}
5029 	//move camera right
5030 	else if(camRightButtonDown == true){
5031 		gameCamera.setMoveX(1);
5032 	}
5033 }
5034 void Game::calcCameraMoveZ(){
5035 	//move camera up
5036 	if(camUpButtonDown == true){
5037 		gameCamera.setMoveZ(1);
5038 	}
5039 	//move camera down
5040 	else if(camDownButtonDown == true){
5041 		gameCamera.setMoveZ(-1);
5042 	}
5043 
5044 }
5045 
5046 void Game::keyPress(SDL_KeyboardEvent c) {
5047 	if(this->masterserverMode == true) {
5048 		return;
5049 	}
5050 
5051 	if(gameStarted == false || totalRenderFps <= 0) {
5052 		return;
5053 	}
5054 	if(currentUIState != NULL) {
5055 		currentUIState->keyPress(c);
5056 		return;
5057 	}
5058 
5059 	chatManager.keyPress(c);
5060 }
5061 
5062 Stats Game::getEndGameStats() {
5063 	Stats endStats;
5064 	endStats = *(world.getStats());
5065 	//NetworkManager &networkManager= NetworkManager::getInstance();
5066 	if (this->masterserverMode == true) {
5067 		endStats.setIsMasterserverMode(true);
5068 	}
5069 	return endStats;
5070 }
5071 
5072 Stats Game::quitGame() {
5073 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
5074 
5075 	if(quitGameCalled == true) {
5076 		Stats endStats = getEndGameStats();
5077 		return endStats;
5078 	}
5079 	quitGameCalled = true;
5080 
5081 	NetworkManager &networkManager= NetworkManager::getInstance();
5082 	NetworkRole role = networkManager.getNetworkRole();
5083 	string suffix = "_client";
5084 	if(role == nrServer) {
5085 		suffix = "_server";
5086 	}
5087 	this->DumpCRCWorldLogIfRequired(suffix);
5088 
5089     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled == true) {
5090         world.DumpWorldToLog();
5091     }
5092 	//printf("Check savegame\n");
5093 	//printf("Saving...\n");
5094     if(Config::getInstance().getBool("AutoTest")){
5095     	this->saveGame(GameConstants::saveGameFileAutoTestDefault);
5096     }
5097 
5098 	Stats endStats = getEndGameStats();
5099 
5100 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
5101 
5102 	//printf("In [%s::%s] Line: %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
5103 	NetworkManager::getInstance().end();
5104 	//sleep(0);
5105 
5106 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
5107 
5108 	return endStats;
5109 }
5110 
5111 void Game::DumpCRCWorldLogIfRequired(string fileSuffix) {
5112 	bool isNetworkGame = this->gameSettings.isNetworkGame();
5113 	if(isNetworkGame == true) {
5114 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Check save world CRC to log. isNetworkGame = %d fileSuffix = %s\n",isNetworkGame,fileSuffix.c_str());
5115 
5116 		GameSettings *settings = world.getGameSettingsPtr();
5117 		if(settings != NULL &&
5118 				(isFlagType1BitEnabled(ft1_network_synch_checks_verbose)  == true ||
5119 				 isFlagType1BitEnabled(ft1_network_synch_checks) 			== true)) {
5120 			string debugCRCWorldLogFile = Config::getInstance().getString("DebugCRCWorldLogFile","debugCRCWorld.log");
5121 			debugCRCWorldLogFile += fileSuffix;
5122 
5123 			if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
5124 				debugCRCWorldLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugCRCWorldLogFile;
5125 			}
5126 			else {
5127 				string userData = Config::getInstance().getString("UserData_Root","");
5128 				if(userData != "") {
5129 					endPathWithSlash(userData);
5130 				}
5131 				debugCRCWorldLogFile = userData + debugCRCWorldLogFile;
5132 			}
5133 
5134 			printf("Save to log debugCRCWorldLogFile = %s\n",debugCRCWorldLogFile.c_str());
5135 
5136 		#if defined(WIN32) && !defined(__MINGW32__)
5137 			FILE *fp = _wfopen(utf8_decode(debugCRCWorldLogFile).c_str(), L"w");
5138 			std::ofstream logFile(fp);
5139 		#else
5140 			std::ofstream logFile;
5141 			logFile.open(debugCRCWorldLogFile.c_str(), ios_base::out | ios_base::trunc);
5142 		#endif
5143 			logFile << "World CRC debug information:"  << std::endl;
5144 			logFile << "============================"  << std::endl;
5145 			logFile << "Software version: " << glestVersionString << "-" << getCompilerNameString() << "-" << getGITRevisionString() << std::endl;
5146 			logFile << "Maximum framecount: " << world.getFaction(0)->getCRC_DetailsForWorldFrameCount() << std::endl;
5147 
5148 
5149 			for(unsigned int worldFrameIndex = 0; worldFrameIndex < world.getFaction(0)->getCRC_DetailsForWorldFrameCount(); ++worldFrameIndex) {
5150 				//factions (and their related info)
5151 				for(int i = 0; i < world.getFactionCount(); ++i) {
5152 					logFile << "Faction detail for index: " << i << std::endl;
5153 					logFile << "--------------------------" << std::endl;
5154 
5155 					std::pair<int,string> details = world.getFaction(i)->getCRC_DetailsForWorldFrameIndex(worldFrameIndex);
5156 
5157 					logFile << string("** world frame: ") << details.first << std::endl;
5158 					logFile << details.second << std::endl;
5159 				}
5160 			}
5161 
5162 			logFile.close();
5163 		#if defined(WIN32) && !defined(__MINGW32__)
5164 			if(fp) {
5165 				fclose(fp);
5166 			}
5167 		#endif
5168 
5169 		}
5170 	}
5171 }
5172 
5173 void Game::exitGameState(Program *program, Stats &endStats) {
5174 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
5175 
5176 	Game *game = dynamic_cast<Game *>(program->getState());
5177 
5178 	//printf("game = %p\n",game);
5179 
5180 	if(game) {
5181 		game->setEndGameTeamWinnersAndLosers();
5182 		game->endGame();
5183 	}
5184 
5185 	if((game != NULL && game->isMasterserverMode() == true) ||
5186 		Config::getInstance().getBool("AutoTest") == true) {
5187 		printf("Game ending with stats:\n");
5188 		printf("-----------------------\n");
5189 
5190 		string gameStats = endStats.getStats();
5191 		printf("%s",gameStats.c_str());
5192 
5193 		printf("-----------------------\n");
5194 	}
5195 
5196 	ProgramState *newState = new BattleEnd(program, &endStats, game);
5197 
5198 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
5199 
5200 	program->setState(newState, false);
5201 
5202 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
5203 }
5204 
5205 // ==================== PRIVATE ====================
5206 
5207 void Game::highlightUnit(int unitId,float radius, float thickness, Vec4f color) {
5208 	HighlightSpecialUnitInfo info;
5209 	info.radius = radius;
5210 	info.thickness = thickness;
5211 	info.color = color;
5212 	unitHighlightList[unitId] = info;
5213 }
5214 
5215 void Game::unhighlightUnit(int unitId) {
5216 	if(unitHighlightList.find(unitId) != unitHighlightList.end()) {
5217 		unitHighlightList.erase(unitId);
5218 	}
5219 }
5220 
5221 // ==================== render ====================
5222 
5223 void Game::render3d(){
5224 	Chrono chrono;
5225 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
5226 
5227 	Renderer &renderer= Renderer::getInstance();
5228 
5229 	//init
5230 	renderer.reset3d();
5231 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [reset3d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5232 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5233 
5234 //	renderer.computeVisibleQuad();
5235 //	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [computeVisibleQuad]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5236 //	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5237 
5238 	renderer.loadGameCameraMatrix();
5239 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [loadGameCameraMatrix]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5240 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5241 
5242 	renderer.computeVisibleQuad();
5243 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [computeVisibleQuad]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5244 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5245 
5246 	renderer.setupLighting();
5247 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [setupLighting]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5248 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5249 
5250 	//shadow map
5251 	renderer.renderShadowsToTexture(avgRenderFps);
5252 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderShadowsToTexture]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5253 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5254 
5255 	//clear buffers
5256 	renderer.clearBuffers();
5257 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d renderFps = %d took msecs: %lld\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5258 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5259 
5260 	//surface
5261 	renderer.renderSurface(avgRenderFps);
5262 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderSurface]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5263 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5264 
5265 	//selection circles
5266 	renderer.renderSelectionEffects(healthbarMode);
5267 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderSelectionEffects]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5268 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5269 
5270 	// renderTeamColorCircle
5271 	if((renderExtraTeamColor&renderTeamColorCircleBit)>0){
5272 		renderer.renderTeamColorCircle();
5273 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderObjects]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5274 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5275 	}
5276 
5277 	renderer.renderSpecialHighlightUnits(unitHighlightList);
5278 
5279 	// renderTeamColorCircle
5280 	renderer.renderMorphEffects();
5281 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderObjects]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5282 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5283 
5284 	//objects
5285 	renderer.renderObjects(avgRenderFps);
5286 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderObjects]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5287 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5288 
5289 	//ground units
5290 	renderer.renderUnits(false, avgRenderFps);
5291 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderUnits]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5292 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5293 
5294 	//water
5295 	renderer.renderWater();
5296 	renderer.renderWaterEffects();
5297 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderWater]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5298 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5299 
5300 	//air units
5301 	renderer.renderUnits(true, avgRenderFps);
5302 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderUnits]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5303 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5304 
5305 	//particles
5306 	renderer.renderParticleManager(rsGame);
5307 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderParticleManager]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5308 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5309 
5310 	//renderOnTopBars (aka Healthbars)
5311 	if(photoModeEnabled == false) {
5312 		renderer.renderHealthBars(healthbarMode);
5313 	}
5314 
5315 	// renderTeamColorPlane
5316 	if((renderExtraTeamColor&renderTeamColorPlaneBit)>0){
5317 		renderer.renderTeamColorPlane();
5318 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderObjects]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5319 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5320 	}
5321 
5322 	//mouse 3d
5323 	renderer.renderMouse3d();
5324 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderMouse3d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5325 
5326 	renderer.renderUnitsToBuild(avgRenderFps);
5327 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] renderFps = %d took msecs: %lld [renderUnitsToBuild]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,renderFps,chrono.getMillis());
5328 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) chrono.start();
5329 
5330 	renderer.setLastRenderFps(lastRenderFps);
5331 }
5332 
5333 void Game::updateWorldStats() {
5334     world.getStats()->setWorldTimeElapsed(world.getTimeFlow()->getTime());
5335 
5336     if(difftime((long int)time(NULL),lastMaxUnitCalcTime) >= 1) {
5337     	lastMaxUnitCalcTime = time(NULL);
5338 
5339 		int totalUnitcount = 0;
5340 		for(int i = 0; i < world.getFactionCount(); ++i) {
5341 			Faction *faction= world.getFaction(i);
5342 			totalUnitcount += faction->getUnitCount();
5343 		}
5344 
5345 		if(world.getStats()->getMaxConcurrentUnitCount() < totalUnitcount) {
5346 			world.getStats()->setMaxConcurrentUnitCount(totalUnitcount);
5347 		}
5348 		world.getStats()->setTotalEndGameConcurrentUnitCount(totalUnitcount);
5349 		world.getStats()->setFramesPlayed(world.getFrameCount());
5350     }
5351 }
5352 
5353 string Game::getDebugStats(std::map<int,string> &factionDebugInfo) {
5354 	string str = "";
5355 
5356 	if(this->masterserverMode == false) {
5357 		str+= "MouseXY: "        + intToStr(mouseX) + "," + intToStr(mouseY)+"\n";
5358 
5359 		if(world.getMap()->isInsideSurface(world.getMap()->toSurfCoords(mouseCellPos)) == true) {
5360 			str+= "MouseXY cell coords: "        + intToStr(mouseCellPos.x) + "," + intToStr(mouseCellPos.y)+"\n";
5361 		}
5362 
5363 		str+= "PosObjWord: "     + intToStr(gui.getPosObjWorld().x) + "," + intToStr(gui.getPosObjWorld().y)+"\n";
5364 	}
5365 
5366 	str+= "Render FPS: "     + intToStr(lastRenderFps) + "[" + intToStr(avgRenderFps) + "]\n";
5367 	str+= "Update FPS: "     + intToStr(lastUpdateFps) + "[" + intToStr(avgUpdateFps) + "]\n";
5368 
5369 	if(this->masterserverMode == false) {
5370 		str+= "GameCamera pos: " + floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n";
5371 		//str+= "Cached surfacedata: " +  intToStr(renderer.getCachedSurfaceDataSize())+"\n";
5372 	}
5373 
5374 	//intToStr(stats.getFramesToCalculatePlaytime()/GameConstants::updateFps/60
5375 	str+= "Time: "           + floatToStr(world.getTimeFlow()->getTime(),2) + " [" + floatToStr((double)world.getStats()->getFramesToCalculatePlaytime() / (float)GameConstants::updateFps / 60.0,2) + "]\n";
5376 
5377 	if(SystemFlags::getThreadedLoggerRunning() == true) {
5378 		str+= "Log buffer count: " + intToStr(SystemFlags::getLogEntryBufferCount())+"\n";
5379 	}
5380 
5381 	str+= "UnitRangeCellsLookupItemCache: " + world.getUnitUpdater()->getUnitRangeCellsLookupItemCacheStats()+"\n";
5382 	str+= "ExploredCellsLookupItemCache: " 	+ world.getExploredCellsLookupItemCacheStats()+"\n";
5383 	str+= "FowAlphaCellsLookupItemCache: "  + world.getFowAlphaCellsLookupItemCacheStats()+"\n";
5384 
5385 	const string selectionType = toLower(Config::getInstance().getString("SelectionType",Config::colorPicking));
5386 	str += "Selection type: " + toLower(selectionType) + "\n";
5387 
5388 	if(selectionType == Config::colorPicking) {
5389 		str += "Color picking used color list size: " + intToStr(BaseColorPickEntity::getUsedColorIDListSize()) +"\n";
5390 	}
5391 
5392 	//str+= "AllFactionsCacheStats: "			+ world.getAllFactionsCacheStats()+"\n";
5393 	//str+= "AttackWarningCount: " + intToStr(world.getUnitUpdater()->getAttackWarningCount()) + "\n";
5394 
5395 	str+= "Map: " + gameSettings.getMap() +"\n";
5396 	str+= "Tileset: " + gameSettings.getTileset() +"\n";
5397 	str+= "Techtree: " + gameSettings.getTech() +"\n";
5398 
5399 	if(this->masterserverMode == false) {
5400 		Renderer &renderer= Renderer::getInstance();
5401 		str+= "Triangle count: " + intToStr(renderer.getTriangleCount())+"\n";
5402 		str+= "Vertex count: "   + intToStr(renderer.getPointCount())+"\n";
5403 	}
5404 
5405 	str+= "Frame count:"     + intToStr(world.getFrameCount())+"\n";
5406 
5407 	//visible quad
5408 	if(this->masterserverMode == false) {
5409 		Renderer &renderer= Renderer::getInstance();
5410 		Quad2i visibleQuad= renderer.getVisibleQuad();
5411 		//Quad2i visibleQuadCamera= renderer.getVisibleQuadFromCamera();
5412 
5413 		str+= "Visible quad:        ";
5414 		for(int i= 0; i<4; ++i){
5415 			str+= "(" + intToStr(visibleQuad.p[i].x) + "," +intToStr(visibleQuad.p[i].y) + ") ";
5416 		}
5417 	//		str+= "\n";
5418 	//		str+= "Visible quad camera: ";
5419 	//		for(int i= 0; i<4; ++i){
5420 	//			str+= "(" + intToStr(visibleQuadCamera.p[i].x) + "," +intToStr(visibleQuadCamera.p[i].y) + ") ";
5421 	//		}
5422 		str+= "\n";
5423 
5424 		str+= "Visible quad area:        " + floatToStr(visibleQuad.area()) +"\n";
5425 	//		str+= "Visible quad camera area: " + floatToStr(visibleQuadCamera.area()) +"\n";
5426 
5427 	//		Rect2i boundingRect= visibleQuad.computeBoundingRect();
5428 	//		Rect2i scaledRect= boundingRect/Map::cellScale;
5429 	//		scaledRect.clamp(0, 0, world.getMap()->getSurfaceW()-1, world.getMap()->getSurfaceH()-1);
5430 	//		renderer.renderText3D("#1", coreData.getMenuFontNormal3D(), Vec3f(1.0f), scaledRect.p[0].x, scaledRect.p[0].y, false);
5431 	//		renderer.renderText3D("#2", coreData.getMenuFontNormal3D(), Vec3f(1.0f), scaledRect.p[1].x, scaledRect.p[1].y, false);
5432 	}
5433 
5434 	int totalUnitcount = 0;
5435 	for(int i = 0; i < world.getFactionCount(); ++i) {
5436 		Faction *faction= world.getFaction(i);
5437 		totalUnitcount += faction->getUnitCount();
5438 	}
5439 
5440 	if(this->masterserverMode == false) {
5441 		Renderer &renderer= Renderer::getInstance();
5442 		VisibleQuadContainerCache &qCache =renderer.getQuadCache();
5443 		int visibleUnitCount = (int)qCache.visibleQuadUnitList.size();
5444 		str+= "Visible unit count: " + intToStr(visibleUnitCount) + " total: " + intToStr(totalUnitcount) + "\n";
5445 
5446 		int visibleObjectCount = (int)qCache.visibleObjectList.size();
5447 		str+= "Visible object count: " + intToStr(visibleObjectCount) +"\n";
5448 	}
5449 	else {
5450 		str+= "Total unit count: " + intToStr(totalUnitcount) + "\n";
5451 	}
5452 
5453 	// resources
5454 	for(int i = 0; i < world.getFactionCount(); ++i) {
5455 		string factionInfo = this->gameSettings.getNetworkPlayerName(i);
5456 		//factionInfo += " [" + this->gameSettings.getNetworkPlayerUUID(i) + "]";
5457 		float multi=world.getStats()->getResourceMultiplier(i);
5458 		string multiplier="["+floatToStr(multi,1)+"]";
5459 		switch(this->gameSettings.getFactionControl(i)) {
5460 			case ctCpuEasy:
5461 				factionInfo += " CPU Easy"+multiplier;
5462 				break;
5463 			case ctCpu:
5464 				factionInfo += " CPU Normal"+multiplier;
5465 				break;
5466 			case ctCpuUltra:
5467 				factionInfo += " CPU Ultra"+multiplier;
5468 				break;
5469 			case ctCpuMega:
5470 				factionInfo += " CPU Mega"+multiplier;
5471 				break;
5472 		}
5473 
5474 		factionInfo +=	" [" + formatString(this->gameSettings.getFactionTypeName(i)) +
5475 				" team: " + intToStr(this->gameSettings.getTeam(i)) + "]";
5476 
5477 //		bool showResourceDebugInfo = true;
5478 //		if(showResourceDebugInfo == true) {
5479 //			factionInfo +=" res: ";
5480 //			for(int j = 0; j < world.getTechTree()->getResourceTypeCount(); ++j) {
5481 //				factionInfo += world.getFaction(i)->getResource(j)->getType()->getName()+":"+intToStr(world.getFaction(i)->getResource(j)->getAmount());
5482 //				factionInfo += " ";
5483 //			}
5484 //		}
5485 
5486 		factionDebugInfo[i] = factionInfo;
5487 	}
5488 
5489 	return str;
5490 }
5491 
5492 void Game::render2d() {
5493 	Renderer &renderer= Renderer::getInstance();
5494 	//Config &config= Config::getInstance();
5495 	CoreData &coreData= CoreData::getInstance();
5496 
5497 	//init
5498 	renderer.reset2d();
5499 
5500 	//HUD
5501 	if(visibleHUD == true && photoModeEnabled == false) {
5502 		renderer.renderHud();
5503 	}
5504 	//display
5505 	renderer.renderDisplay();
5506 
5507 	//minimap
5508 	if(photoModeEnabled == false) {
5509         renderer.renderMinimap();
5510 	}
5511 
5512 	renderer.renderVisibleMarkedCells();
5513 	renderer.renderVisibleMarkedCells(true,lastMousePos.x,lastMousePos.y);
5514 
5515     //selection
5516 	renderer.renderSelectionQuad();
5517 
5518 	//highlighted Cells
5519 	renderer.renderHighlightedCellsOnMinimap();
5520 
5521 	if(switchTeamConfirmMessageBox.getEnabled() == true) {
5522 		renderer.renderMessageBox(&switchTeamConfirmMessageBox);
5523 	}
5524 
5525 	if(disconnectPlayerConfirmMessageBox.getEnabled() == true) {
5526 		renderer.renderMessageBox(&disconnectPlayerConfirmMessageBox);
5527 	}
5528 
5529 	//exit message box
5530 	if(errorMessageBox.getEnabled()) {
5531 		renderer.renderMessageBox(&errorMessageBox);
5532 	}
5533 	if(mainMessageBox.getEnabled()) {
5534 		renderer.renderMessageBox(&mainMessageBox);
5535 	}
5536 
5537 	//script message box
5538 	if( mainMessageBox.getEnabled() == false &&
5539 		errorMessageBox.getEnabled() == false &&
5540 		scriptManager.getMessageBoxEnabled()) {
5541 		renderer.renderMessageBox(scriptManager.getMessageBox());
5542 	}
5543 
5544 	//script display text
5545 	if(!scriptManager.getDisplayText().empty() && !scriptManager.getMessageBoxEnabled()){
5546 		Vec4f fontColor = getGui()->getDisplay()->getColor();
5547 
5548 		if(Renderer::renderText3DEnabled == true) {
5549 			renderer.renderText3D(
5550 				scriptManager.getDisplayText(), coreData.getMenuFontNormal3D(),
5551 				Vec3f(fontColor.x,fontColor.y,fontColor.z), 200, 660, false);
5552 		}
5553 		else {
5554 			renderer.renderText(
5555 				scriptManager.getDisplayText(), coreData.getMenuFontNormal(),
5556 				Vec3f(fontColor.x,fontColor.y,fontColor.z), 200, 660, false);
5557 		}
5558 	}
5559 
5560 	renderVideoPlayer();
5561 
5562 	renderer.renderPopupMenu(&popupMenu);
5563 	renderer.renderPopupMenu(&popupMenuSwitchTeams);
5564 	renderer.renderPopupMenu(&popupMenuDisconnectPlayer);
5565 
5566 	if(program != NULL) program->renderProgramMsgBox();
5567 
5568 	renderer.renderChatManager(&chatManager);
5569 
5570     //debug info
5571 	bool perfLogging = false;
5572 	if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled == true ||
5573 	   SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) {
5574 		perfLogging = true;
5575 	}
5576 
5577     string str="";
5578     std::map<int,string> factionDebugInfo;
5579 
5580 	if( renderer.getShowDebugUI() == true ||
5581 		(perfLogging == true && difftime((long int)time(NULL),lastRenderLog2d) >= 1)) {
5582 		str = getDebugStats(factionDebugInfo);
5583 	}
5584 
5585 	if(this->getRenderInGamePerformance() == true) {
5586 		renderer.renderPerformanceStats();
5587 	}
5588 	else {
5589 		static time_t lastGamePerfCheck = time(NULL);
5590 		if(difftime((long int)time(NULL),lastGamePerfCheck) > 3) {
5591 			lastGamePerfCheck = time(NULL);
5592 
5593 			getGamePerformanceCounts(true);
5594 		}
5595 	}
5596 
5597 	if(renderer.getShowDebugUI() == true) {
5598 		const Metrics &metrics= Metrics::getInstance();
5599 		int mh= metrics.getMinimapH();
5600 
5601 		if(this->getRenderInGamePerformance() == true) {
5602 			mh = mh + ((int)gamePerformanceCounts.size() * 14);
5603 		}
5604 
5605 		const Vec4f fontColor=getGui()->getDisplay()->getColor();
5606 
5607 		if(Renderer::renderText3DEnabled == true) {
5608 			renderer.renderTextShadow3D(str, coreData.getMenuFontNormal3D(),
5609 					fontColor, 10, metrics.getVirtualH() - mh - 60, false);
5610 		}
5611 		else {
5612 			renderer.renderTextShadow(str, coreData.getMenuFontNormal(),
5613 					fontColor, 10, metrics.getVirtualH() - mh - 60, false);
5614 		}
5615 
5616         vector<string> lineTokens;
5617         Tokenize(str,lineTokens,"\n");
5618         int fontHeightNormal = (Renderer::renderText3DEnabled == true ? coreData.getMenuFontNormal3D()->getMetrics()->getHeight("W") : coreData.getMenuFontNormal()->getMetrics()->getHeight("W"));
5619         int fontHeightBig 	 = (Renderer::renderText3DEnabled == true ? coreData.getMenuFontBig3D()->getMetrics()->getHeight("W") : coreData.getMenuFontBig()->getMetrics()->getHeight("W"));
5620         int playerPosY = (int)lineTokens.size() * fontHeightNormal;
5621 
5622         //printf("lineTokens.size() = %d\n",lineTokens.size());
5623 
5624 		for(int i = 0; i < world.getFactionCount(); ++i) {
5625 			string factionInfo = factionDebugInfo[i];
5626 			Vec3f playerColor = world.getFaction(i)->getTexture()->getPixmapConst()->getPixel3f(0, 0);
5627 
5628 			if(Renderer::renderText3DEnabled == true) {
5629 				renderer.renderText3D(factionInfo, coreData.getMenuFontBig3D(),
5630 						Vec4f(playerColor.x,playerColor.y,playerColor.z,1.0),
5631 						10,
5632 						//metrics.getVirtualH() - mh - 90 - 280 - (i * 16),
5633 						metrics.getVirtualH() - mh - 60 - playerPosY - fontHeightBig - (fontHeightBig * i),
5634 						false);
5635 			}
5636 			else {
5637 				renderer.renderText(factionInfo, coreData.getMenuFontBig(),
5638 						Vec4f(playerColor.x,playerColor.y,playerColor.z,1.0),
5639 						10,
5640 						//metrics.getVirtualH() - mh - 90 - 280 - (i * 16),
5641 						metrics.getVirtualH() - mh - 60 - playerPosY - fontHeightBig - (fontHeightBig * i),
5642 						false);
5643 			}
5644 		}
5645 
5646 		if((renderer.getShowDebugUILevel() & debugui_unit_titles) == debugui_unit_titles) {
5647 			if(renderer.getAllowRenderUnitTitles() == false) {
5648 				renderer.setAllowRenderUnitTitles(true);
5649 			}
5650 
5651 			if(Renderer::renderText3DEnabled == true) {
5652 				renderer.renderUnitTitles3D(coreData.getMenuFontNormal3D(),Vec3f(1.0f));
5653 			}
5654 			else {
5655 				renderer.renderUnitTitles(coreData.getMenuFontNormal(),Vec3f(1.0f));
5656 			}
5657 		}
5658 	}
5659 
5660 	//network status
5661 	if(renderNetworkStatus == true) {
5662 		if(NetworkManager::getInstance().getGameNetworkInterface() != NULL) {
5663 			const Metrics &metrics= Metrics::getInstance();
5664 			int mx= metrics.getMinimapX();
5665 			//int my= metrics.getMinimapY();
5666 			int mw= metrics.getMinimapW();
5667 			//int mh= metrics.getMinimapH();
5668 			const Vec4f fontColor=getGui()->getDisplay()->getColor();
5669 
5670 			if(Renderer::renderText3DEnabled == true) {
5671 				renderer.renderTextShadow3D(
5672 								NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(),
5673 								coreData.getMenuFontNormal3D(),
5674 								fontColor, mx + mw + 5 , metrics.getVirtualH()-30-20, false);
5675 			}
5676 			else {
5677 				renderer.renderTextShadow(
5678 					NetworkManager::getInstance().getGameNetworkInterface()->getNetworkStatus(),
5679 					coreData.getMenuFontNormal(),
5680 					fontColor, mx + mw + 5 , metrics.getVirtualH()-30-20, false);
5681 			}
5682 		}
5683 	}
5684 
5685 	// clock
5686 	if(photoModeEnabled == false && timeDisplay == true) {
5687 		renderer.renderClock();
5688 	}
5689 
5690     //resource info
5691 	if(photoModeEnabled == false) {
5692 		if(this->masterserverMode == false) {
5693 			renderer.renderResourceStatus();
5694 		}
5695 		renderer.renderConsole(&console,showFullConsole?consoleFull:consoleNormal);
5696     }
5697 
5698     //2d mouse
5699 	renderer.renderMouse2d(mouseX, mouseY, mouse2d, gui.isSelectingPos()? 1.f: 0.f);
5700 
5701 	if(perfLogging == true && difftime((long int)time(NULL),lastRenderLog2d) >= 1) {
5702 		lastRenderLog2d = time(NULL);
5703 
5704 		if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] Statistics: %s\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,str.c_str());
5705 	}
5706 }
5707 
5708 
5709 // ==================== misc ====================
5710 
5711 void Game::checkWinner() {
5712 	// lookup int is team #, value is players alive on team
5713 	std::map<int, int> teamsAlive = getTeamsAlive();
5714 
5715 	if(gameOver == false || teamsAlive.size() > 1) {
5716 		if(gameSettings.getDefaultVictoryConditions()) {
5717 			checkWinnerStandard();
5718 		}
5719 		else {
5720 			checkWinnerScripted();
5721 		}
5722 	}
5723 }
5724 
5725 void Game::setEndGameTeamWinnersAndLosers() {
5726 	//bool lose= false;
5727 	bool checkTeamIndex = !(this->masterserverMode == false && world.getThisFaction()->getPersonalityType() != fpt_Observer);
5728 
5729 	// lookup int is team #, value is players alive on team
5730 	std::map<int,int> teamsAlive;
5731 	for(int i = 0; i < world.getFactionCount(); ++i) {
5732 		if(checkTeamIndex == false || i != world.getThisFactionIndex()) {
5733 			if(factionLostGame(world.getFaction(i)) == false) {
5734 				teamsAlive[world.getFaction(i)->getTeam()] = teamsAlive[world.getFaction(i)->getTeam()] + 1;
5735 			}
5736 		}
5737 	}
5738 
5739 	// did some team win
5740 	if(teamsAlive.size() <= 1) {
5741 		for(int i=0; i< world.getFactionCount(); ++i) {
5742 			if(checkTeamIndex == false || i != world.getThisFactionIndex()) {
5743 				if(teamsAlive.find(world.getFaction(i)->getTeam()) != teamsAlive.end()) {
5744 					world.getStats()->setVictorious(i);
5745 				}
5746 				else if(i == world.getThisFactionIndex()) {
5747 					//lose= true;
5748 				}
5749 			}
5750 		}
5751 		bool firstGameOverTrigger = false;
5752 		if(gameOver == false) {
5753 			firstGameOverTrigger = true;
5754 			gameOver= true;
5755 		}
5756 		if( this->gameSettings.isNetworkGame() == false ||
5757 			this->gameSettings.getEnableObserverModeAtEndGame() == true) {
5758 			// Let the happy winner view everything left in the world
5759 
5760 			// This caused too much LAG for network games
5761 			if(this->gameSettings.isNetworkGame() == false) {
5762 				Renderer::getInstance().setPhotoMode(true);
5763 				gameCamera.setMaxHeight(PHOTO_MODE_MAXHEIGHT);
5764 			}
5765 			// END
5766 		}
5767 
5768 		if(firstGameOverTrigger == true) {
5769 			scriptManager.onGameOver(true);
5770 		}
5771 
5772 		if(world.getFactionCount() == 1 && world.getFaction(0)->getPersonalityType() == fpt_Observer) {
5773 			//printf("!!!!!!!!!!!!!!!!!!!!");
5774 
5775 			//gameCamera.setMoveY(100.0);
5776 			gameCamera.zoom(-300);
5777 			//gameCamera.update();
5778 		}
5779 //		else {
5780 //			if(lose == true) {
5781 //				showLoseMessageBox();
5782 //			}
5783 //			else {
5784 //				showWinMessageBox();
5785 //			}
5786 //		}
5787 	}
5788 }
5789 
5790 std::map<int, int> Game::getTeamsAlive() {
5791 	std::map<int, int> teamsAlive;
5792 	for (int factionIndex = 0; factionIndex < world.getFactionCount(); ++factionIndex) {
5793 		if (factionIndex != world.getThisFactionIndex()) {
5794 			if (factionLostGame(world.getFaction(factionIndex)) == false) {
5795 				teamsAlive[world.getFaction(factionIndex)->getTeam()] =
5796 						teamsAlive[world.getFaction(factionIndex)->getTeam()] + 1;
5797 			}
5798 		}
5799 	}
5800 	// did some team win
5801 	return teamsAlive;
5802 }
5803 
5804 void Game::checkWinnerStandardHeadlessOrObserver() {
5805 	// lookup int is team #, value is players alive on team
5806 	std::map<int, int> teamsAlive = getTeamsAlive();
5807 
5808 	// did some team win
5809 	if (teamsAlive.size() <= 1) {
5810 		if (this->masterserverMode == true) {
5811 			printf("Game finished...\n");
5812 		}
5813 		for (int factionIndex = 0; factionIndex < world.getFactionCount(); ++factionIndex) {
5814 
5815 			Faction* faction = world.getFaction(factionIndex);
5816 			if (factionIndex != world.getThisFactionIndex() &&
5817 					teamsAlive.find(faction->getTeam()) != teamsAlive.end()) {
5818 
5819 				world.getStats()->setVictorious(factionIndex);
5820 				if (this->masterserverMode == true) {
5821 
5822 					printf("Player: %s is on the winning team #: %d\n",
5823 							this->gameSettings.getNetworkPlayerName(factionIndex).c_str(),
5824 							faction->getTeam());
5825 				}
5826 			}
5827 		}
5828 		bool wasGameOverAlready = gameOver;
5829 		gameOver 				= true;
5830 
5831 		// Only need to process this once
5832 		if(wasGameOverAlready == false) {
5833 			if (this->gameSettings.isNetworkGame() == false ||
5834 				this->gameSettings.getEnableObserverModeAtEndGame() == true) {
5835 
5836 				// Let the happy winner view everything left in the world
5837 				// This caused too much LAG for network games
5838 				if (this->gameSettings.isNetworkGame() == false) {
5839 
5840 					Renderer::getInstance().setPhotoMode(true);
5841 					gameCamera.setMaxHeight(PHOTO_MODE_MAXHEIGHT);
5842 				}
5843 				// END
5844 			}
5845 			scriptManager.onGameOver(true);
5846 			if (world.getFactionCount() == 1 &&
5847 					world.getFaction(0)->getPersonalityType() == fpt_Observer) {
5848 				gameCamera.zoom(-300);
5849 			}
5850 			else {
5851 				showWinMessageBox();
5852 			}
5853 		}
5854 	}
5855 }
5856 
5857 void Game::checkWinnerStandardPlayer() {
5858 	//lose
5859 	bool lose = false;
5860 	if (factionLostGame(world.getThisFaction()) == true) {
5861 
5862 		bool playerLostGame = true;
5863 		// Team Shared units enabled?
5864 		if(isFlagType1BitEnabled(ft1_allow_shared_team_units) == true) {
5865 
5866 			// Check if all team members have lost?
5867 			for (int factionIndex = 0; factionIndex < world.getFactionCount(); ++factionIndex) {
5868 
5869 				if (world.getFaction(factionIndex)->getPersonalityType() != fpt_Observer) {
5870 					if (world.getFaction(factionIndex)->isAlly(world.getThisFaction()) == true &&
5871 							factionLostGame(world.getFaction(factionIndex)) == false) {
5872 
5873 						playerLostGame = false;
5874 						break;
5875 					}
5876 				}
5877 			}
5878 		}
5879 
5880 		if(playerLostGame == true) {
5881 			lose = true;
5882 			for (int factionIndex = 0; factionIndex < world.getFactionCount(); ++factionIndex) {
5883 
5884 				if (world.getFaction(factionIndex)->getPersonalityType() != fpt_Observer) {
5885 					if (world.getFaction(factionIndex)->isAlly(world.getThisFaction()) == false &&
5886 							factionLostGame(world.getFaction(factionIndex)) == false) {
5887 
5888 						world.getStats()->setVictorious(factionIndex);
5889 					}
5890 				}
5891 			}
5892 			bool wasGameOverAlready = gameOver;
5893 			gameOver 				= true;
5894 
5895 			// Only need to process losing once
5896 			if(wasGameOverAlready == false) {
5897 				if (this->gameSettings.isNetworkGame() == false ||
5898 					this->gameSettings.getEnableObserverModeAtEndGame()
5899 								== true) {
5900 					// Let the poor user watch everything unfold
5901 					// This caused too much LAG for network games
5902 					if (this->gameSettings.isNetworkGame() == false) {
5903 						Renderer::getInstance().setPhotoMode(true);
5904 						gameCamera.setMaxHeight(PHOTO_MODE_MAXHEIGHT);
5905 					}
5906 					// END
5907 					// but don't let him cheat via teamchat
5908 					chatManager.setDisableTeamMode(true);
5909 				}
5910 				scriptManager.onGameOver(!lose);
5911 				showLoseMessageBox();
5912 			}
5913 		}
5914 	}
5915 
5916 	//win
5917 	if (lose == false) {
5918 		bool win = true;
5919 		for (int factionIndex = 0; factionIndex < world.getFactionCount(); ++factionIndex) {
5920 
5921 			if (factionIndex != world.getThisFactionIndex()) {
5922 				if (world.getFaction(factionIndex)->getPersonalityType() != fpt_Observer) {
5923 
5924 					if (factionLostGame(world.getFaction(factionIndex)) == false &&
5925 						world.getFaction(factionIndex)->isAlly(world.getThisFaction()) == false) {
5926 
5927 						win = false;
5928 					}
5929 				}
5930 			}
5931 		}
5932 
5933 		if (win) {
5934 			for (int factionIndex = 0; factionIndex < world.getFactionCount(); ++factionIndex) {
5935 				if (world.getFaction(factionIndex)->getPersonalityType() != fpt_Observer) {
5936 					if (world.getFaction(factionIndex)->isAlly(world.getThisFaction())) {
5937 
5938 						world.getStats()->setVictorious(factionIndex);
5939 					}
5940 				}
5941 			}
5942 
5943 			bool wasGameOverAlready = gameOver;
5944 			gameOver 				= true;
5945 
5946 			// Only need to process winning once
5947 			if(wasGameOverAlready == false) {
5948 				if (this->gameSettings.isNetworkGame() == false ||
5949 					this->gameSettings.getEnableObserverModeAtEndGame() == true) {
5950 					// Let the happy winner view everything left in the world
5951 
5952 					// This caused too much LAG for network games
5953 					if (this->gameSettings.isNetworkGame() == false) {
5954 						Renderer::getInstance().setPhotoMode(true);
5955 						gameCamera.setMaxHeight(PHOTO_MODE_MAXHEIGHT);
5956 					}
5957 					// END
5958 				}
5959 				scriptManager.onGameOver(win);
5960 				showWinMessageBox();
5961 			}
5962 		}
5963 	}
5964 }
5965 
5966 void Game::checkWinnerStandard() {
5967 	if(world.getFactionCount() <= 0) {
5968 		return;
5969 	}
5970 	if(this->masterserverMode == true ||
5971 		world.getThisFaction()->getPersonalityType() == fpt_Observer) {
5972 		checkWinnerStandardHeadlessOrObserver();
5973 	}
5974 	else {
5975 		checkWinnerStandardPlayer();
5976 	}
5977 }
5978 
5979 void Game::checkWinnerScripted() {
5980 	if(scriptManager.getIsGameOver()) {
5981 		bool wasGameOverAlready = gameOver;
5982 		gameOver				= true;
5983 
5984 
5985 		for(int index = 0; index < world.getFactionCount(); ++index) {
5986 			if(scriptManager.getPlayerModifiers(index)->getWinner()) {
5987 
5988 				world.getStats()->setVictorious(index);
5989 			}
5990 		}
5991 
5992 		// Only need to process winning once
5993 		if(wasGameOverAlready == false) {
5994 			if( this->gameSettings.isNetworkGame() == false ||
5995 				this->gameSettings.getEnableObserverModeAtEndGame() == true) {
5996 
5997 				// Let the happy winner view everything left in the world
5998 				// This caused too much LAG for network games
5999 				if(this->gameSettings.isNetworkGame() == false) {
6000 					Renderer::getInstance().setPhotoMode(true);
6001 					gameCamera.setMaxHeight(PHOTO_MODE_MAXHEIGHT);
6002 				}
6003 				// END
6004 			}
6005 
6006 			if(this->masterserverMode == true ||
6007 					world.getThisFaction()->getPersonalityType() == fpt_Observer) {
6008 				showWinMessageBox();
6009 			}
6010 			else {
6011 				scriptManager.onGameOver(scriptManager.getPlayerModifiers(world.getThisFactionIndex())->getWinner());
6012 
6013 				if(scriptManager.getPlayerModifiers(world.getThisFactionIndex())->getWinner()){
6014 					showWinMessageBox();
6015 				}
6016 				else {
6017 					showLoseMessageBox();
6018 				}
6019 			}
6020 		}
6021 	}
6022 }
6023 
6024 bool Game::isFlagType1BitEnabled(FlagTypes1 type) const {
6025 	return ((gameSettings.getFlagTypes1() & (uint32)type) == (uint32)type);
6026 }
6027 
6028 bool Game::factionLostGame(int factionIndex) {
6029 	return factionLostGame(world.getFaction(factionIndex));
6030 }
6031 
6032 bool Game::factionLostGame(const Faction *faction) {
6033 	if(faction != NULL) {
6034 		for(int factionIndex=0; factionIndex<faction->getUnitCount(); ++factionIndex) {
6035 			const UnitType *ut = faction->getUnit(factionIndex)->getType();
6036 			if(ut->getCountInVictoryConditions() == ucvcNotSet) {
6037 				if(faction->getUnit(factionIndex)->getType()->hasSkillClass(scBeBuilt)) {
6038 					return false;
6039 				}
6040 			}
6041 			else if(ut->getCountInVictoryConditions() == ucvcTrue) {
6042 				return false;
6043 			}
6044 		}
6045 	}
6046 	return true;
6047 }
6048 
6049 bool Game::hasBuilding(const Faction *faction) {
6050 	if(faction != NULL) {
6051 		for(int i=0; i<faction->getUnitCount(); ++i) {
6052 			if(faction->getUnit(i)->getType()->hasSkillClass(scBeBuilt)) {
6053 				return true;
6054 			}
6055 		}
6056 	}
6057 	return false;
6058 }
6059 
6060 void Game::incSpeed() {
6061 	if(disableSpeedChange == true) {
6062 		return;
6063 	}
6064 
6065 	Lang &lang= Lang::getInstance();
6066 
6067 	if(this->speed < Config::getInstance().getInt("FastSpeedLoops")) {
6068 		if(this->speed == 0) {
6069 			this->speed = 1;
6070 		}
6071 		else {
6072 			this->speed++;
6073 		}
6074 		console.addLine(lang.getString("GameSpeedSet")+" "+((this->speed == 0)?lang.getString("Slow") : (this->speed == 1)?lang.getString("Normal"):"x"+intToStr(this->speed)));
6075 	}
6076 }
6077 
6078 void Game::decSpeed() {
6079 	if(disableSpeedChange == true) {
6080 		return;
6081 	}
6082 
6083 	Lang &lang= Lang::getInstance();
6084 	if(this->speed > 0) {
6085 		this->speed--;
6086 		console.addLine(lang.getString("GameSpeedSet")+" "+((this->speed == 0)?lang.getString("Slow") : (this->speed == 1)?lang.getString("Normal"):"x"+intToStr(this->speed)));
6087 	}
6088 }
6089 
6090 void Game::setPaused(bool value,bool forceAllowPauseStateChange,bool clearCaches, bool joinNetworkGame) {
6091 	bool speedChangesAllowed= !NetworkManager::getInstance().isNetworkGame();
6092 	//printf("Toggle pause value = %d, speedChangesAllowed = %d, forceAllowPauseStateChange = %d\n",value,speedChangesAllowed,forceAllowPauseStateChange);
6093 
6094 	if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"game.cpp line: %d setPaused value: %d clearCaches: %d forceAllowPauseStateChange: %d speedChangesAllowed: %d pausedForJoinGame: %d joinNetworkGame: %d\n",__LINE__,value,clearCaches,forceAllowPauseStateChange,speedChangesAllowed,pausedForJoinGame,joinNetworkGame);
6095 	//printf("Line: %d setPaused value: %d clearCaches: %d forceAllowPauseStateChange: %d speedChangesAllowed: %d pausedForJoinGame: %d joinNetworkGame: %d\n",__LINE__,value,clearCaches,forceAllowPauseStateChange,speedChangesAllowed,pausedForJoinGame,joinNetworkGame);
6096 
6097 	if(forceAllowPauseStateChange == true || speedChangesAllowed == true) {
6098 		//printf("setPaused paused = %d, value = %d\n",paused,value);
6099 
6100 		NetworkManager &networkManager= NetworkManager::getInstance();
6101 
6102 		// Cannot change pause state while client is joining in progress game
6103 		if(pausedForJoinGame == true && joinNetworkGame == false &&
6104 			networkManager.getNetworkRole() == nrServer) {
6105 
6106 			ServerInterface *server = NetworkManager::getInstance().getServerInterface();
6107 			Lang &lang= Lang::getInstance();
6108 			const vector<string> languageList = this->gameSettings.getUniqueNetworkPlayerLanguages();
6109 
6110 			bool haveClientConnectedButNoReady = false;
6111 			for(int i = 0; i < world.getFactionCount(); ++i) {
6112 				Faction *faction = world.getFaction(i);
6113 
6114 				MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE);
6115 				ConnectionSlot *slot =  server->getSlot(faction->getStartLocationIndex(),false);
6116 				if(slot != NULL && slot->isConnected() == true && slot->isReady() == false) {
6117 					for(unsigned int i = 0; i < languageList.size(); ++i) {
6118 
6119 						char szMsg[8096]="";
6120 						if(lang.hasString("JoinPlayerToCurrentGameLaunch",languageList[i]) == true) {
6121 							snprintf(szMsg,8096,lang.getString("JoinPlayerToCurrentGameLaunch",languageList[i]).c_str(), slot->getName().c_str());
6122 						}
6123 						else {
6124 							snprintf(szMsg,8096,"Player: %s is about to join the game, please wait...",slot->getName().c_str());
6125 						}
6126 
6127 						safeMutex.ReleaseLock();
6128 
6129 						bool localEcho = lang.isLanguageLocal(languageList[i]);
6130 						server->sendTextMessage(szMsg,-1, localEcho,languageList[i]);
6131 						sleep(1);
6132 
6133 						haveClientConnectedButNoReady = true;
6134 					}
6135 				}
6136 			}
6137 
6138 			if(haveClientConnectedButNoReady == true) {
6139 				return;
6140 			}
6141 		}
6142 
6143 		Lang &lang= Lang::getInstance();
6144 		if(value == false) {
6145 			console.addLine(lang.getString("GameResumed"));
6146 
6147 			bool wasPausedForJoinGame = pausedForJoinGame;
6148 			paused= false;
6149 			pausedForJoinGame = false;
6150 			pausedBeforeJoinGame = false;
6151 			pauseStateChanged = true;
6152 
6153 			if(clearCaches == true) {
6154 				if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"game.cpp line: %d Clear Caches for resume in progress game\n",__LINE__);
6155 				//printf("Line: %d Clear Caches for resume in progress game\n",__LINE__);
6156 
6157 				world.clearCaches();
6158 				for(int i = 0; i < world.getFactionCount(); ++i) {
6159 					Faction *faction = world.getFaction(i);
6160 					faction->clearCaches();
6161 				}
6162 				world.refreshAllUnitExplorations();
6163 			}
6164 			setupPopupMenus(false);
6165 
6166 			if(networkManager.getNetworkRole() == nrClient &&
6167 				wasPausedForJoinGame == true) {
6168 				initialResumeSpeedLoops = true;
6169 			}
6170 
6171 			commander.setPauseNetworkCommands(false);
6172 		}
6173 		else {
6174 			console.addLine(lang.getString("GamePaused"));
6175 
6176 			if(joinNetworkGame == true) {
6177 				pausedBeforeJoinGame = paused;
6178 			}
6179 			paused= true;
6180 			pausedForJoinGame = joinNetworkGame;
6181 			pauseStateChanged = true;
6182 
6183 			if(clearCaches == true) {
6184 				//printf("Line: %d Clear Caches for resume in progress game\n",__LINE__);
6185 				if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled) SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,"game.cpp line: %d Clear Caches for resume in progress game\n",__LINE__);
6186 
6187 				world.clearCaches();
6188 				for(int i = 0; i < world.getFactionCount(); ++i) {
6189 					Faction *faction = world.getFaction(i);
6190 					faction->clearCaches();
6191 				}
6192 				world.refreshAllUnitExplorations();
6193 			}
6194 			pauseRequestSent=false;
6195 
6196 			commander.setPauseNetworkCommands(joinNetworkGame);
6197 		}
6198 		//printf("setPaused new paused = %d\n",paused);
6199 	}
6200 }
6201 
6202 bool Game::getPaused()
6203 {
6204 	bool speedChangesAllowed= !NetworkManager::getInstance().isNetworkGame();
6205 	if(speedChangesAllowed){
6206 		if(popupMenu.getVisible() == true || popupMenuSwitchTeams.getVisible() == true){
6207 			return true;
6208 		}
6209 //		if(mainMessageBox.getEnabled() == true || errorMessageBox.getEnabled() == true){
6210 //			return true;
6211 //		}
6212 		if(currentUIState != NULL) {
6213 			return true;
6214 		}
6215 	}
6216 	return paused;
6217 }
6218 
6219 int Game::getUpdateLoops() {
6220 	if(commander.hasReplayCommandListForFrame() == true) {
6221 		return 1;
6222 	}
6223 
6224 	if(getPaused()) {
6225 		return 0;
6226 	}
6227 	else if(this->speed == 0) {
6228 		return updateFps % 2 == 0? 1: 0;
6229 	}
6230 	else
6231 		return this->speed;
6232 }
6233 
6234 void Game::showLoseMessageBox() {
6235 	Lang &lang= Lang::getInstance();
6236 
6237 	NetworkManager &networkManager= NetworkManager::getInstance();
6238 	if(networkManager.isNetworkGame() == true && networkManager.getNetworkRole() == nrServer) {
6239 		showMessageBox(lang.getString("YouLose")+" "+lang.getString("ExitBattleServerQuestion"), lang.getString("BattleOver"), false);
6240 	}
6241 	else {
6242 		showMessageBox(lang.getString("YouLose")+" "+lang.getString("ExitBattleQuestion"), lang.getString("BattleOver"), false);
6243 	}
6244 }
6245 
6246 void Game::showWinMessageBox() {
6247 	Lang &lang= Lang::getInstance();
6248 
6249 	if(this->masterserverMode == true || world.getThisFaction()->getPersonalityType() == fpt_Observer) {
6250 		showMessageBox(lang.getString("GameOver")+" "+lang.getString("ExitBattleQuestion"), lang.getString("BattleOver"), false);
6251 	}
6252 	else {
6253 		showMessageBox(lang.getString("YouWin")+" "+lang.getString("ExitBattleQuestion"), lang.getString("BattleOver"), false);
6254 	}
6255 }
6256 
6257 void Game::showMessageBox(const string &text, const string &header, bool toggle) {
6258 	if(toggle == false) {
6259 		mainMessageBox.setEnabled(false);
6260 	}
6261 
6262 	if(mainMessageBox.getEnabled() == false) {
6263 		mainMessageBox.setText(text);
6264 		mainMessageBox.setHeader(header);
6265 		mainMessageBox.setEnabled(true);
6266 	}
6267 	else {
6268 		mainMessageBox.setEnabled(false);
6269 	}
6270 }
6271 
6272 void Game::showErrorMessageBox(const string &text, const string &header, bool toggle) {
6273 	if(toggle == false) {
6274 		errorMessageBox.setEnabled(false);
6275 	}
6276 
6277 	if(errorMessageBox.getEnabled() == false) {
6278 		errorMessageBox.setText(text);
6279 		errorMessageBox.setHeader(header);
6280 		errorMessageBox.setEnabled(true);
6281 	}
6282 	else {
6283 		errorMessageBox.setEnabled(false);
6284 	}
6285 }
6286 
6287 void Game::startPerformanceTimer() {
6288 	captureAvgTestStatus = true;
6289 	updateFpsAvgTest = -1;
6290 	renderFpsAvgTest = -1;
6291 }
6292 
6293 void Game::endPerformanceTimer() {
6294 	captureAvgTestStatus = false;
6295 }
6296 
6297 Vec2i Game::getPerformanceTimerResults() {
6298 	Vec2i results(this->updateFpsAvgTest,this->renderFpsAvgTest);
6299 	return results;
6300 }
6301 
6302 void Game::consoleAddLine(string line) {
6303 	console.addLine(line);
6304 }
6305 void Game::toggleTeamColorMarker() {
6306 	renderExtraTeamColor++;
6307 	renderExtraTeamColor=renderExtraTeamColor%4;
6308 }
6309 
6310 void Game::addNetworkCommandToReplayList(NetworkCommand* networkCommand, int worldFrameCount) {
6311 	Config &config= Config::getInstance();
6312 	if(config.getBool("SaveCommandsForReplay","false") == true) {
6313 		replayCommandList.push_back(make_pair(worldFrameCount,*networkCommand));
6314 	}
6315 }
6316 
6317 void Game::renderVideoPlayer() {
6318 	if(videoPlayer != NULL) {
6319 		if(videoPlayer->isPlaying() == true) {
6320 			videoPlayer->playFrame(false);
6321 		}
6322 		else {
6323 			delete videoPlayer;
6324 			videoPlayer = NULL;
6325 		}
6326 	}
6327 }
6328 
6329 void Game::playStaticVideo(const string &playVideo) {
6330 	if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false &&
6331 			::Shared::Graphics::VideoPlayer::hasBackEndVideoPlayer() == true) {
6332 
6333 		//togglePauseGame(true,true);
6334 		tryPauseToggle(true);
6335 		setupRenderForVideo();
6336 
6337 
6338 //		Context *c= GraphicsInterface::getInstance().getCurrentContext();
6339 //		SDL_Surface *screen = static_cast<ContextGl*>(c)->getPlatformContextGlPtr()->getScreen();
6340 //
6341 //		string vlcPluginsPath = Config::getInstance().getString("VideoPlayerPluginsPath","");
6342 //		//printf("screen->w = %d screen->h = %d screen->format->BitsPerPixel = %d\n",screen->w,screen->h,screen->format->BitsPerPixel);
6343 //		Shared::Graphics::VideoPlayer player(playVideo.c_str(),
6344 //							screen,
6345 //							0,0,
6346 //							screen->w,
6347 //							screen->h,
6348 //							screen->format->BitsPerPixel,
6349 //							vlcPluginsPath,
6350 //							SystemFlags::VERBOSE_MODE_ENABLED);
6351 //		player.PlayVideo();
6352 		//}
6353 		//tryPauseToggle(false);
6354 
6355 		playStreamingVideo(playVideo);
6356 		playingStaticVideo = true;
6357 	}
6358 }
6359 void Game::playStreamingVideo(const string &playVideo) {
6360 	if(videoPlayer == NULL) {
6361 		if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false &&
6362 				::Shared::Graphics::VideoPlayer::hasBackEndVideoPlayer() == true) {
6363 			Context *c= GraphicsInterface::getInstance().getCurrentContext();
6364 			PlatformContextGl *glCtx = static_cast<ContextGl*>(c)->getPlatformContextGlPtr();
6365 			SDL_Window *window = glCtx->getScreenWindow();
6366 			SDL_Surface *screen = glCtx->getScreenSurface();
6367 
6368 			string vlcPluginsPath = Config::getInstance().getString("VideoPlayerPluginsPath","");
6369 
6370 			videoPlayer = new ::Shared::Graphics::VideoPlayer(
6371 					&Renderer::getInstance(),
6372 					playVideo,
6373 					"",
6374 					window,
6375 					0,0,
6376 					screen->w,
6377 					screen->h,
6378 					screen->format->BitsPerPixel,
6379 					false,
6380 					vlcPluginsPath,
6381 					SystemFlags::VERBOSE_MODE_ENABLED);
6382 		}
6383 	}
6384 	else {
6385 		if(videoPlayer->isPlaying() == false) {
6386 			delete videoPlayer;
6387 			videoPlayer = NULL;
6388 
6389 			if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false &&
6390 					::Shared::Graphics::VideoPlayer::hasBackEndVideoPlayer() == true) {
6391 				Context *c= GraphicsInterface::getInstance().getCurrentContext();
6392 				PlatformContextGl *glCtx = static_cast<ContextGl*>(c)->getPlatformContextGlPtr();
6393 				SDL_Window *window = glCtx->getScreenWindow();
6394 				SDL_Surface *screen = glCtx->getScreenSurface();
6395 
6396 				string vlcPluginsPath = Config::getInstance().getString("VideoPlayerPluginsPath","");
6397 
6398 				videoPlayer = new ::Shared::Graphics::VideoPlayer(
6399 						&Renderer::getInstance(),
6400 						playVideo,
6401 						"",
6402 						window,
6403 						0,0,
6404 						screen->w,
6405 						screen->h,
6406 						screen->format->BitsPerPixel,
6407 						false,
6408 						vlcPluginsPath,
6409 						SystemFlags::VERBOSE_MODE_ENABLED);
6410 			}
6411 		}
6412 	}
6413 
6414 	if(videoPlayer != NULL) {
6415 		videoPlayer->initPlayer();
6416 	}
6417 }
6418 void Game::stopStreamingVideo(const string &playVideo) {
6419 	if(videoPlayer != NULL) {
6420 		videoPlayer->StopVideo();
6421 	}
6422 }
6423 
6424 void Game::stopAllVideo() {
6425 	if(videoPlayer != NULL) {
6426 		videoPlayer->StopVideo();
6427 	}
6428 }
6429 
6430 bool Game::clientLagHandler(int slotIndex,bool networkPauseGameForLaggedClients) {
6431 	if(networkPauseGameForLaggedClients == true) {
6432 		printf("**WARNING** Detected lag from client: %d networkPauseGameForLaggedClients: %d\n",slotIndex,networkPauseGameForLaggedClients);
6433 	}
6434 	else {
6435 		printf("==> Requested Resume Game after Pause for lagging client(s)...\n");
6436 	}
6437 
6438 	this->networkPauseGameForLaggedClientsRequested  = networkPauseGameForLaggedClients;
6439 	this->networkResumeGameForLaggedClientsRequested = !networkPauseGameForLaggedClients;
6440 	return true;
6441 }
6442 
6443 void Game::saveGame(){
6444 	string file = this->saveGame(GameConstants::saveGameFilePattern);
6445 	char szBuf[8096]="";
6446 	Lang &lang= Lang::getInstance();
6447 	snprintf(szBuf,8096,lang.getString("GameSaved","",true).c_str(),file.c_str());
6448 	console.addLine(szBuf);
6449 
6450 	Config &config= Config::getInstance();
6451 	config.setString("LastSavedGame",file);
6452 	config.save();
6453 }
6454 
6455 string Game::saveGame(string name, string path) {
6456 	Config &config= Config::getInstance();
6457 	// auto name file if using saved file pattern string
6458 	if(name == GameConstants::saveGameFilePattern) {
6459 		//time_t curTime = time(NULL);
6460 	    //struct tm *loctime = localtime (&curTime);
6461 		struct tm loctime = threadsafe_localtime(systemtime_now());
6462 	    char szBuf2[100]="";
6463 	    strftime(szBuf2,100,"%Y%m%d_%H%M%S",&loctime);
6464 
6465 		char szBuf[8096]="";
6466 		snprintf(szBuf,8096,name.c_str(),szBuf2);
6467 		name = szBuf;
6468 	}
6469 	else if(name == GameConstants::saveGameFileAutoTestDefault) {
6470 		//time_t curTime = time(NULL);
6471 	    //struct tm *loctime = localtime (&curTime);
6472 		struct tm loctime = threadsafe_localtime(systemtime_now());
6473 	    char szBuf2[100]="";
6474 	    strftime(szBuf2,100,"%Y%m%d_%H%M%S",&loctime);
6475 
6476 		char szBuf[8096]="";
6477 		snprintf(szBuf,8096,name.c_str(),szBuf2);
6478 		name = szBuf;
6479 	}
6480 
6481 	// Save the file now
6482 	string saveGameFile = path + name;
6483 	if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
6484 		saveGameFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + saveGameFile;
6485 	}
6486 	else {
6487         string userData = config.getString("UserData_Root","");
6488         if(userData != "") {
6489         	endPathWithSlash(userData);
6490         }
6491         saveGameFile = userData + saveGameFile;
6492 	}
6493 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Saving game to [%s]\n",saveGameFile.c_str());
6494 
6495 	// This condition will re-play all the commands from a replay file
6496 	// INSTEAD of saving from a saved game.
6497 	if(config.getBool("SaveCommandsForReplay","false") == true) {
6498 		std::map<string,string> mapTagReplacements;
6499 		XmlTree xmlTreeSaveGame(XML_RAPIDXML_ENGINE);
6500 
6501 		xmlTreeSaveGame.init("megaglest-saved-game");
6502 		XmlNode *rootNodeReplay = xmlTreeSaveGame.getRootNode();
6503 
6504 		//std::map<string,string> mapTagReplacements;
6505 		//time_t now = time(NULL);
6506 		//struct tm *loctime = localtime (&now);
6507 		struct tm loctime = threadsafe_localtime(systemtime_now());
6508 		char szBuf[4096]="";
6509 		strftime(szBuf,4095,"%Y-%m-%d %H:%M:%S",&loctime);
6510 
6511 		rootNodeReplay->addAttribute("version",glestVersionString, mapTagReplacements);
6512 		rootNodeReplay->addAttribute("timestamp",szBuf, mapTagReplacements);
6513 
6514 		XmlNode *gameNodeReplay = rootNodeReplay->addChild("Game");
6515 		gameSettings.saveGame(gameNodeReplay);
6516 
6517 		gameNodeReplay->addAttribute("LastWorldFrameCount",intToStr(world.getFrameCount()), mapTagReplacements);
6518 
6519 		for(unsigned int i = 0; i < replayCommandList.size(); ++i) {
6520 			std::pair<int,NetworkCommand> &cmd = replayCommandList[i];
6521 			XmlNode *networkCommandNode = cmd.second.saveGame(gameNodeReplay);
6522 			networkCommandNode->addAttribute("worldFrameCount",intToStr(cmd.first), mapTagReplacements);
6523 		}
6524 
6525 		string replayFile = saveGameFile + ".replay";
6526 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Saving game replay commands to [%s]\n",replayFile.c_str());
6527 		xmlTreeSaveGame.save(replayFile);
6528 	}
6529 
6530 	XmlTree xmlTree;
6531 	xmlTree.init("megaglest-saved-game");
6532 	XmlNode *rootNode = xmlTree.getRootNode();
6533 
6534 	std::map<string,string> mapTagReplacements;
6535 	//time_t now = time(NULL);
6536     //struct tm *loctime = localtime (&now);
6537 	struct tm loctime = threadsafe_localtime(systemtime_now());
6538     char szBuf[4096]="";
6539     strftime(szBuf,4095,"%Y-%m-%d %H:%M:%S",&loctime);
6540 
6541 	rootNode->addAttribute("version",glestVersionString, mapTagReplacements);
6542 	rootNode->addAttribute("timestamp",szBuf, mapTagReplacements);
6543 
6544 	XmlNode *gameNode = rootNode->addChild("Game");
6545 	//World world;
6546 	world.saveGame(gameNode);
6547     //AiInterfaces aiInterfaces;
6548 	for(unsigned int i = 0; i < aiInterfaces.size(); ++i) {
6549 		AiInterface *aiIntf = aiInterfaces[i];
6550 		if(aiIntf != NULL) {
6551 			aiIntf->saveGame(gameNode);
6552 		}
6553 	}
6554     //Gui gui;
6555 	gui.saveGame(gameNode);
6556     //GameCamera gameCamera;
6557 	gameCamera.saveGame(gameNode);
6558     //Commander commander;
6559     //Console console;
6560 	//ChatManager chatManager;
6561 	//ScriptManager scriptManager;
6562 	scriptManager.saveGame(gameNode);
6563 
6564 	//misc
6565 	//Checksum checksum;
6566 	gameNode->addAttribute("checksum",intToStr(checksum.getSum()), mapTagReplacements);
6567     //string loadingText;
6568 //    int mouse2d;
6569 	gameNode->addAttribute("mouse2d",intToStr(mouse2d), mapTagReplacements);
6570 //    int mouseX;
6571 	gameNode->addAttribute("mouseX",intToStr(mouseX), mapTagReplacements);
6572 //    int mouseY; //coords win32Api
6573 	gameNode->addAttribute("mouseY",intToStr(mouseY), mapTagReplacements);
6574 //    Vec2i mouseCellPos;
6575 	gameNode->addAttribute("mouseCellPos",mouseCellPos.getString(), mapTagReplacements);
6576 //	int updateFps, lastUpdateFps, avgUpdateFps;
6577 //	int totalRenderFps, renderFps, lastRenderFps, avgRenderFps,currentAvgRenderFpsTotal;
6578 	//Uint64 tickCount;
6579 	gameNode->addAttribute("tickCount",intToStr(tickCount), mapTagReplacements);
6580 
6581 	//bool paused;
6582 	gameNode->addAttribute("paused",intToStr(paused), mapTagReplacements);
6583 	//bool gameOver;
6584 	gameNode->addAttribute("gameOver",intToStr(gameOver), mapTagReplacements);
6585 	//bool renderNetworkStatus;
6586 	//bool showFullConsole;
6587 	//bool mouseMoved;
6588 	//float scrollSpeed;
6589 	gameNode->addAttribute("scrollSpeed",floatToStr(scrollSpeed,6), mapTagReplacements);
6590 	//bool camLeftButtonDown;
6591 	//bool camRightButtonDown;
6592 	//bool camUpButtonDown;
6593 	//bool camDownButtonDown;
6594 
6595 	//Speed speed;
6596 	gameNode->addAttribute("speed",intToStr(speed), mapTagReplacements);
6597 
6598 	//GraphicMessageBox mainMessageBox;
6599 	//GraphicMessageBox errorMessageBox;
6600 
6601 	//misc ptr
6602 	//ParticleSystem *weatherParticleSystem;
6603 	if(weatherParticleSystem != NULL) {
6604 		weatherParticleSystem->saveGame(gameNode);
6605 	}
6606 	//GameSettings gameSettings;
6607 	gameSettings.saveGame(gameNode);
6608 	//Vec2i lastMousePos;
6609 	gameNode->addAttribute("lastMousePos",lastMousePos.getString(), mapTagReplacements);
6610 	//time_t lastRenderLog2d;
6611 	gameNode->addAttribute("lastRenderLog2d",intToStr(lastRenderLog2d), mapTagReplacements);
6612 	//DisplayMessageFunction originalDisplayMsgCallback;
6613 	//bool isFirstRender;
6614 	gameNode->addAttribute("isFirstRender",intToStr(isFirstRender), mapTagReplacements);
6615 
6616 	//bool quitTriggeredIndicator;
6617 	//int original_updateFps;
6618 	gameNode->addAttribute("original_updateFps",intToStr(original_updateFps), mapTagReplacements);
6619 	//int original_cameraFps;
6620 	gameNode->addAttribute("original_cameraFps",intToStr(original_cameraFps), mapTagReplacements);
6621 
6622 	//bool captureAvgTestStatus;
6623 	gameNode->addAttribute("captureAvgTestStatus",intToStr(captureAvgTestStatus), mapTagReplacements);
6624 	//int updateFpsAvgTest;
6625 	gameNode->addAttribute("updateFpsAvgTest",intToStr(updateFpsAvgTest), mapTagReplacements);
6626 	//int renderFpsAvgTest;
6627 	gameNode->addAttribute("renderFpsAvgTest",intToStr(renderFpsAvgTest), mapTagReplacements);
6628 
6629 	//int renderExtraTeamColor;
6630 	gameNode->addAttribute("renderExtraTeamColor",intToStr(renderExtraTeamColor), mapTagReplacements);
6631 
6632 	//static const int renderTeamColorCircleBit=1;
6633 	//static const int renderTeamColorPlaneBit=2;
6634 
6635 	//bool photoModeEnabled;
6636 	gameNode->addAttribute("photoModeEnabled",intToStr(photoModeEnabled), mapTagReplacements);
6637 	//bool visibleHUD;
6638 	gameNode->addAttribute("visibleHUD",intToStr(visibleHUD), mapTagReplacements);
6639 
6640 	//bool timeDisplay
6641 	gameNode->addAttribute("timeDisplay",intToStr(timeDisplay), mapTagReplacements);
6642 
6643 	//bool withRainEffect;
6644 	gameNode->addAttribute("withRainEffect",intToStr(withRainEffect), mapTagReplacements);
6645 	//Program *program;
6646 
6647 	//bool gameStarted;
6648 	gameNode->addAttribute("gameStarted",intToStr(gameStarted), mapTagReplacements);
6649 
6650 	//time_t lastMaxUnitCalcTime;
6651 	gameNode->addAttribute("lastMaxUnitCalcTime",intToStr(lastMaxUnitCalcTime), mapTagReplacements);
6652 
6653 	//PopupMenu popupMenu;
6654 	//PopupMenu popupMenuSwitchTeams;
6655 
6656 	//std::map<int,int> switchTeamIndexMap;
6657 	//GraphicMessageBox switchTeamConfirmMessageBox;
6658 
6659 	//int exitGamePopupMenuIndex;
6660 	//int joinTeamPopupMenuIndex;
6661 	//int pauseGamePopupMenuIndex;
6662 	//int keyboardSetupPopupMenuIndex;
6663 	//GLuint statelist3dMenu;
6664 	//ProgramState *currentUIState;
6665 
6666 	//bool masterserverMode;
6667 
6668 	//StrSound *currentAmbientSound;
6669 
6670 	//time_t lastNetworkPlayerConnectionCheck;
6671 	gameNode->addAttribute("lastNetworkPlayerConnectionCheck",intToStr(lastNetworkPlayerConnectionCheck), mapTagReplacements);
6672 
6673 	//time_t lastMasterServerGameStatsDump;
6674 	gameNode->addAttribute("lastMasterServerGameStatsDump",intToStr(lastMasterServerGameStatsDump), mapTagReplacements);
6675 
6676 	XmlNode *unitHighlightListNode = gameNode->addChild("unitHighlightList");
6677 	//for(unsigned int i = 0; i < unitHighlightList.size(); ++i) {
6678 	for(std::map<int,HighlightSpecialUnitInfo>::iterator iterMap = unitHighlightList.begin();
6679 			iterMap != unitHighlightList.end(); ++iterMap) {
6680 		HighlightSpecialUnitInfo &info = iterMap->second;
6681 		XmlNode *infoNode = unitHighlightListNode->addChild("info");
6682 		infoNode->addAttribute("unitid",intToStr(iterMap->first), mapTagReplacements);
6683 		infoNode->addAttribute("radius",floatToStr(info.radius,6), mapTagReplacements);
6684 		infoNode->addAttribute("thickness",floatToStr(info.thickness,6), mapTagReplacements);
6685 		infoNode->addAttribute("color",info.color.getString(), mapTagReplacements);
6686 	}
6687 
6688 	gameNode->addAttribute("disableSpeedChange",intToStr(disableSpeedChange), mapTagReplacements);
6689 
6690 	xmlTree.save(saveGameFile);
6691 
6692 	if(masterserverMode == false) {
6693 		// take Screenshot
6694 		string jpgFileName=saveGameFile+".jpg";
6695 		// menu is already disabled, last rendered screen is still with enabled one. Lets render again:
6696 		render3d();
6697 		render2d();
6698 		Renderer::getInstance().saveScreen(jpgFileName,config.getInt("SaveGameScreenshotWidth","800"),config.getInt("SaveGameScreenshotHeight","600"));
6699 	}
6700 
6701 	return saveGameFile;
6702 }
6703 
6704 void Game::loadGame(string name,Program *programPtr,bool isMasterserverMode,const GameSettings *joinGameSettings) {
6705 	Config &config= Config::getInstance();
6706 	// This condition will re-play all the commands from a replay file
6707 	// INSTEAD of saving from a saved game.
6708 	if(joinGameSettings == NULL && config.getBool("SaveCommandsForReplay","false") == true) {
6709 		XmlTree	xmlTreeReplay(XML_RAPIDXML_ENGINE);
6710 		std::map<string,string> mapExtraTagReplacementValues;
6711 		xmlTreeReplay.load(name + ".replay", Properties::getTagReplacementValues(&mapExtraTagReplacementValues),true);
6712 
6713 		const XmlNode *rootNode= xmlTreeReplay.getRootNode();
6714 
6715 		if(rootNode->hasChild("megaglest-saved-game") == true) {
6716 			rootNode = rootNode->getChild("megaglest-saved-game");
6717 		}
6718 
6719 		//const XmlNode *versionNode= rootNode->getChild("megaglest-saved-game");
6720 		const XmlNode *versionNode= rootNode;
6721 
6722 		Lang &lang= Lang::getInstance();
6723 		string gameVer = versionNode->getAttribute("version")->getValue();
6724 		if(gameVer != glestVersionString && checkVersionComptability(gameVer, glestVersionString) == false){
6725 			char szBuf[8096]="";
6726 			snprintf(szBuf,8096,lang.getString("SavedGameBadVersion").c_str(),gameVer.c_str(),glestVersionString.c_str());
6727 			throw megaglest_runtime_error(szBuf,true);
6728 		}
6729 
6730 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Found saved game version that matches your application version: [%s] --> [%s]\n",gameVer.c_str(),glestVersionString.c_str());
6731 
6732 		XmlNode *gameNode = rootNode->getChild("Game");
6733 
6734 		GameSettings newGameSettingsReplay;
6735 		newGameSettingsReplay.loadGame(gameNode);
6736 		//printf("Loading scenario [%s]\n",newGameSettingsReplay.getScenarioDir().c_str());
6737 		if(newGameSettingsReplay.getScenarioDir() != "" && fileExists(newGameSettingsReplay.getScenarioDir()) == false) {
6738 			newGameSettingsReplay.setScenarioDir(Scenario::getScenarioPath(Config::getInstance().getPathListForType(ptScenarios),newGameSettingsReplay.getScenario()));
6739 
6740 			//printf("Loading scenario #2 [%s]\n",newGameSettingsReplay.getScenarioDir().c_str());
6741 		}
6742 
6743 		//GameSettings newGameSettings;
6744 		//newGameSettings.loadGame(gameNode);
6745 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Game settings loaded\n");
6746 
6747 		NetworkManager &networkManager= NetworkManager::getInstance();
6748 		networkManager.end();
6749 		networkManager.init(nrServer,true);
6750 
6751 		Game *newGame = new Game(programPtr, &newGameSettingsReplay, isMasterserverMode);
6752 		newGame->lastworldFrameCountForReplay = gameNode->getAttribute("LastWorldFrameCount")->getIntValue();
6753 
6754 		vector<XmlNode *> networkCommandNodeList = gameNode->getChildList("NetworkCommand");
6755 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("networkCommandNodeList.size() = " MG_SIZE_T_SPECIFIER "\n",networkCommandNodeList.size());
6756 		for(unsigned int i = 0; i < networkCommandNodeList.size(); ++i) {
6757 			XmlNode *node = networkCommandNodeList[i];
6758 			int worldFrameCount = node->getAttribute("worldFrameCount")->getIntValue();
6759 			NetworkCommand command;
6760 			command.loadGame(node);
6761 			newGame->commander.addToReplayCommandList(command,worldFrameCount);
6762 		}
6763 
6764 		programPtr->setState(newGame);
6765 		return;
6766 	}
6767 
6768 	XmlTree	xmlTree(XML_RAPIDXML_ENGINE);
6769 
6770 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Before load of XML\n");
6771 	std::map<string,string> mapExtraTagReplacementValues;
6772 	xmlTree.load(name, Properties::getTagReplacementValues(&mapExtraTagReplacementValues),true);
6773 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("After load of XML\n");
6774 
6775 	const XmlNode *rootNode= xmlTree.getRootNode();
6776 	if(rootNode->hasChild("megaglest-saved-game") == true) {
6777 		rootNode = rootNode->getChild("megaglest-saved-game");
6778 	}
6779 
6780 	//const XmlNode *versionNode= rootNode->getChild("megaglest-saved-game");
6781 	const XmlNode *versionNode= rootNode;
6782 
6783 	Lang &lang= Lang::getInstance();
6784 	string gameVer = versionNode->getAttribute("version")->getValue();
6785 	// this is the version check for loading normal save games from menu_state_load_game
6786 	if (gameVer != glestVersionString
6787 			&& (compareMajorMinorVersion(gameVer, lastCompatibleSaveGameVersionString) < 0
6788 					|| compareMajorMinorVersion(glestVersionString, gameVer) < 0)) {
6789 		char szBuf[8096]="";
6790 		snprintf(szBuf,8096,lang.getString("SavedGameBadVersion").c_str(),gameVer.c_str(),glestVersionString.c_str());
6791 		throw megaglest_runtime_error(szBuf,true);
6792 	}
6793 
6794 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Found saved game version that matches your application version: [%s] --> [%s]\n",gameVer.c_str(),glestVersionString.c_str());
6795 
6796 	XmlNode *gameNode = rootNode->getChild("Game");
6797 	GameSettings newGameSettings;
6798 	if(joinGameSettings != NULL) {
6799 		newGameSettings = *joinGameSettings;
6800 
6801 		XmlNode *worldNode = gameNode->getChild("World");
6802 		XmlNode *guiNode = gameNode->getChild("Gui");
6803 		XmlNode *selectionNode = guiNode->getChild("Selection");
6804 		XmlNode *statsNode = worldNode->getChild("Stats");
6805 		XmlNode *minimapNode = worldNode->getChild("Minimap");
6806 
6807 		if(gameVer != glestVersionString && checkVersionComptability(gameVer, glestVersionString) == false){
6808 			char szBuf[8096]="";
6809 			snprintf(szBuf,8096,lang.getString("SavedGameBadVersion").c_str(),gameVer.c_str(),glestVersionString.c_str());
6810 			throw megaglest_runtime_error(szBuf,true);
6811 		}
6812 		// This is explored fog of war for the host player, clear it
6813 		minimapNode->clearChild("fowPixmap1");
6814 
6815 		NetworkManager &networkManager= NetworkManager::getInstance();
6816 		//NetworkRole role = networkManager.getNetworkRole();
6817 		ClientInterface *clientInterface = dynamic_cast<ClientInterface *>(networkManager.getClientInterface());
6818 
6819 		for(int i= 0; i<newGameSettings.getFactionCount(); ++i) {
6820 			//replace by network
6821 			if(newGameSettings.getFactionControl(i)==ctHuman) {
6822 				newGameSettings.setFactionControl(i, ctNetwork);
6823 			}
6824 
6825 			//set the faction index
6826 			if(newGameSettings.getStartLocationIndex(i) == clientInterface->getPlayerIndex()) {
6827 				newGameSettings.setThisFactionIndex(i);
6828 				newGameSettings.setFactionControl(i, ctNetwork);
6829 
6830 				worldNode->getAttribute("thisFactionIndex")->setValue(intToStr(i));
6831 				//worldNode->getAttribute("thisTeamIndex")->setValue(intToStr(newGameSettings.getTeam(i)));
6832 
6833 				XmlNode *factionNode = worldNode->getChild("Faction",i);
6834 				factionNode->getAttribute("thisFaction")->setValue(intToStr(i));
6835 				factionNode->getAttribute("control")->setValue(intToStr(ctNetwork));
6836 
6837 				selectionNode->getAttribute("factionIndex")->setValue(intToStr(i));
6838 				//selectionNode->getAttribute("teamIndex")->setValue(intToStr(newGameSettings.getTeam(i)));
6839 
6840 				statsNode->getAttribute("thisFactionIndex")->setValue(intToStr(i));
6841 			}
6842 			else {
6843 				XmlNode *factionNode = worldNode->getChild("Faction",i);
6844 				factionNode->getAttribute("thisFaction")->setValue(intToStr(0));
6845 			}
6846 		}
6847 	}
6848 	else {
6849 		newGameSettings.loadGame(gameNode);
6850 		//printf("Loading scenario [%s]\n",newGameSettings.getScenarioDir().c_str());
6851 		if(newGameSettings.getScenarioDir() != "" && fileExists(newGameSettings.getScenarioDir()) == false) {
6852 			newGameSettings.setScenarioDir(Scenario::getScenarioPath(Config::getInstance().getPathListForType(ptScenarios),newGameSettings.getScenario()));
6853 
6854 			//printf("Loading scenario #2 [%s]\n",newGameSettings.getScenarioDir().c_str());
6855 		}
6856 	}
6857 
6858 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Game settings loaded\n");
6859 
6860 	if(joinGameSettings == NULL) {
6861 		NetworkManager &networkManager= NetworkManager::getInstance();
6862 		networkManager.end();
6863 		networkManager.init(nrServer,true);
6864 	}
6865 
6866 	Game *newGame = new Game(programPtr, &newGameSettings, isMasterserverMode);
6867 
6868 	newGame->loadGameNode = gameNode;
6869 	newGame->inJoinGameLoading = (joinGameSettings != NULL);
6870 
6871 //	newGame->mouse2d = gameNode->getAttribute("mouse2d")->getIntValue();
6872 //    int mouseX;
6873 //	newGame->mouseX = gameNode->getAttribute("mouseX")->getIntValue();
6874 //    int mouseY; //coords win32Api
6875 //	newGame->mouseY = gameNode->getAttribute("mouseY")->getIntValue();
6876 //    Vec2i mouseCellPos;
6877 //	newGame->mouseCellPos = Vec2i::strToVec2(gameNode->getAttribute("mouseCellPos")->getValue());
6878 //	int updateFps, lastUpdateFps, avgUpdateFps;
6879 //	int totalRenderFps, renderFps, lastRenderFps, avgRenderFps,currentAvgRenderFpsTotal;
6880 	//Uint64 tickCount;
6881 	newGame->tickCount = gameNode->getAttribute("tickCount")->getIntValue();
6882 
6883 	//bool paused;
6884 	if(newGame->inJoinGameLoading==true){
6885 		newGame->paused = gameNode->getAttribute("paused")->getIntValue() != 0;
6886 	}else{
6887 		//newGame->paused = gameNode->getAttribute("paused")->getIntValue() != 0;
6888 		newGame->paused = true;
6889 	}
6890 	if(newGame->paused) newGame->console.addLine(lang.getString("GamePaused"));
6891 	//bool gameOver;
6892 	newGame->gameOver = gameNode->getAttribute("gameOver")->getIntValue() != 0;
6893 	//bool renderNetworkStatus;
6894 	//bool showFullConsole;
6895 	//bool mouseMoved;
6896 	//float scrollSpeed;
6897 //	newGame->scrollSpeed = gameNode->getAttribute("scrollSpeed")->getFloatValue();
6898 	//bool camLeftButtonDown;
6899 	//bool camRightButtonDown;
6900 	//bool camUpButtonDown;
6901 	//bool camDownButtonDown;
6902 
6903 	//Speed speed;
6904 	//gameNode->addAttribute("speed",intToStr(speed), mapTagReplacements);
6905 
6906 	//GraphicMessageBox mainMessageBox;
6907 	//GraphicMessageBox errorMessageBox;
6908 
6909 	//misc ptr
6910 	//ParticleSystem *weatherParticleSystem;
6911 //	if(weatherParticleSystem != NULL) {
6912 //		weatherParticleSystem->saveGame(gameNode);
6913 //	}
6914 	//GameSettings gameSettings;
6915 //	gameSettings.saveGame(gameNode);
6916 	//Vec2i lastMousePos;
6917 //	gameNode->addAttribute("lastMousePos",lastMousePos.getString(), mapTagReplacements);
6918 	//time_t lastRenderLog2d;
6919 //	gameNode->addAttribute("lastRenderLog2d",intToStr(lastRenderLog2d), mapTagReplacements);
6920 	//DisplayMessageFunction originalDisplayMsgCallback;
6921 	//bool isFirstRender;
6922 //	gameNode->addAttribute("isFirstRender",intToStr(isFirstRender), mapTagReplacements);
6923 
6924 	//bool quitTriggeredIndicator;
6925 	//int original_updateFps;
6926 //	gameNode->addAttribute("original_updateFps",intToStr(original_updateFps), mapTagReplacements);
6927 	//int original_cameraFps;
6928 //	gameNode->addAttribute("original_cameraFps",intToStr(original_cameraFps), mapTagReplacements);
6929 
6930 	//bool captureAvgTestStatus;
6931 //	gameNode->addAttribute("captureAvgTestStatus",intToStr(captureAvgTestStatus), mapTagReplacements);
6932 	//int updateFpsAvgTest;
6933 //	gameNode->addAttribute("updateFpsAvgTest",intToStr(updateFpsAvgTest), mapTagReplacements);
6934 	//int renderFpsAvgTest;
6935 //	gameNode->addAttribute("renderFpsAvgTest",intToStr(renderFpsAvgTest), mapTagReplacements);
6936 
6937 	//int renderExtraTeamColor;
6938 	newGame->renderExtraTeamColor = gameNode->getAttribute("renderExtraTeamColor")->getIntValue();
6939 
6940 	//static const int renderTeamColorCircleBit=1;
6941 	//static const int renderTeamColorPlaneBit=2;
6942 
6943 	//bool photoModeEnabled;
6944 	//gameNode->addAttribute("photoModeEnabled",intToStr(photoModeEnabled), mapTagReplacements);
6945 	newGame->photoModeEnabled = gameNode->getAttribute("photoModeEnabled")->getIntValue() != 0;
6946 	//bool visibleHUD;
6947 	//gameNode->addAttribute("visibleHUD",intToStr(visibleHUD), mapTagReplacements);
6948 	newGame->visibleHUD = gameNode->getAttribute("visibleHUD")->getIntValue() != 0;
6949 	newGame->timeDisplay = gameNode->getAttribute("timeDisplay")->getIntValue() != 0;
6950 	//bool withRainEffect;
6951 	//gameNode->addAttribute("withRainEffect",intToStr(withRainEffect), mapTagReplacements);
6952 	newGame->withRainEffect = gameNode->getAttribute("withRainEffect")->getIntValue() != 0;
6953 	//Program *program;
6954 
6955 	if(joinGameSettings == NULL) {
6956 		if(gameNode->hasChild("unitHighlightList") == true) {
6957 			XmlNode *unitHighlightListNode = gameNode->getChild("unitHighlightList");
6958 			vector<XmlNode *> infoNodeList = unitHighlightListNode->getChildList("info");
6959 			for(unsigned int i = 0; i < infoNodeList.size(); ++i) {
6960 				XmlNode *infoNode = infoNodeList[i];
6961 
6962 				int unitId = infoNode->getAttribute("radius")->getIntValue();
6963 				HighlightSpecialUnitInfo info;
6964 				info.radius = infoNode->getAttribute("radius")->getFloatValue();
6965 				info.thickness = infoNode->getAttribute("thickness")->getFloatValue();
6966 				info.color = Vec4f::strToVec4(infoNode->getAttribute("color")->getValue());
6967 
6968 				newGame->unitHighlightList[unitId] = info;
6969 			}
6970 		}
6971 	}
6972 
6973 	newGame->timeDisplay = gameNode->getAttribute("timeDisplay")->getIntValue() != 0;
6974 
6975 	if(gameNode->hasAttribute("disableSpeedChange") == true) {
6976 		newGame->disableSpeedChange = gameNode->getAttribute("disableSpeedChange")->getIntValue() != 0;
6977 	}
6978 
6979 	//bool gameStarted;
6980 	//gameNode->addAttribute("gameStarted",intToStr(gameStarted), mapTagReplacements);
6981 //	newGame->gameStarted = gameNode->getAttribute("gameStarted")->getIntValue();
6982 
6983 	//time_t lastMaxUnitCalcTime;
6984 	//gameNode->addAttribute("lastMaxUnitCalcTime",intToStr(lastMaxUnitCalcTime), mapTagReplacements);
6985 
6986 	//PopupMenu popupMenu;
6987 	//PopupMenu popupMenuSwitchTeams;
6988 
6989 	//std::map<int,int> switchTeamIndexMap;
6990 	//GraphicMessageBox switchTeamConfirmMessageBox;
6991 
6992 	//int exitGamePopupMenuIndex;
6993 	//int joinTeamPopupMenuIndex;
6994 	//int pauseGamePopupMenuIndex;
6995 	//int keyboardSetupPopupMenuIndex;
6996 	//GLuint statelist3dMenu;
6997 	//ProgramState *currentUIState;
6998 
6999 	//bool masterserverMode;
7000 
7001 	//StrSound *currentAmbientSound;
7002 
7003 	//time_t lastNetworkPlayerConnectionCheck;
7004 	//gameNode->addAttribute("lastNetworkPlayerConnectionCheck",intToStr(lastNetworkPlayerConnectionCheck), mapTagReplacements);
7005 
7006 	//time_t lastMasterServerGameStatsDump;
7007 	//gameNode->addAttribute("lastMasterServerGameStatsDump",intToStr(lastMasterServerGameStatsDump), mapTagReplacements);
7008 
7009 	if(joinGameSettings == NULL) {
7010 		newGame->gameCamera.loadGame(gameNode);
7011 	}
7012 
7013 	const XmlNode *worldNode = gameNode->getChild("World");
7014 	newGame->world.loadGame(worldNode);
7015 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Starting Game ...\n");
7016 	programPtr->setState(newGame);
7017 }
7018 
7019 }}//end namespace
7020