1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #include "menu_state_root.h"
13 
14 #include "renderer.h"
15 #include "sound_renderer.h"
16 #include "core_data.h"
17 #include "config.h"
18 #include "menu_state_new_game.h"
19 #include "menu_state_load_game.h"
20 #include "menu_state_options.h"
21 #include "menu_state_about.h"
22 #include "menu_state_mods.h"
23 #include "metrics.h"
24 #include "network_manager.h"
25 #include "network_message.h"
26 #include "socket.h"
27 #include "auto_test.h"
28 #include <stdio.h>
29 
30 #include "leak_dumper.h"
31 
32 namespace Glest{ namespace Game{
33 
34 // =====================================================
35 // 	class MenuStateRoot
36 // =====================================================
37 
38 bool MenuStateRoot::gameUpdateChecked = false;
39 
MenuStateRoot(Program * program,MainMenu * mainMenu)40 MenuStateRoot::MenuStateRoot(Program *program, MainMenu *mainMenu) :
41 	MenuState(program, mainMenu, "root"), 	updatesHttpServerThread(NULL),
42 											buttonNewGame("MainMenu","buttonNewGame"),
43 											buttonLoadGame("MainMenu","buttonLoadGame"),
44 											buttonMods("MainMenu","buttonMods"),
45 											buttonOptions("MainMenu","buttonOptions"),
46 											buttonAbout("MainMenu","buttonAbout"),
47 											buttonExit("MainMenu","buttonExit"),
48 											labelVersion("MainMenu","labelVersion"),
49 
50 											mainMessageBox("MainMenu","mainMessageBox"),
51 											errorMessageBox("MainMenu","errorMessageBox"),
52 											ftpMessageBox("MainMenu","ftpMessageBox"),
53 
54 											popupMenu("MainMenu","popupMenu")
55 
56 {
57 	containerName = "MainMenu";
58 
59 	ftpClientThread 		= NULL;
60 	lastDownloadProgress	= 0;
61 
62 	Lang &lang= Lang::getInstance();
63 	int yPos=440;
64 	int buttonWidth = 200;
65 	int buttonXPosition = (1000 - buttonWidth) / 2;
66 
67 
68 	//labelVersion.registerGraphicComponent(containerName,"labelVersion");
69 	if(EndsWith(glestVersionString, "-dev") == false){
70 		labelVersion.init(525, yPos);
71 		labelVersion.setText(glestVersionString);
72 	}
73 	else {
74 		labelVersion.init(buttonXPosition, yPos);
75 		//labelVersion.setText(glestVersionString + " [" + getCompileDateTime() + ", " + getGITRevisionString() + "]");
76 		labelVersion.setText(glestVersionString + " [" + getGITRevisionString() + "]");
77 	}
78 
79 	yPos-=55;
80 	//buttonNewGame.registerGraphicComponent(containerName,"buttonNewGame");
81 	buttonNewGame.init(buttonXPosition, yPos, buttonWidth);
82     yPos-=40;
83     //buttonLoadGame.registerGraphicComponent(containerName,"buttonLoadGame");
84     buttonLoadGame.init(buttonXPosition, yPos, buttonWidth);
85     yPos-=40;
86     //buttonMods.registerGraphicComponent(containerName,"buttonMods");
87     buttonMods.init(buttonXPosition, yPos, buttonWidth);
88     yPos-=40;
89     //buttonOptions.registerGraphicComponent(containerName,"buttonOptions");
90     buttonOptions.init(buttonXPosition, yPos, buttonWidth);
91     yPos-=40;
92     //buttonAbout.registerGraphicComponent(containerName,"buttonAbout");
93     buttonAbout.init(buttonXPosition, yPos , buttonWidth);
94     yPos-=40;
95     //buttonExit.registerGraphicComponent(containerName,"buttonExit");
96     buttonExit.init(buttonXPosition, yPos, buttonWidth);
97 
98 	buttonNewGame.setText(lang.getString("NewGame"));
99 	buttonLoadGame.setText(lang.getString("LoadGame"));
100 	buttonMods.setText(lang.getString("Mods"));
101 	buttonOptions.setText(lang.getString("Options"));
102 	buttonAbout.setText(lang.getString("About"));
103 	buttonExit.setText(lang.getString("Exit"));
104 
105 	//mesage box
106 	//mainMessageBox.registerGraphicComponent(containerName,"mainMessageBox");
107 	mainMessageBox.init(lang.getString("Yes"), lang.getString("No"));
108 	mainMessageBox.setEnabled(false);
109 
110 	//errorMessageBox.registerGraphicComponent(containerName,"errorMessageBox");
111 	errorMessageBox.init(lang.getString("Ok"));
112 	errorMessageBox.setEnabled(false);
113 
114 	//ftpMessageBox.registerGraphicComponent(containerName,"ftpMessageBox");
115 	ftpMessageBox.init(lang.getString("Yes"), lang.getString("No"));
116 	ftpMessageBox.setEnabled(false);
117 
118 	//PopupMenu popupMenu;
119 	std::vector<string> menuItems;
120 	menuItems.push_back("1");
121 	menuItems.push_back("2");
122 	menuItems.push_back("3");
123 	//popupMenu.registerGraphicComponentOnlyFontCallbacks(containerName, "popupMenu");
124 	popupMenu.setW(100);
125 	popupMenu.setH(100);
126 	popupMenu.init("Test Menu",menuItems);
127 	popupMenu.setEnabled(false);
128 	popupMenu.setVisible(false);
129 
130 	GraphicComponent::applyAllCustomProperties(containerName);
131 }
132 
~MenuStateRoot()133 MenuStateRoot::~MenuStateRoot() {
134 	if(updatesHttpServerThread != NULL) {
135 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
136 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
137 
138 		updatesHttpServerThread->setSimpleTaskInterfaceValid(false);
139 		updatesHttpServerThread->signalQuit();
140 		updatesHttpServerThread->setThreadOwnerValid(false);
141 
142 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
143 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
144 		if( updatesHttpServerThread->canShutdown(true) == true &&
145 				updatesHttpServerThread->shutdownAndWait() == true) {
146 			delete updatesHttpServerThread;
147 		}
148 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
149 		updatesHttpServerThread = NULL;
150 	}
151 
152 	if(ftpClientThread != NULL) {
153 		ftpClientThread->setCallBackObject(NULL);
154 		ftpClientThread->signalQuit();
155 		sleep(0);
156 		if(ftpClientThread->canShutdown(true) == true &&
157 				ftpClientThread->shutdownAndWait() == true) {
158 			delete ftpClientThread;
159 		}
160 		else {
161 			char szBuf[8096]="";
162 			snprintf(szBuf,8096,"In [%s::%s %d] Error cannot shutdown ftpClientThread\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
163 			//SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
164 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s",szBuf);
165 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s",szBuf);
166 
167 			//publishToMasterserverThread->cleanup();
168 		}
169 		ftpClientThread = NULL;
170 
171 //		ftpClientThread->signalQuit();
172 //	    ftpClientThread->setCallBackObject(NULL);
173 //	    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
174 //	    if( ftpClientThread->shutdownAndWait() == true) {
175 //	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
176 //            delete ftpClientThread;
177 //	    }
178 //	    ftpClientThread = NULL;
179 //	    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
180 	}
181 
182 }
183 
reloadUI()184 void MenuStateRoot::reloadUI() {
185 	Lang &lang= Lang::getInstance();
186 
187 	console.resetFonts();
188 
189 	if(EndsWith(glestVersionString, "-dev") == false){
190 		labelVersion.setText(glestVersionString);
191 	}
192 	else {
193 		//labelVersion.setText(glestVersionString + " [" + getCompileDateTime() + ", " + getGITRevisionString() + "]");
194 		labelVersion.setText(glestVersionString + " [" + getGITRevisionString() + "]");
195 	}
196 
197 	buttonNewGame.setText(lang.getString("NewGame"));
198 	buttonLoadGame.setText(lang.getString("LoadGame"));
199 	buttonMods.setText(lang.getString("Mods"));
200 	buttonOptions.setText(lang.getString("Options"));
201 	buttonAbout.setText(lang.getString("About"));
202 	buttonExit.setText(lang.getString("Exit"));
203 
204 	mainMessageBox.init(lang.getString("Yes"), lang.getString("No"));
205 	errorMessageBox.init(lang.getString("Ok"));
206 	ftpMessageBox.init(lang.getString("Yes"), lang.getString("No"));
207 
208 	console.resetFonts();
209 
210 	GraphicComponent::reloadFontsForRegisterGraphicComponents(containerName);
211 }
212 
mouseClick(int x,int y,MouseButton mouseButton)213 void MenuStateRoot::mouseClick(int x, int y, MouseButton mouseButton){
214 	try {
215 		CoreData &coreData=  CoreData::getInstance();
216 		SoundRenderer &soundRenderer= SoundRenderer::getInstance();
217 
218 		if(popupMenu.mouseClick(x, y)) {
219 			//std::pair<int,string> result = popupMenu.mouseClickedMenuItem(x, y);
220 			popupMenu.mouseClickedMenuItem(x, y);
221 
222 			//printf("In popup callback menuItemSelected [%s] menuIndexSelected = %d\n",result.second.c_str(),result.first);
223 		}
224 		//exit message box, has to be the last thing to do in this function
225 		else if(mainMessageBox.getEnabled()){
226 			int button= 0;
227 			if(mainMessageBox.mouseClick(x, y, button)) {
228 				if(button==0) {
229 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
230 					soundRenderer.playFx(coreData.getClickSoundA());
231 					program->exit();
232 				}
233 				else {
234 					if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
235 					//close message box
236 					mainMessageBox.setEnabled(false);
237 				}
238 			}
239 		}
240 		//exit message box, has to be the last thing to do in this function
241 		else if(errorMessageBox.getEnabled()){
242 			int button= 0;
243 			if(mainMessageBox.mouseClick(x, y, button)) {
244 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
245 				//close message box
246 				errorMessageBox.setEnabled(false);
247 			}
248 		}
249 
250 		else if(ftpMessageBox.getEnabled()) {
251 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
252 
253 			int button= 0;
254 			if(ftpMessageBox.mouseClick(x, y, button)) {
255 				ftpMessageBox.setEnabled(false);
256 				if(button == 0) {
257 					startFTPClientIfRequired();
258 
259 					lastDownloadProgress = 0;
260 					printf("Adding ftpFileName [%s] ftpFileURL [%s]\n",ftpFileName.c_str(),ftpFileURL.c_str());
261 					if(ftpClientThread != NULL) ftpClientThread->addTempFileToRequests(ftpFileName,ftpFileURL);
262 
263 					static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
264 					MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
265 					if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
266 					fileFTPProgressList[ftpFileName] = pair<int,string>(0,"");
267 					safeMutexFTPProgress.ReleaseLock();
268 				}
269 			}
270 		}
271 		else if(mainMessageBox.getEnabled() == false && buttonNewGame.mouseClick(x, y)){
272 			soundRenderer.playFx(coreData.getClickSoundB());
273 			mainMenu->setState(new MenuStateNewGame(program, mainMenu));
274 		}
275 		else if(mainMessageBox.getEnabled() == false && buttonLoadGame.mouseClick(x, y)){
276 			soundRenderer.playFx(coreData.getClickSoundB());
277 			mainMenu->setState(new MenuStateLoadGame(program, mainMenu));
278 		}
279 		else if(mainMessageBox.getEnabled() == false && buttonMods.mouseClick(x, y)){
280 			soundRenderer.playFx(coreData.getClickSoundB());
281 			mainMenu->setState(new MenuStateMods(program, mainMenu));
282 		}
283 		else if(mainMessageBox.getEnabled() == false && buttonOptions.mouseClick(x, y)){
284 			soundRenderer.playFx(coreData.getClickSoundB());
285 			mainMenu->setState(new MenuStateOptions(program, mainMenu));
286 		}
287 		else if(mainMessageBox.getEnabled() == false && buttonAbout.mouseClick(x, y)){
288 			soundRenderer.playFx(coreData.getClickSoundB());
289 			mainMenu->setState(new MenuStateAbout(program, mainMenu));
290 		}
291 		else if(buttonExit.mouseClick(x, y)){
292 			soundRenderer.playFx(coreData.getClickSoundA());
293 			program->exit();
294 		}
295 	}
296 	catch(exception &e) {
297 		char szBuf[8096]="";
298 		snprintf(szBuf,8096,"In [%s::%s Line: %d]\nError in menu event:\n%s\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what());
299 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
300 		showErrorMessageBox(szBuf, "", true);
301 	}
302 }
303 
startFTPClientIfRequired()304 void MenuStateRoot::startFTPClientIfRequired() {
305 	if(ftpClientThread == NULL) {
306 		// Setup File Transfer thread
307 		Config &config = Config::getInstance();
308 
309 		vector<string> tilesetFiles;
310 		vector<string> tilesetFilesUserData;
311 
312 		vector<string> techTreeFiles;
313 		vector<string> techTreeFilesUserData;
314 
315 
316 		findDirs(config.getPathListForType(ptTilesets), tilesetFiles);
317 		findDirs(config.getPathListForType(ptTechs), techTreeFiles);
318 
319 		vector<string> mapPathList = config.getPathListForType(ptMaps);
320 		std::pair<string,string> mapsPath;
321 		if(mapPathList.empty() == false) {
322 			mapsPath.first = mapPathList[0];
323 		}
324 		if(mapPathList.size() > 1) {
325 			mapsPath.second = mapPathList[1];
326 		}
327 		std::pair<string,string> tilesetsPath;
328 		vector<string> tilesetsList = Config::getInstance().getPathListForType(ptTilesets);
329 		if(tilesetsList.empty() == false) {
330 			tilesetsPath.first = tilesetsList[0];
331 			if(tilesetsList.size() > 1) {
332 				tilesetsPath.second = tilesetsList[1];
333 			}
334 		}
335 
336 		std::pair<string,string> techtreesPath;
337 		vector<string> techtreesList = Config::getInstance().getPathListForType(ptTechs);
338 		if(techtreesList.empty() == false) {
339 			techtreesPath.first = techtreesList[0];
340 			if(techtreesList.size() > 1) {
341 				techtreesPath.second = techtreesList[1];
342 			}
343 		}
344 
345 		std::pair<string,string> scenariosPath;
346 		vector<string> scenariosList = Config::getInstance().getPathListForType(ptScenarios);
347 		if(scenariosList.empty() == false) {
348 			scenariosPath.first = scenariosList[0];
349 			if(scenariosList.size() > 1) {
350 				scenariosPath.second = scenariosList[1];
351 			}
352 		}
353 
354 		string fileArchiveExtension = config.getString("FileArchiveExtension","");
355 		string fileArchiveExtractCommand = config.getString("FileArchiveExtractCommand","");
356 		string fileArchiveExtractCommandParameters = config.getString("FileArchiveExtractCommandParameters","");
357 		int32 fileArchiveExtractCommandSuccessResult = config.getInt("FileArchiveExtractCommandSuccessResult","0");
358 
359 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
360 
361 		console.setOnlyChatMessagesInStoredLines(false);
362 
363 		// Get path to temp files
364 		string tempFilePath = "temp/";
365 		if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
366 			tempFilePath = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + tempFilePath;
367 		}
368 		else {
369 			string userData = config.getString("UserData_Root","");
370 			if(userData != "") {
371 				endPathWithSlash(userData);
372 			}
373 			tempFilePath = userData + tempFilePath;
374 		}
375 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Temp files path [%s]\n",tempFilePath.c_str());
376 
377 		ftpClientThread = new FTPClientThread(-1,"",
378 				mapsPath,tilesetsPath,techtreesPath,scenariosPath,
379 				this,fileArchiveExtension,fileArchiveExtractCommand,
380 				fileArchiveExtractCommandParameters,
381 				fileArchiveExtractCommandSuccessResult,
382 				tempFilePath);
383 		ftpClientThread->start();
384 
385 
386 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
387 	}
388 }
389 
FTPClient_CallbackEvent(string itemName,FTP_Client_CallbackType type,pair<FTP_Client_ResultType,string> result,void * userdata)390 void MenuStateRoot::FTPClient_CallbackEvent(string itemName,
391 		FTP_Client_CallbackType type, pair<FTP_Client_ResultType,string> result,void *userdata) {
392 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
393 
394     Lang &lang= Lang::getInstance();
395     if(type == ftp_cct_DownloadProgress) {
396         FTPClientCallbackInterface::FtpProgressStats *stats = (FTPClientCallbackInterface::FtpProgressStats *)userdata;
397         if(stats != NULL) {
398             int fileProgress = 0;
399             if(stats->download_total > 0) {
400                 fileProgress = ((stats->download_now / stats->download_total) * 100.0);
401             }
402             //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] current file [%s] fileProgress = %d [now = %f, total = %f]\n",itemName.c_str(),stats->currentFilename.c_str(), fileProgress,stats->download_now,stats->download_total);
403 
404             static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
405             MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
406             if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
407             pair<int,string> lastProgress = fileFTPProgressList[itemName];
408             fileFTPProgressList[itemName] = pair<int,string>(fileProgress,stats->currentFilename);
409             safeMutexFTPProgress.ReleaseLock();
410 
411             if(itemName != "" && (lastDownloadProgress < fileProgress && fileProgress % 25 == 0)) {
412             	lastDownloadProgress = fileProgress;
413 
414     			char szBuf[8096]="";
415     			snprintf(szBuf,8096,"Downloaded %d%% of file: %s",fileProgress,itemName.c_str());
416             	console.addLine(szBuf);
417             }
418         }
419     }
420     else if(type == ftp_cct_ExtractProgress) {
421     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP extract Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
422     	printf("Got FTP extract Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
423 
424     	if(userdata == NULL) {
425 			char szBuf[8096]="";
426 			snprintf(szBuf,8096,lang.getString("DataMissingExtractDownloadMod").c_str(),itemName.c_str());
427 			//printf("%s\n",szBuf);
428 			console.addLine(szBuf,true);
429     	}
430     	else {
431 			char *szBuf = (char *)userdata;
432 			//printf("%s\n",szBuf);
433 			console.addLine(szBuf);
434     	}
435     }
436     else if(type == ftp_cct_TempFile) {
437         if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
438 
439         static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
440         MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
441         if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
442         fileFTPProgressList.erase(itemName);
443         safeMutexFTPProgress.ReleaseLock();
444 
445         if(SystemFlags::VERBOSE_MODE_ENABLED) printf("### downloaded TEMP file [%s] result = %d\n",itemName.c_str(),result.first);
446 
447         if(result.first == ftp_crt_SUCCESS) {
448     		// Get path to temp files
449     		string tempFilePath = "temp/";
450     		if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
451     			tempFilePath = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + tempFilePath;
452     		}
453     		else {
454     			Config &config = Config::getInstance();
455     			string userData = config.getString("UserData_Root","");
456     			if(userData != "") {
457     				endPathWithSlash(userData);
458     			}
459     			tempFilePath = userData + tempFilePath;
460     		}
461     		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Temp files path [%s]\n",tempFilePath.c_str());
462 
463     		// Delete the downloaded archive
464     		if(fileExists(tempFilePath + itemName)) {
465     			removeFile(tempFilePath + itemName);
466     		}
467 
468     		bool result = upgradeFilesInTemp();
469     		if(result == false) {
470     			string binaryName = Properties::getApplicationPath() + extractFileFromDirectoryPath(PlatformExceptionHandler::application_binary);
471     			string binaryNameOld = Properties::getApplicationPath() + extractFileFromDirectoryPath(PlatformExceptionHandler::application_binary) + "__REMOVE";
472     			bool resultRename = renameFile(binaryName,binaryNameOld);
473     			//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Rename: [%s] to [%s] result = %d\n",binaryName.c_str(),binaryNameOld.c_str(),resultRename);
474     			printf("#1 Rename: [%s] to [%s] result = %d errno = %d\n",binaryName.c_str(),binaryNameOld.c_str(),resultRename, errno);
475 
476     			//result = upgradeFilesInTemp();
477     			binaryName = Properties::getApplicationPath() + extractFileFromDirectoryPath(PlatformExceptionHandler::application_binary);
478     			binaryNameOld = tempFilePath + extractFileFromDirectoryPath(PlatformExceptionHandler::application_binary);
479     			resultRename = renameFile(binaryNameOld, binaryName);
480 
481     			//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Rename: [%s] to [%s] result = %d\n",binaryName.c_str(),binaryNameOld.c_str(),resultRename);
482     			printf("#2 Rename: [%s] to [%s] result = %d errno = %d\n",binaryNameOld.c_str(),binaryName.c_str(),resultRename, errno);
483     		}
484 
485     		console.addLine("Successfully updated, please restart!",true);
486         }
487         else {
488 			curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW);
489 
490 			char szBuf[8096]="";
491 			snprintf(szBuf,8096,"FAILED to download the updates: [%s] using CURL version [%s] [%s]",itemName.c_str(),curlVersion->version,result.second.c_str());
492 			console.addLine(szBuf,true);
493 			showErrorMessageBox(szBuf, "ERROR", false);
494         }
495     }
496 }
497 
498 
mouseMove(int x,int y,const MouseState * ms)499 void MenuStateRoot::mouseMove(int x, int y, const MouseState *ms){
500 	popupMenu.mouseMove(x, y);
501 	buttonNewGame.mouseMove(x, y);
502 	buttonLoadGame.mouseMove(x, y);
503     buttonMods.mouseMove(x, y);
504     buttonOptions.mouseMove(x, y);
505     buttonAbout.mouseMove(x, y);
506     buttonExit.mouseMove(x,y);
507 	if (mainMessageBox.getEnabled()) {
508 		mainMessageBox.mouseMove(x, y);
509 	}
510 	if (errorMessageBox.getEnabled()) {
511 		errorMessageBox.mouseMove(x, y);
512 	}
513 	if (ftpMessageBox.getEnabled()) {
514 		ftpMessageBox.mouseMove(x, y);
515 	}
516 }
517 
isMasterserverMode() const518 bool MenuStateRoot::isMasterserverMode() const {
519 	return GlobalStaticFlags::getIsNonGraphicalModeEnabled();
520 }
521 
render()522 void MenuStateRoot::render() {
523 	if(isMasterserverMode() == true) {
524 		return;
525 	}
526 	Renderer &renderer= Renderer::getInstance();
527 	CoreData &coreData= CoreData::getInstance();
528 	const Metrics &metrics= Metrics::getInstance();
529 
530 	int w= 400;
531 	int h= 200;
532 	int yPos= 510;
533 
534 	int logoMainX = (metrics.getVirtualW()-w)/2;
535 	int logoMainY = yPos-h/2;
536 	int logoMainW = w;
537 	int logoMainH = h;
538 	logoMainX = Config::getInstance().getInt(string(containerName) + "_MainLogo_x",intToStr(logoMainX).c_str());
539 	logoMainY = Config::getInstance().getInt(string(containerName) + "_MainLogo_y",intToStr(logoMainY).c_str());
540 	logoMainW = Config::getInstance().getInt(string(containerName) + "_MainLogo_w",intToStr(logoMainW).c_str());
541 	logoMainH = Config::getInstance().getInt(string(containerName) + "_MainLogo_h",intToStr(logoMainH).c_str());
542 
543 	renderer.renderTextureQuad(
544 			logoMainX, logoMainY, logoMainW, logoMainH,
545 		coreData.getLogoTexture(), GraphicComponent::getFade());
546 
547 	int maxLogoWidth=0;
548 	for(int idx = 0; idx < (int)coreData.getLogoTextureExtraCount(); ++idx) {
549 		Texture2D *extraLogo = coreData.getLogoTextureExtra(idx);
550 		maxLogoWidth += extraLogo->getPixmap()->getW();
551 	}
552 
553 	int currentX = (metrics.getVirtualW()-maxLogoWidth)/2;
554 	int currentY = 50;
555 	for(int idx = 0; idx < (int)coreData.getLogoTextureExtraCount(); ++idx) {
556 		Texture2D *extraLogo = coreData.getLogoTextureExtra(idx);
557 
558 		logoMainX = currentX;
559 		logoMainY = currentY;
560 		logoMainW = extraLogo->getPixmap()->getW();
561 		logoMainH = extraLogo->getPixmap()->getH();
562 
563 		string logoTagName = string(containerName) + "_ExtraLogo" + intToStr(idx+1) + "_";
564 		logoMainX = Config::getInstance().getInt(logoTagName + "x",intToStr(logoMainX).c_str());
565 		logoMainY = Config::getInstance().getInt(logoTagName + "y",intToStr(logoMainY).c_str());
566 		logoMainW = Config::getInstance().getInt(logoTagName + "w",intToStr(logoMainW).c_str());
567 		logoMainH = Config::getInstance().getInt(logoTagName + "h",intToStr(logoMainH).c_str());
568 
569 		renderer.renderTextureQuad(
570 				logoMainX, logoMainY,
571 				logoMainW, logoMainH,
572 				extraLogo, GraphicComponent::getFade());
573 
574 		currentX += extraLogo->getPixmap()->getW();
575 	}
576 
577 	renderer.renderButton(&buttonNewGame);
578 	renderer.renderButton(&buttonLoadGame);
579 	renderer.renderButton(&buttonMods);
580 	renderer.renderButton(&buttonOptions);
581 	renderer.renderButton(&buttonAbout);
582 	renderer.renderButton(&buttonExit);
583 	renderer.renderLabel(&labelVersion);
584 
585 	renderer.renderConsole(&console);
586 
587 	renderer.renderPopupMenu(&popupMenu);
588 
589 	//exit message box
590 	if(mainMessageBox.getEnabled()) {
591 		renderer.renderMessageBox(&mainMessageBox);
592 	}
593 	if(errorMessageBox.getEnabled()) {
594 		renderer.renderMessageBox(&errorMessageBox);
595 	}
596 	if(ftpMessageBox.getEnabled()) {
597 		renderer.renderMessageBox(&ftpMessageBox);
598 	}
599 
600 	if(program != NULL) program->renderProgramMsgBox();
601 }
602 
update()603 void MenuStateRoot::update() {
604 	if(Config::getInstance().getBool("AutoTest")) {
605 		if(AutoTest::getInstance().mustExitGame() == false) {
606 			AutoTest::getInstance().updateRoot(program, mainMenu);
607 		}
608 		else {
609 			program->exit();
610 		}
611 		return;
612 	}
613 
614 	if(gameUpdateChecked == false) {
615 		gameUpdateChecked = true;
616 
617 		string updateCheckURL = Config::getInstance().getString("UpdateCheckURL","");
618 		if(updateCheckURL != "") {
619 		    static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
620 		    updatesHttpServerThread = new SimpleTaskThread(this,1,200);
621 		    updatesHttpServerThread->setUniqueID(mutexOwnerId);
622 		    updatesHttpServerThread->start();
623 		}
624 	}
625 
626 	console.update();
627 }
628 
simpleTask(BaseThread * callingThread,void * userdata)629 void MenuStateRoot::simpleTask(BaseThread *callingThread,void *userdata) {
630 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
631 
632 	static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
633     MutexSafeWrapper safeMutexThreadOwner(callingThread->getMutexThreadOwnerValid(),mutexOwnerId);
634     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
635     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
636         return;
637     }
638 
639     callingThread->getMutexThreadOwnerValid()->setOwnerId(mutexOwnerId);
640     if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
641 
642 
643 	string updateCheckURL = Config::getInstance().getString("UpdateCheckURL","");
644 	if(updateCheckURL != "") {
645 
646 		string baseURL = updateCheckURL;
647 
648 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] About to call first http url, base [%s]..\n",__FILE__,__FUNCTION__,__LINE__,baseURL.c_str());
649 
650 		CURL *handle = SystemFlags::initHTTP();
651 		CURLcode curlResult = CURLE_OK;
652 		string updateMetaData = SystemFlags::getHTTP(baseURL,handle,-1,&curlResult);
653 
654 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("techsMetaData [%s] curlResult = %d\n",updateMetaData.c_str(),curlResult);
655 
656 		if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
657 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
658 			return;
659 		}
660 
661 		if(curlResult != CURLE_OK) {
662 			string curlError = curl_easy_strerror(curlResult);
663 
664 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] curlError [%s]..\n",__FILE__,__FUNCTION__,__LINE__,curlError.c_str());
665 
666 			char szMsg[8096]="";
667 			snprintf(szMsg,8096,"An error was detected while checking for new updates\n%s",curlError.c_str());
668 			showErrorMessageBox(szMsg, "ERROR", false);
669 		}
670 
671 		if(curlResult == CURLE_OK ||
672 			(curlResult != CURLE_COULDNT_RESOLVE_HOST &&
673 			 curlResult != CURLE_COULDNT_CONNECT)) {
674 
675 			Properties props;
676 			props.loadFromText(updateMetaData);
677 
678 			int compareResult = compareMajorMinorVersion(glestVersionString, props.getString("LatestGameVersion",""));
679 			if(compareResult==0) {
680 				if(glestVersionString != props.getString("LatestGameVersion","")) {
681 					compareResult = -1;
682 				}
683 			}
684 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("compareResult = %d local [%s] remote [%s]\n",compareResult,glestVersionString.c_str(),props.getString("LatestGameVersion","").c_str());
685 
686 			if(compareResult < 0) {
687 
688 				string downloadBinaryKey = "LatestGameBinaryUpdateArchiveURL-" + getPlatformTypeNameString() + getPlatformArchTypeNameString();
689 				if(props.hasString(downloadBinaryKey)) {
690 					ftpFileName = extractFileFromDirectoryPath(props.getString(downloadBinaryKey));
691 					ftpFileURL = props.getString(downloadBinaryKey);
692 				}
693 
694 				if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Checking update key downloadBinaryKey [%s] ftpFileURL [%s]\n",downloadBinaryKey.c_str(),ftpFileURL.c_str());
695 
696 				if(props.getBool("AllowUpdateDownloads","false") == false || ftpFileURL == "") {
697 					char szMsg[8096]="";
698 					snprintf(szMsg,8096,"A new update was detected: %s\nUpdate Date: %s\nPlease visit megaglest.org for details!",
699 							props.getString("LatestGameVersion","?").c_str(),
700 							props.getString("LatestGameVersionReleaseDate","?").c_str());
701 					showFTPMessageBox(szMsg, "Update", false, true);
702 				}
703 				else {
704 					char szMsg[8096]="";
705 					snprintf(szMsg,8096,"A new update was detected: %s\nUpdate Date: %s\nDownload update now?",
706 							props.getString("LatestGameVersion","?").c_str(),
707 							props.getString("LatestGameVersionReleaseDate","?").c_str());
708 					showFTPMessageBox(szMsg, "Update", false, false);
709 				}
710 			}
711 		}
712 		SystemFlags::cleanupHTTP(&handle);
713 	}
714 }
715 
keyDown(SDL_KeyboardEvent key)716 void MenuStateRoot::keyDown(SDL_KeyboardEvent key) {
717 
718 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);
719 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("In [%s::%s Line: %d] key = [%d - %c]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);
720 
721 	//printf("\n\n\nIN MENU STATE ROOT KEYDOWN!!!\n\n\n");
722 
723 	Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
724 	//exit
725 	//if(key == configKeys.getCharKey("ExitKey")) {
726 	//printf("Check Root menu exit key!\n");
727 	if(isKeyPressed(configKeys.getSDLKey("ExitKey"),key) == true) {
728 		Lang &lang= Lang::getInstance();
729 		showMessageBox(lang.getString("ExitGameQuestion"), "", true);
730 	}
731 	//else if(mainMessageBox.getEnabled() == true && key == vkReturn) {
732 	else if(mainMessageBox.getEnabled() == true && isKeyPressed(SDLK_RETURN,key) == true) {
733 		//SDL_keysym keystate = Window::getKeystate();
734 		SDL_keysym keystate = key.keysym;
735 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] keystate.mod [%d]\n",__FILE__,__FUNCTION__,__LINE__,keystate.mod);
736 
737 		//printf("---> keystate.mod [%d]\n",keystate.mod);
738 		if(keystate.mod & (KMOD_LALT | KMOD_RALT)) {
739 		}
740 		else {
741 			//printf("EXITING ---> keystate.mod [%d]\n",keystate.mod);
742 			program->exit();
743 		}
744 	}
745 	//else if(key == configKeys.getCharKey("SaveGUILayout")) {
746 	else if(isKeyPressed(configKeys.getSDLKey("SaveGUILayout"),key) == true) {
747 		GraphicComponent::saveAllCustomProperties(containerName);
748 		//Lang &lang= Lang::getInstance();
749 		//console.addLine(lang.getString("GUILayoutSaved") + " [" + (saved ? lang.getString("Yes") : lang.getString("No"))+ "]");
750 	}
751 
752 }
753 
showMessageBox(const string & text,const string & header,bool toggle)754 void MenuStateRoot::showMessageBox(const string &text, const string &header, bool toggle) {
755 	if(toggle == false) {
756 		mainMessageBox.setEnabled(false);
757 	}
758 
759 	if(mainMessageBox.getEnabled() == false) {
760 		mainMessageBox.setText(text);
761 		mainMessageBox.setHeader(header);
762 		mainMessageBox.setEnabled(true);
763 	}
764 	else {
765 		mainMessageBox.setEnabled(false);
766 	}
767 }
768 
showErrorMessageBox(const string & text,const string & header,bool toggle)769 void MenuStateRoot::showErrorMessageBox(const string &text, const string &header, bool toggle) {
770 	if(toggle == false) {
771 		errorMessageBox.setEnabled(false);
772 	}
773 
774 	if(errorMessageBox.getEnabled() == false) {
775 		errorMessageBox.setText(text);
776 		errorMessageBox.setHeader(header);
777 		errorMessageBox.setEnabled(true);
778 	}
779 	else {
780 		errorMessageBox.setEnabled(false);
781 	}
782 }
783 
showFTPMessageBox(const string & text,const string & header,bool toggle,bool okOnly)784 void MenuStateRoot::showFTPMessageBox(const string &text, const string &header, bool toggle, bool okOnly) {
785 	if(toggle == false) {
786 		ftpMessageBox.setEnabled(false);
787 	}
788 
789 	Lang &lang= Lang::getInstance();
790 	if(okOnly) {
791 		ftpMessageBox.init(lang.getString("Ok"));
792 	}
793 	else {
794 		ftpMessageBox.init(lang.getString("Yes"), lang.getString("No"));
795 	}
796 
797 	if(ftpMessageBox.getEnabled() == false) {
798 		ftpMessageBox.setText(text);
799 		ftpMessageBox.setHeader(header);
800 		ftpMessageBox.setEnabled(true);
801 	}
802 	else {
803 		ftpMessageBox.setEnabled(false);
804 	}
805 }
806 
807 
808 }}//end namespace
809