1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2011 Mark Vejvoda
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_mods.h"
13 
14 #include "renderer.h"
15 #include "sound_renderer.h"
16 #include "core_data.h"
17 #include "config.h"
18 #include "menu_state_root.h"
19 #include "metrics.h"
20 #include "conversion.h"
21 #include <algorithm>
22 #include <curl/curl.h>
23 #include "cache_manager.h"
24 // Need the include below for vc++ 2010 because Microsoft messed up their STL!
25 #include <iterator>
26 #include "leak_dumper.h"
27 
28 
29 namespace Glest{ namespace Game{
30 
31 using namespace ::Shared::Util;
32 
33 struct FormatString {
operator ()Glest::Game::FormatString34 	void operator()(string &s) {
35 		s = formatString(s);
36 	}
37 };
38 
39 
40 
41 // ===============================
42 // 	class ModInfo
43 // ===============================
44 
ModInfo()45 ModInfo::ModInfo() {
46 	name		= "";
47 	url			= "";
48 	imageUrl	= "";
49 	description	= "";
50 	count		= "";
51 	crc			= "";
52 	type 		= mt_None;
53 }
54 
55 
56 
57 // =====================================================
58 // 	class MenuStateConnectedGame
59 // =====================================================
60 
MenuStateMods(Program * program,MainMenu * mainMenu)61 MenuStateMods::MenuStateMods(Program *program, MainMenu *mainMenu) :
62 	MenuState(program, mainMenu, "mods") {
63 
64 	containerName = "Mods";
65 	Lang &lang= Lang::getInstance();
66 	Config &config = Config::getInstance();
67 
68 	modPreviewImage			= NULL;
69 	displayModPreviewImage.clear();
70 
71 	ftpClientThread 		= NULL;
72 	selectedTechName		= "";
73 	selectedTilesetName		= "";
74 	selectedMapName 		= "";
75 	selectedScenarioName	= "";
76 	modInfoSelected         = NULL;
77 	showFullConsole			= false;
78 	keyButtonsLineHeight	= 20;
79 	keyButtonsHeight		= 20;
80 	keyButtonsWidth			= 200;
81 	keyButtonsWidthTech		= keyButtonsWidth;
82 	keyButtonsWidthMap		= keyButtonsWidth + 15;
83 	keyButtonsWidthTil		= keyButtonsWidth - 5;
84 	keyButtonsWidthScen		= keyButtonsWidth + 20;
85 	scrollListsYPos 		= 700;
86 	listBoxLength 			= 200;
87 	keyButtonsYBase			= scrollListsYPos;
88 	keyButtonsToRender		= listBoxLength / keyButtonsLineHeight;
89 	labelWidth				= 5;
90 	keyButtonsXBase			= 0;
91 	modMenuState            = mmst_None;
92 	oldMenuState            = mmst_None;
93 
94 	int installButtonYPos = scrollListsYPos-listBoxLength-20;
95 
96 	int returnLineY = 80;
97 	enableMapPreview = config.getBool("MapPreview","true");
98 	validMapPreview = false;
99     mapPreviewTexture=NULL;
100 
101 	//create
102 	techInfoXPos = 5;
103 	keyTechScrollBarTitle1.registerGraphicComponent(containerName,"keyTechScrollBarTitle1");
104 	keyTechScrollBarTitle1.init(techInfoXPos + 5,scrollListsYPos + 30,labelWidth,20);
105 	keyTechScrollBarTitle1.setText(lang.getString("TechTitle1"));
106 	keyTechScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
107 	keyTechScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
108 	keyTechScrollBarTitle2.registerGraphicComponent(containerName,"keyTechScrollBarTitle2");
109 	keyTechScrollBarTitle2.init(techInfoXPos - 10 + keyButtonsWidthTech,scrollListsYPos + 17,labelWidth,20);
110 	keyTechScrollBarTitle2.setText(lang.getString("TechTitle2"));
111 	keyTechScrollBarTitle2.setFont(CoreData::getInstance().getMenuFontNormal());
112 	keyTechScrollBarTitle2.setFont3D(CoreData::getInstance().getMenuFontNormal3D());
113 
114 	mapInfoXPos = 260;
115 	keyMapScrollBarTitle1.registerGraphicComponent(containerName,"keyMapScrollBarTitle1");
116 	keyMapScrollBarTitle1.init(mapInfoXPos + 5,scrollListsYPos + 30,labelWidth,20);
117 	keyMapScrollBarTitle1.setText(lang.getString("MapTitle1"));
118 	keyMapScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
119 	keyMapScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
120 	keyMapScrollBarTitle2.registerGraphicComponent(containerName,"keyMapScrollBarTitle2");
121 	keyMapScrollBarTitle2.init(mapInfoXPos - 10 + keyButtonsWidthMap,scrollListsYPos + 17,labelWidth,20);
122 	keyMapScrollBarTitle2.setText(lang.getString("MapTitle2"));
123 	keyMapScrollBarTitle2.setFont(CoreData::getInstance().getMenuFontNormal());
124 	keyMapScrollBarTitle2.setFont3D(CoreData::getInstance().getMenuFontNormal3D());
125 
126 	tilesetInfoXPos = 530;
127 	keyTilesetScrollBarTitle1.registerGraphicComponent(containerName,"keyTilesetScrollBarTitle1");
128 	keyTilesetScrollBarTitle1.init(tilesetInfoXPos + 5,scrollListsYPos + 30,labelWidth,20);
129 	keyTilesetScrollBarTitle1.setText(lang.getString("TilesetTitle1"));
130 	keyTilesetScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
131 	keyTilesetScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
132 
133 
134 	scenarioInfoXPos = 755;
135 	keyScenarioScrollBarTitle1.registerGraphicComponent(containerName,"keyScenarioScrollBarTitle1");
136 	keyScenarioScrollBarTitle1.init(scenarioInfoXPos,scrollListsYPos + 30,labelWidth,20);
137 	keyScenarioScrollBarTitle1.setText(lang.getString("ScenarioTitle1"));
138 	keyScenarioScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
139 	keyScenarioScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
140 
141 	mainMessageBoxState = ftpmsg_None;
142     mainMessageBox.registerGraphicComponent(containerName,"mainMessageBox");
143 	mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
144 	mainMessageBox.setEnabled(false);
145 
146 	lineHorizontal.init(0,installButtonYPos-60);
147 	lineVertical.init(500,returnLineY, 5,  installButtonYPos-60-returnLineY);
148 	lineVertical.setHorizontal(false);
149 	lineReturn.init(0, returnLineY);
150 
151 	modDescrLabel.registerGraphicComponent(containerName,"modDescrLabel");
152 	modDescrLabel.init(15,installButtonYPos-60 - 20,450,20);
153 	modDescrLabel.setWordWrap(true);
154 	modDescrLabel.setText("description is empty");
155 
156 	pleaseWaitLabel.registerGraphicComponent(containerName,"pleaseWaitLabel");
157 	pleaseWaitLabel.init(50,installButtonYPos-120,450,20);
158 	pleaseWaitLabel.setText("");
159 	pleaseWaitLabel.setFont(CoreData::getInstance().getMenuFontBig());
160 	pleaseWaitLabel.setFont3D(CoreData::getInstance().getMenuFontBig3D());
161 
162 	buttonReturn.registerGraphicComponent(containerName,"buttonReturn");
163 	buttonReturn.init(800, returnLineY - 30, 125);
164 	buttonReturn.setText(lang.getString("Return"));
165 
166 	lineVerticalReturn.init(buttonReturn.getX() - 10, returnLineY-80, 5, 81);
167 	lineVerticalReturn.setHorizontal(false);
168 
169 	int buttonLineUpY=installButtonYPos+10;
170 	int buttonLineDownY=installButtonYPos-20;
171 
172 	int legendButtonY= buttonLineDownY-30;
173 	buttonInstalled.registerGraphicComponent(containerName,"buttonInstalled");
174 	buttonInstalled.init(5, legendButtonY, 240);
175 	buttonInstalled.setText(" " + lang.getString("ModInstalled"));
176 	buttonInstalled.setUseCustomTexture(true);
177 	buttonInstalled.setCustomTexture(CoreData::getInstance().getOnServerInstalledTexture());
178 	buttonInstalled.setEnabled(false);
179 
180 	buttonAvailable.registerGraphicComponent(containerName,"buttonAvailable");
181 	buttonAvailable.init(255, legendButtonY, 240);
182 	buttonAvailable.setUseCustomTexture(true);
183 	buttonAvailable.setCustomTexture(CoreData::getInstance().getOnServerTexture());
184 	buttonAvailable.setText(" " + lang.getString("ModAvailable"));
185 
186 	buttonOnlyLocal.registerGraphicComponent(containerName,"buttonOnlyLocal");
187 	buttonOnlyLocal.init(505, legendButtonY, 240);
188 	buttonOnlyLocal.setUseCustomTexture(true);
189 	buttonOnlyLocal.setCustomTexture(CoreData::getInstance().getNotOnServerTexture());
190 	buttonOnlyLocal.setText(" " + lang.getString("ModOnlyLocal"));
191 
192 	buttonConflict.registerGraphicComponent(containerName,"buttonConflict");
193 	buttonConflict.init(755, legendButtonY, 240);
194 	buttonConflict.setUseCustomTexture(true);
195 	buttonConflict.setCustomTexture(CoreData::getInstance().getOnServerDifferentTexture());
196 	buttonConflict.setText(" " + lang.getString("ModHasConflict"));
197 
198 
199 	buttonInstallTech.registerGraphicComponent(containerName,"buttonInstallTech");
200 	buttonInstallTech.init(techInfoXPos + 45, buttonLineUpY, 125);
201 	buttonInstallTech.setText(lang.getString("Install"));
202 	buttonRemoveTech.registerGraphicComponent(containerName,"buttonRemoveTech");
203 	buttonRemoveTech.init(techInfoXPos + 45, buttonLineDownY, 125);
204 	buttonRemoveTech.setText(lang.getString("Remove"));
205 
206 	buttonInstallTileset.registerGraphicComponent(containerName,"buttonInstallTileset");
207 	buttonInstallTileset.init(tilesetInfoXPos + 30, buttonLineUpY, 125);
208 	buttonInstallTileset.setText(lang.getString("Install"));
209 	buttonRemoveTileset.registerGraphicComponent(containerName,"buttonRemoveTileset");
210 	buttonRemoveTileset.init(tilesetInfoXPos + 30, buttonLineDownY, 125);
211 	buttonRemoveTileset.setText(lang.getString("Remove"));
212 
213 	buttonInstallMap.registerGraphicComponent(containerName,"buttonInstallMap");
214 	buttonInstallMap.init(mapInfoXPos + 50, buttonLineUpY, 125);
215 	buttonInstallMap.setText(lang.getString("Install"));
216 	buttonRemoveMap.registerGraphicComponent(containerName,"buttonRemoveMap");
217 	buttonRemoveMap.init(mapInfoXPos + 50, buttonLineDownY, 125);
218 	buttonRemoveMap.setText(lang.getString("Remove"));
219 
220 	buttonInstallScenario.registerGraphicComponent(containerName,"buttonInstallScenario");
221 	buttonInstallScenario.init(scenarioInfoXPos + 45, buttonLineUpY, 125);
222 	buttonInstallScenario.setText(lang.getString("Install"));
223 	buttonRemoveScenario.registerGraphicComponent(containerName,"buttonRemoveScenario");
224 	buttonRemoveScenario.init(scenarioInfoXPos + 45, buttonLineDownY, 125);
225 	buttonRemoveScenario.setText(lang.getString("Remove"));
226 
227 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
228 
229 	keyTilesetScrollBar.init(tilesetInfoXPos + keyButtonsWidthTil,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
230 	keyTilesetScrollBar.setLength(listBoxLength);
231 	keyTilesetScrollBar.setElementCount(0);
232 	keyTilesetScrollBar.setVisibleSize(keyButtonsToRender);
233 	keyTilesetScrollBar.setVisibleStart(0);
234 
235 	keyTechScrollBar.init(techInfoXPos + keyButtonsWidthTech + labelWidth + 20,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
236 	keyTechScrollBar.setLength(listBoxLength);
237 	keyTechScrollBar.setElementCount(0);
238 	keyTechScrollBar.setVisibleSize(keyButtonsToRender);
239 	keyTechScrollBar.setVisibleStart(0);
240 
241 	keyMapScrollBar.init(mapInfoXPos + keyButtonsWidthMap + labelWidth + 20,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
242 	keyMapScrollBar.setLength(listBoxLength);
243 	keyMapScrollBar.setElementCount(0);
244 	keyMapScrollBar.setVisibleSize(keyButtonsToRender);
245 	keyMapScrollBar.setVisibleStart(0);
246 
247 	keyScenarioScrollBar.init(scenarioInfoXPos + keyButtonsWidthScen,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
248 	keyScenarioScrollBar.setLength(listBoxLength);
249 	keyScenarioScrollBar.setElementCount(0);
250 	keyScenarioScrollBar.setVisibleSize(keyButtonsToRender);
251 	keyScenarioScrollBar.setVisibleStart(0);
252 
253 	GraphicComponent::applyAllCustomProperties(containerName);
254 
255 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
256 	// Start http meta data thread
257 	static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
258 	modHttpServerThread = new SimpleTaskThread(this,0,200);
259 	modHttpServerThread->setUniqueID(mutexOwnerId);
260 	modHttpServerThread->start();
261 
262 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
263 
264 	// Setup File Transfer thread
265     findDirs(config.getPathListForType(ptTilesets), tilesetFiles);
266     findDirs(config.getPathListForType(ptTechs), techTreeFiles);
267 
268 	vector<string> mapPathList = config.getPathListForType(ptMaps);
269 	std::pair<string,string> mapsPath;
270 	if(mapPathList.empty() == false) {
271 		mapsPath.first = mapPathList[0];
272 	}
273 	if(mapPathList.size() > 1) {
274 		mapsPath.second = mapPathList[1];
275 	}
276 	std::pair<string,string> tilesetsPath;
277 	vector<string> tilesetsList = Config::getInstance().getPathListForType(ptTilesets);
278 	if(tilesetsList.empty() == false) {
279 		tilesetsPath.first = tilesetsList[0];
280 		if(tilesetsList.size() > 1) {
281 			tilesetsPath.second = tilesetsList[1];
282 		}
283 	}
284 
285 	std::pair<string,string> techtreesPath;
286 	vector<string> techtreesList = Config::getInstance().getPathListForType(ptTechs);
287 	if(techtreesList.empty() == false) {
288 		techtreesPath.first = techtreesList[0];
289 		if(techtreesList.size() > 1) {
290 			techtreesPath.second = techtreesList[1];
291 		}
292 	}
293 
294     std::pair<string,string> scenariosPath;
295     vector<string> scenariosList = Config::getInstance().getPathListForType(ptScenarios);
296     if(scenariosList.empty() == false) {
297     	scenariosPath.first = scenariosList[0];
298         if(scenariosList.size() > 1) {
299         	scenariosPath.second = scenariosList[1];
300         }
301     }
302 
303 	string fileArchiveExtension = config.getString("FileArchiveExtension","");
304 	string fileArchiveExtractCommand = config.getString("FileArchiveExtractCommand","");
305 	string fileArchiveExtractCommandParameters = config.getString("FileArchiveExtractCommandParameters","");
306 	int32 fileArchiveExtractCommandSuccessResult = config.getInt("FileArchiveExtractCommandSuccessResult","0");
307 
308 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
309 
310 	console.setOnlyChatMessagesInStoredLines(false);
311 
312 	// Get path to temp files
313 	string tempFilePath = "temp/";
314 	if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
315 		tempFilePath = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + tempFilePath;
316 	}
317 	else {
318         string userData = config.getString("UserData_Root","");
319         if(userData != "") {
320         	endPathWithSlash(userData);
321         }
322         tempFilePath = userData + tempFilePath;
323 	}
324 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Temp files path [%s]\n",tempFilePath.c_str());
325 
326 	ftpClientThread = new FTPClientThread(-1,"",
327 			mapsPath,tilesetsPath,techtreesPath,scenariosPath,
328 			this,fileArchiveExtension,fileArchiveExtractCommand,
329 			fileArchiveExtractCommandParameters,
330 			fileArchiveExtractCommandSuccessResult,
331 			tempFilePath);
332 	ftpClientThread->start();
333 
334 
335 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
336 
337 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
338 }
339 
reloadUI()340 void MenuStateMods::reloadUI() {
341 	Lang &lang= Lang::getInstance();
342 
343 	console.resetFonts();
344 	keyTechScrollBarTitle1.setText(lang.getString("TechTitle1"));
345 	keyTechScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
346 	keyTechScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
347 	keyTechScrollBarTitle2.setText(lang.getString("TechTitle2"));
348 	keyTechScrollBarTitle2.setFont(CoreData::getInstance().getMenuFontNormal());
349 	keyTechScrollBarTitle2.setFont3D(CoreData::getInstance().getMenuFontNormal3D());
350 
351 	keyMapScrollBarTitle1.setText(lang.getString("MapTitle1"));
352 	keyMapScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
353 	keyMapScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
354 	keyMapScrollBarTitle2.setText(lang.getString("MapTitle2"));
355 	keyMapScrollBarTitle2.setFont(CoreData::getInstance().getMenuFontNormal());
356 	keyMapScrollBarTitle2.setFont3D(CoreData::getInstance().getMenuFontNormal3D());
357 
358 	keyTilesetScrollBarTitle1.setText(lang.getString("TilesetTitle1"));
359 	keyTilesetScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
360 	keyTilesetScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
361 
362 	pleaseWaitLabel.setText("");
363 	pleaseWaitLabel.setFont(CoreData::getInstance().getMenuFontBig());
364 	pleaseWaitLabel.setFont3D(CoreData::getInstance().getMenuFontBig3D());
365 
366 	keyScenarioScrollBarTitle1.setText(lang.getString("ScenarioTitle1"));
367 	keyScenarioScrollBarTitle1.setFont(CoreData::getInstance().getMenuFontBig());
368 	keyScenarioScrollBarTitle1.setFont3D(CoreData::getInstance().getMenuFontBig3D());
369 
370 	mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
371 
372 	modDescrLabel.setText("description is empty");
373 
374 	buttonReturn.setText(lang.getString("Return"));
375 
376 	buttonInstalled.setText(lang.getString("ModInstalled"));
377 
378 	buttonAvailable.setText(lang.getString("ModAvailable"));
379 
380 	buttonOnlyLocal.setText(lang.getString("ModOnlyLocal"));
381 
382 	buttonConflict.setText(lang.getString("ModHasConflict"));
383 
384 	buttonInstallTech.setText(lang.getString("Install"));
385 	buttonRemoveTech.setText(lang.getString("Remove"));
386 
387 	buttonInstallTileset.setText(lang.getString("Install"));
388 	buttonRemoveTileset.setText(lang.getString("Remove"));
389 
390 	buttonInstallMap.setText(lang.getString("Install"));
391 	buttonRemoveMap.setText(lang.getString("Remove"));
392 
393 	buttonInstallScenario.setText(lang.getString("Install"));
394 	buttonRemoveScenario.setText(lang.getString("Remove"));
395 
396 	GraphicComponent::reloadFontsForRegisterGraphicComponents(containerName);
397 }
398 
simpleTask(BaseThread * callingThread,void * userdata)399 void MenuStateMods::simpleTask(BaseThread *callingThread,void *userdata) {
400 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
401 
402 	static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
403     MutexSafeWrapper safeMutexThreadOwner(callingThread->getMutexThreadOwnerValid(),mutexOwnerId);
404     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
405     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
406         return;
407     }
408 
409     callingThread->getMutexThreadOwnerValid()->setOwnerId(mutexOwnerId);
410     if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
411 
412     Lang &lang= Lang::getInstance();
413     Config &config = Config::getInstance();
414     string fileArchiveExtractCommand = config.getString("FileArchiveExtractCommand","");
415     int expectedResult = config.getInt("FileArchiveExtractCommandSuccessResult","0");
416 	bool findArchive = executeShellCommand(fileArchiveExtractCommand,expectedResult);
417 	if(findArchive == false) {
418 		mainMessageBoxState = ftpmsg_None;
419 		mainMessageBox.init(lang.getString("Ok"),450);
420 		showMessageBox(lang.getString("ModRequires7z"), lang.getString("Notice"), true);
421 	}
422 
423 	std::string techsMetaData = "";
424 	std::string tilesetsMetaData = "";
425 	std::string mapsMetaData = "";
426 	std::string scenariosMetaData = "";
427 
428 	modMenuState=mmst_Loading;
429 
430 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
431 
432 	if(config.getString("Masterserver","") != "") {
433 		string baseURL = config.getString("Masterserver");
434 		if(baseURL != "") {
435 			endPathWithSlash(baseURL,false);
436 		}
437 
438 		string phpVersionParam = config.getString("phpVersionParam","?version=0.1");
439 		string playerUUID = "&uuid=" + SystemFlags::escapeURL(Config::getInstance().getString("PlayerId",""));
440 		string gameVersion = "&glestVersion=" + SystemFlags::escapeURL(glestVersionString);
441 
442 		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());
443 
444 		CURL *handle = SystemFlags::initHTTP();
445 		CURLcode curlResult = CURLE_OK;
446 		techsMetaData = SystemFlags::getHTTP(baseURL + "showTechsForGlest.php"+phpVersionParam+gameVersion+playerUUID,handle,-1,&curlResult);
447 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("techsMetaData [%s] curlResult = %d\n",techsMetaData.c_str(),curlResult);
448 
449 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
450 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
451 	        return;
452 	    }
453 
454 	    if(curlResult != CURLE_OK) {
455 			string curlError = curl_easy_strerror(curlResult);
456 			char szBuf[8096]="";
457 			snprintf(szBuf,8096,lang.getString("ModErrorGettingServerData").c_str(),curlError.c_str());
458 			console.addLine(string("#1 ") + szBuf,true);
459 	    }
460 
461 		if(curlResult == CURLE_OK ||
462 			(curlResult != CURLE_COULDNT_RESOLVE_HOST &&
463 			 curlResult != CURLE_COULDNT_CONNECT)) {
464 
465 			tilesetsMetaData = SystemFlags::getHTTP(baseURL + "showTilesetsForGlest.php"+phpVersionParam+gameVersion,handle,-1,&curlResult);
466 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("tilesetsMetaData [%s]\n",tilesetsMetaData.c_str());
467 
468 		    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
469 		    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
470 		        return;
471 		    }
472 
473 		    if(curlResult != CURLE_OK) {
474 				string curlError = curl_easy_strerror(curlResult);
475 				char szBuf[8096]="";
476 				snprintf(szBuf,8096,lang.getString("ModErrorGettingServerData").c_str(),curlError.c_str());
477 				console.addLine(string("#2 ") + szBuf,true);
478 		    }
479 
480 			mapsMetaData = SystemFlags::getHTTP(baseURL + "showMapsForGlest.php"+phpVersionParam+gameVersion,handle,-1,&curlResult);
481 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("mapsMetaData [%s]\n",mapsMetaData.c_str());
482 
483 		    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
484 		    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
485 		        return;
486 		    }
487 
488 		    if(curlResult != CURLE_OK) {
489 				string curlError = curl_easy_strerror(curlResult);
490 				char szBuf[8096]="";
491 				snprintf(szBuf,8096,lang.getString("ModErrorGettingServerData").c_str(),curlError.c_str());
492 				console.addLine(string("#3 ") + szBuf,true);
493 		    }
494 
495 			scenariosMetaData = SystemFlags::getHTTP(baseURL + "showScenariosForGlest.php"+phpVersionParam+gameVersion,handle,-1,&curlResult);
496 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("scenariosMetaData [%s]\n",scenariosMetaData.c_str());
497 
498 		    if(curlResult != CURLE_OK) {
499 				string curlError = curl_easy_strerror(curlResult);
500 				char szBuf[8096]="";
501 				snprintf(szBuf,8096,lang.getString("ModErrorGettingServerData").c_str(),curlError.c_str());
502 				console.addLine(string("#4 ") + szBuf,true);
503 		    }
504 		}
505 		SystemFlags::cleanupHTTP(&handle);
506 	}
507 	else {
508         console.addLine(lang.getString("MasterServerMissing"),true);
509 	}
510 
511 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
512 
513     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
514     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
515         return;
516     }
517 
518     if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
519 	tilesetListRemote.clear();
520 	Tokenize(tilesetsMetaData,tilesetListRemote,"\n");
521 
522 	modMenuState=mmst_CalculatingCRC;
523 
524 	getTilesetsLocalList();
525 	for(unsigned int i=0; i < tilesetListRemote.size(); i++) {
526 
527 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
528 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
529 	        return;
530 	    }
531 
532 		string result=refreshTilesetModInfo(tilesetListRemote[i]);
533 		if(result != "") {
534 			ModInfo modinfo;
535 			modinfo=tilesetCacheList[result];
536 			GraphicButton *button=new GraphicButton();
537 			button->init(tilesetInfoXPos, keyButtonsYBase, keyButtonsWidthTil,keyButtonsHeight);
538 			button->setText(modinfo.name);
539 			button->setUseCustomTexture(true);
540 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
541 			keyTilesetButtons.push_back(button);
542 		}
543 	}
544 
545     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
546     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
547         return;
548     }
549 
550 	for(unsigned int i=0; i < tilesetFilesUserData.size(); i++) {
551 
552 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
553 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
554 	        return;
555 	    }
556 
557 		string tilesetName = tilesetFilesUserData[i];
558 		bool alreadyHasTileset = (tilesetCacheList.find(tilesetName) != tilesetCacheList.end());
559 		if(alreadyHasTileset == false) {
560 			GraphicButton *button=new GraphicButton();
561 			button->init(tilesetInfoXPos, keyButtonsYBase, keyButtonsWidthTil,keyButtonsHeight);
562 			button->setText(tilesetName);
563 			button->setUseCustomTexture(true);
564 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
565 			keyTilesetButtons.push_back(button);
566 		}
567 	}
568 
569 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
570 
571     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
572     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
573         return;
574     }
575 
576     if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
577 
578 	techListRemote.clear();
579 	Tokenize(techsMetaData,techListRemote,"\n");
580 
581     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
582     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
583         return;
584     }
585 
586 	getTechsLocalList();
587 	for(unsigned int i=0; i < techListRemote.size(); i++) {
588 
589 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
590 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
591 	        return;
592 	    }
593 
594 		string result=refreshTechModInfo(techListRemote[i]);
595 		if(result != "") {
596 			ModInfo modinfo;
597 			modinfo=techCacheList[result];
598 
599 			GraphicButton *button=new GraphicButton();
600 			button->init(techInfoXPos, keyButtonsYBase, keyButtonsWidthTech,keyButtonsHeight);
601 			button->setText(modinfo.name);
602 			button->setUseCustomTexture(true);
603 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
604 
605 			keyTechButtons.push_back(button);
606 			GraphicLabel *label=new GraphicLabel();
607 			label->init(techInfoXPos + keyButtonsWidthTech+10,keyButtonsYBase,labelWidth,20);
608 			label->setText(modinfo.count);
609 			labelsTech.push_back(label);
610 		}
611 	}
612 
613     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
614     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
615         return;
616     }
617 
618 	for(unsigned int i=0; i < techTreeFilesUserData.size(); i++) {
619 
620 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
621 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
622 	        return;
623 	    }
624 
625 		string techName = techTreeFilesUserData[i];
626 		bool alreadyHasTech = (techCacheList.find(techName) != techCacheList.end());
627 		if(alreadyHasTech == false) {
628 			vector<string> techPaths = config.getPathListForType(ptTechs);
629 	        string &techPath = techPaths[1];
630 	        endPathWithSlash(techPath);
631 	        vector<string> factions;
632 	        findAll(techPath + techName + "/factions/*.", factions, false, false);
633 
634 			GraphicButton *button=new GraphicButton();
635 			button->init(techInfoXPos, keyButtonsYBase, keyButtonsWidthTech,keyButtonsHeight);
636 			button->setText(techName);
637 			button->setUseCustomTexture(true);
638 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
639 			keyTechButtons.push_back(button);
640 
641 			int techFactionCount = (int)factions.size();
642 			GraphicLabel *label=new GraphicLabel();
643 			label->init(techInfoXPos + keyButtonsWidthTech+10,keyButtonsYBase,labelWidth,20);
644 			label->setText(intToStr(techFactionCount));
645 			labelsTech.push_back(label);
646 		}
647 	}
648 
649 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
650 
651     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
652     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
653         return;
654     }
655 
656     if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
657 
658 	mapListRemote.clear();
659 	Tokenize(mapsMetaData,mapListRemote,"\n");
660 
661 	getMapsLocalList();
662 	for(unsigned int i=0; i < mapListRemote.size(); i++) {
663 
664 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
665 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
666 	        return;
667 	    }
668 
669 		string result=refreshMapModInfo(mapListRemote[i]);
670 		if(result != "") {
671 			ModInfo modinfo;
672 			modinfo=mapCacheList[result];
673 
674 			GraphicButton *button=new GraphicButton();
675 			button->init(mapInfoXPos, keyButtonsYBase, keyButtonsWidthMap,keyButtonsHeight);
676 			button->setText(modinfo.name);
677 			button->setUseCustomTexture(true);
678 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
679 			keyMapButtons.push_back(button);
680 
681 			GraphicLabel *label=new GraphicLabel();
682 			label->init(mapInfoXPos + keyButtonsWidthMap + 10,keyButtonsYBase,labelWidth,20);
683 			label->setText(modinfo.count);
684 			labelsMap.push_back(label);
685 		}
686 	}
687 
688     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
689     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
690         return;
691     }
692 
693 	for(unsigned int i=0; i < mapFilesUserData.size(); i++) {
694 
695 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
696 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
697 	        return;
698 	    }
699 
700 		string mapName = mapFilesUserData[i];
701 		bool alreadyHasMap = (mapCacheList.find(mapName) != mapCacheList.end());
702 		if(alreadyHasMap == false) {
703 			vector<string> mapPaths = config.getPathListForType(ptMaps);
704 	        string &mapPath = mapPaths[1];
705 	        endPathWithSlash(mapPath);
706 	        mapPath += mapName;
707 	        MapInfo mapInfo = loadMapInfo(mapPath);
708 
709 			GraphicButton *button=new GraphicButton();
710 			button->init(mapInfoXPos, keyButtonsYBase, keyButtonsWidthMap,keyButtonsHeight);
711 			button->setText(mapName);
712 			button->setUseCustomTexture(true);
713 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
714 			keyMapButtons.push_back(button);
715 
716 			int mapPlayerCount = mapInfo.players;
717 			GraphicLabel *label=new GraphicLabel();
718 			label->init(mapInfoXPos + keyButtonsWidthMap + 10,keyButtonsYBase,labelWidth,20);
719 			label->setText(intToStr(mapPlayerCount));
720 			labelsMap.push_back(label);
721 		}
722 	}
723 
724     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
725     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
726         return;
727     }
728 
729     if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
730     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
731 
732 
733 	scenarioListRemote.clear();
734 	Tokenize(scenariosMetaData,scenarioListRemote,"\n");
735 
736 	getScenariosLocalList();
737 	for(unsigned int i=0; i < scenarioListRemote.size(); i++) {
738 
739 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
740 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
741 	        return;
742 	    }
743 
744 		string result=refreshScenarioModInfo(scenarioListRemote[i]);
745 		if(result != "") {
746 			ModInfo modinfo;
747 			modinfo=scenarioCacheList[result];
748 			GraphicButton *button=new GraphicButton();
749 			button->init(scenarioInfoXPos, keyButtonsYBase, keyButtonsWidthScen,keyButtonsHeight);
750 			button->setText(modinfo.name);
751 			button->setUseCustomTexture(true);
752 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
753 			keyScenarioButtons.push_back(button);
754 		}
755 	}
756 
757     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
758     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
759         return;
760     }
761 
762 	for(unsigned int i=0; i < scenarioFilesUserData.size(); i++) {
763 
764 	    if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
765 	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
766 	        return;
767 	    }
768 
769 		string scenarioName = scenarioFilesUserData[i];
770 		bool alreadyHasScenario = (scenarioCacheList.find(scenarioName) != scenarioCacheList.end());
771 		if(alreadyHasScenario == false) {
772 			vector<string> scenarioPaths = config.getPathListForType(ptScenarios);
773 	        string &scenarioPath = scenarioPaths[1];
774 	        endPathWithSlash(scenarioPath);
775 	        scenarioPath += scenarioName;
776 
777 			GraphicButton *button=new GraphicButton();
778 			button->init(scenarioInfoXPos, keyButtonsYBase, keyButtonsWidthScen,keyButtonsHeight);
779 			button->setText(scenarioName);
780 			button->setUseCustomTexture(true);
781 			button->setCustomTexture(CoreData::getInstance().getCustomTexture());
782 			keyScenarioButtons.push_back(button);
783 		}
784 	}
785 
786     if(callingThread->getQuitStatus() == true || safeMutexThreadOwner.isValidMutex() == false) {
787     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
788         return;
789     }
790 
791     if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
792     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
793 
794 	keyTilesetScrollBar.init(tilesetInfoXPos + keyButtonsWidthTil,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
795 	keyTilesetScrollBar.setLength(listBoxLength);
796 	keyTilesetScrollBar.setElementCount((int)keyTilesetButtons.size());
797 	keyTilesetScrollBar.setVisibleSize(keyButtonsToRender);
798 	keyTilesetScrollBar.setVisibleStart(0);
799 
800 	keyTechScrollBar.init(techInfoXPos + keyButtonsWidthTech + labelWidth + 20,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
801 	keyTechScrollBar.setLength(listBoxLength);
802 	keyTechScrollBar.setElementCount((int)keyTechButtons.size());
803 	keyTechScrollBar.setVisibleSize(keyButtonsToRender);
804 	keyTechScrollBar.setVisibleStart(0);
805 
806 	keyMapScrollBar.init(mapInfoXPos + keyButtonsWidthMap + labelWidth + 20,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
807 	keyMapScrollBar.setLength(listBoxLength);
808 	keyMapScrollBar.setElementCount((int)keyMapButtons.size());
809 	keyMapScrollBar.setVisibleSize(keyButtonsToRender);
810 	keyMapScrollBar.setVisibleStart(0);
811 
812 	keyScenarioScrollBar.init(scenarioInfoXPos + keyButtonsWidthScen,scrollListsYPos-listBoxLength+keyButtonsLineHeight,false,200,20);
813 	keyScenarioScrollBar.setLength(listBoxLength);
814 	keyScenarioScrollBar.setElementCount((int)keyScenarioButtons.size());
815 	keyScenarioScrollBar.setVisibleSize(keyButtonsToRender);
816 	keyScenarioScrollBar.setVisibleStart(0);
817 
818 	modMenuState=mmst_None;
819 
820 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
821 
822 	if(modHttpServerThread != NULL) {
823 		modHttpServerThread->signalQuit();
824 	}
825 
826 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
827 }
828 
loadMapInfo(string file)829 MapInfo MenuStateMods::loadMapInfo(string file) {
830 	try{
831 		Lang &lang= Lang::getInstance();
832 		// Not painting properly so this is on hold
833 		MapPreview::loadMapInfo(file, &mapInfo, lang.getString("MaxPlayers"),lang.getString("Size"),true);
834 	}
835 	catch(exception &e) {
836 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s] loading map [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what(),file.c_str());
837 		throw megaglest_runtime_error("Error loading map file: [" + file + "] msg: " + e.what());
838 	}
839 
840 	return mapInfo;
841 }
842 
getTechsLocalList()843 void MenuStateMods::getTechsLocalList() {
844 	Config &config = Config::getInstance();
845 	vector<string> results;
846 	findDirs(config.getPathListForType(ptTechs), results);
847 	techTreeFiles = results;
848 
849 	techTreeFilesUserData.clear();
850 	if(config.getPathListForType(ptTechs).size() > 1) {
851 		string path = config.getPathListForType(ptTechs)[1];
852 		endPathWithSlash(path);
853 		findDirs(path, techTreeFilesUserData, false, false);
854 	}
855 }
856 
refreshTechModInfo(string techInfo)857 string MenuStateMods::refreshTechModInfo(string techInfo) {
858 	std::vector<std::string> techInfoList;
859 	Tokenize(techInfo,techInfoList,"|");
860 	if(techInfoList.size() >= 6) {
861 		Config &config = Config::getInstance();
862 		ModInfo modinfo;
863 		modinfo.name = techInfoList[0];
864 		modinfo.count = techInfoList[1];
865 		modinfo.crc = techInfoList[2];
866 		modinfo.description = techInfoList[3];
867 		modinfo.url = techInfoList[4];
868 		modinfo.imageUrl = techInfoList[5];
869 		modinfo.type = mt_Techtree;
870 
871 		string itemPath = config.getPathListForType(ptTechs,"")[1] + "/" + modinfo.name + string("/*");
872 		if(itemPath.empty() == false) {
873 		   bool forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
874 		   uint32 crc = getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh);
875 		   if(crc == 0) {
876 				itemPath = config.getPathListForType(ptTechs,"")[0] + "/" + modinfo.name + string("/*");
877 				if(itemPath.empty() == false) {
878 				   forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
879 				   crc = getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh);
880 				}
881 		   }
882 		   modinfo.localCRC=uIntToStr(crc);
883 		   //printf("itemPath='%s' remote crc:'%s'  local crc:'%s'   crc='%d' \n",itemPath.c_str(),modinfo.crc.c_str(),modinfo.localCRC.c_str(),crc);
884 		}
885 		else {
886 			modinfo.localCRC="";
887 		}
888 		techCacheList[modinfo.name] = modinfo;
889 		return modinfo.name;
890 	}
891 	return "";
892 }
893 
refreshTechs()894 void MenuStateMods::refreshTechs() {
895 	getTechsLocalList();
896 	for(int i=0; i < (int)techListRemote.size(); i++) {
897 		refreshTechModInfo(techListRemote[i]);
898 	}
899 }
900 
getTilesetsLocalList()901 void MenuStateMods::getTilesetsLocalList() {
902 	Config &config = Config::getInstance();
903 	vector<string> results;
904 	findDirs(config.getPathListForType(ptTilesets), results);
905 	tilesetFiles = results;
906 
907 	tilesetFilesUserData.clear();
908 	if(config.getPathListForType(ptTilesets).size() > 1) {
909 		string path = config.getPathListForType(ptTilesets)[1];
910 		endPathWithSlash(path);
911 		findDirs(path, tilesetFilesUserData, false, false);
912 	}
913 }
914 
refreshTilesetModInfo(string tilesetInfo)915 string MenuStateMods::refreshTilesetModInfo(string tilesetInfo) {
916 	std::vector<std::string> tilesetInfoList;
917 	Tokenize(tilesetInfo,tilesetInfoList,"|");
918 	if(tilesetInfoList.size() >= 5) {
919 		Config &config = Config::getInstance();
920 		ModInfo modinfo;
921 		modinfo.name = tilesetInfoList[0];
922 		modinfo.crc = tilesetInfoList[1];
923 		modinfo.description = tilesetInfoList[2];
924 		modinfo.url = tilesetInfoList[3];
925 		modinfo.imageUrl = tilesetInfoList[4];
926 		modinfo.type = mt_Tileset;
927 
928 		string itemPath = config.getPathListForType(ptTilesets,"")[1] + "/" + modinfo.name + string("/*");
929 		if(itemPath.empty() == false) {
930 		   bool forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
931 		   uint32 crc = getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh);
932 		   if(crc == 0) {
933 				itemPath = config.getPathListForType(ptTilesets,"")[0] + "/" + modinfo.name + string("/*");
934 				if(itemPath.empty() == false) {
935 				   forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
936 				   crc=getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh);
937 				}
938 		   }
939 		   modinfo.localCRC=uIntToStr(crc);
940 		   //printf("itemPath='%s' remote crc:'%s'  local crc:'%s'   crc='%d' \n",itemPath.c_str(),modinfo.crc.c_str(),modinfo.localCRC.c_str(),crc);
941 
942 		   //printf("#1 refreshTilesetModInfo name [%s] modInfo.crc [%s] modInfo.localCRC [%s]\n",modinfo.name.c_str(),modinfo.crc.c_str(),modinfo.localCRC.c_str());
943 		}
944 		else {
945 			modinfo.localCRC="";
946 
947 			//printf("#2 refreshTilesetModInfo name [%s] modInfo.crc [%s] modInfo.localCRC [%s]\n",modinfo.name.c_str(),modinfo.crc.c_str(),modinfo.localCRC.c_str());
948 		}
949 
950 		tilesetCacheList[modinfo.name] = modinfo;
951 		return modinfo.name;
952 	}
953 	return "";
954 }
955 
refreshTilesets()956 void MenuStateMods::refreshTilesets() {
957 	getTilesetsLocalList();
958 	for(int i=0; i < (int)tilesetListRemote.size(); i++) {
959 		refreshTilesetModInfo(tilesetListRemote[i]);
960 	}
961 }
962 
getMapsLocalList()963 void MenuStateMods::getMapsLocalList() {
964 
965 /*
966 	Config &config = Config::getInstance();
967 	vector<string> results;
968 	set<string> allMaps;
969     findAll(config.getPathListForType(ptMaps), "*.gbm", results, false, false);
970 	copy(results.begin(), results.end(), std::inserter(allMaps, allMaps.begin()));
971 	results.clear();
972     findAll(config.getPathListForType(ptMaps), "*.mgm", results, false, false);
973 	copy(results.begin(), results.end(), std::inserter(allMaps, allMaps.begin()));
974 	results.clear();
975 
976 	copy(allMaps.begin(), allMaps.end(), std::back_inserter(results));
977 	mapFiles = results;
978 
979 	mapFilesUserData.clear();
980 	if(config.getPathListForType(ptMaps).size() > 1) {
981 		string path = config.getPathListForType(ptMaps)[1];
982 		endPathWithSlash(path);
983 
984 		vector<string> results2;
985 		set<string> allMaps2;
986 	    findAll(path + "*.gbm", results2, false, false);
987 		copy(results2.begin(), results2.end(), std::inserter(allMaps2, allMaps2.begin()));
988 
989 		results2.clear();
990 	    findAll(path + "*.mgm", results2, false, false);
991 		copy(results2.begin(), results2.end(), std::inserter(allMaps2, allMaps2.begin()));
992 
993 		results2.clear();
994 		copy(allMaps2.begin(), allMaps2.end(), std::back_inserter(results2));
995 		mapFilesUserData = results2;
996 		//printf("\n\nMap path [%s] mapFilesUserData.size() = %d\n\n\n",path.c_str(),mapFilesUserData.size());
997 	}
998 */
999 
1000 	Config &config = Config::getInstance();
1001   	string scenarioDir = "";
1002   	vector<string> pathList = config.getPathListForType(ptMaps,scenarioDir);
1003   	vector<string> invalidMapList;
1004   	vector<string> allMaps = MapPreview::findAllValidMaps(pathList,scenarioDir,false,false,&invalidMapList);
1005 	if (allMaps.empty()) {
1006         throw megaglest_runtime_error("No maps were found!");
1007 	}
1008 	vector<string> results;
1009 	copy(allMaps.begin(), allMaps.end(), std::back_inserter(results));
1010 	mapFiles = results;
1011 
1012 	mapFilesUserData = MapPreview::findAllValidMaps(pathList,scenarioDir,true,false,&invalidMapList);
1013 }
1014 
refreshMapModInfo(string mapInfo)1015 string MenuStateMods::refreshMapModInfo(string mapInfo) {
1016 	std::vector<std::string> mapInfoList;
1017 	Tokenize(mapInfo,mapInfoList,"|");
1018 	if(mapInfoList.size() >= 6) {
1019 		//Config &config = Config::getInstance();
1020 		ModInfo modinfo;
1021 		modinfo.name = mapInfoList[0];
1022 		modinfo.count = mapInfoList[1];
1023 		modinfo.crc = mapInfoList[2];
1024 		modinfo.description = mapInfoList[3];
1025 		modinfo.url = mapInfoList[4];
1026 		modinfo.imageUrl = mapInfoList[5];
1027 		modinfo.type = mt_Map;
1028 		modinfo.localCRC=getMapCRC(modinfo.name);
1029 		mapCacheList[modinfo.name] = modinfo;
1030 		return modinfo.name;
1031 	}
1032 	return "";
1033 }
1034 
getMapCRC(string mapName)1035 string MenuStateMods::getMapCRC(string mapName) {
1036 	Config &config = Config::getInstance();
1037 	vector<string> mappaths=config.getPathListForType(ptMaps,"");
1038 	string result="";
1039 	if(mappaths.empty() == false) {
1040 		Checksum checksum;
1041 		string itemPath = mappaths[1] + "/" + mapName;
1042 		if (fileExists(itemPath)){
1043 			checksum.addFile(itemPath);
1044 			uint32 crc=checksum.getSum();
1045 			result=uIntToStr(crc);
1046 			//printf("itemPath='%s' modinfo.name='%s' remote crc:'%s'  local crc:'%s'   crc='%d' \n",itemPath.c_str(),modinfo.name.c_str(),modinfo.crc.c_str(),modinfo.localCRC.c_str(),crc);
1047 		}
1048 		else {
1049 			itemPath = mappaths[0] + "/" + mapName;
1050 			if (fileExists(itemPath)){
1051 				checksum.addFile(itemPath);
1052 				uint32 crc=checksum.getSum();
1053 				result=uIntToStr(crc);
1054 				//printf("itemPath='%s' modinfo.name='%s' remote crc:'%s'  local crc:'%s'   crc='%d' \n",itemPath.c_str(),modinfo.name.c_str(),modinfo.crc.c_str(),modinfo.localCRC.c_str(),crc);
1055 			}
1056 			else {
1057 				result="";
1058 			}
1059 		}
1060 	}
1061 	else {
1062 		result="";
1063 	}
1064 	return result;
1065 }
1066 
refreshMaps()1067 void MenuStateMods::refreshMaps() {
1068 	getMapsLocalList();
1069 	for(int i=0; i < (int)mapListRemote.size(); i++) {
1070 		refreshMapModInfo(mapListRemote[i]);
1071 	}
1072 }
1073 
getScenariosLocalList()1074 void MenuStateMods::getScenariosLocalList() {
1075 	Config &config = Config::getInstance();
1076 	vector<string> results;
1077 	findDirs(config.getPathListForType(ptScenarios), results);
1078 	scenarioFiles = results;
1079 
1080 	scenarioFilesUserData.clear();
1081 	if(config.getPathListForType(ptScenarios).size() > 1) {
1082 		string path = config.getPathListForType(ptScenarios)[1];
1083 		endPathWithSlash(path);
1084 		findDirs(path, scenarioFilesUserData, false, false);
1085 	}
1086 }
1087 
refreshScenarioModInfo(string scenarioInfo)1088 string MenuStateMods::refreshScenarioModInfo(string scenarioInfo) {
1089 	std::vector<std::string> scenarioInfoList;
1090 	Tokenize(scenarioInfo,scenarioInfoList,"|");
1091 	if(scenarioInfoList.size() >= 5) {
1092 		Config &config = Config::getInstance();
1093 		ModInfo modinfo;
1094 		modinfo.name = scenarioInfoList[0];
1095 		modinfo.crc = scenarioInfoList[1];
1096 		modinfo.description = scenarioInfoList[2];
1097 		modinfo.url = scenarioInfoList[3];
1098 		modinfo.imageUrl = scenarioInfoList[4];
1099 		modinfo.type = mt_Scenario;
1100 
1101 		string itemPath = config.getPathListForType(ptScenarios,"")[1] + "/" + modinfo.name + string("/*");
1102 		if(itemPath.empty() == false) {
1103 		   bool forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
1104 		   uint32 crc = getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh);
1105 		   if(crc == 0) {
1106 				itemPath = config.getPathListForType(ptScenarios,"")[0] + "/" + modinfo.name + string("/*");
1107 				if(itemPath.empty() == false) {
1108 				   forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
1109 				   crc = getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh);
1110 				}
1111 		   }
1112 		   modinfo.localCRC=uIntToStr(crc);
1113 		   //printf(" itemPath='%s' remote crc:'%s'  local crc:'%s'   crc='%d' \n",itemPath.c_str(),modinfo.crc.c_str(),modinfo.localCRC.c_str(),crc);
1114 		}
1115 		else {
1116 			modinfo.localCRC="";
1117 		}
1118 		scenarioCacheList[modinfo.name] = modinfo;
1119 		return modinfo.name;
1120 	}
1121 	return "";
1122 }
1123 
refreshScenarios()1124 void MenuStateMods::refreshScenarios() {
1125 	getScenariosLocalList();
1126 	for(int i=0; i < (int)scenarioListRemote.size(); i++) {
1127 		refreshScenarioModInfo(scenarioListRemote[i]);
1128 	}
1129 }
1130 
1131 
cleanUp()1132 void MenuStateMods::cleanUp() {
1133 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1134 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1135 	if(modHttpServerThread != NULL) {
1136 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1137 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1138 		modHttpServerThread->signalQuit();
1139 		//modHttpServerThread->setThreadOwnerValid(false);
1140 
1141 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1142 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1143 		if( modHttpServerThread->canShutdown(true) == true &&
1144 			modHttpServerThread->shutdownAndWait() == true) {
1145 			delete modHttpServerThread;
1146 		}
1147 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1148 		modHttpServerThread = NULL;
1149 	}
1150 
1151 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1152 
1153 	if(ftpClientThread != NULL) {
1154 		ftpClientThread->setCallBackObject(NULL);
1155 		ftpClientThread->signalQuit();
1156 		sleep(0);
1157 		if(ftpClientThread->canShutdown(true) == true &&
1158 				ftpClientThread->shutdownAndWait() == true) {
1159 			delete ftpClientThread;
1160 		}
1161 		else {
1162 			char szBuf[8096]="";
1163 			snprintf(szBuf,8096,"In [%s::%s %d] Error cannot shutdown ftpClientThread\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1164 			//SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
1165 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s",szBuf);
1166 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s",szBuf);
1167 
1168 			//publishToMasterserverThread->cleanup();
1169 		}
1170 		ftpClientThread = NULL;
1171 
1172 //		ftpClientThread->signalQuit();
1173 //	    ftpClientThread->setCallBackObject(NULL);
1174 //	    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1175 //	    if( ftpClientThread->shutdownAndWait() == true) {
1176 //	    	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1177 //            delete ftpClientThread;
1178 //	    }
1179 //	    ftpClientThread = NULL;
1180 //	    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1181 	}
1182 
1183 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1184 
1185 	clearUserButtons();
1186 
1187 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1188 	cleanupPreviewTexture();
1189 	cleanupMapPreviewTexture();
1190 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1191 }
1192 
~MenuStateMods()1193 MenuStateMods::~MenuStateMods() {
1194 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1195 
1196 	cleanUp();
1197 
1198 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1199 }
1200 
clearUserButtons()1201 void MenuStateMods::clearUserButtons() {
1202 	// Techs
1203 	while(!keyTechButtons.empty()) {
1204 		delete keyTechButtons.back();
1205 		keyTechButtons.pop_back();
1206 	}
1207 	keyTechScrollBar.setElementCount(0);
1208 
1209 	while(!labelsTech.empty()) {
1210 		delete labelsTech.back();
1211 		labelsTech.pop_back();
1212 	}
1213 
1214 	// Tilesets
1215 	while(!keyTilesetButtons.empty()) {
1216 		delete keyTilesetButtons.back();
1217 		keyTilesetButtons.pop_back();
1218 	}
1219 	keyTilesetScrollBar.setElementCount(0);
1220 
1221 	// Maps
1222 	while(!keyMapButtons.empty()) {
1223 		delete keyMapButtons.back();
1224 		keyMapButtons.pop_back();
1225 	}
1226 	while(!labelsMap.empty()) {
1227 		delete labelsMap.back();
1228 		labelsMap.pop_back();
1229 	}
1230 	keyMapScrollBar.setElementCount(0);
1231 
1232 	// Scenarios
1233 	while(!keyScenarioButtons.empty()) {
1234 		delete keyScenarioButtons.back();
1235 		keyScenarioButtons.pop_back();
1236 	}
1237 	keyScenarioScrollBar.setElementCount(0);
1238 }
1239 
mouseClick(int x,int y,MouseButton mouseButton)1240 void MenuStateMods::mouseClick(int x, int y, MouseButton mouseButton) {
1241 
1242 	CoreData &coreData= CoreData::getInstance();
1243 	SoundRenderer &soundRenderer= SoundRenderer::getInstance();
1244 	Lang &lang= Lang::getInstance();
1245 
1246 	if(buttonReturn.mouseClick(x,y)) {
1247 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1248 
1249 		soundRenderer.playFx(coreData.getClickSoundA());
1250 
1251 		if(fileFTPProgressList.empty() == false) {
1252 			mainMessageBoxState = ftpmsg_Quit;
1253 			mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
1254 			char szBuf[8096]="";
1255 			snprintf(szBuf,8096,lang.getString("ModDownloadInProgressCancelQuestion").c_str(),fileFTPProgressList.size());
1256 			showMessageBox(szBuf, lang.getString("Question"), true);
1257 		}
1258 		else {
1259 			cleanUp();
1260 			mainMenu->setState(new MenuStateRoot(program, mainMenu));
1261 			return;
1262 		}
1263     }
1264 	else if(mainMessageBox.getEnabled()) {
1265 		int button= 0;
1266 		if(mainMessageBox.mouseClick(x, y, button)) {
1267 			soundRenderer.playFx(coreData.getClickSoundA());
1268 			mainMessageBox.setEnabled(false);
1269 			mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
1270 			if(button == 0) {
1271 			    if(mainMessageBoxState == ftpmsg_Quit) {
1272 			    	mainMessageBoxState = ftpmsg_None;
1273 					mainMenu->setState(new MenuStateRoot(program, mainMenu));
1274 					return;
1275 			    }
1276 			    else if(mainMessageBoxState == ftpmsg_GetMap ||
1277 			    		mainMessageBoxState == ftpmsg_ReplaceMap) {
1278 			    	bool getItemAfterRemoval = (mainMessageBoxState == ftpmsg_ReplaceMap);
1279 			    	mainMessageBoxState = ftpmsg_None;
1280 
1281 			    	Config &config = Config::getInstance();
1282 			    	vector<string> mapPaths = config.getPathListForType(ptMaps);
1283 			    	if(mapPaths.size() > 1) {
1284 			    		string removeMap = mapPaths[1];
1285 			    		endPathWithSlash(removeMap);
1286 			    		removeMap += selectedMapName;
1287 
1288 			    		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Removing Map [%s]\n",removeMap.c_str());
1289 			    		removeFile(removeMap);
1290 
1291 			    		bool remoteHasMap = (mapCacheList.find(selectedMapName) != mapCacheList.end());
1292 			    		if(remoteHasMap == false) {
1293 							for(unsigned int i = 0; i < keyMapButtons.size(); ++i) {
1294 								GraphicButton *button = keyMapButtons[i];
1295 								if(button != NULL && button->getText() == selectedMapName) {
1296 									delete button;
1297 									keyMapButtons.erase(keyMapButtons.begin() + i);
1298 									labelsMap.erase(labelsMap.begin() + i);
1299 									keyMapScrollBar.setElementCount((int)keyMapButtons.size());
1300 									break;
1301 								}
1302 							}
1303 			    		}
1304 
1305 			    		if(getItemAfterRemoval == false) {
1306 			    			selectedMapName = "";
1307 			    		}
1308 			    		refreshMaps();
1309 			    		Checksum::clearFileCache();
1310 
1311 				    	if(getItemAfterRemoval == true) {
1312 							string mapName = selectedMapName;
1313 							string mapURL = mapCacheList[mapName].url;
1314 							if(ftpClientThread != NULL) ftpClientThread->addMapToRequests(mapName,mapURL);
1315 							static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1316 							MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1317 							if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1318 							fileFTPProgressList[mapName] = pair<int,string>(0,"");
1319 							safeMutexFTPProgress.ReleaseLock();
1320 							buttonInstallMap.setEnabled(false);
1321 				    	}
1322 			    	}
1323 			    }
1324 			    else if(mainMessageBoxState == ftpmsg_GetTileset ||
1325 			    		mainMessageBoxState == ftpmsg_ReplaceTileset) {
1326 			    	bool getItemAfterRemoval = (mainMessageBoxState == ftpmsg_ReplaceTileset);
1327 			    	mainMessageBoxState = ftpmsg_None;
1328 
1329 			    	Config &config = Config::getInstance();
1330 			    	vector<string> tilesetPaths = config.getPathListForType(ptTilesets);
1331 			    	if(tilesetPaths.size() > 1) {
1332 			    		string removeTileset = tilesetPaths[1];
1333 			    		endPathWithSlash(removeTileset);
1334 			    		removeTileset += selectedTilesetName;
1335 
1336 			    		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Removing Tileset [%s]\n",removeTileset.c_str());
1337 			    		removeFolder(removeTileset);
1338 
1339 			    		bool remoteHasTileset = (tilesetCacheList.find(selectedTilesetName) != tilesetCacheList.end());
1340 			    		if(remoteHasTileset == false) {
1341 			    			//printf("\n\n\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ remote DOES NOT have removed tileset [%s]\n\n\n",selectedTilesetName.c_str());
1342 
1343 							for(unsigned int i = 0; i < keyTilesetButtons.size(); ++i) {
1344 								GraphicButton *button = keyTilesetButtons[i];
1345 								if(button != NULL && button->getText() == selectedTilesetName) {
1346 									delete button;
1347 									keyTilesetButtons.erase(keyTilesetButtons.begin() + i);
1348 									keyTilesetScrollBar.setElementCount((int)keyTilesetButtons.size());
1349 									break;
1350 								}
1351 							}
1352 			    		}
1353 			    		static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1354 			    		MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1355 			    		if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1356 			            Checksum::clearFileCache();
1357 			            vector<string> paths        = Config::getInstance().getPathListForType(ptTilesets);
1358 			            string pathSearchString     = string("/") + selectedTilesetName + string("/*");
1359 			            const string filterFileExt  = ".xml";
1360 			            clearFolderTreeContentsCheckSum(paths, pathSearchString, filterFileExt);
1361 			            clearFolderTreeContentsCheckSumList(paths, pathSearchString, filterFileExt);
1362 			            safeMutexFTPProgress.ReleaseLock();
1363 
1364 			            if(getItemAfterRemoval == false) {
1365 			            	selectedTilesetName = "";
1366 			            }
1367 			    		refreshTilesets();
1368 			    	}
1369 
1370 			    	if(getItemAfterRemoval == true) {
1371 						string tilesetName = selectedTilesetName;
1372 						string tilesetURL = tilesetCacheList[tilesetName].url;
1373 						if(ftpClientThread != NULL) ftpClientThread->addTilesetToRequests(tilesetName,tilesetURL);
1374 
1375 						static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1376 						MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1377 						if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1378 						fileFTPProgressList[tilesetName] = pair<int,string>(0,"");
1379 						safeMutexFTPProgress.ReleaseLock();
1380 						buttonInstallTileset.setEnabled(false);
1381 			    	}
1382 			    }
1383 			    else if(mainMessageBoxState == ftpmsg_GetTechtree ||
1384 			    		mainMessageBoxState == ftpmsg_ReplaceTechtree) {
1385 			    	bool getItemAfterRemoval = (mainMessageBoxState == ftpmsg_ReplaceTechtree);
1386 			    	mainMessageBoxState = ftpmsg_None;
1387 
1388 			    	Config &config = Config::getInstance();
1389 			    	vector<string> techPaths = config.getPathListForType(ptTechs);
1390 			    	if(techPaths.size() > 1) {
1391 			    		string removeTech = techPaths[1];
1392 			    		endPathWithSlash(removeTech);
1393 			    		removeTech+= selectedTechName;
1394 
1395 			    		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Removing Techtree [%s]\n",removeTech.c_str());
1396 			    		removeFolder(removeTech);
1397 
1398 			    		bool remoteHasTech = (techCacheList.find(selectedTechName) != techCacheList.end());
1399 			    		if(remoteHasTech == false) {
1400 							for(unsigned int i = 0; i < keyTechButtons.size(); ++i) {
1401 								GraphicButton *button = keyTechButtons[i];
1402 								if(button != NULL && button->getText() == selectedTechName) {
1403 									delete button;
1404 									keyTechButtons.erase(keyTechButtons.begin() + i);
1405 									labelsTech.erase(labelsTech.begin() + i);
1406 									keyTechScrollBar.setElementCount((int)keyTechButtons.size());
1407 									break;
1408 								}
1409 							}
1410 			    		}
1411 
1412 			    		static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1413 			    		MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1414 			    		if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1415 			            // Clear the CRC file Cache
1416 			            Checksum::clearFileCache();
1417 			            vector<string> paths        = Config::getInstance().getPathListForType(ptTechs);
1418 			            string pathSearchString     = string("/") + selectedTechName + string("/*");
1419 			            const string filterFileExt  = ".xml";
1420 			            clearFolderTreeContentsCheckSum(paths, pathSearchString, filterFileExt);
1421 			            clearFolderTreeContentsCheckSumList(paths, pathSearchString, filterFileExt);
1422 			            safeMutexFTPProgress.ReleaseLock();
1423 
1424 			            if(getItemAfterRemoval == false) {
1425 			            	selectedTechName = "";
1426 			            }
1427 			    		refreshTechs();
1428 			    	}
1429 
1430 			    	if(getItemAfterRemoval == true) {
1431 						string techName = selectedTechName;
1432 						string techURL = techCacheList[techName].url;
1433 						if(ftpClientThread != NULL) ftpClientThread->addTechtreeToRequests(techName,techURL);
1434 
1435 						static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1436 						MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1437 						if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1438 						fileFTPProgressList[techName] = pair<int,string>(0,"");
1439 						safeMutexFTPProgress.ReleaseLock();
1440 						buttonInstallTech.setEnabled(false);
1441 			    	}
1442 			    }
1443 			    else if(mainMessageBoxState == ftpmsg_GetScenario ||
1444 			    		mainMessageBoxState == ftpmsg_ReplaceScenario) {
1445 			    	bool getItemAfterRemoval = (mainMessageBoxState == ftpmsg_ReplaceScenario);
1446 			    	mainMessageBoxState = ftpmsg_None;
1447 
1448 			    	Config &config = Config::getInstance();
1449 			    	vector<string> scenarioPaths = config.getPathListForType(ptScenarios);
1450 			    	if(scenarioPaths.size() > 1) {
1451 			    		string removeScenario = scenarioPaths[1];
1452 			    		endPathWithSlash(removeScenario);
1453 			    		removeScenario += selectedScenarioName;
1454 
1455 			    		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Removing Scenario [%s]\n",removeScenario.c_str());
1456 			    		removeFolder(removeScenario);
1457 
1458 			    		bool remoteHasScenario = (scenarioCacheList.find(selectedScenarioName) != scenarioCacheList.end());
1459 			    		if(remoteHasScenario == false) {
1460 							for(unsigned int i = 0; i < keyScenarioButtons.size(); ++i) {
1461 								GraphicButton *button = keyScenarioButtons[i];
1462 								if(button != NULL && button->getText() == selectedScenarioName) {
1463 									delete button;
1464 									keyScenarioButtons.erase(keyScenarioButtons.begin() + i);
1465 									keyScenarioScrollBar.setElementCount((int)keyScenarioButtons.size());
1466 									break;
1467 								}
1468 							}
1469 			    		}
1470 
1471 			    		static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1472 			    		MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1473 			    		if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1474 			            Checksum::clearFileCache();
1475 			            vector<string> paths        = Config::getInstance().getPathListForType(ptScenarios);
1476 			            string pathSearchString     = string("/") + selectedScenarioName + string("/*");
1477 			            const string filterFileExt  = ".xml";
1478 			            clearFolderTreeContentsCheckSum(paths, pathSearchString, filterFileExt);
1479 			            clearFolderTreeContentsCheckSumList(paths, pathSearchString, filterFileExt);
1480 			            safeMutexFTPProgress.ReleaseLock();
1481 
1482 			            if(getItemAfterRemoval == false) {
1483 			            	selectedScenarioName = "";
1484 			            }
1485 			    		refreshScenarios();
1486 			    	}
1487 
1488 			    	if(getItemAfterRemoval == true) {
1489 						string scenarioName = selectedScenarioName;
1490 						string scenarioURL = scenarioCacheList[scenarioName].url;
1491 						if(ftpClientThread != NULL) ftpClientThread->addScenarioToRequests(scenarioName,scenarioURL);
1492 
1493 						static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1494 						MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1495 						if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1496 						fileFTPProgressList[scenarioName] = pair<int,string>(0,"");
1497 						safeMutexFTPProgress.ReleaseLock();
1498 						buttonInstallScenario.setEnabled(false);
1499 			    	}
1500 			    }
1501 			}
1502 		}
1503 	}
1504 	else if(keyTechScrollBar.mouseClick(x, y)) {
1505 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1506 		soundRenderer.playFx(coreData.getClickSoundA());
1507 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1508     }
1509 	else if(keyTilesetScrollBar.mouseClick(x, y)) {
1510 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1511 		soundRenderer.playFx(coreData.getClickSoundA());
1512 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1513     }
1514 	else if(keyMapScrollBar.mouseClick(x, y)) {
1515 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1516 		soundRenderer.playFx(coreData.getClickSoundA());
1517 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1518     }
1519 	else if(keyScenarioScrollBar.mouseClick(x, y)) {
1520 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1521 		soundRenderer.playFx(coreData.getClickSoundA());
1522 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1523     }
1524 	else if(buttonInstallTech.mouseClick(x, y) && buttonInstallTech.getEnabled()) {
1525 		soundRenderer.playFx(coreData.getClickSoundB());
1526 		if(selectedTechName != "") {
1527 			bool alreadyHasTech = (std::find(techTreeFiles.begin(),techTreeFiles.end(),selectedTechName) != techTreeFiles.end());
1528 			if(alreadyHasTech == true) {
1529 				bool remoteHasTech = (techCacheList.find(selectedTechName) != techCacheList.end());
1530 				if(remoteHasTech == true){
1531 					ModInfo &modInfo = techCacheList[selectedTechName];
1532 
1533 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] remote CRC [%s]\n",__FILE__,__FUNCTION__,__LINE__,modInfo.crc.c_str());
1534 
1535 					Config &config = Config::getInstance();
1536 					string itemPath = config.getPathListForType(ptTechs,"")[1] + "/" + selectedTechName + string("/*");
1537 					bool forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
1538 					if( strToUInt(modInfo.crc) != 0 &&
1539 							strToUInt(modInfo.crc) != getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh)) {
1540 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] local CRC [%u]\n",__FILE__,__FUNCTION__,__LINE__,getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL));
1541 
1542 						mainMessageBoxState = ftpmsg_ReplaceTechtree;
1543 						mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
1544 						char szBuf[8096]="";
1545 						snprintf(szBuf,8096,lang.getString("ModLocalRemoteMismatch").c_str(),selectedTechName.c_str());
1546 						showMessageBox(szBuf, lang.getString("Notice"), true);
1547 					}
1548 					else {
1549 						mainMessageBoxState = ftpmsg_None;
1550 						mainMessageBox.init(lang.getString("Ok"),450);
1551 						char szBuf[8096]="";
1552 						snprintf(szBuf,8096,lang.getString("ModTechAlreadyInstalled").c_str(),selectedTechName.c_str());
1553 						showMessageBox(szBuf, lang.getString("Notice"), true);
1554 					}
1555 					mapCRCUpdateList[itemPath] = true;
1556 				}
1557 			}
1558 			else {
1559 				string techName = selectedTechName;
1560 				string techURL = techCacheList[techName].url;
1561 				if(ftpClientThread != NULL) ftpClientThread->addTechtreeToRequests(techName,techURL);
1562 
1563 				static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1564 				MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1565 				if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1566 				fileFTPProgressList[techName] = pair<int,string>(0,"");
1567 				safeMutexFTPProgress.ReleaseLock();
1568 				buttonInstallTech.setEnabled(false);
1569 			}
1570 		}
1571 		else {
1572 			mainMessageBoxState = ftpmsg_None;
1573 			mainMessageBox.init(lang.getString("Ok"),450);
1574 			showMessageBox(lang.getString("ModSelectTechToInstall"), lang.getString("Notice"), true);
1575 		}
1576 	}
1577 	else if(buttonRemoveTech.mouseClick(x, y) && buttonRemoveTech.getEnabled()) {
1578 		soundRenderer.playFx(coreData.getClickSoundB());
1579 		if(selectedTechName != "") {
1580 			bool alreadyHasTech = (std::find(techTreeFiles.begin(),techTreeFiles.end(),selectedTechName) != techTreeFiles.end());
1581 			if(alreadyHasTech == true) {
1582 				mainMessageBoxState = ftpmsg_GetTechtree;
1583 
1584 				char szBuf[8096]="";
1585 				snprintf(szBuf,8096,lang.getString("ModRemoveTechConfirm").c_str(),selectedTechName.c_str());
1586 				showMessageBox(szBuf, lang.getString("Question"), true);
1587 			}
1588 			else {
1589 				mainMessageBoxState = ftpmsg_None;
1590 				mainMessageBox.init(lang.getString("Ok"),450);
1591 
1592 				char szBuf[8096]="";
1593 				snprintf(szBuf,8096,lang.getString("ModCannotRemoveTechNotInstalled").c_str(),selectedTechName.c_str());
1594 				showMessageBox(szBuf, lang.getString("Notice"), true);
1595 			}
1596 		}
1597 		else {
1598 			mainMessageBoxState = ftpmsg_None;
1599 			mainMessageBox.init(lang.getString("Ok"),450);
1600 
1601 			showMessageBox(lang.getString("ModSelectTechToRemove"), lang.getString("Notice"), true);
1602 		}
1603 	}
1604 
1605 	else if(buttonInstallTileset.mouseClick(x, y) && buttonInstallTileset.getEnabled()) {
1606 		soundRenderer.playFx(coreData.getClickSoundB());
1607 		if(selectedTilesetName != "") {
1608 			bool alreadyHasTileset = (std::find(tilesetFiles.begin(),tilesetFiles.end(),selectedTilesetName) != tilesetFiles.end());
1609 			if(alreadyHasTileset == true) {
1610 				bool remoteHasTileset = (tilesetCacheList.find(selectedTilesetName) != tilesetCacheList.end());
1611 				if(remoteHasTileset){
1612 					ModInfo &modInfo = tilesetCacheList[selectedTilesetName];
1613 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] remote CRC [%s]\n",__FILE__,__FUNCTION__,__LINE__,modInfo.crc.c_str());
1614 
1615 					Config &config = Config::getInstance();
1616 					string itemPath = config.getPathListForType(ptTilesets,"")[1] + "/" + selectedTilesetName + string("/*");
1617 					bool forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
1618 
1619 					if( strToUInt(modInfo.crc) != 0 &&
1620 						strToUInt(modInfo.crc) != getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL,forceRefresh)) {
1621 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] local CRC [%u] [%s]\n",__FILE__,__FUNCTION__,__LINE__,getFolderTreeContentsCheckSumRecursively(itemPath, ".xml", NULL),itemPath.c_str());
1622 
1623 						mainMessageBoxState = ftpmsg_ReplaceTileset;
1624 						mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
1625 						char szBuf[8096]="";
1626 						snprintf(szBuf,8096,lang.getString("ModLocalRemoteMismatch").c_str(),selectedTilesetName.c_str());
1627 						showMessageBox(szBuf, lang.getString("Notice"), true);
1628 					}
1629 					else {
1630 						mainMessageBoxState = ftpmsg_None;
1631 						mainMessageBox.init(lang.getString("Ok"),450);
1632 						char szBuf[8096]="";
1633 						snprintf(szBuf,8096,lang.getString("ModTilesetAlreadyInstalled").c_str(),selectedTilesetName.c_str());
1634 						showMessageBox(szBuf, lang.getString("Notice"), true);
1635 					}
1636 				}
1637 			}
1638 			else {
1639 				string tilesetName = selectedTilesetName;
1640 				string tilesetURL = tilesetCacheList[tilesetName].url;
1641 				if(ftpClientThread != NULL) ftpClientThread->addTilesetToRequests(tilesetName,tilesetURL);
1642 
1643 				static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1644 				MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1645 				if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1646 				fileFTPProgressList[tilesetName] = pair<int,string>(0,"");
1647 				safeMutexFTPProgress.ReleaseLock();
1648 				buttonInstallTileset.setEnabled(false);
1649 			}
1650 		}
1651 		else {
1652 			mainMessageBoxState = ftpmsg_None;
1653 			mainMessageBox.init(lang.getString("Ok"),450);
1654 			showMessageBox(lang.getString("ModSelectTilesetToInstall"), lang.getString("Notice"), true);
1655 		}
1656 	}
1657 	else if(buttonRemoveTileset.mouseClick(x, y) && buttonRemoveTileset.getEnabled()) {
1658 		soundRenderer.playFx(coreData.getClickSoundB());
1659 		if(selectedTilesetName != "") {
1660 			bool alreadyHasTileset = (std::find(tilesetFiles.begin(),tilesetFiles.end(),selectedTilesetName) != tilesetFiles.end());
1661 			if(alreadyHasTileset == true) {
1662 				mainMessageBoxState = ftpmsg_GetTileset;
1663 
1664 				char szBuf[8096]="";
1665 				snprintf(szBuf,8096,lang.getString("ModRemoveTilesetConfirm").c_str(),selectedTilesetName.c_str());
1666 				showMessageBox(szBuf, lang.getString("Question"), true);
1667 			}
1668 			else {
1669 				mainMessageBoxState = ftpmsg_None;
1670 				mainMessageBox.init(lang.getString("Ok"),450);
1671 
1672 				char szBuf[8096]="";
1673 				snprintf(szBuf,8096,lang.getString("ModCannotRemoveTilesetNotInstalled").c_str(),selectedTilesetName.c_str());
1674 				showMessageBox(szBuf, lang.getString("Notice"), true);
1675 			}
1676 		}
1677 		else {
1678 			mainMessageBoxState = ftpmsg_None;
1679 			mainMessageBox.init(lang.getString("Ok"),450);
1680 			showMessageBox(lang.getString("ModSelectTilesetToRemove"), lang.getString("Notice"), true);
1681 		}
1682 	}
1683 
1684 	else if(buttonInstallMap.mouseClick(x, y) && buttonInstallMap.getEnabled()) {
1685 		soundRenderer.playFx(coreData.getClickSoundB());
1686 		if(selectedMapName != "") {
1687 			bool alreadyHasMap = (std::find(mapFiles.begin(),mapFiles.end(),selectedMapName) != mapFiles.end());
1688 			if(alreadyHasMap == true) {
1689 				bool remoteHasMap = (mapCacheList.find(selectedMapName) != mapCacheList.end());
1690 				if(remoteHasMap){
1691 					ModInfo &modInfo = mapCacheList[selectedMapName];
1692 					if( modInfo.crc != modInfo.localCRC ) {
1693 						mainMessageBoxState = ftpmsg_ReplaceMap;
1694 						mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
1695 						char szBuf[8096]="";
1696 						snprintf(szBuf,8096,lang.getString("ModLocalRemoteMismatch").c_str(),selectedMapName.c_str());
1697 						showMessageBox(szBuf, lang.getString("Notice"), true);
1698 					}
1699 					else {
1700 						mainMessageBoxState = ftpmsg_None;
1701 						mainMessageBox.init(lang.getString("Ok"),450);
1702 						char szBuf[8096]="";
1703 						snprintf(szBuf,8096,lang.getString("ModMapAlreadyInstalled").c_str(),selectedMapName.c_str());
1704 						showMessageBox(szBuf, lang.getString("Notice"), true);
1705 					}
1706 				}
1707 			}
1708 			else {
1709 				string mapName = selectedMapName;
1710 				string mapURL = mapCacheList[mapName].url;
1711 				if(ftpClientThread != NULL) ftpClientThread->addMapToRequests(mapName,mapURL);
1712 
1713 				static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1714 				MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1715 				if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1716 				fileFTPProgressList[mapName] = pair<int,string>(0,"");
1717 				safeMutexFTPProgress.ReleaseLock();
1718 				buttonInstallMap.setEnabled(false);
1719 			}
1720 		}
1721 		else {
1722 			mainMessageBoxState = ftpmsg_None;
1723 			mainMessageBox.init(lang.getString("Ok"),450);
1724 			showMessageBox(lang.getString("ModSelectMapToInstall"), lang.getString("Notice"), true);
1725 		}
1726 	}
1727 	else if(buttonRemoveMap.mouseClick(x, y) && buttonRemoveMap.getEnabled()) {
1728 		soundRenderer.playFx(coreData.getClickSoundB());
1729 		if(selectedMapName != "") {
1730 			bool alreadyHasMap = (std::find(mapFiles.begin(),mapFiles.end(),selectedMapName) != mapFiles.end());
1731 			if(alreadyHasMap == true) {
1732 				mainMessageBoxState = ftpmsg_GetMap;
1733 
1734 				char szBuf[8096]="";
1735 				snprintf(szBuf,8096,lang.getString("ModRemoveMapConfirm").c_str(),selectedMapName.c_str());
1736 				showMessageBox(szBuf, lang.getString("Question"), true);
1737 			}
1738 			else {
1739 				mainMessageBoxState = ftpmsg_None;
1740 				mainMessageBox.init(lang.getString("Ok"),450);
1741 
1742 				char szBuf[8096]="";
1743 				snprintf(szBuf,8096,lang.getString("ModCannotRemoveMapNotInstalled").c_str(),selectedMapName.c_str());
1744 				showMessageBox(szBuf, lang.getString("Notice"), true);
1745 			}
1746 		}
1747 		else {
1748 			mainMessageBoxState = ftpmsg_None;
1749 			mainMessageBox.init(lang.getString("Ok"),450);
1750 			showMessageBox(lang.getString("ModSelectMapToRemove"), lang.getString("Notice"), true);
1751 		}
1752 	}
1753 
1754 	else if(buttonInstallScenario.mouseClick(x, y) && buttonInstallScenario.getEnabled()) {
1755 		soundRenderer.playFx(coreData.getClickSoundB());
1756 		if(selectedScenarioName != "") {
1757 			bool alreadyHasScenario = (std::find(scenarioFiles.begin(),scenarioFiles.end(),selectedScenarioName) != scenarioFiles.end());
1758 			if(alreadyHasScenario == true) {
1759 				bool remoteHasScenario = (scenarioCacheList.find(selectedScenarioName) != scenarioCacheList.end());
1760 				if(remoteHasScenario){
1761 					ModInfo &modInfo = scenarioCacheList[selectedScenarioName];
1762 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] remote CRC [%s]\n",__FILE__,__FUNCTION__,__LINE__,modInfo.crc.c_str());
1763 
1764 					Config &config = Config::getInstance();
1765 					string itemPath = config.getPathListForType(ptScenarios,"")[1] + "/" + selectedScenarioName + string("/*");
1766 					bool forceRefresh = (mapCRCUpdateList.find(itemPath) == mapCRCUpdateList.end());
1767 
1768 					if( strToUInt(modInfo.crc) != 0 &&
1769 						strToUInt(modInfo.crc) != getFolderTreeContentsCheckSumRecursively(itemPath, "", NULL,forceRefresh)) {
1770 						if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] local CRC [%u]\n",__FILE__,__FUNCTION__,__LINE__,getFolderTreeContentsCheckSumRecursively(itemPath, "", NULL));
1771 
1772 						mainMessageBoxState = ftpmsg_ReplaceScenario;
1773 						mainMessageBox.init(lang.getString("Yes"),lang.getString("No"),450);
1774 						char szBuf[8096]="";
1775 						snprintf(szBuf,8096,lang.getString("ModLocalRemoteMismatch").c_str(),selectedScenarioName.c_str());
1776 						showMessageBox(szBuf, lang.getString("Notice"), true);
1777 					}
1778 					else {
1779 						mainMessageBoxState = ftpmsg_None;
1780 						mainMessageBox.init(lang.getString("Ok"),450);
1781 						char szBuf[8096]="";
1782 						snprintf(szBuf,8096,lang.getString("ModScenarioAlreadyInstalled").c_str(),selectedScenarioName.c_str());
1783 						showMessageBox(szBuf, lang.getString("Notice"), true);
1784 					}
1785 				}
1786 			}
1787 			else {
1788 				string scenarioName = selectedScenarioName;
1789 				string scenarioURL = scenarioCacheList[scenarioName].url;
1790 
1791 				//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line %d] adding file to download [%s]\n",__FILE__,__FUNCTION__,__LINE__,scenarioURL.c_str());
1792 				if(ftpClientThread != NULL) ftpClientThread->addScenarioToRequests(scenarioName,scenarioURL);
1793 
1794 				static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1795 				MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
1796 				if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
1797 				fileFTPProgressList[scenarioName] = pair<int,string>(0,"");
1798 				safeMutexFTPProgress.ReleaseLock();
1799 				buttonInstallScenario.setEnabled(false);
1800 			}
1801 		}
1802 		else {
1803 			mainMessageBoxState = ftpmsg_None;
1804 			mainMessageBox.init(lang.getString("Ok"),450);
1805 			showMessageBox(lang.getString("ModSelectScenarioToInstall"), lang.getString("Notice"), true);
1806 		}
1807 	}
1808 	else if(buttonRemoveScenario.mouseClick(x, y) && buttonRemoveScenario.getEnabled()) {
1809 		soundRenderer.playFx(coreData.getClickSoundB());
1810 		if(selectedScenarioName != "") {
1811 			bool alreadyHasScenario = (std::find(scenarioFiles.begin(),scenarioFiles.end(),selectedScenarioName) != scenarioFiles.end());
1812 			if(alreadyHasScenario == true) {
1813 				mainMessageBoxState = ftpmsg_GetScenario;
1814 
1815 				char szBuf[8096]="";
1816 				snprintf(szBuf,8096,lang.getString("ModRemoveScenarioConfirm").c_str(),selectedScenarioName.c_str());
1817 				showMessageBox(szBuf, lang.getString("Question"), true);
1818 			}
1819 			else {
1820 				mainMessageBoxState = ftpmsg_None;
1821 				mainMessageBox.init(lang.getString("Ok"),450);
1822 
1823 				char szBuf[8096]="";
1824 				snprintf(szBuf,8096,lang.getString("ModCannotRemoveScenarioNotInstalled").c_str(),selectedScenarioName.c_str());
1825 				showMessageBox(szBuf, lang.getString("Notice"), true);
1826 			}
1827 		}
1828 		else {
1829 			mainMessageBoxState = ftpmsg_None;
1830 			mainMessageBox.init(lang.getString("Ok"),450);
1831 			showMessageBox(lang.getString("ModSelectScenarioToRemove"), lang.getString("Notice"), true);
1832 		}
1833 	}
1834 
1835     else {
1836     	if(keyMapScrollBar.getElementCount() != 0) {
1837 			for (int i = keyMapScrollBar.getVisibleStart();
1838 					i <= keyMapScrollBar.getVisibleEnd(); ++i) {
1839 				if(keyMapButtons[i]->mouseClick(x, y) && keyMapButtons[i]->getEnabled()) {
1840 					string mapName = keyMapButtons[i]->getText();
1841 					selectedTechName		= "";
1842 					selectedTilesetName		= "";
1843 					selectedMapName 		= "";
1844 					selectedScenarioName	= "";
1845 					if(mapName != "") {
1846 						selectedMapName = mapName;
1847 						bool remoteHasMap = (mapCacheList.find(mapName) != mapCacheList.end());
1848 						if(remoteHasMap) {
1849 							showRemoteDesription(&mapCacheList[selectedMapName]);
1850 							if(mapCacheList[selectedMapName].localCRC!=""){
1851 								loadMapPreview(mapName);
1852 							}
1853 						}
1854 						else {
1855 							showLocalDescription(mapName);
1856 							loadMapPreview(mapName);
1857 						}
1858 
1859 					}
1860 					break;
1861 				}
1862 			}
1863 		}
1864     	if(keyTechScrollBar.getElementCount() != 0) {
1865 			for (int i = keyTechScrollBar.getVisibleStart();
1866 					i <= keyTechScrollBar.getVisibleEnd(); ++i) {
1867 				if(keyTechButtons[i]->mouseClick(x, y) && keyTechButtons[i]->getEnabled()) {
1868 					string techName = keyTechButtons[i]->getText();
1869 					selectedTechName		= "";
1870 					selectedTilesetName		= "";
1871 					selectedMapName 		= "";
1872 					selectedScenarioName	= "";
1873 					if(techName != "") {
1874 						selectedTechName = techName;
1875 						bool remoteHasTech = (techCacheList.find(techName) != techCacheList.end());
1876 						if(remoteHasTech) {
1877 							showRemoteDesription(&techCacheList[techName]);
1878 						}
1879 						else {
1880 							showLocalDescription(techName);
1881 						}
1882 					}
1883 					break;
1884 				}
1885 			}
1886 		}
1887     	if(keyTilesetScrollBar.getElementCount() != 0) {
1888 			for (int i = keyTilesetScrollBar.getVisibleStart();
1889 					i <= keyTilesetScrollBar.getVisibleEnd(); ++i) {
1890 				if(keyTilesetButtons[i]->mouseClick(x, y) && keyTilesetButtons[i]->getEnabled()) {
1891 					string tilesetName = keyTilesetButtons[i]->getText();
1892 					selectedTechName		= "";
1893 					selectedTilesetName		= "";
1894 					selectedMapName 		= "";
1895 					selectedScenarioName	= "";
1896 					if(tilesetName != "") {
1897 						selectedTilesetName = tilesetName;
1898 						bool remoteHasTileset = (tilesetCacheList.find(tilesetName) != tilesetCacheList.end());
1899 						if(remoteHasTileset) {
1900 							showRemoteDesription(&tilesetCacheList[tilesetName]);
1901 						}
1902 						else {
1903 							showLocalDescription(tilesetName);
1904 						}
1905 					}
1906 					break;
1907 				}
1908 			}
1909 		}
1910     	if(keyScenarioScrollBar.getElementCount() != 0) {
1911 			for (int i = keyScenarioScrollBar.getVisibleStart();
1912 					i <= keyScenarioScrollBar.getVisibleEnd(); ++i) {
1913 				if(keyScenarioButtons[i]->mouseClick(x, y) && keyScenarioButtons[i]->getEnabled()) {
1914 					string scenarioName = keyScenarioButtons[i]->getText();
1915 					selectedTechName		= "";
1916 					selectedTilesetName		= "";
1917 					selectedMapName 		= "";
1918 					selectedScenarioName	= "";
1919 					if(scenarioName != "") {
1920 						selectedScenarioName = scenarioName;
1921 						bool remoteHasScenario = (scenarioCacheList.find(scenarioName) != scenarioCacheList.end());
1922 						if(remoteHasScenario) {
1923 							showRemoteDesription(&scenarioCacheList[scenarioName]);
1924 						}
1925 						else {
1926 							showLocalDescription(scenarioName);
1927 						}
1928 
1929 					}
1930 					break;
1931 				}
1932 			}
1933 		}
1934 
1935     }
1936 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
1937 }
1938 
getPreviewImageFileForMod(const ModInfo * modInfo)1939 string MenuStateMods::getPreviewImageFileForMod(const ModInfo *modInfo) {
1940 	string fileName = "";
1941 	if(modInfo->imageUrl != "") {
1942 		Config &config = Config::getInstance();
1943 	    string userData = config.getString("UserData_Root","");
1944 	    if(userData != "") {
1945 	    	endPathWithSlash(userData);
1946 	    }
1947 	    string tempPath = userData + "temp/";
1948 	    if(isdir(tempPath.c_str()) == false) {
1949 	    	createDirectoryPaths(tempPath);
1950 	    }
1951 
1952 	    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("### tempPath [%s] isdir = %d\n",tempPath.c_str(),isdir(tempPath.c_str()));
1953 
1954         if(isdir(tempPath.c_str()) == true) {
1955 			fileName = tempPath;
1956 			switch(modInfo->type) {
1957 				case mt_Map:
1958 					fileName += "map_";
1959 					break;
1960 				case mt_Tileset:
1961 					fileName += "tileset_";
1962 					break;
1963 				case mt_Techtree:
1964 					fileName += "tech_";
1965 					break;
1966 				case mt_Scenario:
1967 					fileName += "scenario_";
1968 					break;
1969 			}
1970 			fileName += extractFileFromDirectoryPath(modInfo->imageUrl);
1971         }
1972 	}
1973 	return fileName;
1974 }
1975 
1976 
showLocalDescription(string name)1977 void MenuStateMods::showLocalDescription(string name) {
1978 	Lang &lang= Lang::getInstance();
1979 	modInfoSelected=NULL;
1980 	cleanupPreviewTexture();
1981 	validMapPreview=false;
1982 	cleanupMapPreviewTexture();
1983 	modDescrLabel.setText(lang.getString("ModOnlyLocal")+":\n'"+name+"'");
1984 }
1985 
loadMapPreview(string mapName)1986 void MenuStateMods::loadMapPreview(string mapName) {
1987 	Config &config = Config::getInstance();
1988 	cleanupMapPreviewTexture();
1989 	vector<string> mapPaths = config.getPathListForType(ptMaps);
1990 	string &mapPath = mapPaths[1];
1991 	endPathWithSlash(mapPath);
1992 	mapPath += mapName;
1993 	MapInfo mapInfo = loadMapInfo(mapPath);
1994 	if(enableMapPreview == true) {
1995 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
1996 
1997 		mapPreview.loadFromFile(mapPath.c_str());
1998 
1999 		//printf("Loading map preview MAP\n");
2000 		cleanupMapPreviewTexture();
2001 		validMapPreview=true;
2002 	}
2003 }
2004 
2005 
2006 
showRemoteDesription(ModInfo * modInfo)2007 void MenuStateMods::showRemoteDesription(ModInfo *modInfo) {
2008 	//displayModPreviewImage = false;
2009 	modInfoSelected = modInfo;
2010 	validMapPreview=false;
2011 	cleanupMapPreviewTexture();
2012 
2013 	string modText = modInfo->description;
2014 	replaceAll(modText, "\\n", "\n");
2015 	modDescrLabel.setText(modText);
2016 
2017 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("### modInfo->imageUrl [%s]\n",modInfo->imageUrl.c_str());
2018 
2019 	if(modInfo->imageUrl != "") {
2020 		cleanupPreviewTexture();
2021 	    string tempImage  = getPreviewImageFileForMod(modInfo);
2022 
2023 	    if(SystemFlags::VERBOSE_MODE_ENABLED) printf("### tempImage [%s] exists [%d]\n",tempImage.c_str(),fileExists(tempImage));
2024 
2025 	    if(tempImage != "" && fileExists(tempImage) == false) {
2026 	    	if(ftpClientThread != NULL) ftpClientThread->addFileToRequests(tempImage,modInfo->imageUrl);
2027 
2028 	    	static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2029 			MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2030 			if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2031 			fileFTPProgressList[tempImage] = pair<int,string>(0,"");
2032 			safeMutexFTPProgress.ReleaseLock();
2033 
2034 	    }
2035 	    else {
2036 	    	static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2037 			MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2038 			if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2039 			if(fileFTPProgressList.find(tempImage) == fileFTPProgressList.end()) {
2040 				//displayModPreviewImage = true;
2041 				displayModPreviewImage[tempImage] = true;
2042 			}
2043 			safeMutexFTPProgress.ReleaseLock();
2044 	    }
2045 	}
2046 }
2047 
mouseUp(int x,int y,const MouseButton mouseButton)2048 void MenuStateMods::mouseUp(int x, int y, const MouseButton mouseButton){
2049 	if (mouseButton == mbLeft) {
2050 		keyTechScrollBar.mouseUp(x, y);
2051 		keyTilesetScrollBar.mouseUp(x, y);
2052 		keyMapScrollBar.mouseUp(x, y);
2053 		keyScenarioScrollBar.mouseUp(x, y);
2054 	}
2055 }
2056 
mouseMove(int x,int y,const MouseState * ms)2057 void MenuStateMods::mouseMove(int x, int y, const MouseState *ms) {
2058 	buttonReturn.mouseMove(x, y);
2059 
2060 	if (mainMessageBox.getEnabled()) {
2061 		mainMessageBox.mouseMove(x, y);
2062 	}
2063 
2064 	buttonInstallTech.mouseMove(x, y);
2065 	buttonRemoveTech.mouseMove(x, y);
2066 	buttonInstallTileset.mouseMove(x, y);
2067 	buttonRemoveTileset.mouseMove(x, y);
2068 	buttonInstallMap.mouseMove(x, y);
2069 	buttonRemoveMap.mouseMove(x, y);
2070 	buttonInstallScenario.mouseMove(x, y);
2071 	buttonRemoveScenario.mouseMove(x, y);
2072 
2073     if (ms->get(mbLeft)) {
2074 		keyMapScrollBar.mouseDown(x, y);
2075 		keyTechScrollBar.mouseDown(x, y);
2076 		keyTilesetScrollBar.mouseDown(x, y);
2077 		keyScenarioScrollBar.mouseDown(x, y);
2078 	}
2079     else {
2080 		keyMapScrollBar.mouseMove(x, y);
2081 		keyTechScrollBar.mouseMove(x, y);
2082 		keyTilesetScrollBar.mouseMove(x, y);
2083 		keyScenarioScrollBar.mouseMove(x, y);
2084 	}
2085 
2086     if(keyMapScrollBar.getElementCount() !=0) {
2087     	for(int i = keyMapScrollBar.getVisibleStart(); i <= keyMapScrollBar.getVisibleEnd(); ++i) {
2088     		keyMapButtons[i]->mouseMove(x, y);
2089     	}
2090     }
2091     if(keyTechScrollBar.getElementCount() !=0) {
2092     	for(int i = keyTechScrollBar.getVisibleStart(); i <= keyTechScrollBar.getVisibleEnd(); ++i) {
2093     		keyTechButtons[i]->mouseMove(x, y);
2094     	}
2095     }
2096     if(keyTilesetScrollBar.getElementCount() !=0) {
2097     	for(int i = keyTilesetScrollBar.getVisibleStart(); i <= keyTilesetScrollBar.getVisibleEnd(); ++i) {
2098     		keyTilesetButtons[i]->mouseMove(x, y);
2099     	}
2100     }
2101     if(keyScenarioScrollBar.getElementCount() !=0) {
2102     	for(int i = keyScenarioScrollBar.getVisibleStart(); i <= keyScenarioScrollBar.getVisibleEnd(); ++i) {
2103     		keyScenarioButtons[i]->mouseMove(x, y);
2104     	}
2105     }
2106 }
2107 
cleanupPreviewTexture()2108 void MenuStateMods::cleanupPreviewTexture() {
2109 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] scenarioLogoTexture [%p]\n",__FILE__,__FUNCTION__,__LINE__,modPreviewImage);
2110 
2111 	if(modPreviewImage != NULL) {
2112 		Renderer::getInstance().endTexture(rsGlobal, modPreviewImage, false);
2113 	}
2114 	modPreviewImage = NULL;
2115 }
2116 
cleanupMapPreviewTexture()2117 void MenuStateMods::cleanupMapPreviewTexture() {
2118 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2119 
2120 	//printf("CLEANUP map preview texture\n");
2121 	if(mapPreviewTexture != NULL) {
2122 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2123 
2124 		mapPreviewTexture->end();
2125 
2126 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2127 		delete mapPreviewTexture;
2128 		mapPreviewTexture = NULL;
2129 	}
2130 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
2131 }
2132 
2133 
render()2134 void MenuStateMods::render() {
2135 	try {
2136 		Renderer &renderer= Renderer::getInstance();
2137 
2138 		renderer.renderLine(&lineHorizontal);
2139 		renderer.renderLine(&lineVertical);
2140 		renderer.renderLine(&lineReturn);
2141 		renderer.renderLine(&lineVerticalReturn);
2142 		renderer.renderButton(&buttonReturn);
2143 
2144 		renderer.renderButton(&buttonInstallTech);
2145 		renderer.renderButton(&buttonRemoveTech);
2146 		renderer.renderButton(&buttonInstallTileset);
2147 		renderer.renderButton(&buttonRemoveTileset);
2148 		renderer.renderButton(&buttonInstallMap);
2149 		renderer.renderButton(&buttonRemoveMap);
2150 		renderer.renderButton(&buttonInstallScenario);
2151 		renderer.renderButton(&buttonRemoveScenario);
2152 
2153 		renderer.renderButton(&buttonInstalled);
2154 		renderer.renderButton(&buttonAvailable);
2155 		renderer.renderButton(&buttonConflict);
2156 		renderer.renderButton(&buttonOnlyLocal);
2157 
2158 		renderer.renderLabel(&modDescrLabel);
2159 		if(modInfoSelected!=NULL){
2160 			string tempImage = getPreviewImageFileForMod(modInfoSelected);
2161 			if(displayModPreviewImage.find(tempImage) != displayModPreviewImage.end() &&
2162 				displayModPreviewImage[tempImage] == true) {
2163 				if(modPreviewImage == NULL) {
2164 					string tempImage = getPreviewImageFileForMod(modInfoSelected);
2165 
2166 					if(SystemFlags::VERBOSE_MODE_ENABLED) printf("### Render tempImage [%s] fileExists(tempImage) = %d\n",tempImage.c_str(),fileExists(tempImage));
2167 
2168 					if(tempImage != "" && fileExists(tempImage) == true) {
2169 						cleanupPreviewTexture();
2170 						modPreviewImage = Renderer::findTexture(tempImage);
2171 					}
2172 				}
2173 				if(modPreviewImage != NULL) {
2174 					renderer.renderTextureQuad(508,90,485,325,modPreviewImage,1.0f);
2175 				}
2176 			}
2177 		}
2178 
2179 		// Render Tech List
2180 		renderer.renderLabel(&keyTechScrollBarTitle1);
2181 		renderer.renderLabel(&keyTechScrollBarTitle2);
2182 		if(keyTechScrollBar.getElementCount() != 0) {
2183 			for(int i = keyTechScrollBar.getVisibleStart();
2184 					i <= keyTechScrollBar.getVisibleEnd(); ++i) {
2185 				bool alreadyHasTech = (std::find(techTreeFiles.begin(),techTreeFiles.end(),keyTechButtons[i]->getText()) != techTreeFiles.end());
2186 				if(keyTechButtons[i]->getText() == selectedTechName) {
2187 					bool lightedOverride = true;
2188 					renderer.renderButton(keyTechButtons[i],&WHITE,&lightedOverride);
2189 				}
2190 				else if(alreadyHasTech == true) {
2191 					Vec4f buttonColor = WHITE;
2192 					buttonColor.w = 0.75f;
2193 					bool remoteHasTech = (techCacheList.find(keyTechButtons[i]->getText()) != techCacheList.end());
2194 					if(remoteHasTech)
2195 					{
2196 						ModInfo &modInfo = techCacheList[keyTechButtons[i]->getText()];
2197 						if( modInfo.crc==modInfo.localCRC) {
2198 							keyTechButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerInstalledTexture());
2199 						}
2200 						else {
2201 							//printf("modInfo.name=%s modInfo.crc=%s modInfo.localCRC=%s\n",modInfo.name.c_str(),modInfo.crc.c_str(),modInfo.localCRC.c_str());
2202 							keyTechButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerDifferentTexture());
2203 						}
2204 					}
2205 					else
2206 					{
2207 						keyTechButtons[i]->setCustomTexture(CoreData::getInstance().getNotOnServerTexture());
2208 					}
2209 					renderer.renderButton(keyTechButtons[i],&buttonColor);
2210 				}
2211 				else {
2212 					Vec4f fontColor=Vec4f(200.0f/255.0f, 187.0f/255.0f, 190.0f/255.0f, 0.75f);
2213 					//Vec4f fontColor=Vec4f(1.0f, 0.0f, 0.0f, 0.75f);
2214 					keyTechButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerTexture());
2215 					renderer.renderButton(keyTechButtons[i],&fontColor);
2216 				}
2217 				renderer.renderLabel(labelsTech[i]);
2218 			}
2219 		}
2220 		renderer.renderScrollBar(&keyTechScrollBar);
2221 
2222 		// Render Tileset List
2223 		renderer.renderLabel(&keyTilesetScrollBarTitle1);
2224 		if(keyTilesetScrollBar.getElementCount() != 0) {
2225 			for(int i = keyTilesetScrollBar.getVisibleStart();
2226 					i <= keyTilesetScrollBar.getVisibleEnd(); ++i) {
2227 				bool alreadyHasTileset = (std::find(tilesetFiles.begin(),tilesetFiles.end(),keyTilesetButtons[i]->getText()) != tilesetFiles.end());
2228 				if(keyTilesetButtons[i]->getText() == selectedTilesetName) {
2229 					bool lightedOverride = true;
2230 					renderer.renderButton(keyTilesetButtons[i],&WHITE,&lightedOverride);
2231 				}
2232 				else if(alreadyHasTileset == true) {
2233 					Vec4f buttonColor = WHITE;
2234 					buttonColor.w = 0.75f;
2235 					bool remoteHasTileset= (tilesetCacheList.find(keyTilesetButtons[i]->getText()) != tilesetCacheList.end());
2236 					if(remoteHasTileset)
2237 					{
2238 						ModInfo &modInfo = tilesetCacheList[keyTilesetButtons[i]->getText()];
2239 
2240 						if( modInfo.crc==modInfo.localCRC) {
2241 							keyTilesetButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerInstalledTexture());
2242 						}
2243 						else {
2244 							//printf("modInfo.name=%s modInfo.crc=%s modInfo.localCRC=%s\n",modInfo.name.c_str(),modInfo.crc.c_str(),modInfo.localCRC.c_str());
2245 							//printf("name [%s] modInfo.crc [%s] modInfo.localCRC [%s]\n",modInfo.name.c_str(),modInfo.crc.c_str(),modInfo.localCRC.c_str());
2246 
2247 							keyTilesetButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerDifferentTexture());
2248 						}
2249 					}
2250 					else
2251 					{
2252 						keyTilesetButtons[i]->setCustomTexture(CoreData::getInstance().getNotOnServerTexture());
2253 					}
2254 					renderer.renderButton(keyTilesetButtons[i],&buttonColor);
2255 				}
2256 				else {
2257 					Vec4f fontColor=Vec4f(200.0f/255.0f, 187.0f/255.0f, 190.0f/255.0f, 0.75f);
2258 					keyTilesetButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerTexture());
2259 					renderer.renderButton(keyTilesetButtons[i],&fontColor);
2260 				}
2261 			}
2262 		}
2263 		renderer.renderScrollBar(&keyTilesetScrollBar);
2264 
2265 		// Render Map list
2266 		renderer.renderLabel(&keyMapScrollBarTitle1);
2267 		renderer.renderLabel(&keyMapScrollBarTitle2);
2268 		if(keyMapScrollBar.getElementCount() != 0) {
2269 			for(int i = keyMapScrollBar.getVisibleStart();
2270 					i <= keyMapScrollBar.getVisibleEnd(); ++i) {
2271 				string mapNameToRender = keyMapButtons[i]->getText();
2272 				bool alreadyHasMap = (std::find(mapFiles.begin(),mapFiles.end(),mapNameToRender) != mapFiles.end());
2273 				if(keyMapButtons[i]->getText() == selectedMapName) {
2274 					bool lightedOverride = true;
2275 					renderer.renderButton(keyMapButtons[i],&WHITE,&lightedOverride);
2276 				}
2277 				else if(alreadyHasMap == true) {
2278 					Vec4f buttonColor = WHITE;
2279 					buttonColor.w = 0.75f;
2280 					bool remoteHasMap = (mapCacheList.find(keyMapButtons[i]->getText()) != mapCacheList.end());
2281 					if(remoteHasMap)
2282 					{
2283 						ModInfo &modInfo = mapCacheList[keyMapButtons[i]->getText()];
2284 						if( modInfo.crc==modInfo.localCRC) {
2285 							keyMapButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerInstalledTexture());
2286 						}
2287 						else {
2288 							//printf("modInfo.name=%s modInfo.crc=%s modInfo.localCRC=%s\n",modInfo.name.c_str(),modInfo.crc.c_str(),modInfo.localCRC.c_str());
2289 							keyMapButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerDifferentTexture());
2290 						}
2291 					}
2292 					else
2293 					{
2294 						keyMapButtons[i]->setCustomTexture(CoreData::getInstance().getNotOnServerTexture());
2295 					}
2296 					renderer.renderButton(keyMapButtons[i],&buttonColor);
2297 				}
2298 				else {
2299 					Vec4f fontColor=Vec4f(200.0f/255.0f, 187.0f/255.0f, 190.0f/255.0f, 0.75f);
2300 					keyMapButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerTexture());
2301 					renderer.renderButton(keyMapButtons[i],&fontColor);
2302 				}
2303 				renderer.renderLabel(labelsMap[i]);
2304 			}
2305 		}
2306 		renderer.renderScrollBar(&keyMapScrollBar);
2307 
2308 		// Render Scenario List
2309 		renderer.renderLabel(&keyScenarioScrollBarTitle1);
2310 		if(keyScenarioScrollBar.getElementCount() != 0) {
2311 			for(int i = keyScenarioScrollBar.getVisibleStart();
2312 					i <= keyScenarioScrollBar.getVisibleEnd(); ++i) {
2313 				if(i >= (int)keyScenarioButtons.size()) {
2314 					char szBuf[8096]="";
2315 					snprintf(szBuf,8096,"i >= keyScenarioButtons.size(), i = %d keyScenarioButtons.size() = %d",i,(int)keyScenarioButtons.size());
2316 					throw megaglest_runtime_error(szBuf);
2317 				}
2318 				bool alreadyHasScenario = (std::find(scenarioFiles.begin(),scenarioFiles.end(),keyScenarioButtons[i]->getText()) != scenarioFiles.end());
2319 
2320 				if(keyScenarioButtons[i]->getText() == selectedScenarioName) {
2321 					bool lightedOverride = true;
2322 					renderer.renderButton(keyScenarioButtons[i],&WHITE,&lightedOverride);
2323 				}
2324 				else if(alreadyHasScenario == true) {
2325 					Vec4f buttonColor = WHITE;
2326 					buttonColor.w = 0.75f;
2327 					bool remoteHasScenario= (scenarioCacheList.find(keyScenarioButtons[i]->getText()) != scenarioCacheList.end());
2328 					if(remoteHasScenario)
2329 					{
2330 						ModInfo &modInfo = scenarioCacheList[keyScenarioButtons[i]->getText()];
2331 						if( modInfo.crc==modInfo.localCRC) {
2332 							keyScenarioButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerInstalledTexture());
2333 						}
2334 						else {
2335 							//printf("modInfo.name=%s modInfo.crc=%s modInfo.localCRC=%s\n",modInfo.name.c_str(),modInfo.crc.c_str(),modInfo.localCRC.c_str());
2336 							keyScenarioButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerDifferentTexture());
2337 						}
2338 					}
2339 					else
2340 					{
2341 						keyScenarioButtons[i]->setCustomTexture(CoreData::getInstance().getNotOnServerTexture());
2342 					}
2343 					renderer.renderButton(keyScenarioButtons[i],&buttonColor);
2344 				}
2345 				else {
2346 					Vec4f fontColor=Vec4f(200.0f/255.0f, 187.0f/255.0f, 190.0f/255.0f, 0.75f);
2347 					keyScenarioButtons[i]->setCustomTexture(CoreData::getInstance().getOnServerTexture());
2348 					renderer.renderButton(keyScenarioButtons[i],&fontColor);
2349 				}
2350 			}
2351 		}
2352 		renderer.renderScrollBar(&keyScenarioScrollBar);
2353 
2354 		static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2355 		MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2356 		if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2357         if(fileFTPProgressList.empty() == false) {
2358         	Lang &lang= Lang::getInstance();
2359         	int xLocation = buttonReturn.getX();
2360             int yLocation = buttonReturn.getY() - 12;
2361             for(std::map<string,pair<int,string> >::iterator iterMap = fileFTPProgressList.begin();
2362                 iterMap != fileFTPProgressList.end(); ++iterMap) {
2363 
2364                 string progressLabelPrefix = lang.getString("ModDownloading") + " " + extractFileFromDirectoryPath(iterMap->first) + " ";
2365                 //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\nRendering file progress with the following prefix [%s]\n",progressLabelPrefix.c_str());
2366 
2367                 if(Renderer::renderText3DEnabled) {
2368 					renderer.renderProgressBar3D(
2369 						iterMap->second.first,
2370 						//10,
2371 						//yLocation,
2372 						xLocation,
2373 						yLocation,
2374 						CoreData::getInstance().getDisplayFontSmall3D(),
2375 						185,progressLabelPrefix,false);
2376                 }
2377                 else {
2378 					renderer.renderProgressBar(
2379 						iterMap->second.first,
2380 						//10,
2381 						//yLocation,
2382 						xLocation,
2383 						yLocation,
2384 						CoreData::getInstance().getDisplayFontSmall(),
2385 						185,progressLabelPrefix,false);
2386                 }
2387 
2388                 yLocation -= 14;
2389             }
2390         }
2391         safeMutexFTPProgress.ReleaseLock();
2392 
2393         renderer.renderConsole(&console,consoleNormal,3);
2394 
2395 		if(mainMessageBox.getEnabled()) {
2396 			renderer.renderMessageBox(&mainMessageBox);
2397 		}
2398 
2399 		if(modMenuState!=mmst_None) {
2400 			if(oldMenuState!=modMenuState)
2401 			{
2402 				Lang &lang= Lang::getInstance();
2403 				if(modMenuState== mmst_Loading){
2404 					pleaseWaitLabel.setText(lang.getString("GettingModlistFromMasterserver"));
2405 				}
2406 				else if(modMenuState== mmst_CalculatingCRC){
2407 					pleaseWaitLabel.setText(lang.getString("PleaseWaitCalculatingCRC"));
2408 				}
2409 				oldMenuState=modMenuState;
2410 			}
2411 			float anim= GraphicComponent::getAnim();
2412 			if(anim < 0.5f) {
2413 				anim = 1.f - anim;
2414 			}
2415 			Vec4f colorWithAlpha = Vec4f(ORANGE.x,ORANGE.y,ORANGE.z,anim);
2416 			renderer.renderLabel(&pleaseWaitLabel,&colorWithAlpha);
2417 		}
2418 		if(validMapPreview){
2419 			if(mapPreviewTexture != NULL) {
2420 				renderer.renderTextureQuad(5,185,150,150,mapPreviewTexture,1.0f);
2421 			}
2422 			if(enableMapPreview && (mapPreview.hasFileLoaded() == true)) {
2423 
2424 				int mouseX = mainMenu->getMouseX();
2425 				int mouseY = mainMenu->getMouseY();
2426 				int mouse2dAnim = mainMenu->getMouse2dAnim();
2427 
2428 				if(mapPreviewTexture == NULL) {
2429 					renderer.renderMouse2d(mouseX, mouseY, mouse2dAnim);
2430 					renderer.renderMapPreview(&mapPreview, true, 10, 350, &mapPreviewTexture);
2431 				}
2432 			}
2433 		}
2434 
2435 	}
2436 	catch(const std::exception &ex) {
2437 		char szBuf[8096]="";
2438 		snprintf(szBuf,8096,"In [%s::%s %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
2439 		SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
2440 		throw megaglest_runtime_error(szBuf);
2441 	}
2442 }
2443 
update()2444 void MenuStateMods::update() {
2445 	Chrono chrono;
2446 	chrono.start();
2447 
2448 	//Lang &lang= Lang::getInstance();
2449 
2450 	// Tech List
2451 	if (keyTechScrollBar.getElementCount() != 0) {
2452 		for (int i = keyTechScrollBar.getVisibleStart();
2453 				i <= keyTechScrollBar.getVisibleEnd(); ++i) {
2454 			if(i >= (int)keyTechButtons.size()) {
2455 				char szBuf[8096]="";
2456 				snprintf(szBuf,8096,"i >= keyTechButtons.size(), i = %d, keyTechButtons.size() = %d",i,(int)keyTechButtons.size());
2457 				throw megaglest_runtime_error(szBuf);
2458 			}
2459 
2460 			keyTechButtons[i]->setY(keyButtonsYBase - keyButtonsLineHeight * (i
2461 					- keyTechScrollBar.getVisibleStart()));
2462 			labelsTech[i]->setY(keyButtonsYBase - keyButtonsLineHeight * (i
2463 					- keyTechScrollBar.getVisibleStart()));
2464 		}
2465 	}
2466 
2467 	// Tileset List
2468 	if (keyTilesetScrollBar.getElementCount() != 0) {
2469 		for (int i = keyTilesetScrollBar.getVisibleStart();
2470 				i <= keyTilesetScrollBar.getVisibleEnd(); ++i) {
2471 			if(i >= (int)keyTilesetButtons.size()) {
2472 				char szBuf[8096]="";
2473 				snprintf(szBuf,8096,"i >= keyTilesetButtons.size(), i = %d, keyTilesetButtons.size() = %d",i,(int)keyTilesetButtons.size());
2474 				throw megaglest_runtime_error(szBuf);
2475 			}
2476 
2477 			int yPos = keyButtonsYBase - keyButtonsLineHeight *
2478 						(i - keyTilesetScrollBar.getVisibleStart());
2479 			keyTilesetButtons[i]->setY(yPos);
2480 		}
2481 	}
2482 
2483 	// Map List
2484 	if (keyMapScrollBar.getElementCount() != 0) {
2485 		for (int i = keyMapScrollBar.getVisibleStart();
2486 				i <= keyMapScrollBar.getVisibleEnd(); ++i) {
2487 			if(i >= (int)keyMapButtons.size()) {
2488 				char szBuf[8096]="";
2489 				snprintf(szBuf,8096,"i >= keyMapButtons.size(), i = %d, keyMapButtons.size() = %d",i,(int)keyMapButtons.size());
2490 				throw megaglest_runtime_error(szBuf);
2491 			}
2492 
2493 			keyMapButtons[i]->setY(keyButtonsYBase - keyButtonsLineHeight * (i
2494 					- keyMapScrollBar.getVisibleStart()));
2495 			labelsMap[i]->setY(keyButtonsYBase - keyButtonsLineHeight * (i
2496 					- keyMapScrollBar.getVisibleStart()));
2497 		}
2498 	}
2499 
2500 	// Scenario List
2501 	if (keyScenarioScrollBar.getElementCount() != 0) {
2502 		for (int i = keyScenarioScrollBar.getVisibleStart();
2503 				i <= keyScenarioScrollBar.getVisibleEnd(); ++i) {
2504 			if(i >= (int)keyScenarioButtons.size()) {
2505 				char szBuf[8096]="";
2506 				snprintf(szBuf,8096,"i >= keyScenarioButtons.size(), i = %d, keyScenarioButtons.size() = %d",i,(int)keyScenarioButtons.size());
2507 				throw megaglest_runtime_error(szBuf);
2508 			}
2509 
2510 			int yPos = keyButtonsYBase - keyButtonsLineHeight *
2511 						(i - keyScenarioScrollBar.getVisibleStart());
2512 			keyScenarioButtons[i]->setY(yPos);
2513 		}
2514 	}
2515 
2516 	console.update();
2517 }
2518 
keyDown(SDL_KeyboardEvent key)2519 void MenuStateMods::keyDown(SDL_KeyboardEvent key) {
2520 	Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
2521 	//if(key == configKeys.getCharKey("ShowFullConsole")) {
2522 	if(isKeyPressed(configKeys.getSDLKey("ShowFullConsole"),key) == true) {
2523 		showFullConsole= true;
2524 	}
2525 }
2526 
keyPress(SDL_KeyboardEvent c)2527 void MenuStateMods::keyPress(SDL_KeyboardEvent c) {
2528 }
2529 
keyUp(SDL_KeyboardEvent key)2530 void MenuStateMods::keyUp(SDL_KeyboardEvent key) {
2531 	Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
2532 	//if(key== configKeys.getCharKey("ShowFullConsole")) {
2533 	if(isKeyPressed(configKeys.getSDLKey("ShowFullConsole"),key) == true) {
2534 		showFullConsole= false;
2535 	}
2536 }
2537 
showMessageBox(const string & text,const string & header,bool toggle)2538 void MenuStateMods::showMessageBox(const string &text, const string &header, bool toggle) {
2539 	if(toggle == false) {
2540 		mainMessageBox.setEnabled(false);
2541 	}
2542 
2543 	if(mainMessageBox.getEnabled() == false) {
2544 		mainMessageBox.setText(text);
2545 		mainMessageBox.setHeader(header);
2546 		mainMessageBox.setEnabled(true);
2547 	}
2548 	else{
2549 		mainMessageBox.setEnabled(false);
2550 	}
2551 }
2552 
FTPClient_CallbackEvent(string itemName,FTP_Client_CallbackType type,pair<FTP_Client_ResultType,string> result,void * userdata)2553 void MenuStateMods::FTPClient_CallbackEvent(string itemName,
2554 		FTP_Client_CallbackType type, pair<FTP_Client_ResultType,string> result,void *userdata) {
2555 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
2556 
2557     Lang &lang= Lang::getInstance();
2558     if(type == ftp_cct_DownloadProgress) {
2559         FTPClientCallbackInterface::FtpProgressStats *stats = (FTPClientCallbackInterface::FtpProgressStats *)userdata;
2560         if(stats != NULL) {
2561             int fileProgress = 0;
2562             if(stats->download_total > 0) {
2563                 fileProgress = ((stats->download_now / stats->download_total) * 100.0);
2564             }
2565             //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);
2566 
2567             static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2568             MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2569             if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2570             pair<int,string> lastProgress = fileFTPProgressList[itemName];
2571             fileFTPProgressList[itemName] = pair<int,string>(fileProgress,stats->currentFilename);
2572             safeMutexFTPProgress.ReleaseLock();
2573         }
2574     }
2575     else if(type == ftp_cct_ExtractProgress) {
2576     	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());
2577     	//printf("Got FTP extract Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
2578 
2579     	if(userdata == NULL) {
2580 			char szBuf[8096]="";
2581 			snprintf(szBuf,8096,lang.getString("DataMissingExtractDownloadMod").c_str(),itemName.c_str());
2582 			//printf("%s\n",szBuf);
2583 			console.addLine(szBuf,true);
2584     	}
2585     	else {
2586 			char *szBuf = (char *)userdata;
2587 			//printf("%s\n",szBuf);
2588 			console.addLine(szBuf);
2589     	}
2590     }
2591     else if(type == ftp_cct_File) {
2592         if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
2593 
2594         static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2595         MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2596         if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2597         fileFTPProgressList.erase(itemName);
2598         safeMutexFTPProgress.ReleaseLock();
2599 
2600         //printf("### downloaded file [%s] result = %d\n",itemName.c_str(),result.first);
2601 
2602         if(result.first == ftp_crt_SUCCESS) {
2603         	displayModPreviewImage[itemName] = true;
2604         }
2605     }
2606 
2607     else if(type == ftp_cct_Map) {
2608         if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
2609 
2610         static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2611         MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2612         if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2613         fileFTPProgressList.erase(itemName);
2614         safeMutexFTPProgress.ReleaseLock();
2615         selectedMapName = "";
2616         buttonInstallMap.setEnabled(true);
2617 
2618         if(result.first == ftp_crt_SUCCESS) {
2619         	refreshMaps();
2620 			char szBuf[8096]="";
2621 			snprintf(szBuf,8096,lang.getString("ModDownloadMapSuccess").c_str(),itemName.c_str());
2622             console.addLine(szBuf,true);
2623         }
2624         else {
2625             curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW);
2626 
2627 			char szBuf[8096]="";
2628 			snprintf(szBuf,8096,lang.getString("ModDownloadMapFail").c_str(),itemName.c_str(),curlVersion->version,result.second.c_str());
2629             console.addLine(szBuf,true);
2630         }
2631     }
2632     else if(type == ftp_cct_Tileset) {
2633     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
2634 
2635     	static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2636     	MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2637     	if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2638         fileFTPProgressList.erase(itemName);
2639         safeMutexFTPProgress.ReleaseLock(true);
2640 
2641         selectedTilesetName = "";
2642         buttonInstallTileset.setEnabled(true);
2643 
2644         if(result.first == ftp_crt_SUCCESS) {
2645         	refreshTilesets();
2646 
2647 			char szBuf[8096]="";
2648 			snprintf(szBuf,8096,lang.getString("ModDownloadTilesetSuccess").c_str(),itemName.c_str());
2649            	console.addLine(szBuf,true);
2650             // END
2651         }
2652         else {
2653             curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW);
2654 
2655 			char szBuf[8096]="";
2656 			snprintf(szBuf,8096,lang.getString("ModDownloadTilesetFail").c_str(),itemName.c_str(),curlVersion->version,result.second.c_str());
2657            	console.addLine(szBuf,true);
2658         }
2659     }
2660     else if(type == ftp_cct_Techtree) {
2661     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
2662 
2663     	static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2664     	MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2665     	if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2666         fileFTPProgressList.erase(itemName);
2667         safeMutexFTPProgress.ReleaseLock(true);
2668 
2669         selectedTechName = "";
2670         buttonInstallTech.setEnabled(true);
2671 
2672         if(result.first == ftp_crt_SUCCESS) {
2673 
2674 			char szBuf[8096]="";
2675 			snprintf(szBuf,8096,lang.getString("ModDownloadTechSuccess").c_str(),itemName.c_str());
2676            	console.addLine(szBuf,true);
2677 
2678             // START
2679             // Clear the CRC Cache if it is populated
2680             safeMutexFTPProgress.Lock();
2681             Checksum::clearFileCache();
2682 
2683             vector<string> paths        = Config::getInstance().getPathListForType(ptTechs);
2684             string pathSearchString     = string("/") + itemName + string("/*");
2685             const string filterFileExt  = ".xml";
2686             clearFolderTreeContentsCheckSum(paths, pathSearchString, filterFileExt);
2687             clearFolderTreeContentsCheckSumList(paths, pathSearchString, filterFileExt);
2688 
2689             // Refresh CRC
2690             Config &config = Config::getInstance();
2691             getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,""), string("/") + itemName + string("/*"), ".xml", NULL, true);
2692             safeMutexFTPProgress.ReleaseLock();
2693 
2694         	refreshTechs();
2695             // END
2696         }
2697         else {
2698             curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW);
2699 
2700 			char szBuf[8096]="";
2701 			snprintf(szBuf,8096,lang.getString("ModDownloadTechFail").c_str(),itemName.c_str(),curlVersion->version,result.second.c_str());
2702            	console.addLine(szBuf,true);
2703         }
2704     }
2705     else if(type == ftp_cct_Scenario) {
2706     	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got FTP Callback for [%s] result = %d [%s]\n",itemName.c_str(),result.first,result.second.c_str());
2707 
2708     	static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
2709         MutexSafeWrapper safeMutexFTPProgress((ftpClientThread != NULL ? ftpClientThread->getProgressMutex() : NULL),mutexOwnerId);
2710         if(ftpClientThread != NULL && ftpClientThread->getProgressMutex() != NULL) ftpClientThread->getProgressMutex()->setOwnerId(mutexOwnerId);
2711         fileFTPProgressList.erase(itemName);
2712         safeMutexFTPProgress.ReleaseLock(true);
2713 
2714         selectedScenarioName = "";
2715         buttonInstallScenario.setEnabled(true);
2716 
2717         if(result.first == ftp_crt_SUCCESS) {
2718 			char szBuf[8096]="";
2719 			snprintf(szBuf,8096,lang.getString("ModDownloadScenarioSuccess").c_str(),itemName.c_str());
2720            	console.addLine(szBuf,true);
2721 
2722             // START
2723             // Clear the CRC Cache if it is populated
2724             //
2725             // Clear the CRC file Cache
2726             safeMutexFTPProgress.Lock();
2727             Checksum::clearFileCache();
2728 
2729             vector<string> paths        = Config::getInstance().getPathListForType(ptScenarios);
2730             string pathSearchString     = string("/") + itemName + string("/*");
2731             const string filterFileExt  = ".xml";
2732             clearFolderTreeContentsCheckSum(paths, pathSearchString, filterFileExt);
2733             clearFolderTreeContentsCheckSumList(paths, pathSearchString, filterFileExt);
2734 
2735             // Refresh CRC
2736             Config &config = Config::getInstance();
2737             getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptScenarios,""), string("/") + itemName + string("/*"), ".xml", NULL, true);
2738             safeMutexFTPProgress.ReleaseLock();
2739 
2740             refreshScenarios();
2741             // END
2742         }
2743         else {
2744             curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW);
2745 
2746 			char szBuf[8096]="";
2747 			snprintf(szBuf,8096,lang.getString("ModDownloadScenarioFail").c_str(),itemName.c_str(),curlVersion->version,result.second.c_str());
2748            	console.addLine(szBuf,true);
2749         }
2750     }
2751 
2752 }
2753 
2754 }}//end namespace
2755