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