1 // This file is part of Glest (www.glest.org)
2 //
3 // Copyright (C) 2001-2008 Martiño Figueroa
4 //
5 // You can redistribute this code and/or modify it under
6 // the terms of the GNU General Public License as published
7 // by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version
9 // ==============================================================
10
11 #ifdef WIN32
12 #include <winsock2.h>
13 #include <winsock.h>
14 #include <process.h>
15 #include <io.h>
16 #endif
17
18 #ifdef HAVE_GOOGLE_BREAKPAD
19 #include "handler/exception_handler.h"
20 #endif
21
22 #include "math_wrapper.h"
23 #include "main.h"
24
25 #include <string>
26 #include <cstdlib>
27
28 #include "game.h"
29 #include "main_menu.h"
30 #include "program.h"
31 #include "config.h"
32 #include "metrics.h"
33 #include "game_util.h"
34 #include "platform_util.h"
35 #include "platform_main.h"
36 #include "network_interface.h"
37 #include "ImageReaders.h"
38 #include "renderer.h"
39 #include "simple_threads.h"
40 //#include <memory>
41 #include "font.h"
42 #include <curl/curl.h>
43 #include "menu_state_masterserver.h"
44 #include "checksum.h"
45 #include <algorithm>
46 #include "sound_renderer.h"
47 #include "font_gl.h"
48 #include "FileReader.h"
49 #include "cache_manager.h"
50 #include <iterator>
51 #include "core_data.h"
52 #include "font_text.h"
53 #include <locale.h>
54 #include "string_utils.h"
55 #include "auto_test.h"
56 #include "lua_script.h"
57 #include "interpolation.h"
58 #include "common_scoped_ptr.h"
59
60 // To handle signal catching
61 #if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__DragonFly__) && !defined(BSD)
62 #include <signal.h>
63 #endif
64
65 #if defined WIN32 && !defined(HAVE_GOOGLE_BREAKPAD)
66 #if defined(__WIN32__) && !defined(__GNUC__)
67 #include <eh.h>
68 #endif
69 #include <dbghelp.h>
70 #endif
71
72 #ifndef WIN32
73 #include <poll.h>
74
75 #define stricmp strcasecmp
76 #define strnicmp strncasecmp
77 #define _strnicmp strncasecmp
78 #endif
79
80 #include <stdlib.h>
81 #include "network_message.h"
82 #include "network_protocol.h"
83 #include "conversion.h"
84 #include "gen_uuid.h"
85 //#include "intro.h"
86 #include "leak_dumper.h"
87
88 #if defined(WIN32)
89 #ifndef _DEBUG
90 #ifndef __GNUC__
91
92 #define WIN32_STACK_TRACE
93
94 #endif
95 #endif
96 #endif
97
98 using namespace std;
99 using namespace Shared::Platform;
100 using namespace Shared::Util;
101 using namespace Shared::Graphics;
102 using namespace Shared::Graphics::Gl;
103 using namespace Shared::Xml;
104 using namespace Shared;
105
106 /**
107 * @namespace Glest
108 * Namespace used for all %Glest related code.
109 */
110 /**
111 * @namespace Game
112 * Namespace used for game related code.
113 */
114 namespace Glest { namespace Game {
115
116 static string tempDataLocation = getUserHome();
117 static string mg_app_name = "";
118 static string mailStringSupport = "";
119 static bool sdl_quitCalled = false;
120
121 static bool disableheadless_console = false;
122 static bool disableBacktrace = false;
123 static bool gameInitialized = false;
124
125 static Program *mainProgram = NULL;
126 static FileCRCPreCacheThread *preCacheThread = NULL;
127 #ifdef WIN32
128 static string runtimeErrorMsg = "";
129 // keeps in scope for duration of the application
130 //SocketManager *winSockManager = NULL;
131
132 #endif
133
134 #ifdef HAVE_GOOGLE_BREAKPAD
135 auto_ptr<google_breakpad::ExceptionHandler> errorHandlerPtr;
136 #endif
137
138 class NavtiveLanguageNameListCacheGenerator : public SimpleTaskCallbackInterface {
simpleTask(BaseThread * callingThread,void * userdata)139 virtual void simpleTask(BaseThread *callingThread,void *userdata) {
140 Lang &lang = Lang::getInstance();
141 lang.getDiscoveredLanguageList(true);
142 }
143 };
144
145 // =====================================================
146 // class ExceptionHandler
147 // =====================================================
148 class ExceptionHandler: public PlatformExceptionHandler{
149 public:
150
151 #if defined(__WIN32__) && !defined(__GNUC__)
152 virtual void handle(LPEXCEPTION_POINTERS pointers);
153 #endif
154
155 virtual void handle();
156
157 static void logError(const char *msg, bool confirmToConsole);
158 static void handleRuntimeError(const megaglest_runtime_error &ex);
159 static void handleRuntimeError(const char *msg, bool getStackTraceString);
160 static int DisplayMessage(const char *msg, bool exitApp);
161 };
162
cleanupCRCThread()163 void cleanupCRCThread() {
164 if(preCacheThread != NULL) {
165 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
166
167 const double MAX_THREAD_WAIT = 60;
168 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("START - shutting down crc threads\n");
169 time_t elapsed = time(NULL);
170 preCacheThread->signalQuit();
171 for(;preCacheThread->canShutdown(false) == false &&
172 difftime((long int)time(NULL),elapsed) <= MAX_THREAD_WAIT;) {
173 }
174 if(difftime((long int)time(NULL),elapsed) <= MAX_THREAD_WAIT) {
175 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("B - shutting down crc threads\n");
176
177 for(;preCacheThread->shutdownAndWait() == false &&
178 difftime((long int)time(NULL),elapsed) <= MAX_THREAD_WAIT;) {
179 }
180 if(preCacheThread->getRunningStatus() == false) {
181 delete preCacheThread;
182 preCacheThread=NULL;
183 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("C - shutting down crc threads\n");
184 }
185 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
186 }
187 else {
188 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("D - shutting down crc threads\n");
189
190 if(preCacheThread->canShutdown(false) == true) {
191 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
192 delete preCacheThread;
193 preCacheThread=NULL;
194
195 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("E - shutting down crc threads\n");
196 }
197 }
198 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("F - shutting down crc threads\n");
199 preCacheThread = NULL;
200 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
201 }
202 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
203 }
204
cleanupProcessObjects()205 static void cleanupProcessObjects() {
206 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
207
208 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
209 showCursor(true);
210 restoreVideoMode(::Shared::Platform::Window::getSDLWindow(), true);
211 }
212
213 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#1 IRCCLient Cache SHUTDOWN\n");
214 IRCThread * &ircClient = CacheManager::getCachedItem< IRCThread * >(GameConstants::ircClientCacheLookupKey);
215 if(ircClient != NULL) {
216 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#2 IRCCLient Cache SHUTDOWN\n");
217 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
218
219 ircClient->disconnect();
220 ircClient->signalQuit();
221 ircClient = NULL;
222 sleep(0);
223 }
224 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#4 IRCCLient Cache SHUTDOWN\n");
225
226 cleanupCRCThread();
227 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
228
229 if(Renderer::isEnded() == false) {
230 Renderer::getInstance().end();
231 CoreData &coreData= CoreData::getInstance();
232 coreData.cleanup();
233 }
234
235 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
236
237 SystemFlags::Close();
238 SystemFlags::SHUTDOWN_PROGRAM_MODE=true;
239
240 //printf("Closing IRC CLient %d\n",__LINE__);
241
242 Thread::shutdownThreads();
243
244 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("start running threads = " MG_SIZE_T_SPECIFIER "\n",Thread::getThreadList().size());
245 time_t elapsed = time(NULL);
246 int lastLazyThreadDump = 0;
247 for(;Thread::getThreadList().size() > 0 &&
248 difftime((long int)time(NULL),elapsed) <= 10;) {
249
250 if(difftime((long int)time(NULL),elapsed) > 1) {
251 if(lastLazyThreadDump != (int)difftime((long int)time(NULL),elapsed)) {
252 lastLazyThreadDump = difftime((long int)time(NULL),elapsed);
253
254 printf("Waiting for the following threads to exit [" MG_SIZE_T_SPECIFIER "]:\n",Thread::getThreadList().size());
255
256 for(int i = 0; i < (int)Thread::getThreadList().size(); ++i) {
257 BaseThread *baseThread = dynamic_cast<BaseThread *>(Thread::getThreadList()[i]);
258 printf("Thread index: %d ptr [%p] isBaseThread: %d, Name: [%s]\n",i,baseThread,(baseThread != NULL ? 1 : 0),(baseThread != NULL ? baseThread->getUniqueID().c_str() : "<na>"));
259 }
260 }
261 }
262 }
263 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("end running threads = " MG_SIZE_T_SPECIFIER "\n",Thread::getThreadList().size());
264
265 Thread::shutdownThreads();
266
267 std::map<int,Texture2D *> &crcPlayerTextureCache = CacheManager::getCachedItem< std::map<int,Texture2D *> >(GameConstants::playerTextureCacheLookupKey);
268 crcPlayerTextureCache.clear();
269
270 std::map<string,Texture2D *> &crcFactionPreviewTextureCache = CacheManager::getCachedItem< std::map<string,Texture2D *> >(GameConstants::factionPreviewTextureCacheLookupKey);
271 crcFactionPreviewTextureCache.clear();
272
273 std::map<string, vector<FileReader<Pixmap2D> const * >* > &list2d = FileReader<Pixmap2D>::getFileReadersMap();
274 deleteMapValues(list2d.begin(),list2d.end());
275 std::map<string, vector<FileReader<Pixmap3D> const * >* > &list3d = FileReader<Pixmap3D>::getFileReadersMap();
276 deleteMapValues(list3d.begin(),list3d.end());
277
278 #if defined(WANT_XERCES)
279
280 XmlIo::getInstance().cleanup();
281
282 #endif
283
284 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
285
286 SystemFlags::globalCleanupHTTP();
287 CacheManager::cleanupMutexes();
288 }
289
290 #if defined(WIN32) && !defined(_DEBUG) && !defined(__GNUC__)
fatal(const char * s,...)291 void fatal(const char *s, ...) // failure exit
292 {
293 static int errors = 0;
294 errors++;
295
296 if(errors <= 5) { // print up to two extra recursive errors
297 defvformatstring(msg,s,s);
298 string errText = string(msg) + " [" + runtimeErrorMsg + "]";
299 //puts(msg);
300 string sErr = string(mg_app_name) + " fatal error";
301 SystemFlags::OutputDebug(SystemFlags::debugError,"%s\n",errText.c_str());
302 SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",errText.c_str());
303
304 if(errors <= 1) { // avoid recursion
305 if(SDL_WasInit(SDL_INIT_VIDEO)) {
306 SDL_SetRelativeMouseMode(SDL_FALSE);
307 }
308 #ifdef WIN32
309 LPWSTR wstr = Ansi2WideString(errText.c_str());
310 LPWSTR wstr1 = Ansi2WideString(sErr.c_str());
311
312 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
313 MessageBox(NULL, wstr, wstr1, MB_OK|MB_SYSTEMMODAL);
314 }
315
316 if(wstr) delete [] wstr;
317 if(wstr1) delete [] wstr1;
318 #endif
319 }
320 }
321
322 // Now try to shutdown threads if possible
323 delete mainProgram;
324 mainProgram = NULL;
325 // END
326
327 if(sdl_quitCalled == false) {
328 sdl_quitCalled = true;
329 SDL_Quit();
330 }
331 exit(EXIT_FAILURE);
332 }
333
get_module_path(HMODULE module=0)334 std::string get_module_path(HMODULE module = 0) {
335 char path_name[MAX_PATH] = {};
336 DWORD size = GetModuleFileNameA(module, path_name, MAX_PATH);
337 return std::string(path_name, size);
338 }
write_module_name(string & out,HANDLE process,DWORD64 program_counter)339 void write_module_name(string &out, HANDLE process, DWORD64 program_counter) {
340 DWORD64 module_base = SymGetModuleBase64(process, program_counter);
341 if (module_base) {
342 std::string module_name = get_module_path(reinterpret_cast<HMODULE>(module_base));
343 if (!module_name.empty())
344 out += module_name + "|";
345 else
346 out += "Unknown module|";
347 } else {
348 out += "Unknown module|";
349 }
350 }
351
write_function_name(string & out,HANDLE process,DWORD64 program_counter)352 void write_function_name(string &out, HANDLE process, DWORD64 program_counter) {
353 SYMBOL_INFO_PACKAGE sym = { sizeof(sym) };
354 sym.si.MaxNameLen = MAX_SYM_NAME;
355 if (SymFromAddr(process, program_counter, 0, &sym.si)) {
356 out += string(sym.si.Name) + "()";
357 } else {
358 out += "Unknown function";
359 }
360 }
361
write_file_and_line(string & out,HANDLE process,DWORD64 program_counter)362 void write_file_and_line(string & out, HANDLE process, DWORD64 program_counter) {
363 IMAGEHLP_LINE64 ih_line = { sizeof(IMAGEHLP_LINE64) };
364 DWORD dummy = 0;
365 if (SymGetLineFromAddr64(process, program_counter, &dummy, &ih_line)) {
366 out += string("|") + string(ih_line.FileName) + ":" + intToStr(ih_line.LineNumber);
367 }
368 }
generate_stack_trace(string & out,CONTEXT ctx,int skip)369 void generate_stack_trace(string &out, CONTEXT ctx, int skip) {
370 STACKFRAME64 sf = {};
371 #if !defined(_WIN64)
372 sf.AddrPC.Offset = ctx.Eip;
373 #else
374 sf.AddrPC.Offset = ctx.Rip;
375 #endif
376 sf.AddrPC.Mode = AddrModeFlat;
377 #if !defined(_WIN64)
378 sf.AddrStack.Offset = ctx.Esp;
379 #else
380 sf.AddrStack.Offset = ctx.Rsp;
381 #endif
382 sf.AddrStack.Mode = AddrModeFlat;
383 #if !defined(_WIN64)
384 sf.AddrFrame.Offset = ctx.Ebp;
385 #else
386 sf.AddrFrame.Offset = ctx.Rbp;
387 #endif
388 sf.AddrFrame.Mode = AddrModeFlat;
389
390 HANDLE process = GetCurrentProcess();
391 HANDLE thread = GetCurrentThread();
392
393 bool tryThreadContext = true;
394 CONTEXT threadContext;
395 memset(&threadContext, 0, sizeof(CONTEXT));
396 threadContext.ContextFlags = CONTEXT_FULL;
397
398 for (;;) {
399 SetLastError(0);
400 #if !defined(_WIN64)
401 BOOL stack_walk_ok = StackWalk64(IMAGE_FILE_MACHINE_I386,
402 #else
403 BOOL stack_walk_ok = StackWalk64(IMAGE_FILE_MACHINE_AMD64,
404 #endif
405 process, thread, &sf,
406 (tryThreadContext == false ? &threadContext : &ctx),
407 0, &SymFunctionTableAccess64,
408 &SymGetModuleBase64, 0);
409 if (!stack_walk_ok || !sf.AddrFrame.Offset) {
410 if(tryThreadContext == true) {
411 tryThreadContext = false;
412 if(GetThreadContext(thread, &threadContext) != 0) {
413 #if !defined(_WIN64)
414 sf.AddrPC.Offset = threadContext.Eip;
415 #else
416 sf.AddrPC.Offset = threadContext.Rip;
417 #endif
418 sf.AddrPC.Mode = AddrModeFlat;
419 #if !defined(_WIN64)
420 sf.AddrStack.Offset = threadContext.Esp;
421 #else
422 sf.AddrStack.Offset = threadContext.Rsp;
423 #endif
424 sf.AddrStack.Mode = AddrModeFlat;
425 #if !defined(_WIN64)
426 sf.AddrFrame.Offset = threadContext.Ebp;
427 #else
428 sf.AddrFrame.Offset = threadContext.Rbp;
429 #endif
430 sf.AddrFrame.Mode = AddrModeFlat;
431 }
432 else {
433 return;
434 }
435 }
436 else {
437 return;
438 }
439 }
440
441 if (skip) {
442 --skip;
443 }
444 else {
445 // write the address
446 out += intToStr(sf.AddrPC.Offset) + "|";
447
448 write_module_name(out, process, sf.AddrPC.Offset);
449 write_function_name(out, process, sf.AddrPC.Offset);
450 write_file_and_line(out, process, sf.AddrPC.Offset);
451
452 out += "\n";
453 }
454 }
455 }
456
457 struct UntypedException {
UntypedExceptionGlest::Game::UntypedException458 UntypedException(const EXCEPTION_RECORD & er)
459 : exception_object(reinterpret_cast<void *>(er.ExceptionInformation[1])),
460 type_array(reinterpret_cast<_ThrowInfo *>(er.ExceptionInformation[2])->pCatchableTypeArray)
461 {}
462 void * exception_object;
463 _CatchableTypeArray * type_array;
464 };
465
exception_cast_worker(const UntypedException & e,const type_info & ti)466 void * exception_cast_worker(const UntypedException & e, const type_info & ti) {
467 for (int i = 0; i < e.type_array->nCatchableTypes; ++i) {
468 _CatchableType & type_i = *e.type_array->arrayOfCatchableTypes[i];
469 const std::type_info & ti_i = *reinterpret_cast<std::type_info *>(type_i.pType);
470 if (ti_i == ti) {
471 char * base_address = reinterpret_cast<char *>(e.exception_object);
472 base_address += type_i.thisDisplacement.mdisp;
473 return base_address;
474 }
475 }
476 return 0;
477 }
478
479 template <typename T>
exception_cast(const UntypedException & e)480 T * exception_cast(const UntypedException & e) {
481 const std::type_info & ti = typeid(T);
482 return reinterpret_cast<T *>(exception_cast_worker(e, ti));
483 }
stackdumper(unsigned int type,EXCEPTION_POINTERS * ep,bool fatalExit)484 void stackdumper(unsigned int type, EXCEPTION_POINTERS *ep, bool fatalExit) {
485 #ifdef HAVE_GOOGLE_BREAKPAD
486 if(errorHandlerPtr.get() != NULL) {
487 errorHandlerPtr->WriteMinidump();
488 }
489 #endif
490 if(!ep) {
491 fatal("unknown type");
492 return;
493 }
494 EXCEPTION_RECORD *er = ep->ExceptionRecord;
495 CONTEXT *context = ep->ContextRecord;
496 string out="";
497 int skip = 0;
498
499 switch (er->ExceptionCode) {
500 case 0xE06D7363: { // C++ exception
501 UntypedException ue(*er);
502 if (std::exception * e = exception_cast<std::exception>(ue)) {
503 const std::type_info & ti = typeid(*e);
504 out += string(ti.name()) + ":" + string(e->what());
505 }
506 else {
507 out += "Unknown C++ exception thrown.";
508 }
509 skip = 2; // skip RaiseException and _CxxThrowException
510 } break;
511 case EXCEPTION_ACCESS_VIOLATION: {
512 out += string("Access violation. Illegal ")
513 + (er->ExceptionInformation[0] ? "write" : "read")
514 + string(" by ")
515 + intToStr((int)er->ExceptionAddress)
516 + string(" at ")
517 + intToStr(er->ExceptionInformation[1]);
518 } break;
519 default: {
520 out += "SEH exception thrown. Exception code: "
521 + er->ExceptionCode
522 + string(" at ")
523 + intToStr((int)er->ExceptionAddress);
524 }
525 }
526
527 generate_stack_trace(out, *context, skip);
528
529 if(fatalExit == true) {
530 fatal(out.c_str());
531 }
532 else {
533 ExceptionHandler::logError(out.c_str(), true);
534 }
535 }
536 #endif
537
538 // =====================================================
539 // class ExceptionHandler
540 // =====================================================
541 #if defined(WIN32) && !defined(__GNUC__)
handle(LPEXCEPTION_POINTERS pointers)542 void ExceptionHandler::handle(LPEXCEPTION_POINTERS pointers) {
543 string msg = "#1 An error occurred and " + string(mg_app_name) + " will close.\nPlease report this bug to: " + string(mailString);
544 msg += ", attaching the generated " + getCrashDumpFileName()+ " file.";
545
546 SystemFlags::OutputDebug(SystemFlags::debugError,"%s\n",msg.c_str());
547 SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",msg.c_str());
548
549 stackdumper(0, pointers, false);
550
551 if(mainProgram && gameInitialized == true) {
552 mainProgram->showMessage(msg.c_str());
553 }
554
555 message(msg.c_str(),GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
556 }
557 #endif
558
handle()559 void ExceptionHandler::handle() {
560 string msg = "#1 An error occurred and " + string(mg_app_name) + " will close.\nPlease report this bug to: " + string(mailString);
561 #ifdef WIN32
562 msg += ", attaching the generated " + getCrashDumpFileName()+ " file.";
563 #endif
564 SystemFlags::OutputDebug(SystemFlags::debugError,"%s\n",msg.c_str());
565 SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",msg.c_str());
566
567 if(mainProgram && gameInitialized == true) {
568 mainProgram->showMessage(msg.c_str());
569 }
570
571 message(msg.c_str(),GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
572 }
573
logError(const char * msg,bool confirmToConsole)574 void ExceptionHandler::logError(const char *msg, bool confirmToConsole) {
575 string errorLogFile = "error.log";
576 if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
577 errorLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + errorLogFile;
578 }
579 else {
580 string userData = Config::getInstance().getString("UserData_Root","");
581 if(userData != "") {
582 endPathWithSlash(userData);
583 }
584 errorLogFile = userData + errorLogFile;
585 }
586
587 #if defined(WIN32) && !defined(__MINGW32__)
588 FILE *fp = _wfopen(utf8_decode(errorLogFile).c_str(), L"w");
589 std::ofstream logFile(fp);
590 #else
591 std::ofstream logFile;
592 logFile.open(errorLogFile.c_str(), ios_base::out | ios_base::trunc);
593 #endif
594
595 if(logFile.is_open() == true) {
596 //time_t curtime = time (NULL);
597 //struct tm *loctime = localtime (&curtime);
598 struct tm loctime = threadsafe_localtime(systemtime_now());
599 char szBuf2[100]="";
600 strftime(szBuf2,100,"%Y-%m-%d %H:%M:%S",&loctime);
601
602 logFile << "[" << szBuf2 << "] Runtime Error information:" << std::endl;
603 logFile << "======================================================" << std::endl;
604 logFile << (msg != NULL ? msg : "null") << std::endl;
605 logFile.close();
606
607 #if defined(WIN32) && !defined(__MINGW32__)
608 if(fp) {
609 fclose(fp);
610 }
611 #endif
612 if(confirmToConsole == true) {
613 printf("Error saved to logfile [%s]\n",errorLogFile.c_str());
614 fflush(stdout);
615 }
616 }
617 else {
618 if(confirmToConsole == true) {
619 printf("COULD NOT SAVE TO ERROR logfile [%s]\n",errorLogFile.c_str());
620 fflush(stdout);
621 }
622 }
623 }
624
handleRuntimeError(const megaglest_runtime_error & ex)625 void ExceptionHandler::handleRuntimeError(const megaglest_runtime_error &ex) {
626 const char *msg = ex.what();
627 handleRuntimeError(msg,false);
628 }
629
handleRuntimeError(const char * msg,bool getStackTraceString)630 void ExceptionHandler::handleRuntimeError(const char *msg, bool getStackTraceString) {
631 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
632
633 static bool inErrorNow = false;
634 if(inErrorNow == true) {
635 printf("\n=====================================\n");
636 printf("\n** Already in error handler aborting, msg [%s]\n",msg);
637 fflush(stdout);
638 abort();
639 return;
640 }
641 inErrorNow = true;
642
643 logError(msg,true);
644
645 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] program = %p gameInitialized = %d msg [%s]\n",__FILE__,__FUNCTION__,__LINE__,mainProgram,gameInitialized,msg);
646 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] [%s] gameInitialized = %d, program = %p\n",__FILE__,__FUNCTION__,__LINE__,msg,gameInitialized,mainProgram);
647 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%s] gameInitialized = %d, program = %p\n",__FILE__,__FUNCTION__,__LINE__,msg,gameInitialized,mainProgram);
648
649 string errMsg = (msg != NULL ? msg : "null");
650
651 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
652
653 bool gotStackTrace = false;
654 if(getStackTraceString == true && disableBacktrace == false && sdl_quitCalled == false) {
655 string stackTrace = getStackTrace();
656 errMsg += stackTrace;
657 gotStackTrace = true;
658 }
659
660 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
661
662 logError(errMsg.c_str(),false);
663
664 if(gotStackTrace == true) {
665 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] [%s]\n",__FILE__,__FUNCTION__,__LINE__,errMsg.c_str());
666 }
667 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%s]\n",__FILE__,__FUNCTION__,__LINE__,errMsg.c_str());
668
669 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
670
671 //abort();
672
673 if(mainProgram && gameInitialized == true) {
674 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
675
676 if(mainProgram->getState() != NULL) {
677 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
678 mainProgram->showMessage(errMsg.c_str());
679 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
680
681 if(glActiveTexture != NULL) {
682 for(;GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false && mainProgram->isMessageShowing();) {
683 ::Shared::Platform::Window::handleEvent();
684 try {
685 mainProgram->loop();
686 }
687 catch(const exception &e) {
688 printf("\n=====================================\n");
689 printf("\n** Already in error handler exiting error rendering, msg [%s]\n",e.what());
690 fflush(stdout);
691 break;
692 }
693 }
694 }
695 }
696 else {
697 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
698 mainProgram->showMessage(errMsg.c_str());
699 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
700
701 if(glActiveTexture != NULL) {
702 for(;GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false && mainProgram->isMessageShowing();) {
703 ::Shared::Platform::Window::handleEvent();
704 try {
705 mainProgram->loop();
706 }
707 catch(const exception &e) {
708 printf("\n=====================================\n");
709 printf("\n** Already in error handler exiting error rendering, msg [%s]\n",e.what());
710 fflush(stdout);
711 break;
712 }
713 }
714 }
715 }
716 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
717 }
718 else {
719 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
720
721 string err = "#2 An error occurred and ";
722 if(sdl_quitCalled == false) {
723 err += mg_app_name;
724 }
725 err += " will close.\nError msg = [" + errMsg + "]\n\nPlease report this bug to ";
726 if(sdl_quitCalled == false) {
727 err += mailStringSupport;
728 }
729 #ifdef WIN32
730 err += string(", attaching the generated ") + getCrashDumpFileName() + string(" file.");
731 #endif
732 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
733
734 message(err,GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
735 }
736
737 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
738
739 // Now try to shutdown threads if possible
740 delete mainProgram;
741 mainProgram = NULL;
742 // END
743
744 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
745
746 #ifdef WIN32
747
748 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
749 showCursor(true);
750 restoreVideoMode(::Shared::Platform::Window::getSDLWindow(), true);
751 }
752
753 runtimeErrorMsg = errMsg;
754 inErrorNow = false;
755 throw runtimeErrorMsg;
756 #endif
757
758 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
759
760 cleanupProcessObjects();
761
762 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
763
764 if(sdl_quitCalled == false) {
765 sdl_quitCalled = true;
766 SDL_Quit();
767 }
768
769 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
770
771 inErrorNow = false;
772
773 abort();
774 }
775
DisplayMessage(const char * msg,bool exitApp)776 int ExceptionHandler::DisplayMessage(const char *msg, bool exitApp) {
777 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
778 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
779
780 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
781
782 if(mainProgram && gameInitialized == true) {
783 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
784 mainProgram->showMessage(msg);
785 }
786 else {
787 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
788 message(msg,GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
789 }
790
791 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
792
793 if(exitApp == true) {
794 SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",msg);
795
796 // Now try to shutdown threads if possible
797 delete mainProgram;
798 mainProgram = NULL;
799 // END
800
801 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
802 cleanupProcessObjects();
803
804 if(sdl_quitCalled == false) {
805 sdl_quitCalled = true;
806 SDL_Quit();
807 }
808 exit(-1);
809 }
810
811 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
812 return 0;
813 }
814
815 // =====================================================
816 // class MainWindow
817 // =====================================================
818
MainWindow(Program * program)819 MainWindow::MainWindow(Program *program) : WindowGl(), popupMenu("MainWindow", "popupMenu") {
820 this->program= program;
821 //this->popupMenu.registerGraphicComponentOnlyFontCallbacks("MainWindow", "popupMenu");
822 this->popupMenu.setEnabled(false);
823 this->popupMenu.setVisible(false);
824 this->triggerLanguageToggle = false;
825 this->triggerLanguage = "";
826 this->cancelLanguageSelection = -1;
827 }
828
~MainWindow()829 MainWindow::~MainWindow(){
830 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
831 delete program;
832 program = NULL;
833 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
834 }
835
getDesiredScreenWidth()836 int MainWindow::getDesiredScreenWidth() {
837 Config &config= Config::getInstance();
838 return config.getInt("ScreenWidth");
839 }
getDesiredScreenHeight()840 int MainWindow::getDesiredScreenHeight() {
841 Config &config= Config::getInstance();
842 return config.getInt("ScreenHeight");
843 }
844
eventToggleFullScreen(bool isFullscreen)845 void MainWindow::eventToggleFullScreen(bool isFullscreen) {
846 WindowGl::eventToggleFullScreen(isFullscreen);
847
848 if(isFullscreen) {
849 Metrics::reload(this->program->getWindow()->getScreenWidth(),
850 this->program->getWindow()->getScreenHeight());
851 }
852 else {
853 Config &config= Config::getInstance();
854 Metrics::reload(config.getInt("ScreenWidth"),config.getInt("ScreenHeight"));
855 //window->setText(config.getString("WindowTitle","MegaGlest"));
856 //this->mainMenu->init();
857 }
858
859 }
860
eventMouseDown(int x,int y,MouseButton mouseButton)861 void MainWindow::eventMouseDown(int x, int y, MouseButton mouseButton){
862 const Metrics &metrics = Metrics::getInstance();
863 int vx = metrics.toVirtualX(x);
864 int vy = metrics.toVirtualY(getH() - y);
865
866 if(program == NULL) {
867 throw megaglest_runtime_error("In [MainWindow::eventMouseDown] ERROR, program == NULL!");
868 }
869
870 if(popupMenu.getVisible() == true && popupMenu.mouseClick(vx, vy)) {
871 std::pair<int,string> result = popupMenu.mouseClickedMenuItem(vx, vy);
872
873 popupMenu.setEnabled(false);
874 popupMenu.setVisible(false);
875
876 // Exit game
877 if(result.first != cancelLanguageSelection) {
878 Lang &lang= Lang::getInstance();
879 map<string,string> languageList = lang.getDiscoveredLanguageList(true);
880 for(map<string,string>::iterator iterMap = languageList.begin();
881 iterMap != languageList.end(); ++iterMap) {
882 string matchLanguage = iterMap->first + "-" + iterMap->second;
883 if(matchLanguage == result.second) {
884 this->triggerLanguageToggle = true;
885 this->triggerLanguage = iterMap->first;
886 break;
887 }
888 }
889
890 }
891
892 return;
893 }
894 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
895
896 switch(mouseButton) {
897 case mbLeft:
898 program->mouseDownLeft(vx, vy);
899 break;
900 case mbRight:
901 //program->mouseDownRight(vx, vy);
902 break;
903 case mbCenter:
904 //program->mouseDownCenter(vx, vy);
905 break;
906 default:
907 break;
908 }
909
910 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
911
912 ProgramState *programState = program->getState();
913 if(programState != NULL) {
914 switch(mouseButton) {
915 case mbLeft:
916 programState->mouseDownLeft(vx, vy);
917 break;
918 case mbRight:
919 programState->mouseDownRight(vx, vy);
920 break;
921 case mbCenter:
922 programState->mouseDownCenter(vx, vy);
923 break;
924 default:
925 break;
926 }
927 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
928 }
929 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
930 }
931
eventMouseUp(int x,int y,MouseButton mouseButton)932 void MainWindow::eventMouseUp(int x, int y, MouseButton mouseButton){
933 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
934
935 const Metrics &metrics = Metrics::getInstance();
936 int vx = metrics.toVirtualX(x);
937 int vy = metrics.toVirtualY(getH() - y);
938
939 if(program == NULL) {
940 throw megaglest_runtime_error("In [MainWindow::eventMouseUp] ERROR, program == NULL!");
941 }
942
943 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
944
945 ProgramState *programState = program->getState();
946
947 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
948
949 if(programState != NULL) {
950 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
951
952 switch(mouseButton) {
953 case mbLeft:
954 programState->mouseUpLeft(vx, vy);
955 break;
956 case mbRight:
957 programState->mouseUpRight(vx, vy);
958 break;
959 case mbCenter:
960 programState->mouseUpCenter(vx, vy);
961 break;
962 default:
963 break;
964 }
965 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
966 }
967 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
968 }
969
eventMouseDoubleClick(int x,int y,MouseButton mouseButton)970 void MainWindow::eventMouseDoubleClick(int x, int y, MouseButton mouseButton) {
971 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
972
973 const Metrics &metrics= Metrics::getInstance();
974 int vx = metrics.toVirtualX(x);
975 int vy = metrics.toVirtualY(getH() - y);
976
977 if(program == NULL) {
978 throw megaglest_runtime_error("In [MainWindow::eventMouseDoubleClick] ERROR, program == NULL!");
979 }
980
981 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
982
983 ProgramState *programState = program->getState();
984
985 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
986
987 if(programState != NULL) {
988 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
989
990 switch(mouseButton){
991 case mbLeft:
992 programState->mouseDoubleClickLeft(vx, vy);
993 break;
994 case mbRight:
995 programState->mouseDoubleClickRight(vx, vy);
996 break;
997 case mbCenter:
998 programState->mouseDoubleClickCenter(vx, vy);
999 break;
1000 default:
1001 break;
1002 }
1003
1004 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1005 }
1006 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1007 }
1008
eventMouseMove(int x,int y,const MouseState * ms)1009 void MainWindow::eventMouseMove(int x, int y, const MouseState *ms){
1010
1011 const Metrics &metrics= Metrics::getInstance();
1012 int vx = metrics.toVirtualX(x);
1013 int vy = metrics.toVirtualY(getH() - y);
1014
1015 if(program == NULL) {
1016 throw megaglest_runtime_error("In [MainWindow::eventMouseMove] ERROR, program == NULL!");
1017 }
1018
1019 program->eventMouseMove(vx, vy, ms);
1020
1021 ProgramState *programState = program->getState();
1022 if(programState != NULL) {
1023 programState->mouseMove(vx, vy, ms);
1024 }
1025 }
1026
eventMouseWheel(int x,int y,int zDelta)1027 void MainWindow::eventMouseWheel(int x, int y, int zDelta) {
1028
1029 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1030
1031 const Metrics &metrics= Metrics::getInstance();
1032 int vx = metrics.toVirtualX(x);
1033 int vy = metrics.toVirtualY(getH() - y);
1034
1035 if(program == NULL) {
1036 throw megaglest_runtime_error("In [MainWindow::eventMouseMove] ERROR, program == NULL!");
1037 }
1038
1039 ProgramState *programState = program->getState();
1040
1041 if(programState != NULL) {
1042 programState->eventMouseWheel(vx, vy, zDelta);
1043 }
1044
1045 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1046 }
1047
render()1048 void MainWindow::render() {
1049 if(popupMenu.getVisible() == true) {
1050 Renderer &renderer= Renderer::getInstance();
1051 renderer.renderPopupMenu(&popupMenu);
1052 }
1053 }
1054
showLanguages()1055 void MainWindow::showLanguages() {
1056 Lang &lang= Lang::getInstance();
1057 std::vector<string> menuItems;
1058 map<string,string> languageList = lang.getDiscoveredLanguageList(true);
1059 for(map<string,string>::iterator iterMap = languageList.begin();
1060 iterMap != languageList.end(); ++iterMap) {
1061 menuItems.push_back(iterMap->first + "-" + iterMap->second);
1062 }
1063
1064 menuItems.push_back(lang.getString("Exit"));
1065 cancelLanguageSelection = (int)menuItems.size()-1;
1066
1067 popupMenu.setW(100);
1068 popupMenu.setH(100);
1069 popupMenu.init(lang.getString("GameMenuTitle"),menuItems);
1070 popupMenu.setEnabled(true);
1071 popupMenu.setVisible(true);
1072 }
1073
toggleLanguage(string language)1074 void MainWindow::toggleLanguage(string language) {
1075 popupMenu.setEnabled(false);
1076 popupMenu.setVisible(false);
1077 this->triggerLanguageToggle = false;
1078 this->triggerLanguage = "";
1079
1080 Lang &lang= Lang::getInstance();
1081 string currentLanguage = lang.getLanguage();
1082
1083 string newLanguageSelected = language;
1084 if(language == "") {
1085 newLanguageSelected = currentLanguage;
1086
1087 vector<string> langResults;
1088 string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
1089
1090 string userDataPath = getGameCustomCoreDataPath(data_path, "");
1091 findAll(userDataPath + "data/lang/*.lng", langResults, true, false);
1092
1093 vector<string> langResults2;
1094 findAll(data_path + "data/lang/*.lng", langResults2, true);
1095 if(langResults2.empty() && langResults.empty()) {
1096 throw megaglest_runtime_error("There are no lang files");
1097 }
1098 for(unsigned int i = 0; i < langResults2.size(); ++i) {
1099 string testLanguage = langResults2[i];
1100 if(std::find(langResults.begin(),langResults.end(),testLanguage) == langResults.end()) {
1101 langResults.push_back(testLanguage);
1102 }
1103 }
1104
1105 for(unsigned int i = 0; i < langResults.size(); ++i) {
1106 string testLanguage = langResults[i];
1107 if(testLanguage == currentLanguage) {
1108 if( i+1 < langResults.size()) {
1109 newLanguageSelected = langResults[i+1];
1110 }
1111 else {
1112 newLanguageSelected = langResults[0];
1113 }
1114 break;
1115 }
1116 }
1117 }
1118 if(newLanguageSelected != currentLanguage) {
1119 lang.loadGameStrings(newLanguageSelected);
1120 program->reloadUI();
1121 program->consoleAddLine(lang.getString("Language") + " " + newLanguageSelected);
1122 }
1123 }
1124
eventTextInput(std::string text)1125 bool MainWindow::eventTextInput(std::string text) {
1126 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%s]\n",__FILE__,__FUNCTION__,__LINE__,text.c_str());
1127
1128 if(program == NULL) {
1129 throw megaglest_runtime_error("In [MainWindow::eventKeyDown] ERROR, program == NULL!");
1130 }
1131
1132 bool result = program->textInput(text);
1133
1134 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] result = %d\n",__FILE__,__FUNCTION__,__LINE__,result);
1135
1136 return result;
1137 }
1138
eventSdlKeyDown(SDL_KeyboardEvent key)1139 bool MainWindow::eventSdlKeyDown(SDL_KeyboardEvent key) {
1140 if(program == NULL) {
1141 throw megaglest_runtime_error("In [MainWindow::eventKeyDown] ERROR, program == NULL!");
1142 }
1143 return program->sdlKeyDown(key);
1144 }
1145
eventKeyDown(SDL_KeyboardEvent key)1146 void MainWindow::eventKeyDown(SDL_KeyboardEvent key) {
1147 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym);
1148
1149 //printf("In mainwindow checking keypress for key [%d]\n",key.keysym.sym);
1150
1151 SDL_keysym keystate = key.keysym;
1152
1153 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c][%d]\n",__FILE__,__FUNCTION__,__LINE__,key,key);
1154
1155 if(program == NULL) {
1156 throw megaglest_runtime_error("In [MainWindow::eventKeyDown] ERROR, program == NULL!");
1157 }
1158
1159 if(popupMenu.getVisible() == true && isKeyPressed(SDLK_ESCAPE,key) == true) {
1160 this->popupMenu.setEnabled(false);
1161 this->popupMenu.setVisible(false);
1162 return;
1163 }
1164
1165 program->keyDown(key);
1166
1167 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1168
1169 if(keystate.mod & (KMOD_LALT | KMOD_RALT)) {
1170 //if(key == vkReturn) {
1171 if(isKeyPressed(SDLK_RETURN,key) == true) {
1172 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] ALT-ENTER pressed\n",__FILE__,__FUNCTION__,__LINE__);
1173
1174 // This stupidity only required in win32.
1175 // We reload the textures so that the canvas paints textures properly
1176 #ifdef WIN32
1177 if(Window::getAllowAltEnterFullscreenToggle() == true) {
1178 Renderer &renderer= Renderer::getInstance();
1179 renderer.reinitAll();
1180 }
1181 #endif
1182
1183 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1184 }
1185 }
1186
1187 //printf("In mainwindow checking keypress for key [%d] mod [%d] modvalue: %d\n",key.keysym.sym,keystate.mod,(keystate.mod & (KMOD_LCTRL | KMOD_RCTRL)));
1188
1189 if(program != NULL && program->isInSpecialKeyCaptureEvent() == false) {
1190 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1191
1192 vector<int> modifiersToCheck;
1193 modifiersToCheck.push_back(KMOD_LCTRL);
1194 modifiersToCheck.push_back(KMOD_RCTRL);
1195 modifiersToCheck.push_back(KMOD_LALT);
1196 modifiersToCheck.push_back(KMOD_RALT);
1197 modifiersToCheck.push_back(KMOD_LSHIFT);
1198 modifiersToCheck.push_back(KMOD_RSHIFT);
1199
1200 Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
1201 if(isKeyPressed(configKeys.getSDLKey("HotKeyShowDebug"),key) == true) {
1202
1203 Renderer &renderer= Renderer::getInstance();
1204 if(keystate.mod & (KMOD_LALT | KMOD_RALT)) {
1205 renderer.cycleShowDebugUILevel();
1206 printf("**Cycled Debug UI level to: %d\n",renderer.getShowDebugUILevel());
1207 }
1208 else {
1209 bool showDebugUI = renderer.getShowDebugUI();
1210 renderer.setShowDebugUI(!showDebugUI);
1211 }
1212 }
1213 else if((keystate.mod & (KMOD_LCTRL | KMOD_RCTRL)) &&
1214 isKeyPressed(configKeys.getSDLKey("SwitchLanguage"),key) == true) {
1215 if((keystate.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) {
1216 this->triggerLanguageToggle = true;
1217 this->triggerLanguage = "";
1218 }
1219 else {
1220 showLanguages();
1221 }
1222 }
1223 else if(isKeyPressed(configKeys.getSDLKey("ReloadINI"),key,modifiersToCheck) == true) {
1224 Config &config = Config::getInstance();
1225 config.reload();
1226 }
1227 else if(isKeyPressed(configKeys.getSDLKey("Screenshot"),key,modifiersToCheck) == true) {
1228 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot key pressed\n");
1229
1230 string userData = Config::getInstance().getString("UserData_Root","");
1231 if(userData != "") {
1232 endPathWithSlash(userData);
1233 }
1234
1235 string path = userData + GameConstants::folder_path_screenshots;
1236 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot checking path [%s]\n",path.c_str());
1237
1238 if(isdir(path.c_str()) == false) {
1239 createDirectoryPaths(path);
1240 }
1241
1242 if(isdir(path.c_str()) == true) {
1243 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot path [%s]\n",path.c_str());
1244
1245 Config &config= Config::getInstance();
1246 string fileFormat = config.getString("ScreenShotFileType","jpg");
1247
1248 unsigned int queueSize = Renderer::getInstance().getSaveScreenQueueSize();
1249
1250 for(int i=0; i < 5000; ++i) {
1251 path = userData + GameConstants::folder_path_screenshots;
1252 path += string("screen") + intToStr(i + queueSize) + string(".") + fileFormat;
1253 #ifdef WIN32
1254 FILE *f= _wfopen(utf8_decode(path).c_str(), L"rb");
1255 #else
1256 FILE *f= fopen(path.c_str(), "rb");
1257 #endif
1258 if(f == NULL) {
1259 Lang &lang= Lang::getInstance();
1260 char szBuf[8096]="";
1261 if(lang.getString("ScreenshotSavedTo").length() > 0 && lang.getString("ScreenshotSavedTo")[0] != '?') {
1262 snprintf(szBuf,8096,lang.getString("ScreenshotSavedTo").c_str(),path.c_str());
1263 }
1264 else {
1265 snprintf(szBuf,8096,"Screenshot will be saved to: %s",path.c_str());
1266 }
1267
1268 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
1269
1270 bool showScreenshotSavedMsg = Config::getInstance().getBool("DisableScreenshotConsoleText","false");
1271 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot console showScreenshotSavedMsg = %d\n",showScreenshotSavedMsg);
1272
1273 if(showScreenshotSavedMsg == false) {
1274 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot console [%s]\n",szBuf);
1275 program->consoleAddLine(szBuf);
1276 }
1277
1278 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot save to [%s]\n",path.c_str());
1279 Renderer::getInstance().saveScreen(path);
1280 break;
1281 }
1282 else {
1283 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CANNOT save Screenshot [%s]\n",path.c_str());
1284 fclose(f);
1285 }
1286 }
1287 }
1288 }
1289 }
1290
1291 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1292 }
1293
eventKeyUp(SDL_KeyboardEvent key)1294 void MainWindow::eventKeyUp(SDL_KeyboardEvent key) {
1295 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key);
1296 if(program == NULL) {
1297 throw megaglest_runtime_error("In [MainWindow::eventKeyUp] ERROR, program == NULL!");
1298 }
1299
1300 program->keyUp(key);
1301 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key);
1302 }
1303
eventKeyPress(SDL_KeyboardEvent c)1304 void MainWindow::eventKeyPress(SDL_KeyboardEvent c) {
1305 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,c);
1306 if(program == NULL) {
1307 throw megaglest_runtime_error("In [MainWindow::eventKeyPress] ERROR, program == NULL!");
1308 }
1309
1310 program->keyPress(c);
1311
1312 if(program != NULL && program->isInSpecialKeyCaptureEvent() == false) {
1313 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1314
1315 Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
1316 if(isKeyPressed(configKeys.getSDLKey("HotKeyToggleOSMouseEnabled"),c) == true) {
1317 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1318
1319 bool showCursorState = false;
1320 int state = SDL_ShowCursor(SDL_QUERY);
1321 if(state == SDL_DISABLE) {
1322 showCursorState = true;
1323 }
1324
1325 showCursor(showCursorState);
1326 Renderer &renderer= Renderer::getInstance();
1327 renderer.setNo2DMouseRendering(showCursorState);
1328
1329 Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
1330 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
1331 }
1332 }
1333 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,c);
1334 }
1335
eventWindowEvent(SDL_WindowEvent event)1336 void MainWindow::eventWindowEvent(SDL_WindowEvent event) {
1337 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,event.event);
1338 if(program == NULL) {
1339 throw megaglest_runtime_error("In [MainWindow::eventKeyPress] ERROR, program == NULL!");
1340 }
1341
1342 // if(program->getState() != NULL && dynamic_cast<Intro *>(program->getState()) != NULL) {
1343 // printf("In eventWindowEvent skip\n");
1344 // return;
1345 // }
1346 //Renderer &renderer= Renderer::getInstance();
1347 switch(event.event) {
1348 case SDL_WINDOWEVENT_ENTER:
1349 {
1350 //printf("In SDL_WINDOWEVENT_ENTER\n");
1351 // bool showCursorState = Window::lastShowMouseState;
1352 // showCursor(showCursorState);
1353 // renderer.setNo2DMouseRendering(showCursorState);
1354 //
1355 // Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
1356 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
1357 }
1358 break;
1359 case SDL_WINDOWEVENT_LEAVE:
1360 {
1361 //printf("In SDL_WINDOWEVENT_LEAVE\n");
1362 // bool showCursorState = false;
1363 // int state = SDL_ShowCursor(SDL_QUERY);
1364 // if(state == SDL_DISABLE) {
1365 // showCursorState = true;
1366 // }
1367 // showCursor(showCursorState);
1368 // renderer.setNo2DMouseRendering(showCursorState);
1369 //
1370 // Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
1371 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
1372 }
1373 break;
1374 case SDL_WINDOWEVENT_FOCUS_GAINED:
1375 {
1376 //printf("SDL_WINDOWEVENT_FOCUS_GAINED\n");
1377 // bool showCursorState = Window::lastShowMouseState;
1378 // showCursor(showCursorState);
1379 // renderer.setNo2DMouseRendering(showCursorState);
1380 //
1381 // Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
1382 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
1383 }
1384 break;
1385 case SDL_WINDOWEVENT_FOCUS_LOST:
1386 {
1387 //printf("SDL_WINDOWEVENT_FOCUS_LOST\n");
1388 // bool showCursorState = false;
1389 // int state = SDL_ShowCursor(SDL_QUERY);
1390 // if(state == SDL_DISABLE) {
1391 // showCursorState = true;
1392 // }
1393 // showCursor(showCursorState);
1394 // renderer.setNo2DMouseRendering(showCursorState);
1395 //
1396 // Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
1397 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
1398 }
1399 break;
1400
1401 }
1402
1403 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,event.event);
1404 }
1405
eventActivate(bool active)1406 void MainWindow::eventActivate(bool active) {
1407 if(!active){
1408 //minimize();
1409 }
1410 }
1411
eventResize(SizeState sizeState)1412 void MainWindow::eventResize(SizeState sizeState) {
1413 if(program == NULL) {
1414 throw megaglest_runtime_error("In [MainWindow::eventResize] ERROR, program == NULL!");
1415 }
1416
1417 program->resize(sizeState);
1418 }
1419
eventClose()1420 void MainWindow::eventClose(){
1421 delete program;
1422 program= NULL;
1423 }
1424
setProgram(Program * program)1425 void MainWindow::setProgram(Program *program) {
1426 this->program= program;
1427 }
1428
1429 // =====================================================
1430 // Main
1431 // =====================================================
1432 SystemFlags debugger;
1433
print_SDL_version(const char * preamble,SDL_version * v)1434 void print_SDL_version(const char *preamble, SDL_version *v) {
1435 printf("%s %u.%u.%u\n", preamble, v->major, v->minor, v->patch);
1436 }
1437
setupGameItemPaths(int argc,char ** argv,Config * config)1438 int setupGameItemPaths(int argc, char** argv, Config *config) {
1439 // Setup path cache for files and folders used in the game
1440 std::map<string,string> &pathCache = CacheManager::getCachedItem< std::map<string,string> >(GameConstants::pathCacheLookupKey);
1441
1442 Properties devProperties;
1443 string devPropertyFile = Properties::getApplicationPath() + "glest-dev.ini";
1444 if(fileExists(devPropertyFile) == true) {
1445 devProperties.load(devPropertyFile);
1446
1447 if(devProperties.hasString("ServerListPath") == true) {
1448 string devItem = devProperties.getString("ServerListPath");
1449 if(devItem != "") {
1450 endPathWithSlash(devItem);
1451 }
1452 if(config != NULL) {
1453 config->setString("ServerListPath",devItem,true);
1454 }
1455 }
1456
1457 if(devProperties.hasString("GlestKeysIniPath") == true) {
1458 string devItem = devProperties.getString("GlestKeysIniPath");
1459 if(devItem != "") {
1460 endPathWithSlash(devItem);
1461 }
1462 if(config != NULL) {
1463 config->setString("GlestKeysIniPath",devItem,true);
1464 }
1465 }
1466 }
1467
1468 //GAME_ARG_DATA_PATH
1469 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DATA_PATH]) == true) {
1470 int foundParamIndIndex = -1;
1471 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_DATA_PATH]) + string("="),&foundParamIndIndex);
1472 if(foundParamIndIndex < 0) {
1473 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_DATA_PATH]),&foundParamIndIndex);
1474 }
1475 string customPath = argv[foundParamIndIndex];
1476 vector<string> paramPartTokens;
1477 Tokenize(customPath,paramPartTokens,"=");
1478 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
1479 string customPathValue = paramPartTokens[1];
1480 Properties::applyTagsToValue(customPathValue);
1481 if(customPathValue != "") {
1482 endPathWithSlash(customPathValue);
1483 }
1484 pathCache[GameConstants::path_data_CacheLookupKey] = customPathValue;
1485 Properties::setApplicationDataPath(pathCache[GameConstants::path_data_CacheLookupKey]);
1486
1487 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom data path [%s]\n",customPathValue.c_str());
1488 }
1489 else {
1490
1491 printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
1492 printParameterHelp(argv[0],false);
1493 return 1;
1494 }
1495 }
1496 else if(config != NULL) {
1497
1498 bool foundPath = false;
1499 string customPathValue = "";
1500
1501 if(fileExists(devPropertyFile) == true && devProperties.hasString("DataPath") == true) {
1502 foundPath = true;
1503 customPathValue = devProperties.getString("DataPath","");
1504 }
1505 else if(config->getString("DataPath","") != "") {
1506 foundPath = true;
1507 customPathValue = config->getString("DataPath","");
1508 }
1509
1510 if(foundPath == true) {
1511 pathCache[GameConstants::path_data_CacheLookupKey] = customPathValue;
1512
1513 if(customPathValue != "") {
1514 endPathWithSlash(customPathValue);
1515 }
1516
1517 Properties::setApplicationDataPath(pathCache[GameConstants::path_data_CacheLookupKey]);
1518
1519 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using ini specified data path [%s]\n",config->getString("DataPath","").c_str());
1520 }
1521 }
1522
1523 //GAME_ARG_INI_PATH
1524 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_INI_PATH]) == true) {
1525 int foundParamIndIndex = -1;
1526 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_INI_PATH]) + string("="),&foundParamIndIndex);
1527 if(foundParamIndIndex < 0) {
1528 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_INI_PATH]),&foundParamIndIndex);
1529 }
1530 string customPath = argv[foundParamIndIndex];
1531 vector<string> paramPartTokens;
1532 Tokenize(customPath,paramPartTokens,"=");
1533 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
1534 string customPathValue = paramPartTokens[1];
1535 Properties::applyTagsToValue(customPathValue);
1536 pathCache[GameConstants::path_ini_CacheLookupKey]=customPathValue;
1537 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom ini path [%s]\n",customPathValue.c_str());
1538 }
1539 else {
1540
1541 printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
1542 printParameterHelp(argv[0],false);
1543 return 1;
1544 }
1545 }
1546
1547 //GAME_ARG_LOG_PATH
1548 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LOG_PATH]) == true) {
1549 int foundParamIndIndex = -1;
1550 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOG_PATH]) + string("="),&foundParamIndIndex);
1551 if(foundParamIndIndex < 0) {
1552 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOG_PATH]),&foundParamIndIndex);
1553 }
1554 string customPath = argv[foundParamIndIndex];
1555 vector<string> paramPartTokens;
1556 Tokenize(customPath,paramPartTokens,"=");
1557 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
1558 string customPathValue = paramPartTokens[1];
1559 Properties::applyTagsToValue(customPathValue);
1560 pathCache[GameConstants::path_logs_CacheLookupKey]=customPathValue;
1561 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom logs path [%s]\n",customPathValue.c_str());
1562 }
1563 else {
1564
1565 printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
1566 printParameterHelp(argv[0],false);
1567 return 1;
1568 }
1569 }
1570 else if(config != NULL) {
1571
1572 bool foundPath = false;
1573 string customPathValue = "";
1574
1575 if(fileExists(devPropertyFile) == true && devProperties.hasString("LogPath") == true) {
1576 foundPath = true;
1577 customPathValue = devProperties.getString("LogPath","");
1578 }
1579 else if(config->getString("LogPath","") != "") {
1580 foundPath = true;
1581 customPathValue = config->getString("LogPath","");
1582 }
1583
1584 if(foundPath == true) {
1585 pathCache[GameConstants::path_logs_CacheLookupKey] = customPathValue;
1586 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using ini specified logs path [%s]\n",config->getString("LogPath","").c_str());
1587 }
1588 }
1589
1590 Text::DEFAULT_FONT_PATH = pathCache[GameConstants::path_data_CacheLookupKey];
1591 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_FONT_PATH]) == true) {
1592 int foundParamIndIndex = -1;
1593 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_PATH]) + string("="),&foundParamIndIndex);
1594 if(foundParamIndIndex < 0) {
1595 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_PATH]),&foundParamIndIndex);
1596 }
1597 string customPath = argv[foundParamIndIndex];
1598 vector<string> paramPartTokens;
1599 Tokenize(customPath,paramPartTokens,"=");
1600 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
1601 string customPathValue = paramPartTokens[1];
1602 Properties::applyTagsToValue(customPathValue);
1603
1604 Text::DEFAULT_FONT_PATH_ABSOLUTE = customPathValue;
1605 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom fonts path [%s]\n",customPathValue.c_str());
1606 }
1607 else {
1608
1609 printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
1610 printParameterHelp(argv[0],false);
1611 return 1;
1612 }
1613 }
1614
1615 return 0;
1616 }
1617
setupLogging(Config & config,bool haveSpecialOutputCommandLineOption)1618 void setupLogging(Config &config, bool haveSpecialOutputCommandLineOption) {
1619
1620 SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled = config.getBool("DebugMode","false");
1621 SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled = config.getBool("DebugNetwork","false");
1622 SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled = config.getBool("DebugPerformance","false");
1623 SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled = config.getBool("DebugWorldSynch","false");
1624 SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled = config.getBool("DebugUnitCommands","false");
1625 SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled = config.getBool("DebugPathFinder","false");
1626 SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled = config.getBool("DebugLUA","false");
1627 LuaScript::setDebugModeEnabled(SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled);
1628 SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled = config.getBool("DebugSound","false");
1629 SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled = config.getBool("DebugError","true");
1630
1631 string userData = config.getString("UserData_Root","");
1632 if(userData != "") {
1633 endPathWithSlash(userData);
1634 }
1635
1636 #ifdef HAVE_GOOGLE_BREAKPAD
1637 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#1 In setting up errorHandlerPtr->set_dump_path [%p]...\n",errorHandlerPtr.get());
1638 if(errorHandlerPtr.get() != NULL) {
1639 string dumpFilePath;
1640 if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1641 dumpFilePath = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey);
1642 }
1643 else {
1644 dumpFilePath = userData;
1645 }
1646
1647 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#2 In setting up errorHandlerPtr->set_dump_path...\n");
1648 #if defined(WIN32)
1649 wstring dumpfilepath = utf8_decode(dumpFilePath);
1650 if(SystemFlags::VERBOSE_MODE_ENABLED) wprintf(L"Hooking up google_breakpad::ExceptionHandler to save dmp files to [%s]...\n",dumpfilepath.c_str());
1651 errorHandlerPtr->set_dump_path(dumpfilepath);
1652 #else
1653 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Hooking up google_breakpad::ExceptionHandler to save dmp files to [%s]...\n",dumpFilePath.c_str());
1654 //errorHandlerPtr->set_dump_path(dumpfilepath);
1655 google_breakpad::MinidumpDescriptor descriptor(dumpFilePath);
1656 errorHandlerPtr->set_minidump_descriptor(descriptor);
1657 #endif
1658
1659 }
1660 #endif
1661
1662 string debugLogFile = config.getString("DebugLogFile","");
1663 if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1664 debugLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugLogFile;
1665 }
1666 else {
1667 debugLogFile = userData + debugLogFile;
1668 }
1669
1670 string debugWorldSynchLogFile = config.getString("DebugLogFileWorldSynch","");
1671 if(debugWorldSynchLogFile == "") {
1672 debugWorldSynchLogFile = debugLogFile;
1673 }
1674 else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1675 debugWorldSynchLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugWorldSynchLogFile;
1676 }
1677 else {
1678 debugWorldSynchLogFile = userData + debugWorldSynchLogFile;
1679 }
1680
1681 string debugPerformanceLogFile = config.getString("DebugLogFilePerformance","");
1682 if(debugPerformanceLogFile == "") {
1683 debugPerformanceLogFile = debugLogFile;
1684 }
1685 else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1686 debugPerformanceLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugPerformanceLogFile;
1687 }
1688 else {
1689 debugPerformanceLogFile = userData + debugPerformanceLogFile;
1690 }
1691
1692 string debugNetworkLogFile = config.getString("DebugLogFileNetwork","");
1693 if(debugNetworkLogFile == "") {
1694 debugNetworkLogFile = debugLogFile;
1695 }
1696 else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1697 debugNetworkLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugNetworkLogFile;
1698 }
1699 else {
1700 debugNetworkLogFile = userData + debugNetworkLogFile;
1701 }
1702
1703 string debugUnitCommandsLogFile = config.getString("DebugLogFileUnitCommands","");
1704 if(debugUnitCommandsLogFile == "") {
1705 debugUnitCommandsLogFile = debugLogFile;
1706 }
1707 else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1708 debugUnitCommandsLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugUnitCommandsLogFile;
1709 }
1710 else {
1711 debugUnitCommandsLogFile = userData + debugUnitCommandsLogFile;
1712 }
1713
1714 string debugPathFinderLogFile = config.getString("DebugLogFilePathFinder","");
1715 if(debugPathFinderLogFile == "") {
1716 debugPathFinderLogFile = debugLogFile;
1717 }
1718 else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1719 debugPathFinderLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugPathFinderLogFile;
1720 }
1721 else {
1722 debugPathFinderLogFile = userData + debugPathFinderLogFile;
1723 }
1724
1725 string debugLUALogFile = config.getString("DebugLogFileLUA","");
1726 if(debugLUALogFile == "") {
1727 debugLUALogFile = debugLogFile;
1728 }
1729 else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1730 debugLUALogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugLUALogFile;
1731 }
1732 else {
1733 debugLUALogFile = userData + debugLUALogFile;
1734 }
1735
1736 string debugSoundLogFile = config.getString("DebugLogFileSound","");
1737 if(debugSoundLogFile == "") {
1738 debugSoundLogFile = debugLogFile;
1739 }
1740 else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
1741 debugSoundLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugSoundLogFile;
1742 }
1743 else {
1744 debugSoundLogFile = userData + debugSoundLogFile;
1745 }
1746
1747 string debugErrorLogFile = config.getString("DebugLogFileError","");
1748
1749 SystemFlags::getSystemSettingType(SystemFlags::debugSystem).debugLogFileName = debugLogFile;
1750 SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).debugLogFileName = debugNetworkLogFile;
1751 SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).debugLogFileName = debugPerformanceLogFile;
1752 SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).debugLogFileName = debugWorldSynchLogFile;
1753 SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).debugLogFileName = debugUnitCommandsLogFile;
1754 SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).debugLogFileName = debugPathFinderLogFile;
1755 SystemFlags::getSystemSettingType(SystemFlags::debugLUA).debugLogFileName = debugLUALogFile;
1756 SystemFlags::getSystemSettingType(SystemFlags::debugSound).debugLogFileName = debugSoundLogFile;
1757 SystemFlags::getSystemSettingType(SystemFlags::debugError).debugLogFileName = debugErrorLogFile;
1758
1759 if(haveSpecialOutputCommandLineOption == false) {
1760 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("--- Startup log settings are ---\ndebugSystem [%d][%s]\ndebugNetwork [%d][%s]\ndebugPerformance [%d][%s]\ndebugWorldSynch [%d][%s]\ndebugUnitCommands[%d][%s]\ndebugPathFinder[%d][%s]\ndebugLUA [%d][%s]\ndebugSound [%d][%s]\ndebugError [%d][%s]\n",
1761 SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled,
1762 debugLogFile.c_str(),
1763 SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled,
1764 debugNetworkLogFile.c_str(),
1765 SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled,
1766 debugPerformanceLogFile.c_str(),
1767 SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled,
1768 debugWorldSynchLogFile.c_str(),
1769 SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled,
1770 debugUnitCommandsLogFile.c_str(),
1771 SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled,
1772 debugPathFinderLogFile.c_str(),
1773 SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled,
1774 debugLUALogFile.c_str(),
1775 SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled,
1776 debugSoundLogFile.c_str(),
1777 SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled,
1778 debugErrorLogFile.c_str());
1779 }
1780 }
1781
runTilesetValidationForPath(string tilesetPath,string tilesetName,World & world,bool purgeUnusedFiles,bool purgeDuplicateFiles,bool showDuplicateFiles,bool gitPurgeFiles,double & purgedMegaBytes)1782 void runTilesetValidationForPath(string tilesetPath, string tilesetName,
1783 World &world, bool purgeUnusedFiles,bool purgeDuplicateFiles,
1784 bool showDuplicateFiles, bool gitPurgeFiles,double &purgedMegaBytes) {
1785 Checksum checksum;
1786
1787 bool techtree_errors = false;
1788
1789 std::map<string,vector<pair<string, string> > > loadedFileList;
1790 vector<string> pathList;
1791 pathList.push_back(tilesetPath);
1792 world.loadTileset(pathList, tilesetName,&checksum, loadedFileList);
1793
1794 // Fixup paths with ..
1795 {
1796 std::map<string,vector<pair<string, string> > > newLoadedFileList;
1797 for( std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
1798 iterMap != loadedFileList.end(); ++iterMap) {
1799 string loadedFile = iterMap->first;
1800
1801 replaceAll(loadedFile,"//","/");
1802 replaceAll(loadedFile,"\\\\","\\");
1803 updatePathClimbingParts(loadedFile);
1804
1805 if(newLoadedFileList.find(loadedFile) != newLoadedFileList.end()) {
1806 for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
1807 pair<string, string> &newVal = iterMap->second[xx1];
1808 replaceAll(newVal.first,"//","/");
1809 replaceAll(newVal.first,"\\\\","\\");
1810 updatePathClimbingParts(newVal.first);
1811 replaceAll(newVal.second,"//","/");
1812 replaceAll(newVal.second,"\\\\","\\");
1813 updatePathClimbingParts(newVal.second);
1814
1815 newLoadedFileList[loadedFile].push_back(newVal);
1816 }
1817 }
1818 else {
1819 for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
1820 pair<string, string> &newVal = iterMap->second[xx1];
1821 replaceAll(newVal.first,"//","/");
1822 replaceAll(newVal.first,"\\\\","\\");
1823 updatePathClimbingParts(newVal.first);
1824 replaceAll(newVal.second,"//","/");
1825 replaceAll(newVal.second,"\\\\","\\");
1826 updatePathClimbingParts(newVal.second);
1827 }
1828
1829 newLoadedFileList[loadedFile] = iterMap->second;
1830 }
1831 }
1832 loadedFileList = newLoadedFileList;
1833 }
1834
1835 // Validate the faction setup to ensure we don't have any bad associations
1836 // std::vector<std::string> resultErrors = world.validateFactionTypes();
1837
1838 // Now check for unused files in the techtree
1839 std::map<string,vector<pair<string, string> > > foundFileList;
1840 for(unsigned int i = 0; i < pathList.size(); ++i) {
1841 string path = pathList[i];
1842 endPathWithSlash(path);
1843 path = path + tilesetName + "/";
1844
1845 replaceAll(path, "//", "/");
1846 replaceAll(path, "\\\\", "\\");
1847
1848 vector<string> foundFiles = getFolderTreeContentsListRecursively(path + "*.", "");
1849 for(unsigned int j = 0; j < foundFiles.size(); ++j) {
1850 string file = foundFiles[j];
1851 replaceAll(file, "//", "/");
1852 replaceAll(file, "\\\\", "\\");
1853
1854 replaceAll(file,"//","/");
1855 replaceAll(file,"\\\\","\\");
1856
1857 foundFileList[file].push_back(make_pair(path,path));
1858 }
1859 }
1860
1861 printf("Found tileset filecount = " MG_SIZE_T_SPECIFIER ", used = " MG_SIZE_T_SPECIFIER "\n",foundFileList.size(),loadedFileList.size());
1862
1863 int purgeCount = 0;
1864 bool foundUnusedFile = false;
1865 for( std::map<string,vector<pair<string, string> > >::iterator iterMap = foundFileList.begin();
1866 iterMap != foundFileList.end(); ++iterMap) {
1867 string foundFile = iterMap->first;
1868 replaceAll(foundFile, "//", "/");
1869 replaceAll(foundFile, "\\\\", "\\");
1870
1871 if(loadedFileList.find(foundFile) == loadedFileList.end() &&
1872 foundFile.find("lang/") == foundFile.npos) {
1873 if(foundUnusedFile == false) {
1874 printf("\nLine ref: %d, Warning, unused files were detected - START:\n=====================\n",__LINE__);
1875 }
1876 foundUnusedFile = true;
1877
1878 printf("[%s]\n",foundFile.c_str());
1879
1880 string fileName = extractFileFromDirectoryPath(foundFile);
1881 if(loadedFileList.find(fileName) != loadedFileList.end()) {
1882 printf("possible match on [%s] ?\n",loadedFileList.find(fileName)->first.c_str());
1883 }
1884 else if(purgeUnusedFiles == true) {
1885 off_t fileSize = getFileSize(foundFile);
1886 // convert to MB
1887 purgedMegaBytes += ((double)fileSize / 1048576.0);
1888 purgeCount++;
1889
1890 if(gitPurgeFiles == true) {
1891 char szBuf[8096]="";
1892 snprintf(szBuf,8096,"git rm \"%s\"",foundFile.c_str());
1893 bool gitOk = executeShellCommand(szBuf,0);
1894 if(gitOk == false) {
1895 throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
1896 }
1897 }
1898 else {
1899 removeFile(foundFile);
1900 }
1901 }
1902 }
1903 }
1904 if(foundUnusedFile == true) {
1905 if(purgedMegaBytes > 0) {
1906 printf("Purged %.2f MB (%d) in files\n",purgedMegaBytes,purgeCount);
1907 }
1908 printf("\nLine ref: %d, Warning, unused files were detected - END:\n",__LINE__);
1909 }
1910
1911 if(showDuplicateFiles == true) {
1912 std::map<uint32,vector<string> > mapDuplicateFiles;
1913 // Now check for duplicate data content
1914 for(std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
1915 iterMap != loadedFileList.end(); ++iterMap) {
1916 string fileName = iterMap->first;
1917 Checksum checksum;
1918 checksum.addFile(fileName);
1919 uint32 crcValue = checksum.getSum();
1920 mapDuplicateFiles[crcValue].push_back(fileName);
1921 }
1922
1923 double duplicateMegaBytesPurged=0;
1924 int duplicateCountPurged=0;
1925
1926 double duplicateMegaBytes=0;
1927 int duplicateCount=0;
1928
1929 bool foundDuplicates = false;
1930 for(std::map<uint32,vector<string> >::iterator iterMap = mapDuplicateFiles.begin();
1931 iterMap != mapDuplicateFiles.end(); ++iterMap) {
1932 vector<string> &fileList = iterMap->second;
1933 if(fileList.size() > 1) {
1934 if(foundDuplicates == false) {
1935 foundDuplicates = true;
1936 printf("\nWarning, duplicate files were detected - START:\n=====================\n");
1937 }
1938
1939 map<string,int> parentList;
1940 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
1941 string duplicateFile = fileList[idx];
1942 if(idx > 0) {
1943 off_t fileSize = getFileSize(duplicateFile);
1944 // convert to MB
1945 duplicateMegaBytes += ((double)fileSize / 1048576.0);
1946 duplicateCount++;
1947 }
1948 else {
1949 printf("\n");
1950 }
1951
1952 printf("[%s]\n",duplicateFile.c_str());
1953 std::map<string,vector<pair<string, string> > >::iterator iterFind = loadedFileList.find(duplicateFile);
1954 if(iterFind != loadedFileList.end()) {
1955 for(unsigned int jdx = 0; jdx < iterFind->second.size(); jdx++) {
1956 parentList[iterFind->second[jdx].first]++;
1957 }
1958 }
1959 }
1960
1961 for(map<string,int>::iterator iterMap1 = parentList.begin();
1962 iterMap1 != parentList.end(); ++iterMap1) {
1963
1964 if(iterMap1 == parentList.begin()) {
1965 printf("\tParents:\n");
1966 }
1967 printf("\t[%s]\n",iterMap1->first.c_str());
1968 }
1969
1970 if(purgeDuplicateFiles == true) {
1971
1972 string newCommonFileName = "";
1973 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
1974 string duplicateFile = fileList[idx];
1975 string fileExt = extractExtension(duplicateFile);
1976 if(fileExt == "wav" || fileExt == "ogg") {
1977 off_t fileSize = getFileSize(duplicateFile);
1978 if(idx == 0) {
1979 newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
1980
1981 string expandedNewCommonFileName = newCommonFileName;
1982
1983 std::map<string,string> mapExtraTagReplacementValues;
1984
1985 mapExtraTagReplacementValues = Properties::getTagReplacementValues(&mapExtraTagReplacementValues);
1986 Properties::applyTagsToValue(expandedNewCommonFileName,&mapExtraTagReplacementValues);
1987 replaceAll(expandedNewCommonFileName, "//", "/");
1988 createDirectoryPaths(extractDirectoryPathFromFile(expandedNewCommonFileName));
1989
1990 if(gitPurgeFiles == true) {
1991 copyFileTo(duplicateFile, expandedNewCommonFileName);
1992
1993 char szBuf[8096]="";
1994 snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
1995 bool gitOk = executeShellCommand(szBuf,0);
1996 if(gitOk == false) {
1997 throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
1998 }
1999 printf("*** Duplicate file:\n[%s]\nwas git rm and copied to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2000 }
2001 else {
2002 //int result = 0;
2003 int result = rename(duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2004 if(result != 0) {
2005 char szBuf[8096]="";
2006 char *errmsg = strerror(errno);
2007 snprintf(szBuf,8096,"!!! Error [%s] Could not rename [%s] to [%s]!",errmsg,duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2008 throw megaglest_runtime_error(szBuf);
2009 }
2010 else {
2011 printf("*** Duplicate file:\n[%s]\nwas renamed to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2012 }
2013 }
2014 }
2015 else {
2016 if(gitPurgeFiles == true) {
2017 char szBuf[8096]="";
2018 snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
2019 bool gitOk = executeShellCommand(szBuf,0);
2020 if(gitOk == false) {
2021 throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
2022 }
2023 printf("*** Duplicate file:\n[%s]\nwas git rm\n",duplicateFile.c_str());
2024 }
2025 else {
2026 removeFile(duplicateFile);
2027 }
2028 printf("*** Duplicate file:\n[%s]\nwas removed\n",duplicateFile.c_str());
2029
2030 // convert to MB
2031 duplicateMegaBytesPurged += ((double)fileSize / 1048576.0);
2032 duplicateCountPurged++;
2033 }
2034 }
2035 }
2036
2037 std::map<string,int> mapUniqueParentList;
2038
2039 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2040 string duplicateFile = fileList[idx];
2041 string fileExt = extractExtension(duplicateFile);
2042 if(fileExt == "wav" || fileExt == "ogg") {
2043 std::map<string,vector<pair<string, string> > >::iterator iterFind2 = loadedFileList.find(duplicateFile);
2044 if(iterFind2 != loadedFileList.end()) {
2045 for(unsigned int jdx1 = 0; jdx1 < iterFind2->second.size(); jdx1++) {
2046 string parentFile = iterFind2->second[jdx1].first;
2047 string searchText = iterFind2->second[jdx1].second;
2048
2049 if(mapUniqueParentList.find(parentFile) == mapUniqueParentList.end()) {
2050 printf("*** Searching parent file:\n[%s]\nfor duplicate file reference:\n[%s]\nto replace with newname:\n[%s]\n",parentFile.c_str(),searchText.c_str(),newCommonFileName.c_str());
2051 bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, false);
2052 printf("foundText = %d\n",foundText);
2053 if(foundText == false) {
2054 char szBuf[8096]="";
2055 snprintf(szBuf,8096,"Line ref = %d, Error finding text [%s] in file [%s]",__LINE__,searchText.c_str(),parentFile.c_str());
2056 throw megaglest_runtime_error(szBuf);
2057 }
2058 mapUniqueParentList[parentFile]++;
2059 }
2060 }
2061 }
2062 }
2063 }
2064 }
2065 else {
2066 string newCommonFileName = "";
2067 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2068 string duplicateFile = fileList[idx];
2069 string fileExt = extractExtension(duplicateFile);
2070 if(fileExt == "wav" || fileExt == "ogg") {
2071 //off_t fileSize = getFileSize(duplicateFile);
2072 if(idx == 0) {
2073 newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
2074 break;
2075 }
2076 }
2077 }
2078
2079 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2080 string duplicateFile = fileList[idx];
2081 string fileExt = extractExtension(duplicateFile);
2082 if(fileExt == "wav" || fileExt == "ogg") {
2083 std::map<string,vector<pair<string, string> > >::iterator iterFind4 = loadedFileList.find(duplicateFile);
2084 if(iterFind4 != loadedFileList.end()) {
2085 for(unsigned int jdx = 0; jdx < iterFind4->second.size(); jdx++) {
2086 string parentFile = iterFind4->second[jdx].first;
2087 string searchText = iterFind4->second[jdx].second;
2088
2089 bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, true);
2090 if(foundText == false) {
2091
2092 char szBuf[8096]="";
2093 snprintf(szBuf,8096,"Line ref = %d, Error finding text\n[%s]\nin file\n[%s]\nnew Common File [%s]\n",__LINE__,searchText.c_str(),parentFile.c_str(),newCommonFileName.c_str());
2094 printf("\n\n=================================================\n%s",szBuf);
2095
2096 throw megaglest_runtime_error(szBuf);
2097 }
2098 }
2099 }
2100 }
2101 }
2102 }
2103 }
2104 }
2105 if(foundDuplicates == true) {
2106 printf("Duplicates %.2f MB (%d) in files\n",duplicateMegaBytes,duplicateCount);
2107 printf("Duplicates purged %.2f MB (%d) in files\n",duplicateMegaBytesPurged,duplicateCountPurged);
2108
2109 printf("\nWarning, duplicate files were detected - END:\n");
2110 }
2111 }
2112
2113 if(techtree_errors == false) {
2114 printf("\nValidation found NO ERRORS for tilesetPath [%s] tilesetName [%s]:\n",tilesetPath.c_str(), tilesetName.c_str());
2115 }
2116
2117 printf("----------------------------------------------------------------");
2118 }
2119
runTechValidationForPath(string techPath,string techName,const std::vector<string> & filteredFactionList,World & world,bool purgeUnusedFiles,bool purgeDuplicateFiles,bool showDuplicateFiles,bool gitPurgeFiles,double & purgedMegaBytes)2120 void runTechValidationForPath(string techPath, string techName,
2121 const std::vector<string> &filteredFactionList, World &world,
2122 bool purgeUnusedFiles,bool purgeDuplicateFiles, bool showDuplicateFiles,
2123 bool gitPurgeFiles,double &purgedMegaBytes) {
2124
2125 string techTreeFolder = techPath + techName;
2126 string techTreeFactionFolder = techTreeFolder + "/factions/";
2127 vector<string> factionsList;
2128 findDirs(techTreeFactionFolder, factionsList, false, false);
2129
2130 if(factionsList.empty() == false) {
2131 Checksum checksum;
2132 set<string> factions;
2133 for(int j = 0; j < (int)factionsList.size(); ++j) {
2134 if( filteredFactionList.empty() == true ||
2135 std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
2136 factions.insert(factionsList[j]);
2137 }
2138 }
2139
2140 printf("\n----------------------------------------------------------------");
2141 printf("\nChecking techPath [%s] techName [%s] total faction count = %d\n",techPath.c_str(), techName.c_str(),(int)factionsList.size());
2142 for(int j = 0; j < (int)factionsList.size(); ++j) {
2143 if( filteredFactionList.empty() == true ||
2144 std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
2145 printf("Using faction [%s]\n",factionsList[j].c_str());
2146 }
2147 }
2148
2149 if(factions.empty() == false) {
2150 bool techtree_errors = false;
2151
2152 std::map<string,vector<pair<string, string> > > loadedFileList;
2153 vector<string> pathList;
2154 pathList.push_back(techPath);
2155 Config &config = Config::getInstance();
2156 vector<string> otherTechPaths = config.getPathListForType(ptTechs,"");
2157 pathList.insert(pathList.end(), otherTechPaths.begin(), otherTechPaths.end());
2158
2159 try {
2160 world.loadTech(pathList, techName, factions, &checksum, loadedFileList, true);
2161
2162 // Fixup paths with ..
2163 {
2164 std::map<string,vector<pair<string, string> > > newLoadedFileList;
2165 for( std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
2166 iterMap != loadedFileList.end(); ++iterMap) {
2167 string loadedFile = iterMap->first;
2168
2169 replaceAll(loadedFile,"//","/");
2170 replaceAll(loadedFile,"\\\\","\\");
2171 updatePathClimbingParts(loadedFile);
2172
2173 if(newLoadedFileList.find(loadedFile) != newLoadedFileList.end()) {
2174 for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
2175 pair<string, string> &newVal = iterMap->second[xx1];
2176 replaceAll(newVal.first,"//","/");
2177 replaceAll(newVal.first,"\\\\","\\");
2178 updatePathClimbingParts(newVal.first);
2179 replaceAll(newVal.second,"//","/");
2180 replaceAll(newVal.second,"\\\\","\\");
2181 updatePathClimbingParts(newVal.second);
2182
2183 newLoadedFileList[loadedFile].push_back(newVal);
2184 }
2185 }
2186 else {
2187 for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
2188 pair<string, string> &newVal = iterMap->second[xx1];
2189 replaceAll(newVal.first,"//","/");
2190 replaceAll(newVal.first,"\\\\","\\");
2191 updatePathClimbingParts(newVal.first);
2192 replaceAll(newVal.second,"//","/");
2193 replaceAll(newVal.second,"\\\\","\\");
2194 updatePathClimbingParts(newVal.second);
2195 }
2196
2197 newLoadedFileList[loadedFile] = iterMap->second;
2198 }
2199 }
2200 loadedFileList = newLoadedFileList;
2201 }
2202
2203 // Validate the faction setup to ensure we don't have any bad associations
2204 std::vector<std::string> resultErrors = world.validateFactionTypes();
2205 if(resultErrors.empty() == false) {
2206 techtree_errors = true;
2207 // Display the validation errors
2208 string errorText = "\nErrors were detected:\n=====================\n";
2209 for(int i = 0; i < (int)resultErrors.size(); ++i) {
2210 if(i > 0) {
2211 errorText += "\n";
2212 }
2213 errorText = errorText + resultErrors[i];
2214 }
2215 errorText += "\n=====================\n";
2216 printf("%s",errorText.c_str());
2217 }
2218
2219 // Validate the faction resource setup to ensure we don't have any bad associations
2220 printf("\nChecking resources, count = %d\n",world.getTechTree()->getResourceTypeCount());
2221
2222 for(int i = 0; i < world.getTechTree()->getResourceTypeCount(); ++i) {
2223 printf("Found techtree resource [%s]\n",world.getTechTree()->getResourceType(i)->getName().c_str());
2224 }
2225
2226 resultErrors = world.validateResourceTypes();
2227 if(resultErrors.empty() == false) {
2228 techtree_errors = true;
2229 // Display the validation errors
2230 string errorText = "\nErrors were detected:\n=====================\n";
2231 for(int i = 0; i < (int)resultErrors.size(); ++i) {
2232 if(i > 0) {
2233 errorText += "\n";
2234 }
2235 errorText = errorText + resultErrors[i];
2236 }
2237 errorText += "\n=====================\n";
2238 printf("%s",errorText.c_str());
2239 }
2240
2241 // Now check for unused files in the techtree
2242 std::map<string,vector<pair<string, string> > > foundFileList;
2243 for(unsigned int i = 0; i < pathList.size(); ++i) {
2244 string path = pathList[i];
2245 endPathWithSlash(path);
2246 path = path + techName + "/";
2247
2248 replaceAll(path, "//", "/");
2249 replaceAll(path, "\\\\", "\\");
2250
2251 vector<string> foundFiles = getFolderTreeContentsListRecursively(path + "*.", "");
2252 for(unsigned int j = 0; j < foundFiles.size(); ++j) {
2253 string file = foundFiles[j];
2254 replaceAll(file, "//", "/");
2255 replaceAll(file, "\\\\", "\\");
2256
2257 // ignore loading screen, preview screen and hud
2258 if( file.find(GameConstants::LOADING_SCREEN_FILE) != string::npos ||
2259 file.find(GameConstants::PREVIEW_SCREEN_FILE) != string::npos ||
2260 file.find(GameConstants::HUD_SCREEN_FILE) != string::npos) {
2261 continue;
2262 }
2263
2264 // ignore commondata since we are not loading all factions
2265 if(filteredFactionList.size() > 0) {
2266 if( file.find("/commondata/") != string::npos) {
2267 continue;
2268 }
2269 }
2270
2271 if(file.find("/factions/") != string::npos) {
2272 bool includeFaction = false;
2273 for ( set<string>::iterator it = factions.begin(); it != factions.end(); ++it ) {
2274 string currentFaction = *it;
2275 if(file.find("/factions/" + currentFaction) != string::npos) {
2276 includeFaction = true;
2277 break;
2278 }
2279 }
2280 if(includeFaction == false) {
2281 continue;
2282 }
2283 }
2284
2285 replaceAll(file,"//","/");
2286 replaceAll(file,"\\\\","\\");
2287
2288 foundFileList[file].push_back(make_pair(path,path));
2289 }
2290 }
2291
2292 printf("Found techtree filecount = " MG_SIZE_T_SPECIFIER ", used = " MG_SIZE_T_SPECIFIER "\n",foundFileList.size(),loadedFileList.size());
2293
2294 int purgeCount = 0;
2295 bool foundUnusedFile = false;
2296 for( std::map<string,vector<pair<string, string> > >::iterator iterMap = foundFileList.begin();
2297 iterMap != foundFileList.end(); ++iterMap) {
2298 string foundFile = iterMap->first;
2299 replaceAll(foundFile, "//", "/");
2300 replaceAll(foundFile, "\\\\", "\\");
2301
2302 if(loadedFileList.find(foundFile) == loadedFileList.end() &&
2303 foundFile.find("lang/") == foundFile.npos) {
2304 if(foundUnusedFile == false) {
2305 printf("\nLine ref: %d, Warning, unused files were detected - START:\n=====================\n",__LINE__);
2306 }
2307 foundUnusedFile = true;
2308
2309 printf("[%s]\n",foundFile.c_str());
2310
2311 string fileName = extractFileFromDirectoryPath(foundFile);
2312 if(loadedFileList.find(fileName) != loadedFileList.end()) {
2313 printf("possible match on [%s] ?\n",loadedFileList.find(fileName)->first.c_str());
2314 }
2315 else if(purgeUnusedFiles == true) {
2316 off_t fileSize = getFileSize(foundFile);
2317 // convert to MB
2318 purgedMegaBytes += ((double)fileSize / 1048576.0);
2319 purgeCount++;
2320
2321 if(gitPurgeFiles == true) {
2322 char szBuf[8096]="";
2323 snprintf(szBuf,8096,"git rm \"%s\"",foundFile.c_str());
2324 bool gitOk = executeShellCommand(szBuf,0);
2325 if(gitOk == false) {
2326 throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
2327 }
2328 }
2329 else {
2330 removeFile(foundFile);
2331 }
2332 }
2333 }
2334 }
2335 if(foundUnusedFile == true) {
2336 if(purgedMegaBytes > 0) {
2337 printf("Purged %.2f MB (%d) in files\n",purgedMegaBytes,purgeCount);
2338 }
2339 printf("\nLine ref: %d, Warning, unused files were detected - END:\n",__LINE__);
2340 }
2341
2342 if(showDuplicateFiles == true) {
2343 std::map<uint32,vector<string> > mapDuplicateFiles;
2344 // Now check for duplicate data content
2345 for(std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
2346 iterMap != loadedFileList.end(); ++iterMap) {
2347 string fileName = iterMap->first;
2348 Checksum checksum;
2349 checksum.addFile(fileName);
2350 uint32 crcValue = checksum.getSum();
2351 if(crcValue == 0) {
2352 char szBuf[8096]="";
2353 snprintf(szBuf,8096,"Error calculating CRC for file [%s]",fileName.c_str());
2354 throw megaglest_runtime_error(szBuf);
2355 }
2356 mapDuplicateFiles[crcValue].push_back(fileName);
2357 }
2358
2359 double duplicateMegaBytesPurged=0;
2360 int duplicateCountPurged=0;
2361
2362 double duplicateMegaBytes=0;
2363 int duplicateCount=0;
2364
2365 bool foundDuplicates = false;
2366 for(std::map<uint32,vector<string> >::iterator iterMap = mapDuplicateFiles.begin();
2367 iterMap != mapDuplicateFiles.end(); ++iterMap) {
2368 vector<string> &fileList = iterMap->second;
2369 if(fileList.size() > 1) {
2370 if(foundDuplicates == false) {
2371 foundDuplicates = true;
2372 printf("\nWarning, duplicate files were detected - START:\n=====================\n");
2373 }
2374
2375 printf("----- START duplicate files for CRC [%u] count [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",iterMap->first,fileList.size(),fileList[0].c_str());
2376
2377 map<string,int> parentList;
2378 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2379 string duplicateFile = fileList[idx];
2380 if(idx > 0) {
2381 off_t fileSize = getFileSize(duplicateFile);
2382 // convert to MB
2383 duplicateMegaBytes += ((double)fileSize / 1048576.0);
2384 duplicateCount++;
2385 }
2386 else {
2387 printf("\n");
2388 }
2389
2390 printf("[%s]\n",duplicateFile.c_str());
2391 std::map<string,vector<pair<string, string> > >::iterator iterFind = loadedFileList.find(duplicateFile);
2392 if(iterFind != loadedFileList.end()) {
2393 for(unsigned int jdx = 0; jdx < iterFind->second.size(); jdx++) {
2394 parentList[iterFind->second[jdx].first]++;
2395 }
2396 }
2397
2398 string newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
2399 string expandedNewCommonFileName = newCommonFileName;
2400 std::map<string,string> mapExtraTagReplacementValues;
2401 string techCommonData = techPath + techName + "/commondata/";
2402 replaceAll(techCommonData, "//", "/");
2403 mapExtraTagReplacementValues["$COMMONDATAPATH"] = techCommonData;
2404 mapExtraTagReplacementValues = Properties::getTagReplacementValues(&mapExtraTagReplacementValues);
2405 Properties::applyTagsToValue(expandedNewCommonFileName,&mapExtraTagReplacementValues);
2406 replaceAll(expandedNewCommonFileName, "//", "/");
2407 }
2408
2409 printf("----- Finding parents for duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
2410
2411 for(map<string,int>::iterator iterMap1 = parentList.begin();
2412 iterMap1 != parentList.end(); ++iterMap1) {
2413
2414 if(iterMap1 == parentList.begin()) {
2415 printf("\tParents:\n");
2416 }
2417 printf("\t[%s]\n",iterMap1->first.c_str());
2418 }
2419
2420 if(purgeDuplicateFiles == true) {
2421
2422 printf("----- move / remove duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
2423 // First move first duplicate to commondata and delete all other copies
2424 string newCommonFileName = "";
2425 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2426 string duplicateFile = fileList[idx];
2427 string fileExt = extractExtension(duplicateFile);
2428 if(fileExt == "wav" || fileExt == "ogg") {
2429 off_t fileSize = getFileSize(duplicateFile);
2430
2431 printf("#1 [%u / " MG_SIZE_T_SPECIFIER "] removing duplicate [%s]\n",idx,fileList.size(),duplicateFile.c_str());
2432
2433 if(idx == 0) {
2434 newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
2435
2436 string expandedNewCommonFileName = newCommonFileName;
2437
2438 std::map<string,string> mapExtraTagReplacementValues;
2439
2440 string techCommonData = techPath + techName + "/commondata/";
2441 replaceAll(techCommonData, "//", "/");
2442
2443 mapExtraTagReplacementValues["$COMMONDATAPATH"] = techCommonData;
2444 mapExtraTagReplacementValues = Properties::getTagReplacementValues(&mapExtraTagReplacementValues);
2445 Properties::applyTagsToValue(expandedNewCommonFileName,&mapExtraTagReplacementValues);
2446 replaceAll(expandedNewCommonFileName, "//", "/");
2447 createDirectoryPaths(extractDirectoryPathFromFile(expandedNewCommonFileName));
2448
2449 if(gitPurgeFiles == true) {
2450 copyFileTo(duplicateFile, expandedNewCommonFileName);
2451
2452 char szBuf[8096]="";
2453 snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
2454 bool gitOk = executeShellCommand(szBuf,0);
2455 if(gitOk == false) {
2456 throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
2457 }
2458 printf("*** Duplicate file:\n[%s]\nwas git rm and copied to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2459 }
2460 else {
2461 printf("moving duplicate [%s] to common data [%s] expanded to [%s]\n",duplicateFile.c_str(),newCommonFileName.c_str(),expandedNewCommonFileName.c_str());
2462
2463 int result = rename(duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2464 if(result != 0) {
2465 char szBuf[8096]="";
2466 char *errmsg = strerror(errno);
2467 snprintf(szBuf,8096,"!!! Error [%s] Could not rename [%s] to [%s]!",errmsg,duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2468 throw megaglest_runtime_error(szBuf);
2469 }
2470 else {
2471 printf("*** Duplicate file:\n[%s]\nwas renamed to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
2472 }
2473 }
2474 }
2475 else {
2476 if(gitPurgeFiles == true) {
2477 char szBuf[8096]="";
2478 snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
2479 bool gitOk = executeShellCommand(szBuf,0);
2480 if(gitOk == false) {
2481 throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
2482 }
2483 printf("*** Duplicate file:\n[%s]\nwas git rm\n",duplicateFile.c_str());
2484 }
2485 else {
2486 printf("removing duplicate [%s]\n",duplicateFile.c_str());
2487 removeFile(duplicateFile);
2488 }
2489 printf("*** Duplicate file:\n[%s]\nwas removed\n",duplicateFile.c_str());
2490
2491 // convert to MB
2492 duplicateMegaBytesPurged += ((double)fileSize / 1048576.0);
2493 duplicateCountPurged++;
2494 }
2495 }
2496 }
2497
2498 printf("----- update XML files for duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
2499 std::map<string,int> mapUniqueParentList;
2500
2501 // Update the XML files to point to the new single copy in commondata
2502 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2503 string duplicateFile = fileList[idx];
2504 string fileExt = extractExtension(duplicateFile);
2505 if(fileExt == "wav" || fileExt == "ogg") {
2506 std::map<string,vector<pair<string, string> > >::iterator iterFind2 = loadedFileList.find(duplicateFile);
2507 if(iterFind2 != loadedFileList.end()) {
2508 for(unsigned int jdx1 = 0; jdx1 < iterFind2->second.size(); jdx1++) {
2509 string parentFile = iterFind2->second[jdx1].first;
2510 string searchText = iterFind2->second[jdx1].second;
2511
2512 if(mapUniqueParentList.find(parentFile) == mapUniqueParentList.end()) {
2513 printf("*** Searching parent file:\n[%s]\nfor duplicate file reference:\n[%s]\nto replace with newname:\n[%s]\n",parentFile.c_str(),searchText.c_str(),newCommonFileName.c_str());
2514 bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, false);
2515 printf("foundText = %d\n",foundText);
2516 if(foundText == false) {
2517
2518 string techCommonData = techPath + techName + "/commondata/";
2519 replaceAll(techCommonData, "//", "/");
2520
2521 if(StartsWith(searchText, techCommonData) == true) {
2522 printf("WARNING #1 [%d] techCommonData check\n[%s]\n[%s]\n[%s]\n[%s]\n",
2523 foundText,parentFile.c_str(),techCommonData.c_str(),searchText.c_str(),newCommonFileName.c_str());
2524
2525 replaceAll(searchText, techCommonData, "$COMMONDATAPATH/");
2526 foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, false);
2527
2528 printf("WARNING #2 [%d] techCommonData check\n[%s]\n[%s]\n[%s]\n[%s]\n",
2529 foundText,parentFile.c_str(),techCommonData.c_str(),searchText.c_str(),newCommonFileName.c_str());
2530 }
2531 if(foundText == false) {
2532 char szBuf[8096]="";
2533 snprintf(szBuf,8096,"Line ref = %d, Error finding text\n[%s]\nin file\n[%s]\nnew Common File [%s]\n",__LINE__,searchText.c_str(),parentFile.c_str(),newCommonFileName.c_str());
2534 printf("\n\n=================================================\n%s",szBuf);
2535
2536 throw megaglest_runtime_error(szBuf);
2537 }
2538 }
2539 mapUniqueParentList[parentFile]++;
2540 }
2541 }
2542 }
2543 }
2544 }
2545 }
2546 else {
2547
2548 string newCommonFileName = "";
2549 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2550 string duplicateFile = fileList[idx];
2551 string fileExt = extractExtension(duplicateFile);
2552 if(fileExt == "wav" || fileExt == "ogg") {
2553 //off_t fileSize = getFileSize(duplicateFile);
2554 if(idx == 0) {
2555 newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
2556 break;
2557 }
2558 }
2559 }
2560
2561 for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
2562 string duplicateFile = fileList[idx];
2563 string fileExt = extractExtension(duplicateFile);
2564 if(fileExt == "wav" || fileExt == "ogg") {
2565 std::map<string,vector<pair<string, string> > >::iterator iterFind4 = loadedFileList.find(duplicateFile);
2566 if(iterFind4 != loadedFileList.end()) {
2567 for(unsigned int jdx = 0; jdx < iterFind4->second.size(); jdx++) {
2568 string parentFile = iterFind4->second[jdx].first;
2569 string searchText = iterFind4->second[jdx].second;
2570
2571 bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, true);
2572
2573 if(foundText == false) {
2574 string techCommonData = techPath + techName + "/commondata/";
2575 replaceAll(techCommonData, "//", "/");
2576
2577 if(StartsWith(searchText, techCommonData) == true) {
2578 replaceAll(searchText, techCommonData, "$COMMONDATAPATH/");
2579 foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, true);
2580
2581 }
2582 if(foundText == false) {
2583
2584 // Check if the sound file already references commandata
2585 foundText = searchAndReplaceTextInFile(parentFile, newCommonFileName, newCommonFileName, true);
2586 if(foundText == false) {
2587 char szBuf[8096]="";
2588 snprintf(szBuf,8096,"Line ref = %d, Error finding text\n[%s]\nin file\n[%s]\nnew Common File [%s]\n",__LINE__,searchText.c_str(),parentFile.c_str(),newCommonFileName.c_str());
2589 printf("\n\n=================================================\n%s",szBuf);
2590
2591 throw megaglest_runtime_error(szBuf);
2592 }
2593 }
2594 }
2595 }
2596 }
2597 }
2598 }
2599 }
2600
2601
2602 printf("----- END duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
2603 }
2604 }
2605 if(foundDuplicates == true) {
2606 printf("Duplicates %.2f MB (%d) in files\n",duplicateMegaBytes,duplicateCount);
2607 printf("Duplicates purged %.2f MB (%d) in files\n",duplicateMegaBytesPurged,duplicateCountPurged);
2608
2609 printf("\nWarning, duplicate files were detected - END:\n");
2610 }
2611 }
2612 }
2613 catch(const megaglest_runtime_error &ex) {
2614 techtree_errors = true;
2615 printf("\n\n****ERROR**** detected while validating the techName: %s\nMESSAGE: %s\n",techName.c_str(),ex.what());
2616 }
2617
2618 if(techtree_errors == false) {
2619 printf("\nValidation found NO ERRORS for techPath [%s] techName [%s] factions checked (count = %d):\n",techPath.c_str(), techName.c_str(),(int)factions.size());
2620 for ( set<string>::iterator it = factions.begin(); it != factions.end(); ++it ) {
2621 printf("Faction [%s]\n",(*it).c_str());
2622 }
2623 }
2624 }
2625 printf("----------------------------------------------------------------");
2626 }
2627 else if(folderExists(techTreeFolder) == true) {
2628 printf("\nWarning, No factions were found for the techtree located in: [%s]\n",techTreeFolder.c_str());
2629 }
2630 }
2631
2632
runTechTranslationExtractionForPath(string techPath,string techName,const std::vector<string> & filteredFactionList,World & world)2633 void runTechTranslationExtractionForPath(string techPath, string techName,
2634 const std::vector<string> &filteredFactionList, World &world) {
2635 vector<string> factionsList;
2636 findDirs(techPath + techName + "/factions/", factionsList, false, false);
2637
2638 if(factionsList.empty() == false) {
2639 Checksum checksum;
2640 set<string> factions;
2641 for(int j = 0; j < (int)factionsList.size(); ++j) {
2642 if( filteredFactionList.empty() == true ||
2643 std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
2644 factions.insert(factionsList[j]);
2645 }
2646 }
2647
2648 printf("\n----------------------------------------------------------------");
2649 printf("\nChecking techPath [%s] techName [%s] total faction count = %d\n",techPath.c_str(), techName.c_str(),(int)factionsList.size());
2650 for(int j = 0; j < (int)factionsList.size(); ++j) {
2651 if( filteredFactionList.empty() == true ||
2652 std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
2653 printf("Using faction [%s]\n",factionsList[j].c_str());
2654 }
2655 }
2656
2657 if(factions.empty() == false) {
2658 std::map<string,vector<pair<string, string> > > loadedFileList;
2659 vector<string> pathList;
2660 pathList.push_back(techPath);
2661 Config &config = Config::getInstance();
2662 vector<string> otherTechPaths = config.getPathListForType(ptTechs,"");
2663 pathList.insert(pathList.end(), otherTechPaths.begin(), otherTechPaths.end());
2664
2665 try {
2666 world.loadTech(pathList, techName, factions, &checksum, loadedFileList, true);
2667
2668 const TechTree *techtree = world.getTechTree();
2669 string translationFile = techtree->getPath();
2670 endPathWithSlash(translationFile);
2671 translationFile += "lang/" + techName + "_default.lng";
2672 if(fileExists(translationFile) == false) {
2673 string txFilePath = extractDirectoryPathFromFile(translationFile);
2674 createDirectoryPaths(txFilePath);
2675
2676 #if defined(WIN32) && !defined(__MINGW32__)
2677 FILE *fp = _wfopen(utf8_decode(translationFile).c_str(), L"w");
2678 std::ofstream txFile(fp);
2679 #else
2680 std::ofstream txFile;
2681 txFile.open(translationFile.c_str(), ios_base::out | ios_base::trunc);
2682 #endif
2683
2684 if(txFile.is_open() == true) {
2685 string _transl_TechTreeName = techName;
2686 replaceAll(_transl_TechTreeName,"_"," ");
2687 txFile << "; TechTree" << std::endl;
2688 txFile << "TechTreeName=" << _transl_TechTreeName << std::endl;
2689
2690 txFile << "; -------------------------------------" << std::endl;
2691 txFile << "; Types of Armor" << std::endl;
2692 for(int index = 0; index < techtree->getArmorTypeCount(); ++index) {
2693 const ArmorType *at = techtree->getArmorTypeByIndex(index);
2694 string _transl_ArmorTypeName = at->getName(false);
2695 replaceAll(_transl_ArmorTypeName,"_"," ");
2696 txFile << "ArmorTypeName_" << at->getName(false) << "=" << _transl_ArmorTypeName << std::endl;
2697 }
2698
2699 txFile << "; --------------------" << std::endl;
2700 txFile << "; Types of Attack" << std::endl;
2701 for(int index = 0; index < techtree->getAttackTypeCount(); ++index) {
2702 const AttackType *at = techtree->getAttackTypeByIndex(index);
2703 string _transl_AttackTypeName = at->getName(false);
2704 replaceAll(_transl_AttackTypeName,"_"," ");
2705 txFile << "AttackTypeName_" << at->getName(false) << "=" << _transl_AttackTypeName << std::endl;
2706 }
2707
2708 txFile << "; --------------------" << std::endl;
2709 txFile << "; Types of Resources" << std::endl;
2710 for(int index = 0; index < techtree->getResourceTypeCount(); ++index) {
2711 const ResourceType *rt = techtree->getResourceType(index);
2712 string _transl_ResourceTypeName = rt->getName(false);
2713 replaceAll(_transl_ResourceTypeName,"_"," ");
2714 txFile << "ResourceTypeName_" << rt->getName(false) << "=" << _transl_ResourceTypeName << std::endl;
2715 }
2716
2717 //txFile << "FactionName_" << GameConstants::OBSERVER_SLOTNAME << "=" << GameConstants::OBSERVER_SLOTNAME << std::endl;
2718 //txFile << "FactionName_" << GameConstants::RANDOMFACTION_SLOTNAME << "=" << GameConstants::RANDOMFACTION_SLOTNAME << std::endl;
2719 for(int index = 0; index < techtree->getTypeCount(); ++index) {
2720 const FactionType *ft = techtree->getType(index);
2721 string _transl_FactionName = ft->getName(false);
2722 replaceAll(_transl_FactionName,"_"," ");
2723 txFile << "; -----------------------------------------------------------------------------" << std::endl;
2724 txFile << "; Faction" << std::endl;
2725 txFile << "FactionName_" << ft->getName(false) << "=" << _transl_FactionName << std::endl;
2726
2727 txFile << "; -------------------------------------" << std::endl;
2728 txFile << "; Types of Upgrades for this Faction" << std::endl;
2729 for(int upgradeIndex = 0; upgradeIndex < ft->getUpgradeTypeCount(); ++upgradeIndex) {
2730 const UpgradeType *upt = ft->getUpgradeType(upgradeIndex);
2731 string _transl_UpgradeTypeName = upt->getName(false);
2732 replaceAll(_transl_UpgradeTypeName,"_"," ");
2733 txFile << "UpgradeTypeName_" << upt->getName(false) << "=" << _transl_UpgradeTypeName << std::endl;
2734 }
2735
2736 for(int unitIndex = 0; unitIndex < ft->getUnitTypeCount(); ++unitIndex) {
2737 const UnitType *ut = ft->getUnitType(unitIndex);
2738 string _transl_UnitTypeName = ut->getName(false);
2739 replaceAll(_transl_UnitTypeName,"_"," ");
2740 txFile << "; -------------------------------------" << std::endl;
2741 txFile << "; Unit" << std::endl;
2742 txFile << "UnitTypeName_" << ut->getName(false) << "=" << _transl_UnitTypeName << std::endl;
2743
2744 txFile << "; --------------------" << std::endl;
2745 txFile << "; Levels for this Unit" << std::endl;
2746 for(int levelIndex = 0; levelIndex < ut->getLevelCount(); ++levelIndex) {
2747 const Level *level = ut->getLevel(levelIndex);
2748 string _transl_LevelName = level->getName(false);
2749 replaceAll(_transl_LevelName,"_"," ");
2750 txFile << "LevelName_" << level->getName(false) << "=" << _transl_LevelName << std::endl;
2751 }
2752
2753 txFile << "; --------------------" << std::endl;
2754 txFile << "; Types of Commands for this Unit" << std::endl;
2755 for(int commandIndex = 0; commandIndex < ut->getCommandTypeCount(); ++commandIndex) {
2756 const CommandType *ct = ut->getCommandType(commandIndex);
2757 string _transl_CommandName = ct->getName(false);
2758 replaceAll(_transl_CommandName,"_"," ");
2759 txFile << "CommandName_" << ct->getName(false) << "=" << _transl_CommandName << std::endl;
2760 }
2761 }
2762 }
2763 txFile << "; -------------------------------------" << std::endl;
2764 }
2765 txFile.close();
2766
2767 #if defined(WIN32) && !defined(__MINGW32__)
2768 if(fp) {
2769 fclose(fp);
2770 }
2771 #endif
2772
2773 }
2774 else {
2775 printf("\n** Cannot product techtree translation file [%s] for techPath [%s] techName [%s] because the file already exists!\n",translationFile.c_str(),techPath.c_str(), techName.c_str());
2776 }
2777 }
2778 catch(const megaglest_runtime_error &ex) {
2779 printf("\n\n****ERROR**** detected while loading the techName: %s\nMESSAGE: %s\n",techName.c_str(),ex.what());
2780 }
2781
2782 }
2783 printf("----------------------------------------------------------------");
2784 }
2785 }
2786
runTechTranslationExtraction(int argc,char ** argv)2787 void runTechTranslationExtraction(int argc, char** argv) {
2788 printf("====== Started Translation Extraction ======\n");
2789
2790 Config &config = Config::getInstance();
2791
2792 // Did the user pass a specific list of factions to validate?
2793 std::vector<string> filteredFactionList;
2794
2795 vector<string> results;
2796 findDirs(config.getPathListForType(ptTechs), results);
2797 vector<string> techTreeFiles = results;
2798 // Did the user pass a specific list of techtrees to validate?
2799 std::vector<string> filteredTechTreeList;
2800 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) + string("=")) == true) {
2801 int foundParamIndIndex = -1;
2802 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) + string("="),&foundParamIndIndex);
2803 string filterList = argv[foundParamIndIndex];
2804 vector<string> paramPartTokens;
2805 Tokenize(filterList,paramPartTokens,"=");
2806 if(paramPartTokens.size() >= 2) {
2807 string techtreeList = paramPartTokens[1];
2808 Tokenize(techtreeList,filteredTechTreeList,",");
2809
2810 if(filteredTechTreeList.empty() == false) {
2811 printf("Filtering techtrees and only looking for the following:\n");
2812 for(int idx = 0; idx < (int)filteredTechTreeList.size(); ++idx) {
2813 filteredTechTreeList[idx] = trim(filteredTechTreeList[idx]);
2814 printf("%s\n",filteredTechTreeList[idx].c_str());
2815 }
2816 }
2817 }
2818 }
2819
2820 {
2821 printf("\n---------------- Loading factions inside world ----------------");
2822 World world;
2823
2824 vector<string> techPaths = config.getPathListForType(ptTechs);
2825 for(int idx = 0; idx < (int)techPaths.size(); idx++) {
2826 string &techPath = techPaths[idx];
2827 endPathWithSlash(techPath);
2828
2829 for(int idx2 = 0; idx2 < (int)techTreeFiles.size(); idx2++) {
2830 string &techName = techTreeFiles[idx2];
2831
2832 if( filteredTechTreeList.empty() == true ||
2833 std::find(filteredTechTreeList.begin(),filteredTechTreeList.end(),techName) != filteredTechTreeList.end()) {
2834
2835 runTechTranslationExtractionForPath(techPath, techName,
2836 filteredFactionList,world);
2837 }
2838 }
2839 }
2840
2841 printf("\n====== Finished Translation ======\n");
2842 }
2843
2844 }
2845
2846
runTechValidationReport(int argc,char ** argv)2847 void runTechValidationReport(int argc, char** argv) {
2848 printf("====== Started Validation ======\n");
2849
2850 bool purgeDuplicateFiles = false;
2851 bool showDuplicateFiles = true;
2852 bool purgeUnusedFiles = false;
2853 bool gitPurgeFiles = false;
2854
2855 double purgedMegaBytes=0;
2856 Config &config = Config::getInstance();
2857
2858 // Did the user pass a specific scenario to validate?
2859 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) + string("=")) == true) {
2860
2861 int foundParamIndIndex = -1;
2862 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) + string("="),&foundParamIndIndex);
2863
2864 string filterList = argv[foundParamIndIndex];
2865 vector<string> paramPartTokens;
2866 Tokenize(filterList,paramPartTokens,"=");
2867
2868 if(paramPartTokens.size() >= 2) {
2869 string validateScenarioName = paramPartTokens[1];
2870
2871 printf("Filtering scenario: %s\n",validateScenarioName.c_str());
2872
2873 if(paramPartTokens.size() >= 3) {
2874 if(paramPartTokens[2] == "purgeunused") {
2875 purgeUnusedFiles = true;
2876 printf("*NOTE All unused scenario files will be deleted!\n");
2877 }
2878 }
2879
2880 {
2881 printf("\n---------------- Loading scenario inside world ----------------\n");
2882
2883 bool scenarioFound = false;
2884 World world;
2885 std::vector<string> filteredFactionList;
2886
2887 vector<string> scenarioPaths = config.getPathListForType(ptScenarios);
2888 for(int idx = 0; idx < (int)scenarioPaths.size(); idx++) {
2889 string &scenarioPath = scenarioPaths[idx];
2890 endPathWithSlash(scenarioPath);
2891
2892 vector<string> scenarioList;
2893 findDirs(scenarioPath, scenarioList, false, false);
2894 for(int idx2 = 0; idx2 < (int)scenarioList.size(); idx2++) {
2895 string &scenarioName = scenarioList[idx2];
2896
2897 if(scenarioName == validateScenarioName) {
2898 scenarioFound = true;
2899
2900 string file = scenarioPath + scenarioName + "/" + scenarioName + ".xml";
2901
2902 XmlTree xmlTree;
2903 xmlTree.load(file,Properties::getTagReplacementValues());
2904 const XmlNode *scenarioNode= xmlTree.getRootNode();
2905 string techName = scenarioNode->getChild("tech-tree")->getAttribute("value")->getValue();
2906
2907 // Self Contained techtree?
2908 string scenarioTechtree = scenarioPath + scenarioName + "/" + techName + "/" + techName + ".xml";
2909
2910 printf("\nFound Scenario [%s] looking for techtree [%s]...\n",scenarioName.c_str(),scenarioTechtree.c_str());
2911
2912 if(fileExists(scenarioTechtree) == true) {
2913 string techPath = scenarioPath + scenarioName + "/";
2914
2915 printf("\nFound Scenario [%s] with custom techtree [%s] validating...\n",scenarioName.c_str(),techName.c_str());
2916 runTechValidationForPath(techPath, techName, filteredFactionList,
2917 world, purgeUnusedFiles, showDuplicateFiles, false, false, purgedMegaBytes);
2918 }
2919 else {
2920 vector<string> techPaths = config.getPathListForType(ptTechs);
2921 for(int idx = 0; idx < (int)techPaths.size(); idx++) {
2922 string &techPath = techPaths[idx];
2923 endPathWithSlash(techPath);
2924 scenarioTechtree = techPath + "/" + techName + "/" + techName + ".xml";
2925 if(fileExists(scenarioTechtree) == true) {
2926 printf("\nFound Scenario [%s] with techtree [%s] validating...\n",scenarioName.c_str(),techName.c_str());
2927 runTechValidationForPath(techPath, techName, filteredFactionList,
2928 world, purgeUnusedFiles, showDuplicateFiles, false, false, purgedMegaBytes);
2929
2930 break;
2931 }
2932 }
2933 }
2934 }
2935 }
2936 }
2937
2938 if(scenarioFound == false) {
2939 printf("\nWARNING, the scenario [%s] was NOT FOUND!\n",validateScenarioName.c_str());
2940 }
2941 printf("\n====== Finished Validation ======\n");
2942 }
2943 return;
2944 }
2945 else {
2946 printf("\nInvalid missing scenario specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
2947 return;
2948 }
2949 }
2950
2951 // Did the user pass a specific list of factions to validate?
2952 std::vector<string> filteredFactionList;
2953 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) + string("=")) == true) {
2954 int foundParamIndIndex = -1;
2955 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) + string("="),&foundParamIndIndex);
2956
2957 string filterList = argv[foundParamIndIndex];
2958 vector<string> paramPartTokens;
2959 Tokenize(filterList,paramPartTokens,"=");
2960
2961 if(paramPartTokens.size() >= 2) {
2962 string factionList = paramPartTokens[1];
2963 Tokenize(factionList,filteredFactionList,",");
2964
2965 if(filteredFactionList.empty() == false) {
2966 printf("Filtering factions and only looking for the following:\n");
2967 for(int idx = 0; idx < (int)filteredFactionList.size(); ++idx) {
2968 filteredFactionList[idx] = trim(filteredFactionList[idx]);
2969 printf("%s\n",filteredFactionList[idx].c_str());
2970 }
2971 }
2972
2973 if(paramPartTokens.size() >= 3) {
2974 if(paramPartTokens[2] == "purgeunused") {
2975 purgeUnusedFiles = true;
2976 printf("*NOTE All unused faction files will be deleted!\n");
2977 }
2978 }
2979 }
2980 }
2981 vector<string> results;
2982 findDirs(config.getPathListForType(ptTechs), results);
2983 vector<string> techTreeFiles = results;
2984 // Did the user pass a specific list of techtrees to validate?
2985 std::vector<string> filteredTechTreeList;
2986 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) + string("=")) == true) {
2987 int foundParamIndIndex = -1;
2988 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) + string("="),&foundParamIndIndex);
2989 string filterList = argv[foundParamIndIndex];
2990 vector<string> paramPartTokens;
2991 Tokenize(filterList,paramPartTokens,"=");
2992 if(paramPartTokens.size() >= 2) {
2993 string techtreeList = paramPartTokens[1];
2994 Tokenize(techtreeList,filteredTechTreeList,",");
2995
2996 if(filteredTechTreeList.empty() == false) {
2997 printf("Filtering techtrees and only looking for the following:\n");
2998 for(int idx = 0; idx < (int)filteredTechTreeList.size(); ++idx) {
2999 filteredTechTreeList[idx] = trim(filteredTechTreeList[idx]);
3000 printf("%s\n",filteredTechTreeList[idx].c_str());
3001 }
3002 }
3003
3004 if(paramPartTokens.size() >= 3) {
3005 if(paramPartTokens[2] == "purgeunused") {
3006 purgeUnusedFiles = true;
3007 printf("*NOTE All unused techtree files will be deleted!\n");
3008 }
3009 else if(paramPartTokens[2] == "purgeduplicates") {
3010 purgeDuplicateFiles = true;
3011 printf("*NOTE All duplicate techtree files will be merged!\n");
3012 }
3013 else if(paramPartTokens[2] == "gitdelete") {
3014 gitPurgeFiles = true;
3015 printf("*NOTE All unused / duplicate techtree files will be removed from git!\n");
3016 }
3017 else if(paramPartTokens[2] == "hideduplicates") {
3018 showDuplicateFiles = false;
3019 printf("*NOTE All duplicate techtree files will NOT be shown!\n");
3020 }
3021 }
3022 if(paramPartTokens.size() >= 4) {
3023 if(paramPartTokens[3] == "purgeunused") {
3024 purgeUnusedFiles = true;
3025 printf("*NOTE All unused techtree files will be deleted!\n");
3026 }
3027 else if(paramPartTokens[3] == "purgeduplicates") {
3028 purgeDuplicateFiles = true;
3029 printf("*NOTE All duplicate techtree files will be merged!\n");
3030 }
3031 else if(paramPartTokens[3] == "gitdelete") {
3032 gitPurgeFiles = true;
3033 printf("*NOTE All unused / duplicate techtree files will be removed from git!\n");
3034 }
3035 else if(paramPartTokens[3] == "hideduplicates") {
3036 showDuplicateFiles = false;
3037 printf("*NOTE All duplicate techtree files will NOT be shown!\n");
3038 }
3039 }
3040 if(paramPartTokens.size() >= 5) {
3041 if(paramPartTokens[4] == "purgeunused") {
3042 purgeUnusedFiles = true;
3043 printf("*NOTE All unused techtree files will be deleted!\n");
3044 }
3045 else if(paramPartTokens[4] == "purgeduplicates") {
3046 purgeDuplicateFiles = true;
3047 printf("*NOTE All duplicate techtree files will be merged!\n");
3048 }
3049 else if(paramPartTokens[4] == "gitdelete") {
3050 gitPurgeFiles = true;
3051 printf("*NOTE All unused / duplicate techtree files will be removed from git!\n");
3052 }
3053 else if(paramPartTokens[4] == "hideduplicates") {
3054 showDuplicateFiles = false;
3055 printf("*NOTE All duplicate techtree files will NOT be shown!\n");
3056 }
3057 }
3058 }
3059 }
3060
3061 {
3062 printf("\n---------------- Loading factions inside world ----------------");
3063 World world;
3064
3065 vector<string> techPaths = config.getPathListForType(ptTechs);
3066 for(int idx = 0; idx < (int)techPaths.size(); idx++) {
3067 string &techPath = techPaths[idx];
3068 endPathWithSlash(techPath);
3069
3070 for(int idx2 = 0; idx2 < (int)techTreeFiles.size(); idx2++) {
3071 string &techName = techTreeFiles[idx2];
3072
3073 if( filteredTechTreeList.empty() == true ||
3074 std::find(filteredTechTreeList.begin(),filteredTechTreeList.end(),techName) != filteredTechTreeList.end()) {
3075
3076 runTechValidationForPath(techPath, techName, filteredFactionList,
3077 world, purgeUnusedFiles,purgeDuplicateFiles,
3078 showDuplicateFiles,gitPurgeFiles,purgedMegaBytes);
3079 }
3080 }
3081 }
3082
3083 printf("\n====== Finished Validation ======\n");
3084 }
3085
3086 }
3087
runTilesetValidationReport(int argc,char ** argv)3088 void runTilesetValidationReport(int argc, char** argv) {
3089 printf("====== Started Validation ======\n");
3090
3091 Config &config = Config::getInstance();
3092
3093 // Did the user pass a specific tileset to validate?
3094 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) + string("=")) == true) {
3095 int foundParamIndIndex = -1;
3096 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) + string("="),&foundParamIndIndex);
3097
3098 string filterList = argv[foundParamIndIndex];
3099 vector<string> paramPartTokens;
3100 Tokenize(filterList,paramPartTokens,"=");
3101
3102 if(paramPartTokens.size() >= 2) {
3103 string validateTilesetName = paramPartTokens[1];
3104
3105 printf("Filtering tileset: %s\n",validateTilesetName.c_str());
3106
3107 bool purgeUnusedFiles = false;
3108 if(paramPartTokens.size() >= 3) {
3109 if(paramPartTokens[2] == "purgeunused") {
3110 purgeUnusedFiles = true;
3111 printf("*NOTE All unused tileset files will be deleted!\n");
3112 }
3113 }
3114
3115 {
3116 printf("\n---------------- Loading tileset inside world ----------------\n");
3117
3118 World world;
3119 double purgedMegaBytes=0;
3120 bool showDuplicateFiles = true;
3121
3122 bool tilesetFound = false;
3123
3124 vector<string> tilesetPaths = config.getPathListForType(ptTilesets);
3125 for(int idx = 0; idx < (int)tilesetPaths.size(); idx++) {
3126 string &tilesetPath = tilesetPaths[idx];
3127 endPathWithSlash(tilesetPath);
3128
3129 vector<string> tilesetList;
3130 findDirs(tilesetPath, tilesetList, false, false);
3131 for(int idx2 = 0; idx2 < (int)tilesetList.size(); idx2++) {
3132 string &tilesetName = tilesetList[idx2];
3133 if(tilesetName == validateTilesetName) {
3134 tilesetFound = true;
3135 runTilesetValidationForPath(tilesetPath, tilesetName,
3136 world, purgeUnusedFiles, showDuplicateFiles,
3137 false, false, purgedMegaBytes);
3138 }
3139 }
3140 }
3141
3142 if(tilesetFound == false) {
3143 printf("*ERROR The specified tileset [%s] was NOT FOUND!\n",validateTilesetName.c_str());
3144 }
3145 printf("\n====== Finished Validation ======\n");
3146 }
3147 return;
3148 }
3149 else {
3150 printf("\nInvalid missing tileset specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
3151 return;
3152 }
3153 }
3154 else {
3155 printf("\nInvalid missing tileset specified on commandline\n\n");
3156 return;
3157 }
3158 }
3159
ShowINISettings(int argc,char ** argv,Config & config,Config & configKeys)3160 void ShowINISettings(int argc, char **argv,Config &config,Config &configKeys) {
3161 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true) {
3162 vector<string> filteredPropertyList;
3163 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) + string("=")) == true) {
3164 int foundParamIndIndex = -1;
3165 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) + string("="),&foundParamIndIndex);
3166 string filterList = argv[foundParamIndIndex];
3167 vector<string> paramPartTokens;
3168 Tokenize(filterList,paramPartTokens,"=");
3169 if(paramPartTokens.size() >= 2) {
3170 string tokenList = paramPartTokens[1];
3171 Tokenize(tokenList,filteredPropertyList,",");
3172
3173 if(filteredPropertyList.empty() == false) {
3174 printf("Filtering properties and only looking for the following:\n");
3175 for(int idx = 0; idx < (int)filteredPropertyList.size(); ++idx) {
3176 filteredPropertyList[idx] = trim(filteredPropertyList[idx]);
3177 printf("%s\n",filteredPropertyList[idx].c_str());
3178 }
3179 }
3180 }
3181 }
3182
3183 printf("\nMain settings report\n");
3184 printf("====================\n");
3185 vector<pair<string,string> > mergedMainSettings = config.getMergedProperties();
3186 vector<pair<string,string> > mergedKeySettings = configKeys.getMergedProperties();
3187
3188 // Figure out the max # of tabs we need to format display nicely
3189 int tabCount = 1;
3190 for(int i = 0; i < (int)mergedMainSettings.size(); ++i) {
3191 const pair<string,string> &nameValue = mergedMainSettings[i];
3192
3193 bool displayProperty = false;
3194 if(filteredPropertyList.empty() == false) {
3195 if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
3196 displayProperty = true;
3197 }
3198 }
3199 else {
3200 displayProperty = true;
3201 }
3202
3203 if(displayProperty == true) {
3204 int requredTabs = ((int)nameValue.first.length() / 8)+1;
3205 if(nameValue.first.length() % 8) {
3206 requredTabs++;
3207 }
3208 if(requredTabs > tabCount) {
3209 tabCount = requredTabs;
3210 }
3211 }
3212 }
3213 for(int i = 0; i < (int)mergedKeySettings.size(); ++i) {
3214 const pair<string,string> &nameValue = mergedKeySettings[i];
3215
3216 bool displayProperty = false;
3217 if(filteredPropertyList.empty() == false) {
3218 if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
3219 displayProperty = true;
3220 }
3221 }
3222 else {
3223 displayProperty = true;
3224 }
3225
3226 if(displayProperty == true) {
3227 int requredTabs = ((int)nameValue.first.length() / 8)+1;
3228 if(nameValue.first.length() % 8) {
3229 requredTabs++;
3230 }
3231 if(requredTabs > tabCount) {
3232 tabCount = requredTabs;
3233 }
3234 }
3235 }
3236
3237 // Output the properties
3238 for(int i = 0; i < (int)mergedMainSettings.size(); ++i) {
3239 const pair<string,string> &nameValue = mergedMainSettings[i];
3240
3241 bool displayProperty = false;
3242 if(filteredPropertyList.empty() == false) {
3243 if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
3244 displayProperty = true;
3245 }
3246 }
3247 else {
3248 displayProperty = true;
3249 }
3250
3251 if(displayProperty == true) {
3252 printf("Property Name [%s]",nameValue.first.c_str());
3253
3254 int tabs = ((int)nameValue.first.length() / 8) + 1;
3255 for(int j = 0; j < (tabCount - tabs); ++j) {
3256 printf("\t");
3257 }
3258
3259 string displayValue = nameValue.second;
3260 if(nameValue.first == "TranslationGetURLPassword") {
3261 displayValue = "*****";
3262 }
3263
3264 printf("Value [%s]\n",displayValue.c_str());
3265 }
3266 }
3267
3268 printf("\n\nMain key binding settings report\n");
3269 printf("====================================\n");
3270
3271 for(int i = 0; i < (int)mergedKeySettings.size(); ++i) {
3272 const pair<string,string> &nameValue = mergedKeySettings[i];
3273
3274 bool displayProperty = false;
3275 if(filteredPropertyList.empty() == false) {
3276 if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
3277 displayProperty = true;
3278 }
3279 }
3280 else {
3281 displayProperty = true;
3282 }
3283
3284 if(displayProperty == true) {
3285 printf("Property Name [%s]",nameValue.first.c_str());
3286
3287 int tabs = ((int)nameValue.first.length() / 8) + 1;
3288 for(int j = 0; j < (tabCount - tabs); ++j) {
3289 printf("\t");
3290 }
3291
3292 printf("Value [%s]\n",nameValue.second.c_str());
3293 }
3294 }
3295 }
3296 }
3297
CheckForDuplicateData()3298 void CheckForDuplicateData() {
3299 Config &config = Config::getInstance();
3300
3301 string duplicateWarnings="";
3302
3303 try {
3304
3305
3306 {
3307
3308 string scenarioDir = "";
3309 vector<string> pathList = config.getPathListForType(ptMaps,scenarioDir);
3310 vector<string> invalidMapList;
3311 vector<string> maps = MapPreview::findAllValidMaps(pathList,scenarioDir,false,true,&invalidMapList);
3312 std::sort(maps.begin(),maps.end());
3313
3314 if(maps.empty() == true) {
3315 throw megaglest_runtime_error("No maps were found!",true);
3316 }
3317 else if(invalidMapList.empty() == false) {
3318 string errorMsg = "Warning invalid maps were detected (will be ignored):\n";
3319 for(int i = 0; i < (int)invalidMapList.size(); ++i) {
3320 char szBuf[8096]="";
3321 snprintf(szBuf,8096,"map [%s]\n",invalidMapList[i].c_str());
3322
3323 errorMsg += szBuf;
3324 }
3325 duplicateWarnings += errorMsg;
3326 }
3327
3328 vector<string> duplicateMapsToRename;
3329 for(int i = 0; i < (int)maps.size(); ++i) {
3330 string map1 = maps[i];
3331 for(int j = 0; j < (int)maps.size(); ++j) {
3332 if(i != j) {
3333 string map2 = maps[j];
3334
3335 if(map1 == map2) {
3336 if(std::find(duplicateMapsToRename.begin(),duplicateMapsToRename.end(),map1) == duplicateMapsToRename.end()) {
3337 duplicateMapsToRename.push_back(map1);
3338 }
3339 }
3340 }
3341 }
3342 }
3343 if(duplicateMapsToRename.empty() == false) {
3344 string errorMsg = "Warning duplicate maps were detected and renamed:\n";
3345 for(int i = 0; i < (int)duplicateMapsToRename.size(); ++i) {
3346 string currentPath = pathList[1];
3347 endPathWithSlash(currentPath);
3348
3349 string oldFile = currentPath + duplicateMapsToRename[i];
3350 string newFile = currentPath + duplicateMapsToRename[i];
3351 string ext = extractExtension(newFile);
3352 newFile = newFile.substr( 0, newFile.length()-ext.length()-1);
3353 newFile = newFile + "_custom." + ext;
3354
3355 char szBuf[8096]="";
3356 int result = rename(oldFile.c_str(),newFile.c_str());
3357 if(result != 0) {
3358 char *errmsg = strerror(errno);
3359 snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
3360 throw megaglest_runtime_error(szBuf,true);
3361 }
3362 else {
3363 snprintf(szBuf,8096,"map [%s] in [%s]\nwas renamed to [%s]",duplicateMapsToRename[i].c_str(),oldFile.c_str(),newFile.c_str());
3364 }
3365 errorMsg += szBuf;
3366 }
3367 duplicateWarnings += errorMsg;
3368 }
3369 }
3370
3371 {
3372 //tilesets
3373 std::vector<std::string> tileSets;
3374 vector<string> tilesetPaths = config.getPathListForType(ptTilesets);
3375 findDirs(tilesetPaths, tileSets, false, true);
3376
3377 if (tileSets.empty()) {
3378 throw megaglest_runtime_error("No tilesets were found!",true);
3379 }
3380
3381 vector<string> duplicateTilesetsToRename;
3382 for(int i = 0; i < (int)tileSets.size(); ++i) {
3383 string tileSet1 = tileSets[i];
3384 for(int j = 0; j < (int)tileSets.size(); ++j) {
3385 if(i != j) {
3386 string tileSet2= tileSets[j];
3387 if(tileSet1 == tileSet2) {
3388 if(std::find(duplicateTilesetsToRename.begin(),duplicateTilesetsToRename.end(),tileSet1) == duplicateTilesetsToRename.end()) {
3389 duplicateTilesetsToRename.push_back(tileSet1);
3390 }
3391 }
3392 }
3393 }
3394 }
3395 if(duplicateTilesetsToRename.empty() == false) {
3396 string errorMsg = "Warning duplicate tilesets were detected and renamed:\n";
3397
3398 for(int i = 0; i < (int)duplicateTilesetsToRename.size(); ++i) {
3399 string currentPath = tilesetPaths[1];
3400 endPathWithSlash(currentPath);
3401
3402 string oldFile = currentPath + duplicateTilesetsToRename[i];
3403 string newFile = currentPath + duplicateTilesetsToRename[i];
3404 newFile = newFile + "_custom";
3405
3406 char szBuf[8096]="";
3407 int result = rename(oldFile.c_str(),newFile.c_str());
3408 if(result != 0) {
3409 char *errmsg = strerror(errno);
3410 snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
3411 throw megaglest_runtime_error(szBuf,true);
3412 }
3413 else {
3414 snprintf(szBuf,8096,"tileset [%s] in [%s]\nwas renamed to [%s]",duplicateTilesetsToRename[i].c_str(),oldFile.c_str(),newFile.c_str());
3415
3416 string tilesetName = extractFileFromDirectoryPath(oldFile);
3417 oldFile = newFile + "/" + tilesetName + ".xml";
3418 newFile = newFile + "/" + tilesetName + "_custom.xml";
3419
3420 result = rename(oldFile.c_str(),newFile.c_str());
3421
3422 if(result != 0) {
3423 char *errmsg = strerror(errno);
3424 snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
3425 throw megaglest_runtime_error(szBuf,true);
3426 }
3427
3428 }
3429 errorMsg += szBuf;
3430 }
3431 duplicateWarnings += errorMsg;
3432 }
3433 }
3434
3435 {
3436 vector<string> techPaths = config.getPathListForType(ptTechs);
3437 vector<string> techTrees;
3438 findDirs(techPaths, techTrees, false, true);
3439 if(techTrees.empty()) {
3440 throw megaglest_runtime_error("No tech-trees were found (dup)!",true);
3441 }
3442
3443 vector<string> duplicateTechtreesToRename;
3444 for(int i = 0; i < (int)techTrees.size(); ++i) {
3445 string techtree1 = techTrees[i];
3446 for(int j = 0; j < (int)techTrees.size(); ++j) {
3447 if(i != j) {
3448 string techtree2 = techTrees[j];
3449 if(techtree1 == techtree2) {
3450 if(std::find(duplicateTechtreesToRename.begin(),duplicateTechtreesToRename.end(),techtree1) == duplicateTechtreesToRename.end()) {
3451 duplicateTechtreesToRename.push_back(techtree1);
3452 }
3453 }
3454 }
3455 }
3456 }
3457 if(duplicateTechtreesToRename.empty() == false) {
3458 string errorMsg = "Warning duplicate techtrees were detected and renamed:\n";
3459
3460 for(int i = 0; i < (int)duplicateTechtreesToRename.size(); ++i) {
3461 string currentPath = techPaths[1];
3462 endPathWithSlash(currentPath);
3463
3464 string oldFile = currentPath + duplicateTechtreesToRename[i];
3465 string newFile = currentPath + duplicateTechtreesToRename[i];
3466 newFile = newFile + "_custom";
3467
3468 char szBuf[8096]="";
3469 int result = rename(oldFile.c_str(),newFile.c_str());
3470 if(result != 0) {
3471 char *errmsg = strerror(errno);
3472 snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
3473 throw megaglest_runtime_error(szBuf,true);
3474 }
3475 else {
3476 snprintf(szBuf,8096,"techtree [%s] in [%s]\nwas renamed to [%s]",duplicateTechtreesToRename[i].c_str(),oldFile.c_str(),newFile.c_str());
3477
3478 string tilesetName = extractFileFromDirectoryPath(oldFile);
3479 oldFile = newFile + "/" + tilesetName + ".xml";
3480 newFile = newFile + "/" + tilesetName + "_custom.xml";
3481
3482 int rename_result = rename(oldFile.c_str(),newFile.c_str());
3483 if(rename_result != 0) {
3484 printf("Error renaming [%s] to [%s]\n",oldFile.c_str(),newFile.c_str());
3485 }
3486 }
3487 errorMsg += szBuf;
3488 }
3489 duplicateWarnings += errorMsg;
3490 }
3491 }
3492
3493 }
3494 catch(const megaglest_runtime_error &ex) {
3495 if(mainProgram) {
3496 mainProgram->getState()->setForceMouseRender(true);
3497 }
3498 ExceptionHandler::DisplayMessage(ex.what(), false);
3499 }
3500
3501 if(duplicateWarnings != "") {
3502 if(mainProgram) {
3503 mainProgram->getState()->setForceMouseRender(true);
3504 }
3505 ExceptionHandler::DisplayMessage(duplicateWarnings.c_str(), false);
3506 }
3507 }
3508
handleCreateDataArchivesCommand(int argc,char ** argv)3509 int handleCreateDataArchivesCommand(int argc, char** argv) {
3510 int return_value = 1;
3511 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
3512 int foundParamIndIndex = -1;
3513 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) + string("="),&foundParamIndIndex);
3514 if(foundParamIndIndex < 0) {
3515 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]),&foundParamIndIndex);
3516 }
3517 string paramValue = argv[foundParamIndIndex];
3518 vector<string> paramPartTokens;
3519 Tokenize(paramValue,paramPartTokens,"=");
3520 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3521 string compress_item = paramPartTokens[1];
3522 bool includeMainData = false;
3523 if(paramPartTokens.size() >= 3 && paramPartTokens[2] == "include_main") {
3524 includeMainData = true;
3525 }
3526
3527 Config &config = Config::getInstance();
3528 string fileArchiveExtension = config.getString("FileArchiveExtension","");
3529 string fileArchiveCompressCommand = config.getString("FileArchiveCompressCommand","");
3530 string fileArchiveCompressCommandParameters = config.getString("FileArchiveCompressCommandParameters","");
3531 int32 fileArchiveCompressCommandSuccessResult = config.getInt("FileArchiveCompressCommandSuccessResult","0");
3532
3533 string userData = config.getString("UserData_Root","");
3534 if(userData != "") {
3535 endPathWithSlash(userData);
3536 }
3537
3538 int typesSelected = 0;
3539 if(compress_item == "techtrees" || compress_item == "all") {
3540 typesSelected++;
3541
3542 vector<string> pathList = config.getPathListForType(ptTechs,"");
3543 vector<string> results;
3544 findDirs(pathList, results);
3545
3546 printf("Techtrees found:\n===========================================\n");
3547 for(unsigned int i = 0; i < results.size(); ++i) {
3548 string name = results[i];
3549
3550 for(unsigned int j = 0; j < pathList.size(); ++j) {
3551 string techPath = pathList[j];
3552 if(techPath != "") {
3553 endPathWithSlash(techPath);
3554 }
3555
3556 vector<string> results2;
3557 findDirs(techPath + name + "/factions", results2, false,true);
3558 if(results2.empty() == false) {
3559 string techtreePath = techPath + name;
3560 if(includeMainData == false) {
3561 if(techtreePath.find(userData) == techPath.npos) {
3562 printf("Skipping techtree: [%s]\n",techtreePath.c_str());
3563 continue;
3564 }
3565 }
3566
3567 string downloadArchive = techtreePath + fileArchiveExtension;
3568
3569 if(fileExists(downloadArchive) == true) {
3570 bool removed = removeFile(downloadArchive);
3571 if(removed == false) {
3572 printf("Error could not remove old file: [%s]\n",downloadArchive.c_str());
3573 }
3574 }
3575 string compressCmd = getFullFileArchiveCompressCommand(
3576 fileArchiveCompressCommand,
3577 fileArchiveCompressCommandParameters,
3578 downloadArchive,techtreePath );
3579
3580 printf("Running compression command: %s\n",compressCmd.c_str());
3581
3582 if(executeShellCommand(compressCmd,fileArchiveCompressCommandSuccessResult) == false) {
3583 printf("Error could not create new file: [%s]\n",downloadArchive.c_str());
3584 }
3585
3586 if(fileExists(downloadArchive) == true) {
3587 off_t fileSize = getFileSize(downloadArchive);
3588 // convert to MB
3589 double megaBytes = ((double)fileSize / 1048576.0);
3590 printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
3591 }
3592 }
3593 }
3594 }
3595 printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
3596 }
3597 if(compress_item == "tilesets" || compress_item == "all") {
3598 typesSelected++;
3599
3600 vector<string> pathList = config.getPathListForType(ptTilesets,"");
3601 vector<string> results;
3602 findDirs(pathList, results);
3603
3604 printf("Tilesets found:\n===========================================\n");
3605 for(unsigned int i = 0; i < results.size(); ++i) {
3606 string name = results[i];
3607
3608 for(unsigned int j = 0; j < pathList.size(); ++j) {
3609 string tilesetPath = pathList[j];
3610 if(tilesetPath != "") {
3611 endPathWithSlash(tilesetPath);
3612 }
3613
3614 if(fileExists(tilesetPath + name + "/" + name + ".xml") == true) {
3615 string tilesetDataPath = tilesetPath + name;
3616 if(includeMainData == false) {
3617 if(tilesetPath.find(userData) == tilesetPath.npos) {
3618 printf("Skipping tileset data: [%s]\n",tilesetDataPath.c_str());
3619 continue;
3620 }
3621 }
3622
3623 string downloadArchive = tilesetDataPath + fileArchiveExtension;
3624
3625 if(fileExists(downloadArchive) == true) {
3626 bool removed = removeFile(downloadArchive);
3627 if(removed == false) {
3628 printf("Error could not remove old file: [%s]\n",downloadArchive.c_str());
3629 }
3630 }
3631 string compressCmd = getFullFileArchiveCompressCommand(
3632 fileArchiveCompressCommand,
3633 fileArchiveCompressCommandParameters,
3634 downloadArchive,tilesetDataPath );
3635
3636 printf("Running compression command: %s\n",compressCmd.c_str());
3637
3638 if(executeShellCommand(compressCmd,fileArchiveCompressCommandSuccessResult) == false) {
3639 printf("Error could not create new file: [%s]\n",downloadArchive.c_str());
3640 }
3641
3642 if(fileExists(downloadArchive) == true) {
3643 off_t fileSize = getFileSize(downloadArchive);
3644 // convert to MB
3645 double megaBytes = ((double)fileSize / 1048576.0);
3646 printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
3647 }
3648
3649 break;
3650 }
3651 }
3652 }
3653 printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
3654
3655 }
3656 if(typesSelected == 0) {
3657 printf("Compress item [%s] is not valid!\n",compress_item.c_str());
3658 return_value = 1;
3659 }
3660 else
3661 return_value = 0;
3662 }
3663 else {
3664 printf("\nInvalid missing map specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
3665
3666 return_value = 1;
3667 }
3668 }
3669
3670 return return_value;
3671 }
3672
handleShowCRCValuesCommand(int argc,char ** argv)3673 int handleShowCRCValuesCommand(int argc, char** argv) {
3674 int return_value = 1;
3675 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]) == true) {
3676 int foundParamIndIndex = -1;
3677 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]) + string("="),&foundParamIndIndex);
3678 if(foundParamIndIndex < 0) {
3679 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]),&foundParamIndIndex);
3680 }
3681 string paramValue = argv[foundParamIndIndex];
3682 vector<string> paramPartTokens;
3683 Tokenize(paramValue,paramPartTokens,"=");
3684 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3685 string itemName = paramPartTokens[1];
3686
3687 string file = Config::getMapPath(itemName,"",false);
3688 if(file != "") {
3689 Checksum checksum;
3690 checksum.addFile(file);
3691 uint32 crcValue = checksum.getSum();
3692
3693 printf("CRC value for map [%s] file [%s] is [%u]\n",itemName.c_str(),file.c_str(),crcValue);
3694
3695 return_value = 0;
3696 }
3697 else {
3698 printf("Map [%s] was NOT FOUND\n",itemName.c_str());
3699 return_value = 1;
3700 }
3701 }
3702 else {
3703 printf("\nInvalid missing map specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
3704
3705 return_value = 1;
3706 }
3707 }
3708
3709 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]) == true) {
3710 int foundParamIndIndex = -1;
3711 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]) + string("="),&foundParamIndIndex);
3712 if(foundParamIndIndex < 0) {
3713 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]),&foundParamIndIndex);
3714 }
3715 string paramValue = argv[foundParamIndIndex];
3716 vector<string> paramPartTokens;
3717 Tokenize(paramValue,paramPartTokens,"=");
3718 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3719 string itemName = paramPartTokens[1];
3720
3721 Config &config = Config::getInstance();
3722 uint32 crcValue = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,""), string("/") + itemName + string("/*"), ".xml", NULL, true);
3723 if(crcValue != 0) {
3724 printf("CRC value for tileset [%s] is [%u]\n",itemName.c_str(),crcValue);
3725
3726 return_value = 0;
3727 }
3728 else {
3729 printf("Tileset [%s] was NOT FOUND\n",itemName.c_str());
3730 return_value = 1;
3731 }
3732 }
3733 else {
3734 printf("\nInvalid missing tileset specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
3735
3736 return_value = 1;
3737 }
3738 }
3739
3740 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]) == true) {
3741 int foundParamIndIndex = -1;
3742 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]) + string("="),&foundParamIndIndex);
3743 if(foundParamIndIndex < 0) {
3744 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]),&foundParamIndIndex);
3745 }
3746 string paramValue = argv[foundParamIndIndex];
3747 vector<string> paramPartTokens;
3748 Tokenize(paramValue,paramPartTokens,"=");
3749 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3750 string itemName = paramPartTokens[1];
3751
3752 Config &config = Config::getInstance();
3753 uint32 crcValue = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,""), "/" + itemName + "/*", ".xml", NULL, true);
3754 if(crcValue != 0) {
3755 printf("CRC value for techtree [%s] is [%u]\n",itemName.c_str(),crcValue);
3756
3757 return_value = 0;
3758 }
3759 else {
3760 printf("Techtree [%s] was NOT FOUND\n",itemName.c_str());
3761
3762 return_value = 1;
3763 }
3764 }
3765 else {
3766 printf("\nInvalid missing techtree specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
3767
3768 return_value = 1;
3769 }
3770 }
3771
3772 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]) == true) {
3773 int foundParamIndIndex = -1;
3774 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]) + string("="),&foundParamIndIndex);
3775 if(foundParamIndIndex < 0) {
3776 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]),&foundParamIndIndex);
3777 }
3778 string paramValue = argv[foundParamIndIndex];
3779 vector<string> paramPartTokens;
3780 Tokenize(paramValue,paramPartTokens,"=");
3781 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3782 string itemName = paramPartTokens[1];
3783
3784 Config &config = Config::getInstance();
3785 uint32 crcValue = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptScenarios,""), "/" + itemName + "/*", ".xml", NULL, true);
3786 if(crcValue != 0) {
3787 printf("CRC value for scenario [%s] is [%u]\n",itemName.c_str(),crcValue);
3788
3789 return_value = 0;
3790 }
3791 else {
3792 printf("Scenario [%s] was NOT FOUND\n",itemName.c_str());
3793 return_value = 1;
3794 }
3795 }
3796 else {
3797 printf("\nInvalid missing scenario specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
3798
3799 return_value = 0;
3800 }
3801 }
3802
3803 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]) == true) {
3804 int foundParamIndIndex = -1;
3805 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]) + string("="),&foundParamIndIndex);
3806 if(foundParamIndIndex < 0) {
3807 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]),&foundParamIndIndex);
3808 }
3809
3810 string paramValue = argv[foundParamIndIndex];
3811 vector<string> paramPartTokens;
3812 Tokenize(paramValue,paramPartTokens,"=");
3813 if(paramPartTokens.size() >= 3 && paramPartTokens[1].length() > 0) {
3814 string itemName = paramPartTokens[1];
3815 string itemNameFilter = paramPartTokens[2];
3816 uint32 crcValue = getFolderTreeContentsCheckSumRecursively(itemName, itemNameFilter, NULL, true);
3817
3818 printf("CRC value for path [%s] filter [%s] is [%u]\n",itemName.c_str(),itemNameFilter.c_str(),crcValue);
3819
3820 return_value = 0;
3821 }
3822 else {
3823 if(paramPartTokens.size() < 2) {
3824 printf("\nInvalid missing path and filter specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
3825 }
3826 if(paramPartTokens.size() < 3) {
3827 printf("\nInvalid missing filter specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 3 ? paramPartTokens[2].c_str() : NULL));
3828 }
3829
3830 return_value = 1;
3831 }
3832 }
3833
3834 return return_value;
3835 }
3836
handleListDataCommand(int argc,char ** argv)3837 int handleListDataCommand(int argc, char** argv) {
3838 int return_value = 1;
3839 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true) {
3840 int foundParamIndIndex = -1;
3841 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_MAPS]) + string("="),&foundParamIndIndex);
3842 if(foundParamIndIndex < 0) {
3843 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_MAPS]),&foundParamIndIndex);
3844 }
3845
3846 Config &config = Config::getInstance();
3847 vector<string> pathList = config.getPathListForType(ptMaps,"");
3848 vector<string> maps = MapPreview::findAllValidMaps(pathList,"",false,true);
3849 std::sort(maps.begin(),maps.end());
3850
3851 string paramValue = argv[foundParamIndIndex];
3852 vector<string> paramPartTokens;
3853 Tokenize(paramValue,paramPartTokens,"=");
3854 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3855 string itemNameFilter = paramPartTokens[1];
3856 printf("Using filter for maps list [%s]\n",itemNameFilter.c_str());
3857
3858 vector<string> filteredMaps;
3859 for(unsigned int i = 0; i < maps.size(); ++i) {
3860 string mapName = maps[i];
3861 if(itemNameFilter.find("*") != itemNameFilter.npos) {
3862 if(StartsWith(mapName, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
3863 filteredMaps.push_back(mapName);
3864 }
3865 }
3866 else if(mapName == itemNameFilter) {
3867 filteredMaps.push_back(mapName);
3868 }
3869 }
3870 maps = filteredMaps;
3871 }
3872
3873 printf("Maps found:\n===========================================\n");
3874 for(unsigned int i = 0; i < maps.size(); ++i) {
3875 string mapName = maps[i];
3876 printf("%s\n",mapName.c_str());
3877 }
3878 printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",maps.size());
3879
3880 return_value = 0;
3881 }
3882
3883 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true) {
3884 int foundParamIndIndex = -1;
3885 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) + string("="),&foundParamIndIndex);
3886 if(foundParamIndIndex < 0) {
3887 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TECHTRESS]),&foundParamIndIndex);
3888 }
3889
3890 Config &config = Config::getInstance();
3891 vector<string> pathList = config.getPathListForType(ptTechs,"");
3892 vector<string> results;
3893 findDirs(pathList, results);
3894
3895 bool showfactions=false;
3896 string paramValue = argv[foundParamIndIndex];
3897 vector<string> paramPartTokens;
3898 Tokenize(paramValue,paramPartTokens,"=");
3899 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3900 string cmd = paramPartTokens[1];
3901 if(cmd == "showfactions") {
3902 showfactions = true;
3903 }
3904 else {
3905 throw megaglest_runtime_error("unknown command for techtreelist [" + cmd + "]");
3906 }
3907 printf("Using special command for techtree list [%s]\n",cmd.c_str());
3908 }
3909
3910 printf("Techtrees found:\n===========================================\n");
3911 for(unsigned int i = 0; i < results.size(); ++i) {
3912 string name = results[i];
3913
3914 for(unsigned int j = 0; j < pathList.size(); ++j) {
3915 string techPath = pathList[j];
3916 if(techPath != "") {
3917 endPathWithSlash(techPath);
3918 }
3919 vector<string> results2;
3920 findDirs(techPath + name + "/factions", results2, false,true);
3921 if(results2.empty() == false) {
3922 string downloadArchive = techPath + name + ".7z";
3923
3924 if(fileExists(downloadArchive) == true) {
3925 off_t fileSize = getFileSize(downloadArchive);
3926 // convert to MB
3927 double megaBytes = ((double)fileSize / 1048576.0);
3928 printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
3929 }
3930 else {
3931 printf("%s\n",name.c_str());
3932 }
3933
3934 if(showfactions == true) {
3935 printf("--> Factions:\n");
3936 for(unsigned int k = 0; k < results2.size(); ++k) {
3937 string name2 = results2[k];
3938 printf("--> %s\n",name2.c_str());
3939 }
3940 printf("--> Total Factions: " MG_SIZE_T_SPECIFIER "\n",results2.size());
3941 break;
3942 }
3943 }
3944 }
3945 }
3946 printf("===========================================\nTotal Techtrees: " MG_SIZE_T_SPECIFIER "\n",results.size());
3947
3948 return_value = 0;
3949 }
3950
3951 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true) {
3952 int foundParamIndIndex = -1;
3953 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) + string("="),&foundParamIndIndex);
3954 if(foundParamIndIndex < 0) {
3955 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_SCENARIOS]),&foundParamIndIndex);
3956 }
3957
3958 Config &config = Config::getInstance();
3959 vector<string> pathList = config.getPathListForType(ptScenarios,"");
3960 vector<string> results;
3961 findDirs(pathList, results);
3962
3963 string paramValue = argv[foundParamIndIndex];
3964 vector<string> paramPartTokens;
3965 Tokenize(paramValue,paramPartTokens,"=");
3966 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
3967 string itemNameFilter = paramPartTokens[1];
3968 printf("Using filter for scenarios list [%s]\n",itemNameFilter.c_str());
3969
3970 vector<string> filtered;
3971 for(unsigned int i = 0; i < results.size(); ++i) {
3972 string name = results[i];
3973 if(itemNameFilter.find("*") != itemNameFilter.npos) {
3974 if(StartsWith(name, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
3975 filtered.push_back(name);
3976 }
3977 }
3978 else if(name == itemNameFilter) {
3979 filtered.push_back(name);
3980 }
3981 }
3982 results = filtered;
3983 }
3984
3985 printf("Scenarios found:\n===========================================\n");
3986 for(unsigned int i = 0; i < results.size(); ++i) {
3987 string name = results[i];
3988 printf("%s\n",name.c_str());
3989 }
3990 printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
3991
3992 return_value = 0;
3993 }
3994
3995 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true) {
3996 int foundParamIndIndex = -1;
3997 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TILESETS]) + string("="),&foundParamIndIndex);
3998 if(foundParamIndIndex < 0) {
3999 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TILESETS]),&foundParamIndIndex);
4000 }
4001
4002 Config &config = Config::getInstance();
4003 vector<string> pathList = config.getPathListForType(ptTilesets,"");
4004 vector<string> results;
4005 findDirs(pathList, results);
4006
4007 string paramValue = argv[foundParamIndIndex];
4008 vector<string> paramPartTokens;
4009 Tokenize(paramValue,paramPartTokens,"=");
4010 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4011 string itemNameFilter = paramPartTokens[1];
4012 printf("Using filter for tilesets list [%s]\n",itemNameFilter.c_str());
4013
4014 vector<string> filtered;
4015 for(unsigned int i = 0; i < results.size(); ++i) {
4016 string name = results[i];
4017 if(itemNameFilter.find("*") != itemNameFilter.npos) {
4018 if(StartsWith(name, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
4019 filtered.push_back(name);
4020 }
4021 }
4022 else if(name == itemNameFilter) {
4023 filtered.push_back(name);
4024 }
4025 }
4026 results = filtered;
4027 }
4028
4029 printf("Tilesets found:\n===========================================\n");
4030 for(unsigned int i = 0; i < results.size(); ++i) {
4031 string name = results[i];
4032
4033 for(unsigned int j = 0; j < pathList.size(); ++j) {
4034 string tilesetPath = pathList[j];
4035 if(tilesetPath != "") {
4036 endPathWithSlash(tilesetPath);
4037 }
4038 if(fileExists(tilesetPath + name + "/" + name + ".xml") == true) {
4039 string downloadArchive = tilesetPath + name + ".7z";
4040 if(fileExists(downloadArchive) == true) {
4041 off_t fileSize = getFileSize(downloadArchive);
4042 // convert to MB
4043 double megaBytes = ((double)fileSize / 1048576.0);
4044 printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
4045 }
4046 else {
4047 printf("%s\n",name.c_str());
4048 }
4049
4050 break;
4051 }
4052 }
4053 }
4054 printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
4055
4056 return_value = 0;
4057 }
4058
4059 else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true) {
4060 int foundParamIndIndex = -1;
4061 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) + string("="),&foundParamIndIndex);
4062 if(foundParamIndIndex < 0) {
4063 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TUTORIALS]),&foundParamIndIndex);
4064 }
4065
4066 Config &config = Config::getInstance();
4067 vector<string> pathList = config.getPathListForType(ptTutorials,"");
4068 vector<string> results;
4069 findDirs(pathList, results);
4070
4071 string paramValue = argv[foundParamIndIndex];
4072 vector<string> paramPartTokens;
4073 Tokenize(paramValue,paramPartTokens,"=");
4074 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4075 string itemNameFilter = paramPartTokens[1];
4076 printf("Using filter for tutorials list [%s]\n",itemNameFilter.c_str());
4077
4078 vector<string> filtered;
4079 for(unsigned int i = 0; i < results.size(); ++i) {
4080 string name = results[i];
4081 if(itemNameFilter.find("*") != itemNameFilter.npos) {
4082 if(StartsWith(name, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
4083 filtered.push_back(name);
4084 }
4085 }
4086 else if(name == itemNameFilter) {
4087 filtered.push_back(name);
4088 }
4089 }
4090 results = filtered;
4091 }
4092
4093 printf("Tutorials found:\n===========================================\n");
4094 for(unsigned int i = 0; i < results.size(); ++i) {
4095 string name = results[i];
4096
4097 for(unsigned int j = 0; j < pathList.size(); ++j) {
4098 string tutorialsPath = pathList[j];
4099 if(tutorialsPath != "") {
4100 endPathWithSlash(tutorialsPath);
4101 }
4102 if(fileExists(tutorialsPath + name + "/" + name + ".xml") == true) {
4103 string downloadArchive = tutorialsPath + name + ".7z";
4104 if(fileExists(downloadArchive) == true) {
4105 off_t fileSize = getFileSize(downloadArchive);
4106 // convert to MB
4107 double megaBytes = ((double)fileSize / 1048576.0);
4108 printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
4109 }
4110 else {
4111 printf("%s\n",name.c_str());
4112 }
4113
4114 break;
4115 }
4116 }
4117 }
4118 printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
4119
4120 return_value = 0;
4121 }
4122
4123 return return_value;
4124 }
4125
glestMain(int argc,char ** argv)4126 int glestMain(int argc, char** argv) {
4127 #ifdef SL_LEAK_DUMP
4128 //AllocInfo::set_application_binary(executable_path(argv[0],true));
4129 string &app = AllocInfo::get_application_binary();
4130 app = executable_path(argv[0],true);
4131 //want_full_leak_stacktrace = true;
4132 //want_full_leak_stacktrace_line_numbers = true;
4133
4134 #endif
4135
4136 Thread::setMainThreadId();
4137 // printf("START ALLOC char 200\n");
4138 //char *ptr = new char[200];
4139 // printf("END ALLOC char 200\n");
4140 // return -1;
4141 SystemFlags::VERBOSE_MODE_ENABLED = false;
4142 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERBOSE_MODE]) == true) {
4143 SystemFlags::VERBOSE_MODE_ENABLED = true;
4144 Thread::setEnableVerboseMode(true);
4145 //LuaScript::setDebugModeEnabled(true);
4146 }
4147 // DEbug testing threads
4148 //Thread::setEnableVerboseMode(true);
4149
4150 PlatformExceptionHandler::application_binary= executable_path(argv[0],true);
4151 mg_app_name = GameConstants::application_name;
4152 mailStringSupport = mailString;
4153 SystemFlags::ENABLE_THREADED_LOGGING = false;
4154 disableBacktrace = false;
4155 bool foundInvalidArgs = false;
4156 preCacheThread=NULL;
4157
4158 Properties::setApplicationPath(executable_path(argv[0]));
4159 Properties::setApplicationDataPath(executable_path(argv[0]));
4160 Properties::setGameVersion(glestVersionString);
4161
4162 ServerSocket::setMaxPlayerCount(GameConstants::maxPlayers);
4163
4164 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_BACKTRACE]) == true) {
4165 disableBacktrace = true;
4166 }
4167 PlatformExceptionHandler::disableBacktrace= disableBacktrace;
4168
4169 #if defined(CUSTOM_DATA_INSTALL_PATH)
4170 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\nCUSTOM_DATA_INSTALL_PATH = [%s]\n\n",formatPath(TOSTRING(CUSTOM_DATA_INSTALL_PATH)).c_str());
4171 #endif
4172
4173 const int knownArgCount = sizeof(GAME_ARGS) / sizeof(GAME_ARGS[0]);
4174 for(int idx = 1; idx < argc; ++idx) {
4175 if( hasCommandArgument(knownArgCount, (char **)&GAME_ARGS[0], argv[idx], NULL, 0, true) == false) {
4176 foundInvalidArgs = true;
4177 printf("\nInvalid argument: %s",argv[idx]);
4178 }
4179 }
4180
4181 if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_HELP]) == true ||
4182 foundInvalidArgs == true) {
4183
4184 printParameterHelp(argv[0],foundInvalidArgs);
4185 return 2;
4186 }
4187
4188
4189
4190
4191 if( hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
4192 //isMasterServerModeEnabled = true;
4193 //Window::setMasterserverMode(isMasterServerModeEnabled);
4194 GlobalStaticFlags::setIsNonGraphicalModeEnabled(true);
4195
4196 int foundParamIndIndex = -1;
4197 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE]) + string("="),&foundParamIndIndex);
4198 if(foundParamIndIndex < 0) {
4199 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE]),&foundParamIndIndex);
4200 }
4201 string paramValue = argv[foundParamIndIndex];
4202 vector<string> paramPartTokens;
4203 Tokenize(paramValue,paramPartTokens,"=");
4204 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4205 string headless_command_list = paramPartTokens[1];
4206
4207 vector<string> paramHeadlessCommandList;
4208 Tokenize(headless_command_list,paramHeadlessCommandList,",");
4209
4210 for(unsigned int i = 0; i < paramHeadlessCommandList.size(); ++i) {
4211 string headless_command = paramHeadlessCommandList[i];
4212 if(headless_command == "exit") {
4213 printf("Forcing quit after game has completed [%s]\n",headless_command.c_str());
4214 Program::setWantShutdownApplicationAfterGame(true);
4215 }
4216 else if(headless_command == "vps") {
4217 printf("Disabled reading from console [%s]\n",headless_command.c_str());
4218 disableheadless_console = true;
4219 }
4220 else if(headless_command == "lan") {
4221 printf("Forcing local LAN mode [%s]\n",headless_command.c_str());
4222 GlobalStaticFlags::setFlag(gsft_lan_mode);
4223 }
4224 }
4225 }
4226 }
4227
4228 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SERVER_TITLE]) == true) {
4229 int foundParamIndIndex = -1;
4230 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SERVER_TITLE]) + string("="),&foundParamIndIndex);
4231 if(foundParamIndIndex < 0) {
4232 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SERVER_TITLE]),&foundParamIndIndex);
4233 }
4234 string paramValue = argv[foundParamIndIndex];
4235 vector<string> paramPartTokens;
4236 Tokenize(paramValue,paramPartTokens,"=");
4237 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4238 Config &config = Config::getInstance();
4239 string serverTitle = paramPartTokens[1];
4240 printf("Forcing serverTitle[%s]\n",serverTitle.c_str());
4241
4242 config.setString("ServerTitle",serverTitle,true);
4243 }
4244 else {
4245 printf("\nInvalid missing server title specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4246
4247 return 1;
4248 }
4249 }
4250
4251
4252
4253 //#ifdef WIN32
4254 //SocketManager winSockManager;
4255 //#endif
4256
4257 bool haveSpecialOutputCommandLineOption = false;
4258
4259 if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true ||
4260 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true ||
4261 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true ||
4262 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true ||
4263 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true ||
4264 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true ||
4265 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true ||
4266 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == true ||
4267 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == true ||
4268 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == true ||
4269 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == true ||
4270 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == true ||
4271 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true ||
4272 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true ||
4273 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true ||
4274 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true ||
4275 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true ||
4276 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
4277 haveSpecialOutputCommandLineOption = true;
4278 }
4279
4280 if( haveSpecialOutputCommandLineOption == false ||
4281 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true) {
4282 printf("%s %s",extractFileFromDirectoryPath(argv[0]).c_str(),getNetworkPlatformFreeVersionString().c_str());
4283 // printf("\nCompiled using: %s on: %s platform: %s endianness: %s",getCompilerNameString().c_str(),getCompileDateTime().c_str(),getPlatformNameString().c_str(),(::Shared::PlatformByteOrder::isBigEndian() == true ? "big" : "little"));
4284 printf("\nCompiled using: %s platform: %s endianness: %s",getCompilerNameString().c_str(),getPlatformNameString().c_str(),(::Shared::PlatformByteOrder::isBigEndian() == true ? "big" : "little"));
4285
4286 // printf("\n\nData type sizes int8 = " MG_SIZE_T_SPECIFIER " int16 = " MG_SIZE_T_SPECIFIER " int32 = " MG_SIZE_T_SPECIFIER " int64 = " MG_SIZE_T_SPECIFIER "\n\n",sizeof(int8),sizeof(int16),sizeof(int32),sizeof(int64));
4287 //
4288 // Config::getInstance().setBool("DebugNetworkPackets",true,true);
4289 // NetworkMessageIntro data(424336, "mg_version_x","player_x", 3, nmgstOk,444444, 555555, "english");
4290 // unsigned char *buf = data.packMessage();
4291 // printf("\nSend packet size = %u\n%s\n",data.getPackedSize(),data.toString().c_str());
4292 // data.dump_packet("Send data", buf, data.getPackedSize());
4293 // //delete [] buf;
4294 //
4295 // NetworkMessageIntro data2;
4296 // data2.unpackMessage(buf);
4297 // printf("\nReceive packet size = %u\n%s\n",data2.getPackedSize(),data2.toString().c_str());
4298 // data2.dump_packet("nReceive data", buf, data2.getPackedSize());
4299 // delete [] buf;
4300
4301 // SwitchSetupRequest data("factionname", 3,-1,2,"softcoder",10, 11,"eng");
4302 //
4303 // unsigned char *buf = data.packMessage();
4304 // printf("\nSend packet size = %u\n%s\nTeam = %d faction [%s] currentFactionIndex = %d toFactionIndex = %d [%s] [%s] %d %d\n",data.getPackedSize(),buf,data.getToTeam(),data.getSelectedFactionName().c_str(),data.getCurrentFactionIndex(),data.getToFactionIndex(),data.getNetworkPlayerLanguage().c_str(),data.getNetworkPlayerName().c_str(),data.getNetworkPlayerStatus(),data.getSwitchFlags());
4305 // //delete [] buf;
4306 //
4307 // data.unpackMessage(buf);
4308 // printf("\nGot packet size = %u\n%s\nTeam = %d faction [%s] currentFactionIndex = %d toFactionIndex = %d [%s] [%s] %d %d\n",data.getPackedSize(),buf,data.getToTeam(),data.getSelectedFactionName().c_str(),data.getCurrentFactionIndex(),data.getToFactionIndex(),data.getNetworkPlayerLanguage().c_str(),data.getNetworkPlayerName().c_str(),data.getNetworkPlayerStatus(),data.getSwitchFlags());
4309 // delete [] buf;
4310
4311 // int8 a = 1;
4312 // uint8 b = 2;
4313 // int16 c = 3;
4314 // uint16 d = 4;
4315 // int32 e = 5;
4316 // uint32 f = 6;
4317 //
4318 // printf("\nPack test #1: [%d][%u][%d][%u][%d][%u]\n,",a,b,c,d,e,f);
4319 //
4320 // unsigned char *buf = new unsigned char[100];
4321 // unsigned int packedsize = pack(buf, "cChHlL",
4322 // a,
4323 // b,
4324 // c,
4325 // d,
4326 // e,
4327 // f);
4328 //
4329 // printf("Pack test #2: [%u][%s]\n,",packedsize,buf);
4330 //
4331 // int8 a1 = 0;
4332 // uint8 b1 = 0;
4333 // int16 c1 = 0;
4334 // uint16 d1 = 0;
4335 // int32 e1 = 0;
4336 // uint32 f1 = 0;
4337 //
4338 // unpack(buf, "cChHlL",
4339 // &a1,
4340 // &b1,
4341 // &c1,
4342 // &d1,
4343 // &e1,
4344 // &f1);
4345 //
4346 // printf("UnPack test #3: [%d][%u][%d][%u][%d][%u]\n,",a1,b1,c1,d1,e1,f1);
4347
4348 if(SystemFlags::VERBOSE_MODE_ENABLED == true) {
4349 int8 testVar = 111;
4350 printf("\nEndian value = %d",testVar);
4351 testVar = ::Shared::PlatformByteOrder::toCommonEndian(testVar);
4352 printf("\nEndian to common value = %d",testVar);
4353 testVar = ::Shared::PlatformByteOrder::fromCommonEndian(testVar);
4354 printf("\nEndian from common value = %d",testVar);
4355
4356 printf("\nint8 sizeof = " MG_SIZE_T_SPECIFIER "",sizeof(int8));
4357 printf("\nSwitchSetupRequest sizeof = " MG_SIZE_T_SPECIFIER "",SwitchSetupRequest().getDataSize());
4358 }
4359
4360 printf("\nGIT: [%s]",getGITRevisionString().c_str());
4361
4362 #ifdef USE_STREFLOP
4363
4364 #if defined(STREFLOP_SSE)
4365 const char *instruction_set = "[SSE]";
4366 #elif defined(STREFLOP_X87)
4367 const char *instruction_set = "[X87]";
4368 #elif defined(STREFLOP_SOFT)
4369 const char *instruction_set = "[SOFTFLOAT]";
4370 #else
4371 const char *instruction_set = "[none]";
4372 #endif
4373
4374 #if defined(STREFLOP_NO_DENORMALS)
4375 const char *denormals = "[no-denormals]";
4376 #else
4377 const char *denormals = "[denormals]";
4378 #endif
4379
4380 printf(" - using STREFLOP %s - %s\n",instruction_set,denormals);
4381
4382 #else
4383 printf("\n");
4384 #endif
4385 }
4386
4387 setGameVersion(glestVersionString);
4388 setGameGITVersion(getRAWGITRevisionString());
4389
4390 #ifdef WIN32
4391 CheckPacketThrottling();
4392 #endif
4393
4394 if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true ||
4395 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true ||
4396 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true ||
4397 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true ||
4398 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true ||
4399 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true ||
4400 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true ||
4401 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == true ||
4402 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == true ||
4403 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == true ||
4404 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == true ||
4405 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == true ||
4406 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true ||
4407 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true ||
4408 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true ||
4409 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true ||
4410 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true ||
4411 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
4412 VideoPlayer::setDisabled(true);
4413 }
4414
4415 //throw megaglest_runtime_error("Test!");
4416
4417 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true) {
4418 SDL_version ver;
4419
4420 // Prints the compile time version
4421 SDL_VERSION(&ver);
4422 print_SDL_version("SDL compile-time version", &ver);
4423
4424 // Prints the run-time version
4425 SDL_GetVersion(&ver);
4426 print_SDL_version("SDL runtime version", &ver);
4427 //const SDL_VideoInfo *vidInfo = SDL_GetVideoInfo();
4428 //printf("Video card Memory: %u\n",vidInfo->video_mem);
4429 }
4430
4431 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true) {
4432 printf("LUA version: %s\n", LUA_RELEASE);
4433 }
4434
4435 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true) {
4436 curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW);
4437 printf("CURL version: %s [%s] SSL enabled: %d\n", curlVersion->version,(curlVersion->ssl_version != NULL ? curlVersion->ssl_version : ""),((curlVersion->features & CURL_VERSION_SSL) == CURL_VERSION_SSL ? true : false));
4438 if(curlVersion->protocols != NULL && curlVersion->protocols[0] != NULL) {
4439 printf("protocols: ");
4440 for(unsigned int i = 0; curlVersion->protocols != NULL && curlVersion->protocols[i] != NULL; ++i) {
4441 printf("%s ", curlVersion->protocols[i]);
4442 if(i > 0 && i % 10 == 0) {
4443 printf("\n ");
4444 }
4445 }
4446 printf("\n");
4447 }
4448 }
4449
4450 #if defined(WANT_XERCES)
4451
4452 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true) {
4453 printf("XERCES version: %s\n", XERCES_FULLVERSIONDOT);
4454 }
4455
4456 #endif
4457
4458 if( (hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true ||
4459 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true ||
4460 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true ||
4461 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true ||
4462 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true) &&
4463 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == false &&
4464 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == false &&
4465 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == false &&
4466 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == false &&
4467 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == false &&
4468 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == false &&
4469 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == false &&
4470 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == false &&
4471 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == false &&
4472 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == false &&
4473 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == false &&
4474 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == false) {
4475 return 0;
4476 }
4477
4478 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MOD])) == true) {
4479
4480 int foundParamIndIndex = -1;
4481 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MOD]) + string("="),&foundParamIndIndex);
4482 if(foundParamIndIndex < 0) {
4483 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MOD]),&foundParamIndIndex);
4484 }
4485 string scenarioName = argv[foundParamIndIndex];
4486 vector<string> paramPartTokens;
4487 Tokenize(scenarioName,paramPartTokens,"=");
4488 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4489 string autoloadModName = paramPartTokens[1];
4490 if(Properties::applyTagsToValue(autoloadModName) == true) {
4491 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Property key [%s] now has value [%s]\n",Config::ACTIVE_MOD_PROPERTY_NAME,autoloadModName.c_str());
4492 }
4493
4494 Config::setCustomRuntimeProperty(Config::ACTIVE_MOD_PROPERTY_NAME,autoloadModName);
4495
4496 printf("Setting mod active [%s]\n",autoloadModName.c_str());
4497 }
4498 else {
4499 printf("\nInvalid mod pathname specified on commandline [%s] mod [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4500 printParameterHelp(argv[0],foundInvalidArgs);
4501 return 1;
4502 }
4503 }
4504
4505 SystemFlags::init(haveSpecialOutputCommandLineOption);
4506 //SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled = true;
4507 //SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled = true;
4508
4509 MainWindow *mainWindow= NULL;
4510 Program *program= NULL;
4511 ExceptionHandler exceptionHandler;
4512 exceptionHandler.install( getCrashDumpFileName() );
4513
4514 int shutdownFadeSoundMilliseconds = 1000;
4515 Chrono chronoshutdownFadeSound;
4516 SimpleTaskThread *soundThreadManager = NULL;
4517
4518 try {
4519 // Setup paths to game items (like data, logs, ini etc)
4520 int setupResult = setupGameItemPaths(argc, argv, NULL);
4521 if(setupResult != 0) {
4522 return setupResult;
4523 }
4524
4525 // Attempt to read ini files
4526 Config &config = Config::getInstance();
4527 setupGameItemPaths(argc, argv, &config);
4528
4529 if(config.getString("PlayerId","") == "") {
4530 char uuid_str[38];
4531 get_uuid_string(uuid_str,sizeof(uuid_str));
4532
4533 config.setString("PlayerId",uuid_str);
4534 config.save();
4535 }
4536 //printf("Players UUID: [%s]\n",config.getString("PlayerId","").c_str());
4537
4538 if(config.getBool("DisableLuaSandbox","false") == true) {
4539 LuaScript::setDisableSandbox(true);
4540 }
4541
4542 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DEBUG_NETWORK_PACKETS]) == true) {
4543 printf("*NOTE: debugging network packets.\n");
4544 config.setBool("DebugNetworkPackets",true,true);
4545 }
4546
4547 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DEBUG_NETWORK_PACKET_SIZES]) == true) {
4548 printf("*NOTE: debugging network packet SIZES.\n");
4549 config.setBool("DebugNetworkPacketSizes",true,true);
4550 }
4551
4552 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DEBUG_NETWORK_PACKET_STATS]) == true) {
4553 printf("*NOTE: debugging network packet STATISTICS.\n");
4554 config.setBool("DebugNetworkPacketStats",true,true);
4555 }
4556
4557 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_ENABLE_NEW_PROTOCOL]) == true) {
4558 printf("*NOTE: enabling new newtork protocol.\n");
4559 NetworkMessage::useOldProtocol = false;
4560 }
4561
4562 Socket::setBroadCastPort(config.getInt("BroadcastPort",intToStr(Socket::getBroadCastPort()).c_str()));
4563
4564 Socket::disableNagle = config.getBool("DisableNagle","false");
4565 if(Socket::disableNagle) {
4566 printf("*WARNING users wants to disable the socket nagle algorithm.\n");
4567 }
4568 Socket::DEFAULT_SOCKET_SENDBUF_SIZE = config.getInt("DefaultSocketSendBufferSize",intToStr(Socket::DEFAULT_SOCKET_SENDBUF_SIZE).c_str());
4569 if(Socket::DEFAULT_SOCKET_SENDBUF_SIZE >= 0) {
4570 printf("*WARNING users wants to set default socket send buffer size to: %d\n",Socket::DEFAULT_SOCKET_SENDBUF_SIZE);
4571 }
4572 Socket::DEFAULT_SOCKET_RECVBUF_SIZE = config.getInt("DefaultSocketReceiveBufferSize",intToStr(Socket::DEFAULT_SOCKET_RECVBUF_SIZE).c_str());
4573 if(Socket::DEFAULT_SOCKET_RECVBUF_SIZE >= 0) {
4574 printf("*WARNING users wants to set default socket receive buffer size to: %d\n",Socket::DEFAULT_SOCKET_RECVBUF_SIZE);
4575 }
4576
4577 shutdownFadeSoundMilliseconds = config.getInt("ShutdownFadeSoundMilliseconds",intToStr(shutdownFadeSoundMilliseconds).c_str());
4578
4579 string userData = config.getString("UserData_Root","");
4580 if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
4581 userData = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey);
4582 }
4583 if(userData != "") {
4584 endPathWithSlash(userData);
4585 }
4586
4587 string data_path_check = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
4588 string userDataPath_check = getGameCustomCoreDataPath(data_path_check, "");
4589 if(data_path_check == userDataPath_check) {
4590 printf("****WARNING**** your game data path and user data path are the same.\nThis will likely create problems: %s\n",data_path_check.c_str());
4591 throw megaglest_runtime_error("Regular and User data paths cannot have the same value [" + userDataPath_check + "]");
4592 }
4593
4594 if(userData != "") {
4595 if(isdir(userData.c_str()) == false) {
4596 createDirectoryPaths(userData);
4597 }
4598 }
4599 string crcCachePath = userData + "cache/";
4600 if(isdir(crcCachePath.c_str()) == false) {
4601 createDirectoryPaths(crcCachePath);
4602 }
4603 setCRCCacheFilePath(crcCachePath);
4604
4605 string savedGamePath = userData + "saved/";
4606 if(isdir(savedGamePath.c_str()) == false) {
4607 createDirectoryPaths(savedGamePath);
4608 }
4609
4610 string tempDataPath = userData + "temp/";
4611 tempDataLocation = tempDataPath;
4612 if(isdir(tempDataPath.c_str()) == true) {
4613 removeFolder(tempDataPath);
4614 }
4615 createDirectoryPaths(tempDataPath);
4616
4617 string binaryNameOld = Properties::getApplicationPath() + extractFileFromDirectoryPath(PlatformExceptionHandler::application_binary) + "__REMOVE";
4618 if(fileExists(binaryNameOld)) {
4619 removeFile(binaryNameOld);
4620 }
4621
4622 string netInterfaces = config.getString("NetworkInterfaces","");
4623 if(netInterfaces != "") {
4624 //printf("Using network interfaces: %s\n",netInterfaces.c_str());
4625 std::vector<std::string> intfList;
4626 Tokenize(netInterfaces,intfList,",");
4627 Socket::setIntfTypes(intfList);
4628 }
4629
4630 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_PORTS]) == true) {
4631 int foundParamIndIndex = -1;
4632 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_PORTS]) + string("="),&foundParamIndIndex);
4633 if(foundParamIndIndex < 0) {
4634 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_PORTS]),&foundParamIndIndex);
4635 }
4636 string paramValue = argv[foundParamIndIndex];
4637 vector<string> paramPartTokens;
4638 Tokenize(paramValue,paramPartTokens,"=");
4639 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4640 string portsToUse = paramPartTokens[1];
4641
4642 vector<string> paramPartPortsTokens;
4643 Tokenize(portsToUse,paramPartPortsTokens,",");
4644 if(paramPartPortsTokens.size() >= 2 && paramPartPortsTokens[1].length() > 0) {
4645 int internalPort = strToInt(paramPartPortsTokens[0]);
4646 int externalPort = strToInt(paramPartPortsTokens[1]);
4647
4648 printf("Forcing internal port# %d, external port# %d\n",internalPort,externalPort);
4649
4650 config.setInt("PortServer",internalPort,true);
4651 config.setInt("PortExternal",externalPort,true);
4652 config.setInt("FTPServerPort",internalPort+1,true);
4653
4654 if(paramPartPortsTokens.size() >= 3 && paramPartPortsTokens[2].length() > 0) {
4655 int statusPort = strToInt(paramPartPortsTokens[2]);
4656
4657 printf("Forcing status port# %d\n",statusPort);
4658
4659 config.setInt("ServerAdminPort",statusPort,true);
4660 }
4661 }
4662 else {
4663 printf("\nInvalid ports specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4664 return 1;
4665 }
4666 }
4667 else {
4668 printf("\nInvalid missing ports specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4669 return 1;
4670 }
4671 }
4672
4673 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_STATUS])) == true) {
4674 Ip ip("localhost");
4675 int port = Config::getInstance().getInt("ServerAdminPort", intToStr(GameConstants::serverAdminPort).c_str());
4676 ClientSocket clientSocket;
4677 clientSocket.setBlock(false);
4678 clientSocket.connect(ip, port);
4679 if(clientSocket.isConnected() == true) {
4680 clientSocket.setBlock(true);
4681
4682 char szBuf[8096]="";
4683 clientSocket.receive(&szBuf[0],8095,false);
4684 std::cout << szBuf << std::endl;
4685 }
4686 else {
4687 std::cout << "Could not connect (possibly no clients connected) to host: " << ip.getString() << " port: " << port << std::endl;
4688 }
4689
4690 return 0;
4691 }
4692
4693 if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_SOUND]) == true ||
4694 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
4695 config.setString("FactorySound","None",true);
4696 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
4697 //Logger::getInstance().setMasterserverMode(true);
4698 //Model::setMasterserverMode(true);
4699 //Shared::Sound::Sound::setMasterserverMode(true);
4700 }
4701 }
4702
4703 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_OPENGL_CAPS_CHECK]) == true ||
4704 config.getBool("CheckGlCaps") == false) {
4705 printf("**WARNING** disabling opengl capability checking...\n");
4706 config.setBool("CheckGlCaps",false,true);
4707 }
4708
4709 bool enableATIHacks = config.getBool("EnableATIHacks","false");
4710 if(enableATIHacks == true) {
4711 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**WARNING** Enabling ATI video card hacks\n");
4712 TextureGl::setEnableATIHacks(enableATIHacks);
4713 }
4714
4715 Renderer::renderText3DEnabled = config.getBool("Enable3DFontRendering",intToStr(Renderer::renderText3DEnabled).c_str());
4716
4717 if(config.getBool("EnableLegacyFonts","false") == true || hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_ENABLE_LEGACYFONTS]) == true) {
4718 ::Shared::Graphics::Font::forceLegacyFonts = true;
4719 Renderer::renderText3DEnabled = false;
4720 printf("**WARNING** Forcing Legacy Fonts Enabled\n");
4721 }
4722 else {
4723 Renderer::renderText3DEnabled = config.getBool("Enable3DFontRendering",intToStr(Renderer::renderText3DEnabled).c_str());
4724 }
4725
4726 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_RESOLUTION]) == true) {
4727 int foundParamIndIndex = -1;
4728 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_RESOLUTION]) + string("="),&foundParamIndIndex);
4729 if(foundParamIndIndex < 0) {
4730 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_RESOLUTION]),&foundParamIndIndex);
4731 }
4732 string paramValue = argv[foundParamIndIndex];
4733 vector<string> paramPartTokens;
4734 Tokenize(paramValue,paramPartTokens,"=");
4735 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4736 string settings = paramPartTokens[1];
4737 printf("Forcing resolution [%s]\n",settings.c_str());
4738
4739 paramPartTokens.clear();
4740 Tokenize(settings,paramPartTokens,"x");
4741 if(paramPartTokens.size() >= 2) {
4742 int newScreenWidth = strToInt(paramPartTokens[0]);
4743 config.setInt("ScreenWidth",newScreenWidth,true);
4744
4745 int newScreenHeight = strToInt(paramPartTokens[1]);
4746 config.setInt("ScreenHeight",newScreenHeight,true);
4747 }
4748 else {
4749 printf("\nInvalid missing resolution settings specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4750 return 1;
4751 }
4752 }
4753 else {
4754 printf("\nInvalid missing resolution setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4755 return 1;
4756 }
4757 }
4758
4759 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_COLORBITS]) == true) {
4760 int foundParamIndIndex = -1;
4761 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_COLORBITS]) + string("="),&foundParamIndIndex);
4762 if(foundParamIndIndex < 0) {
4763 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_COLORBITS]),&foundParamIndIndex);
4764 }
4765 string paramValue = argv[foundParamIndIndex];
4766 vector<string> paramPartTokens;
4767 Tokenize(paramValue,paramPartTokens,"=");
4768 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4769 string settings = paramPartTokens[1];
4770 printf("Forcing colorbits [%s]\n",settings.c_str());
4771
4772 int newColorBits = strToInt(settings);
4773 config.setInt("ColorBits",newColorBits,true);
4774 }
4775 else {
4776 printf("\nInvalid missing colorbits settings specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4777 return 1;
4778 }
4779 }
4780
4781 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_DEPTHBITS]) == true) {
4782 int foundParamIndIndex = -1;
4783 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_DEPTHBITS]) + string("="),&foundParamIndIndex);
4784 if(foundParamIndIndex < 0) {
4785 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_DEPTHBITS]),&foundParamIndIndex);
4786 }
4787 string paramValue = argv[foundParamIndIndex];
4788 vector<string> paramPartTokens;
4789 Tokenize(paramValue,paramPartTokens,"=");
4790 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4791 string settings = paramPartTokens[1];
4792 printf("Forcing depthbits [%s]\n",settings.c_str());
4793
4794 int newDepthBits = strToInt(settings);
4795 config.setInt("DepthBits",newDepthBits,true);
4796 }
4797 else {
4798 printf("\nInvalid missing depthbits setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4799 return 1;
4800 }
4801 }
4802
4803 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_FULLSCREEN]) == true) {
4804 int foundParamIndIndex = -1;
4805 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FULLSCREEN]) + string("="),&foundParamIndIndex);
4806 if(foundParamIndIndex < 0) {
4807 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FULLSCREEN]),&foundParamIndIndex);
4808 }
4809 string paramValue = argv[foundParamIndIndex];
4810 vector<string> paramPartTokens;
4811 Tokenize(paramValue,paramPartTokens,"=");
4812 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4813 string settings = paramPartTokens[1];
4814 printf("Forcing fullscreen [%s]\n",settings.c_str());
4815
4816 bool newFullScreenMode = strToBool(settings);
4817 config.setBool("Windowed",!newFullScreenMode,true);
4818 }
4819 else {
4820 printf("\nInvalid missing fullscreen setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4821 return 1;
4822 }
4823 }
4824
4825 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SET_GAMMA]) == true) {
4826 int foundParamIndIndex = -1;
4827 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SET_GAMMA]) + string("="),&foundParamIndIndex);
4828 if(foundParamIndIndex < 0) {
4829 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SET_GAMMA]),&foundParamIndIndex);
4830 }
4831 string paramValue = argv[foundParamIndIndex];
4832 vector<string> paramPartTokens;
4833 Tokenize(paramValue,paramPartTokens,"=");
4834 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4835 string settings = paramPartTokens[1];
4836 printf("Forcing gamma [%s]\n",settings.c_str());
4837
4838 float newGammaValue = strToFloat(settings);
4839 config.setFloat("GammaValue",newGammaValue,true);
4840 }
4841 else {
4842 printf("\nInvalid missing gamma setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4843 return 1;
4844 }
4845 }
4846
4847
4848 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_VIDEOS]) == true) {
4849 VideoPlayer::setDisabled(true);
4850 }
4851 else if(config.getBool("EnableVideos","true") == false) {
4852 VideoPlayer::setDisabled(true);
4853 }
4854
4855 // Set some statics based on ini entries
4856 SystemFlags::ENABLE_THREADED_LOGGING = config.getBool("ThreadedLogging","true");
4857 FontGl::setDefault_fontType(config.getString("DefaultFont",FontGl::getDefault_fontType().c_str()));
4858 UPNP_Tools::isUPNP = !config.getBool("DisableUPNP","false");
4859 Texture::useTextureCompression = config.getBool("EnableTextureCompression","false");
4860
4861 // 256 for English
4862 // 30000 for Chinese
4863 ::Shared::Graphics::Font::charCount = config.getInt("FONT_CHARCOUNT",intToStr(::Shared::Graphics::Font::charCount).c_str());
4864 ::Shared::Graphics::Font::fontTypeName = config.getString("FONT_TYPENAME",::Shared::Graphics::Font::fontTypeName.c_str());
4865 ::Shared::Graphics::Font::fontIsMultibyte = config.getBool("FONT_MULTIBYTE",intToStr(::Shared::Graphics::Font::fontIsMultibyte).c_str());
4866 ::Shared::Graphics::Font::fontIsRightToLeft = config.getBool("FONT_RIGHTTOLEFT",intToStr(::Shared::Graphics::Font::fontIsRightToLeft).c_str());
4867 ::Shared::Graphics::Font::baseSize = config.getInt("FONT_BASE_SIZE",intToStr(::Shared::Graphics::Font::baseSize).c_str());
4868 ::Shared::Graphics::Font::scaleFontValue = config.getFloat("FONT_SCALE_SIZE",floatToStr(::Shared::Graphics::Font::scaleFontValue).c_str());
4869 ::Shared::Graphics::Font::scaleFontValueCenterHFactor = config.getFloat("FONT_SCALE_CENTERH_FACTOR",floatToStr(::Shared::Graphics::Font::scaleFontValueCenterHFactor).c_str());
4870 ::Shared::Graphics::Font::langHeightText = config.getString("FONT_HEIGHT_TEXT",::Shared::Graphics::Font::langHeightText.c_str());
4871 ::Shared::Graphics::Font::fontSupportMixedRightToLeft = config.getBool("FONT_RIGHTTOLEFT_MIXED_SUPPORT",intToStr(::Shared::Graphics::Font::fontSupportMixedRightToLeft).c_str());
4872
4873 // Example values:
4874 // DEFAULT_CHARSET (English) = 1
4875 // GB2312_CHARSET (Chinese) = 134
4876 ::Shared::Platform::PlatformContextGl::charSet = config.getInt("FONT_CHARSET",intToStr(::Shared::Platform::PlatformContextGl::charSet).c_str());
4877 if(config.getBool("No2DMouseRendering","false") == false) {
4878 showCursor(false);
4879 //showWindowCursorState = false;
4880 }
4881 if(config.getInt("DEFAULT_HTTP_TIMEOUT",intToStr(SystemFlags::DEFAULT_HTTP_TIMEOUT).c_str()) >= 0) {
4882 SystemFlags::DEFAULT_HTTP_TIMEOUT = config.getInt("DEFAULT_HTTP_TIMEOUT",intToStr(SystemFlags::DEFAULT_HTTP_TIMEOUT).c_str());
4883 }
4884
4885 bool allowAltEnterFullscreenToggle = config.getBool("AllowAltEnterFullscreenToggle",boolToStr(::Shared::Platform::Window::getAllowAltEnterFullscreenToggle()).c_str());
4886 ::Shared::Platform::Window::setAllowAltEnterFullscreenToggle(allowAltEnterFullscreenToggle);
4887
4888 if(config.getBool("noTeamColors","false") == true) {
4889 MeshCallbackTeamColor::noTeamColors = true;
4890 }
4891
4892
4893 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_DEBUG]) == true) {
4894 printf("Forcing LUA debugging enabled!\n");
4895 config.setBool("DebugLUA",true, true);
4896 }
4897
4898 // Setup debug logging etc
4899 setupLogging(config, haveSpecialOutputCommandLineOption);
4900
4901 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::PlatformContextGl::charSet = %d, Font::fontIsMultibyte = %d, fontIsRightToLeft = %d\n",__FILE__,__FUNCTION__,__LINE__,::Shared::Graphics::Font::charCount,::Shared::Graphics::Font::fontTypeName.c_str(),::Shared::Platform::PlatformContextGl::charSet,::Shared::Graphics::Font::fontIsMultibyte, ::Shared::Graphics::Font::fontIsRightToLeft);
4902
4903 NetworkInterface::setDisplayMessageFunction(ExceptionHandler::DisplayMessage);
4904 MenuStateMasterserver::setDisplayMessageFunction(ExceptionHandler::DisplayMessage);
4905
4906 #ifdef USE_STREFLOP
4907 SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s, STREFLOP enabled.\n",getNetworkVersionString().c_str());
4908 #else
4909 SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s, STREFLOP NOT enabled.\n",getNetworkVersionString().c_str());
4910 #endif
4911
4912 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
4913 SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"START\n");
4914 SystemFlags::OutputDebug(SystemFlags::debugPathFinder,"START\n");
4915
4916 // Setup hotkeys from key ini files
4917 Config &configKeys = Config::getInstance(
4918 std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys),
4919 std::pair<string,string>(Config::glestkeys_ini_filename,Config::glestuserkeys_ini_filename),
4920 std::pair<bool,bool>(true,false),config.getString("GlestKeysIniPath",""));
4921
4922 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
4923
4924 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true) {
4925 ShowINISettings(argc,argv,config,configKeys);
4926 return 0;
4927 }
4928
4929 // Explicitly disable VBO's
4930 if(config.getBool("DisableVBO","false") == true || hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_VBO]) == true) {
4931 setVBOSupported(false);
4932 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**INFO** Disabling VBOs\n");
4933 }
4934
4935 if(config.getBool("DisableVertexInterpolation","false") || hasCommandArgument(argc, argv, GAME_ARGS[GAME_ARG_DISABLE_VERTEX_INTERPOLATION])) {
4936 InterpolationData::setEnableInterpolation(false);
4937 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**INFO** Disabling Interpolation\n");
4938 }
4939
4940
4941 if(config.getBool("EnableVSynch","false") == true) {
4942 ::Shared::Platform::Window::setTryVSynch(true);
4943 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**ENABLED OPENGL VSYNCH**\n");
4944 }
4945
4946 //float pingTime = Socket::getAveragePingMS("soft-haus.com");
4947 //printf("Ping time = %f\n",pingTime);
4948
4949 // Load the language strings
4950 Lang &lang= Lang::getInstance();
4951 string language = config.getString("Lang");
4952 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_LANGUAGE]) == true) {
4953 int foundParamIndIndex = -1;
4954 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_LANGUAGE]) + string("="),&foundParamIndIndex);
4955 if(foundParamIndIndex < 0) {
4956 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_LANGUAGE]),&foundParamIndIndex);
4957 }
4958 string paramValue = argv[foundParamIndIndex];
4959 vector<string> paramPartTokens;
4960 Tokenize(paramValue,paramPartTokens,"=");
4961 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
4962 language = paramPartTokens[1];
4963 printf("Forcing language [%s]\n",language.c_str());
4964 }
4965 else {
4966 printf("\nInvalid missing language specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
4967 return 1;
4968 }
4969 }
4970 else {
4971
4972 #ifdef _WIN32
4973 int localeBufferSize = GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, NULL, 0);
4974 wchar_t *sysLocale = new wchar_t[localeBufferSize];
4975 GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, sysLocale,localeBufferSize);
4976
4977 //String langValue(sysLocale);
4978 //const char *lang_locale = langValue.c_str();
4979 char langValue[1024]="";
4980 wcstombs(langValue,sysLocale, 1023);
4981 const char *lang_locale = &langValue[0];
4982
4983 delete [] sysLocale;
4984 #else
4985 const char *lang_locale = setlocale(LC_ALL,"");
4986 #endif
4987
4988 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Locale is: [%s]\n", lang_locale);
4989
4990 if(lang_locale != NULL && strlen(lang_locale) >= 2) {
4991 if(config.getBool("AutoLocaleLanguageDetect","true") == true) {
4992 language = lang_locale;
4993 language = language.substr(0,2);
4994 printf("Auto setting language [%s]\n",language.c_str());
4995
4996 config.setString("AutoLocaleLanguageDetect","false");
4997 config.save();
4998 }
4999 }
5000 }
5001
5002 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST])) == true ||
5003 Config::getInstance().getBool("AutoTest","false") == true) {
5004 printf("Running in auto test mode\n");
5005 }
5006 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST])) == true) {
5007 Config::getInstance().setBool("AutoTest",true,true);
5008
5009 int foundParamIndIndex = -1;
5010 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST]) + string("="),&foundParamIndIndex);
5011 if(foundParamIndIndex < 0) {
5012 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST]),&foundParamIndIndex);
5013 }
5014 string paramValue = argv[foundParamIndIndex];
5015 vector<string> paramPartTokens;
5016 Tokenize(paramValue,paramPartTokens,"=");
5017 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5018 vector<string> paramPartTokens2;
5019 Tokenize(paramPartTokens[1],paramPartTokens2,",");
5020 if(paramPartTokens2.empty() == false && paramPartTokens2[0].length() > 0) {
5021 string newMaxSeconds = paramPartTokens2[0];
5022 time_t newTimeMaxSeconds = strToInt(newMaxSeconds);
5023 AutoTest::setMaxGameTime(newTimeMaxSeconds);
5024 printf("Forcing maximum game time to [%ld] seconds (%.2f minutes)\n",(long int)newTimeMaxSeconds,((double)newTimeMaxSeconds / 60.0));
5025 }
5026 if(paramPartTokens2.size() >= 3 && paramPartTokens2[2].length() > 0) {
5027 string autoTestCmd = paramPartTokens2[2];
5028 if(autoTestCmd == "exit") {
5029 printf("Detected auto test command [%s], will exit after game.\n",autoTestCmd.c_str());
5030
5031 AutoTest::setWantExitGameWhenDone(true);
5032 }
5033 else {
5034 printf("WARNING: Detected and UNKNOWN auto test command [%s].\n",autoTestCmd.c_str());
5035 }
5036 }
5037
5038 if(paramPartTokens2.size() >= 2 && paramPartTokens2[1].length() > 0) {
5039 string newGameSettingsFileToLoad = paramPartTokens2[1];
5040
5041 printf("About to auto test using game settings file [%s]\n",newGameSettingsFileToLoad.c_str());
5042 AutoTest::setLoadGameSettingsFile(newGameSettingsFileToLoad);
5043 }
5044 }
5045 }
5046
5047 Renderer &renderer= Renderer::getInstance();
5048 lang.loadGameStrings(language,false, true);
5049
5050 if( lang.hasString("FONT_HEIGHT_TEXT")) {
5051 ::Shared::Graphics::Font::langHeightText = config.getString("FONT_HEIGHT_TEXT",::Shared::Graphics::Font::langHeightText.c_str());
5052 }
5053
5054 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_FONT_BASESIZE]) == true) {
5055 int foundParamIndIndex = -1;
5056 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_BASESIZE]) + string("="),&foundParamIndIndex);
5057 if(foundParamIndIndex < 0) {
5058 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_BASESIZE]),&foundParamIndIndex);
5059 }
5060 string paramValue = argv[foundParamIndIndex];
5061 vector<string> paramPartTokens;
5062 Tokenize(paramValue,paramPartTokens,"=");
5063 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5064 string newfontBaseSize = paramPartTokens[1];
5065 printf("Forcing font base size[%s]\n",newfontBaseSize.c_str());
5066
5067 ::Shared::Graphics::Font::baseSize = strToInt(newfontBaseSize);
5068 }
5069 else {
5070 printf("\nInvalid missing font base size specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
5071
5072 return 1;
5073 }
5074 }
5075
5076 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::PlatformContextGl::charSet = %d, Font::fontIsMultibyte = %d, Font::fontIsRightToLeft = %d\n",__FILE__,__FUNCTION__,__LINE__,::Shared::Graphics::Font::charCount,::Shared::Graphics::Font::fontTypeName.c_str(),::Shared::Platform::PlatformContextGl::charSet,::Shared::Graphics::Font::fontIsMultibyte,::Shared::Graphics::Font::fontIsRightToLeft);
5077 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using Font::charCount = %d, Font::fontTypeName [%s] Shared::Platform::PlatformContextGl::charSet = %d, Font::fontIsMultibyte = %d, Font::fontIsRightToLeft = %d\n",::Shared::Graphics::Font::charCount,::Shared::Graphics::Font::fontTypeName.c_str(),::Shared::Platform::PlatformContextGl::charSet,::Shared::Graphics::Font::fontIsMultibyte,::Shared::Graphics::Font::fontIsRightToLeft);
5078
5079 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_FONT]) == true) {
5080 int foundParamIndIndex = -1;
5081 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FONT]) + string("="),&foundParamIndIndex);
5082 if(foundParamIndIndex < 0) {
5083 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FONT]),&foundParamIndIndex);
5084 }
5085 string paramValue = argv[foundParamIndIndex];
5086 vector<string> paramPartTokens;
5087 Tokenize(paramValue,paramPartTokens,"=");
5088 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5089 string newfont = paramPartTokens[1];
5090
5091 Properties::applyTagsToValue(newfont);
5092 printf("Forcing font [%s]\n",newfont.c_str());
5093
5094 #if defined(WIN32)
5095 string newEnvValue = "MEGAGLEST_FONT=" + newfont;
5096 _putenv(newEnvValue.c_str());
5097 #else
5098 setenv("MEGAGLEST_FONT",newfont.c_str(),1);
5099 #endif
5100 }
5101 else {
5102 printf("\nInvalid missing font specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
5103 return 1;
5104 }
5105 }
5106
5107 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
5108 return handleCreateDataArchivesCommand(argc, argv);
5109 }
5110
5111 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]) == true ||
5112 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]) == true ||
5113 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]) == true ||
5114 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]) == true ||
5115 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]) == true) {
5116 return handleShowCRCValuesCommand(argc, argv);
5117 }
5118
5119 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true ||
5120 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true ||
5121 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true ||
5122 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true ||
5123 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true) {
5124 return handleListDataCommand(argc, argv);
5125
5126 }
5127
5128 program= new Program();
5129 mainProgram = program;
5130 renderer.setProgram(program);
5131
5132 if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
5133 renderer.setAllowRenderUnitTitles(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled);
5134 SystemFlags::OutputDebug(SystemFlags::debugPathFinder,"In [%s::%s Line: %d] renderer.setAllowRenderUnitTitles = %d\n",__FILE__,__FUNCTION__,__LINE__,SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled);
5135 }
5136 renderer.setAllowRenderUnitTitles(true);
5137
5138 string screenShotsPath = userData + GameConstants::folder_path_screenshots;
5139 if(isdir(screenShotsPath.c_str()) == false) {
5140 createDirectoryPaths(screenShotsPath);
5141 }
5142
5143 // Cache Player textures - START
5144 string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
5145 std::map<int,Texture2D *> &crcPlayerTextureCache = CacheManager::getCachedItem< std::map<int,Texture2D *> >(GameConstants::playerTextureCacheLookupKey);
5146 for(int index = 0; index < GameConstants::maxPlayers; ++index) {
5147 string playerTexture = getGameCustomCoreDataPath(data_path, "data/core/faction_textures/faction" + intToStr(index) + ".tga");
5148 if(fileExists(playerTexture) == true) {
5149 Texture2D *texture = Renderer::getInstance().newTexture2D(rsGlobal);
5150 if(texture) {
5151 texture->load(playerTexture);
5152 }
5153 crcPlayerTextureCache[index] = texture;
5154 }
5155 else {
5156 crcPlayerTextureCache[index] = NULL;
5157 }
5158 }
5159 // Cache Player textures - END
5160
5161 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5162
5163 mainWindow= new MainWindow(program);
5164
5165 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5166
5167 GameSettings startupGameSettings;
5168
5169 //parse command line
5170 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SERVER]) == true) {
5171 program->initServer(mainWindow,false,true);
5172 gameInitialized = true;
5173 }
5174 else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
5175 program->initServer(mainWindow,false,true,true);
5176 gameInitialized = true;
5177 }
5178 else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LASTGAME])) == true) {
5179 program->initServer(mainWindow,true,false);
5180 gameInitialized = true;
5181 }
5182 else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LAST_SAVED_GAME])) == true) {
5183 string fileName = "";
5184 int foundParamIndIndex = -1;
5185 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LAST_SAVED_GAME]) + string("="),&foundParamIndIndex);
5186 if(foundParamIndIndex >= 0) {
5187 string loadfileName = argv[foundParamIndIndex];
5188 vector<string> paramPartTokens;
5189 Tokenize(loadfileName,paramPartTokens,"=");
5190 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5191 fileName = paramPartTokens[1];
5192
5193 if(fileExists(fileName) == false) {
5194 // Save the file now
5195 string saveGameFile = "saved/" + fileName;
5196 if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
5197 saveGameFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + saveGameFile;
5198 }
5199 else {
5200 saveGameFile = userData + saveGameFile;
5201 }
5202 if(fileExists(saveGameFile) == true) {
5203 fileName = saveGameFile;
5204 }
5205 }
5206
5207 if(fileExists(fileName) == false) {
5208 char szBuf[8096]="";
5209 snprintf(szBuf,8096,"File specified for loading a saved game cannot be found: [%s]",fileName.c_str());
5210 printf("\n\n======================================================================================\n%s\n======================================================================================\n\n\n",szBuf);
5211
5212 throw megaglest_runtime_error(szBuf);
5213 }
5214 }
5215 }
5216 program->initSavedGame(mainWindow,false,fileName);
5217 gameInitialized = true;
5218 }
5219 else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP])) == true) {
5220 int foundParamIndIndex = -1;
5221 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP]) + string("="),&foundParamIndIndex);
5222 if(foundParamIndIndex < 0) {
5223 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP]),&foundParamIndIndex);
5224 }
5225 string mapName = argv[foundParamIndIndex];
5226 vector<string> paramPartTokens;
5227 Tokenize(mapName,paramPartTokens,"=");
5228 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5229 vector<string> paramPartTokens2;
5230 string tileset="forest";
5231 Tokenize(paramPartTokens[1],paramPartTokens2,",");
5232 if(paramPartTokens2.size() >= 2 && paramPartTokens2[1].length() > 0) {
5233 tileset = paramPartTokens2[1];
5234 }
5235 string autoloadMapName = paramPartTokens2[0];
5236
5237 GameSettings *gameSettings = &startupGameSettings;
5238 gameSettings->setMap(autoloadMapName);
5239 gameSettings->setTileset(tileset);
5240 gameSettings->setTech("megapack");
5241 gameSettings->setDefaultUnits(false);
5242 gameSettings->setDefaultResources(false);
5243 gameSettings->setDefaultVictoryConditions(true);
5244 gameSettings->setFogOfWar(false);
5245 gameSettings->setAllowObservers(true);
5246 gameSettings->setPathFinderType(pfBasic);
5247
5248 for(int i = 0; i < GameConstants::maxPlayers; ++i) {
5249 ControlType ct= ctClosed;
5250
5251 gameSettings->setNetworkPlayerStatuses(i, npst_None);
5252 gameSettings->setFactionControl(i, ct);
5253 gameSettings->setStartLocationIndex(i, i);
5254 gameSettings->setResourceMultiplierIndex(i, 10);
5255 gameSettings->setNetworkPlayerName(i, GameConstants::NETWORK_SLOT_CLOSED_SLOTNAME);
5256 }
5257
5258 ControlType ct= ctHuman;
5259
5260 gameSettings->setNetworkPlayerStatuses(0, npst_None);
5261 gameSettings->setFactionControl(0, ct);
5262 gameSettings->setFactionTypeName(0, formatString(GameConstants::OBSERVER_SLOTNAME));
5263 gameSettings->setTeam(0, GameConstants::maxPlayers + fpt_Observer - 1);
5264 gameSettings->setStartLocationIndex(0, 0);
5265 gameSettings->setNetworkPlayerName(0, GameConstants::OBSERVER_SLOTNAME);
5266
5267 gameSettings->setFactionCount(1);
5268
5269 Config &config = Config::getInstance();
5270 gameSettings->setEnableServerControlledAI(config.getBool("ServerControlledAI","true"));
5271 gameSettings->setNetworkFramePeriod(config.getInt("NetworkSendFrameCount","20"));
5272
5273 program->initServer(mainWindow,gameSettings);
5274 gameInitialized = true;
5275 }
5276 else {
5277 printf("\nInvalid map name specified on commandline [%s] map [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
5278 printParameterHelp(argv[0],foundInvalidArgs);
5279 delete mainWindow;
5280 mainWindow=NULL;
5281 return 1;
5282 }
5283 }
5284
5285 else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONNECT])) == true) {
5286 int foundParamIndIndex = -1;
5287 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONNECT]) + string("="),&foundParamIndIndex);
5288 if(foundParamIndIndex < 0) {
5289 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONNECT]),&foundParamIndIndex);
5290 }
5291 string serverToConnectTo = argv[foundParamIndIndex];
5292 vector<string> paramPartTokens;
5293 Tokenize(serverToConnectTo,paramPartTokens,"=");
5294 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5295 string autoConnectServer = paramPartTokens[1];
5296
5297 int port = config.getInt("PortServer",intToStr(GameConstants::serverPort).c_str());
5298 vector<string> paramPartTokens2;
5299 Tokenize(autoConnectServer,paramPartTokens2,":");
5300 autoConnectServer = paramPartTokens2[0];
5301 if(paramPartTokens2.size() >= 2 && paramPartTokens2[1].length() > 0) {
5302 port = strToInt(paramPartTokens2[1]);
5303 }
5304
5305 printf("Connecting to host [%s] using port: %d\n",autoConnectServer.c_str(),port);
5306 if(autoConnectServer == "auto-connect") {
5307 program->initClientAutoFindHost(mainWindow);
5308 }
5309 else {
5310 program->initClient(mainWindow, autoConnectServer,port);
5311 }
5312 gameInitialized = true;
5313 }
5314 else {
5315
5316 printf("\nInvalid host specified on commandline [%s] host [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
5317 printParameterHelp(argv[0],foundInvalidArgs);
5318 delete mainWindow;
5319 mainWindow=NULL;
5320 return 1;
5321 }
5322 }
5323
5324 else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CLIENT])) == true) {
5325 int foundParamIndIndex = -1;
5326 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CLIENT]) + string("="),&foundParamIndIndex);
5327 if(foundParamIndIndex < 0) {
5328 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CLIENT]),&foundParamIndIndex);
5329 }
5330 string serverToConnectTo = argv[foundParamIndIndex];
5331 vector<string> paramPartTokens;
5332 Tokenize(serverToConnectTo,paramPartTokens,"=");
5333 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5334 string autoConnectServer = paramPartTokens[1];
5335
5336 if(autoConnectServer == "auto-connect") {
5337 program->initClientAutoFindHost(mainWindow);
5338 }
5339 else {
5340 program->initClient(mainWindow, autoConnectServer);
5341 }
5342 gameInitialized = true;
5343 }
5344 else {
5345
5346 printf("\nInvalid host specified on commandline [%s] host [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
5347 printParameterHelp(argv[0],foundInvalidArgs);
5348 delete mainWindow;
5349 mainWindow=NULL;
5350 return 1;
5351 }
5352 }
5353 else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOADSCENARIO])) == true) {
5354
5355 int foundParamIndIndex = -1;
5356 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOADSCENARIO]) + string("="),&foundParamIndIndex);
5357 if(foundParamIndIndex < 0) {
5358 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOADSCENARIO]),&foundParamIndIndex);
5359 }
5360 string scenarioName = argv[foundParamIndIndex];
5361 vector<string> paramPartTokens;
5362 Tokenize(scenarioName,paramPartTokens,"=");
5363 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5364 string autoloadScenarioName = paramPartTokens[1];
5365
5366 program->initScenario(mainWindow, autoloadScenarioName);
5367 gameInitialized = true;
5368 }
5369 else {
5370 printf("\nInvalid scenario name specified on commandline [%s] scenario [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
5371 printParameterHelp(argv[0],foundInvalidArgs);
5372 delete mainWindow;
5373 mainWindow=NULL;
5374 return 1;
5375 }
5376 }
5377 else {
5378 program->initNormal(mainWindow);
5379 }
5380
5381 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5382
5383 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] OpenGL Info:\n%s\n",__FILE__,__FUNCTION__,__LINE__,renderer.getGlInfo().c_str());
5384
5385 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true) {
5386 printf("%s",renderer.getGlInfo().c_str());
5387 printf("%s",renderer.getGlMoreInfo().c_str());
5388
5389 delete mainWindow;
5390 mainWindow=NULL;
5391 return 0;
5392 }
5393
5394 if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CONVERT_MODELS]) == true) {
5395 int foundParamIndIndex = -1;
5396 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONVERT_MODELS]) + string("="),&foundParamIndIndex);
5397 if(foundParamIndIndex < 0) {
5398 hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONVERT_MODELS]),&foundParamIndIndex);
5399 }
5400 string paramValue = argv[foundParamIndIndex];
5401 vector<string> paramPartTokens;
5402 Tokenize(paramValue,paramPartTokens,"=");
5403 if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
5404 string modelFile = paramPartTokens[1];
5405 printf("About to convert model(s) [%s]\n",modelFile.c_str());
5406
5407 string textureFormat = "";
5408 if(paramPartTokens.size() >= 3 && paramPartTokens[1].length() > 0) {
5409 textureFormat = paramPartTokens[2];
5410 printf("About to convert using texture format [%s]\n",textureFormat.c_str());
5411 }
5412
5413 bool keepsmallest = false;
5414 if(paramPartTokens.size() >= 4 && paramPartTokens[1].length() > 0) {
5415 keepsmallest = (paramPartTokens[3] == "keepsmallest");
5416 printf("About to convert using keepsmallest = %d\n",keepsmallest);
5417 }
5418
5419 showCursor(true);
5420
5421 const Metrics &metrics= Metrics::getInstance();
5422 renderer.clearBuffers();
5423 renderer.clearZBuffer();
5424 renderer.reset2d();
5425
5426 if(CoreData::getInstance().getMenuFontBig3D() != NULL) {
5427 renderer.renderText3D(
5428 "Please wait, converting models...",
5429 CoreData::getInstance().getMenuFontBig3D(),
5430 Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
5431 (metrics.getScreenH() / 2), true);
5432 }
5433 else {
5434 renderer.renderText(
5435 "Please wait, converting models...",
5436 CoreData::getInstance().getMenuFontBig(),
5437 Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
5438 (metrics.getScreenH() / 2), true);
5439 }
5440 renderer.swapBuffers();
5441
5442 std::vector<string> models;
5443 if(isdir(modelFile.c_str()) == true) {
5444 models = getFolderTreeContentsListRecursively(modelFile, ".g3d");
5445 }
5446 else {
5447 models.push_back(modelFile);
5448 }
5449
5450 sleep(0);
5451 ::Shared::Platform::Window::handleEvent();
5452 SDL_PumpEvents();
5453
5454 int result = 0;
5455 char szTextBuf[8096]="";
5456 for(unsigned int i =0; i < models.size(); ++i) {
5457 string &file = models[i];
5458
5459 renderer.clearBuffers();
5460 renderer.clearZBuffer();
5461 renderer.reset2d();
5462 snprintf(szTextBuf,8096,"Please wait, converting models [%u of " MG_SIZE_T_SPECIFIER "] ...",i,models.size());
5463
5464 if(CoreData::getInstance().getMenuFontBig3D() != NULL) {
5465 renderer.renderText3D(
5466 szTextBuf,
5467 CoreData::getInstance().getMenuFontBig3D(),
5468 Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
5469 (metrics.getScreenH() / 2), true);
5470 }
5471 else {
5472 renderer.renderText(
5473 szTextBuf,
5474 CoreData::getInstance().getMenuFontBig(),
5475 Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
5476 (metrics.getScreenH() / 2), true);
5477 }
5478 renderer.swapBuffers();
5479
5480 sleep(0);
5481 ::Shared::Platform::Window::handleEvent();
5482 SDL_PumpEvents();
5483
5484 try {
5485 printf("About to load model [%s] [%u of " MG_SIZE_T_SPECIFIER "]\n",file.c_str(),i,models.size());
5486 Model *model = renderer.newModel(rsGlobal, file);
5487 printf("About to save converted model [%s]\n",file.c_str());
5488 model->save(file,textureFormat,keepsmallest);
5489 Renderer::getInstance().endModel(rsGlobal, model);
5490 }
5491 catch(const exception &ex) {
5492 result = 1;
5493 printf("ERROR loading model [%s] message [%s]\n",file.c_str(),ex.what());
5494 }
5495
5496 }
5497
5498 delete mainWindow;
5499 mainWindow=NULL;
5500 return result;
5501 }
5502 else {
5503 printf("\nInvalid model specified on commandline [%s] texture [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
5504 printParameterHelp(argv[0],foundInvalidArgs);
5505 delete mainWindow;
5506 mainWindow=NULL;
5507 return 1;
5508 }
5509 }
5510
5511 if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == true ||
5512 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == true ||
5513 hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == true) {
5514 runTechValidationReport(argc, argv);
5515
5516 delete mainWindow;
5517 mainWindow=NULL;
5518 return 0;
5519 }
5520
5521 if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == true) {
5522 runTechTranslationExtraction(argc, argv);
5523 delete mainWindow;
5524 mainWindow=NULL;
5525 return 0;
5526 }
5527
5528 if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == true) {
5529 runTilesetValidationReport(argc, argv);
5530
5531 delete mainWindow;
5532 mainWindow=NULL;
5533 return 0;
5534 }
5535
5536 gameInitialized = true;
5537
5538 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5539
5540 CheckForDuplicateData();
5541
5542 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5543
5544 //throw "BLAH!";
5545
5546 // START Test out SIGSEGV error handling
5547 //int *foo = (int*)-1; // make a bad pointer
5548 //printf("%d\n", *foo); // causes segfault
5549 // END
5550
5551 bool startCRCPrecacheThread = config.getBool("PreCacheCRCThread","true");
5552 //printf("### In [%s::%s Line: %d] precache thread enabled = %d SystemFlags::VERBOSE_MODE_ENABLED = %d\n",__FILE__,__FUNCTION__,__LINE__,startCRCPrecacheThread,SystemFlags::VERBOSE_MODE_ENABLED);
5553 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] precache thread enabled = %d\n",__FILE__,__FUNCTION__,__LINE__,startCRCPrecacheThread);
5554 if (startCRCPrecacheThread == true
5555 && GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5556 static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
5557 vector<string> techDataPaths = config.getPathListForType(ptTechs);
5558
5559 FileCRCPreCacheThread::setPreCacheThreadCacheLookupKey(GameConstants::preCacheThreadCacheLookupKey);
5560 FileCRCPreCacheThread * &preCacheCRCThreadPtr = CacheManager::getCachedItem< FileCRCPreCacheThread * >(GameConstants::preCacheThreadCacheLookupKey);
5561 if(preCacheCRCThreadPtr == NULL) {
5562 preCacheCRCThreadPtr = new FileCRCPreCacheThread();
5563 }
5564 preCacheThread = preCacheCRCThreadPtr;
5565 preCacheThread->setUniqueID(mutexOwnerId);
5566 preCacheThread->setTechDataPaths(techDataPaths);
5567 //preCacheThread->setFileCRCPreCacheThreadCallbackInterface(&preCacheThreadGame);
5568 preCacheThread->start();
5569 }
5570
5571 auto_ptr<NavtiveLanguageNameListCacheGenerator> lngCacheGen;
5572 auto_ptr<SimpleTaskThread> languageCacheGen;
5573
5574 bool startNativeLanguageNamesPrecacheThread = config.getBool("PreCacheNativeLanguageNamesThread","true");
5575 if(startNativeLanguageNamesPrecacheThread == true &&
5576 GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5577 lngCacheGen.reset(new NavtiveLanguageNameListCacheGenerator());
5578 languageCacheGen.reset(new SimpleTaskThread(lngCacheGen.get(),1));
5579
5580 languageCacheGen->start();
5581 }
5582
5583 // test
5584 //Shared::Platform::MessageBox(NULL,"Mark's test.","Test",0);
5585 //throw megaglest_runtime_error("test!");
5586 //ExceptionHandler::DisplayMessage("test!", false);
5587
5588 // Check for commands being input from stdin
5589 string command="";
5590
5591 #ifndef WIN32
5592 pollfd cinfd[1];
5593 #else
5594 HANDLE h = 0;
5595 #endif
5596 if(disableheadless_console == false) {
5597 #ifndef WIN32
5598 // Theoretically this should always be 0, but one fileno call isn't going to hurt, and if
5599 // we try to run somewhere that stdin isn't fd 0 then it will still just work
5600 cinfd[0].fd = fileno(stdin);
5601 cinfd[0].events = POLLIN;
5602 #else
5603 h = GetStdHandle(STD_INPUT_HANDLE);
5604 //DWORD dwMode;
5605 //GetConsoleMode(h, &dwMode);
5606 //SetConsoleMode(h, dwMode & ~ENABLE_MOUSE_INPUT);
5607 FlushConsoleInputBuffer(h);
5608 #endif
5609 }
5610
5611 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
5612 printf("Headless server is now running...\n");
5613 printf("To shutdown type: quit\n");
5614 printf("All commands require you to press ENTER\n");
5615 }
5616
5617 //throw megaglest_runtime_error("Test!");
5618 //printf("About to throw an exception...\n");
5619 //throw 123;
5620
5621 //main loop
5622 while(program->isShutdownApplicationEnabled() == false && ::Shared::Platform::Window::handleEvent()) {
5623 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
5624
5625 if(disableheadless_console == false) {
5626 #ifndef WIN32
5627 int pollresult = poll(cinfd, 1, 0);
5628 int pollerror = errno;
5629 if(pollresult)
5630 #else
5631 // This is problematic because input on Windows is not line-buffered so this will return
5632 // even if getline may block. I haven't found a good way to fix it, so for the moment
5633 // I just strongly suggest only running the server from the Python frontend, which does
5634 // line buffer input. This does work okay as long as the user doesn't enter characters
5635 // without pressing enter, and then try to end the server another way (say a remote
5636 // console command), in which case we'll still be waiting for the stdin EOL and hang.
5637
5638 DWORD saveMode;
5639 GetConsoleMode(h, &saveMode);
5640 DWORD dwMode = saveMode;
5641 dwMode &= ~ENABLE_MOUSE_INPUT;
5642 dwMode &= ~ENABLE_WINDOW_INPUT;
5643 SetConsoleMode(h, dwMode);
5644
5645 bool gotData = (WaitForSingleObject(h, 0) == WAIT_OBJECT_0);
5646 SetConsoleMode(h, saveMode);
5647 if(gotData == true)
5648 #endif
5649 {
5650
5651
5652 #ifdef WIN32
5653 bool skip = true;
5654 DWORD nNumberOfCharsToRead = 1024;
5655 DWORD nRead = 0;
5656 INPUT_RECORD irInRec[1025];
5657
5658 PeekConsoleInput(h,&irInRec[0],nNumberOfCharsToRead,&nRead);
5659 for(int i = 0; i < nRead; ++i) {
5660 INPUT_RECORD &inr = irInRec[i];
5661
5662 //printf("inr.EventType = %d\n",inr.EventType);
5663 if(inr.EventType == KEY_EVENT) {
5664 if(inr.Event.KeyEvent.bKeyDown) {
5665 char cHoldKey = inr.Event.KeyEvent.uChar.AsciiChar;
5666 if(cHoldKey == '\r') {
5667 skip = false;
5668 break;
5669 }
5670 }
5671 }
5672 }
5673 #else
5674 bool skip = false;
5675 #endif
5676 if(skip == false) {
5677 getline(cin, command);
5678 cin.clear();
5679
5680 printf("server command [%s]\n",command.c_str());
5681 if(command == "quit") {
5682 break;
5683 }
5684
5685 #ifndef WIN32
5686 if (cinfd[0].revents & POLLNVAL) {
5687 printf("invalid file descriptor\n");
5688 }
5689 if (cinfd[0].revents & POLLERR) {
5690 printf("error in file descriptor\n");
5691 }
5692 if (cinfd[0].revents & POLLHUP) {
5693 printf("hang up in file descriptor\n");
5694 }
5695
5696 if(pollresult < 0) {
5697 printf("pollresult = %d errno = %d [%s]\n",pollresult,pollerror,strerror(pollerror));
5698
5699 cinfd[0].fd = fileno(stdin);
5700 cinfd[0].events = POLLIN;
5701 }
5702 #endif
5703 }
5704 }
5705 }
5706 //printf("looping\n");
5707 }
5708
5709 program->loop();
5710
5711 // Because OpenGL really doesn't do multi-threading well
5712 // if(difftime(time(NULL),lastTextureLoadEvent) >= 3) {
5713 // lastTextureLoadEvent = time(NULL);
5714 // vector<Texture2D *> textureList = preCacheThread->getPendingTextureList(1);
5715 // for(unsigned int i = 0; i < textureList.size(); ++i) {
5716 // Texture2D * factionLogo = textureList[i];
5717 // if(factionLogo != NULL) {
5718 // printf("\n\n\n\n|||||||||||||||||||||||||| Load texture [%s]\n",factionLogo->getPath().c_str());
5719 // //Renderer::findTexture(factionLogo);
5720 // renderer.initTexture(rsGlobal,factionLogo);
5721 // }
5722 // }
5723 // }
5724 }
5725
5726 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
5727 printf("\nHeadless server is about to quit...\n");
5728 }
5729
5730 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] starting normal application shutdown\n",__FILE__,__FUNCTION__,__LINE__);
5731
5732 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5733 soundThreadManager = program->getSoundThreadManager(true);
5734 if(soundThreadManager) {
5735 SoundRenderer &soundRenderer= SoundRenderer::getInstance();
5736 soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
5737 chronoshutdownFadeSound.start();
5738 }
5739 }
5740
5741 cleanupCRCThread();
5742 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5743
5744 showCursor(true);
5745 //showWindowCursorState = true;
5746 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5747 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5748 }
5749 catch(const megaglest_runtime_error &e) {
5750
5751 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5752 soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
5753 if(soundThreadManager) {
5754 SoundRenderer &soundRenderer= SoundRenderer::getInstance();
5755 soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
5756 chronoshutdownFadeSound.start();
5757 }
5758 if(program != NULL &&
5759 program->getTryingRendererInit() == true &&
5760 program->getRendererInitOk() == false) {
5761
5762 message(e.what(),GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
5763 }
5764 }
5765
5766 if(program == NULL || program->getTryingRendererInit() == false ||
5767 (program->getTryingRendererInit() == true &&
5768 program->getRendererInitOk() == true)) {
5769
5770 ExceptionHandler::handleRuntimeError(e);
5771 }
5772 }
5773 catch(const exception &e) {
5774 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5775 soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
5776 if(soundThreadManager) {
5777 SoundRenderer &soundRenderer= SoundRenderer::getInstance();
5778 soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
5779 chronoshutdownFadeSound.start();
5780 }
5781 }
5782
5783 ExceptionHandler::handleRuntimeError(e.what(),true);
5784 }
5785 catch(const char *e) {
5786 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5787 soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
5788 if(soundThreadManager) {
5789 SoundRenderer &soundRenderer= SoundRenderer::getInstance();
5790 soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
5791 chronoshutdownFadeSound.start();
5792 }
5793 }
5794
5795 ExceptionHandler::handleRuntimeError(e,true);
5796 }
5797 catch(const string &ex) {
5798 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5799 soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
5800 if(soundThreadManager) {
5801 SoundRenderer &soundRenderer= SoundRenderer::getInstance();
5802 soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
5803 chronoshutdownFadeSound.start();
5804 }
5805 }
5806
5807 ExceptionHandler::handleRuntimeError(ex.c_str(),true);
5808 }
5809 #if !defined(HAVE_GOOGLE_BREAKPAD)
5810 catch(...) {
5811 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5812 soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
5813 if(soundThreadManager) {
5814 SoundRenderer &soundRenderer= SoundRenderer::getInstance();
5815 soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
5816 chronoshutdownFadeSound.start();
5817 }
5818 }
5819
5820 ExceptionHandler::handleRuntimeError("Unknown error [main]!",true);
5821 }
5822 #endif
5823
5824 cleanupCRCThread();
5825
5826 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5827 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5828
5829 delete mainWindow;
5830 mainWindow = NULL;
5831
5832 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5833 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5834
5835 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5836 GraphicComponent::clearRegisteredComponents();
5837
5838 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5839 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5840
5841 if(soundThreadManager) {
5842 SoundRenderer &soundRenderer= SoundRenderer::getInstance();
5843 if( Config::getInstance().getString("FactorySound","") != "None" &&
5844 soundRenderer.isVolumeTurnedOff() == false) {
5845
5846 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5847 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5848
5849 for(;chronoshutdownFadeSound.getMillis() <= shutdownFadeSoundMilliseconds;) {
5850 sleep(10);
5851 }
5852 }
5853
5854 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5855 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5856
5857 BaseThread::shutdownAndWait(soundThreadManager);
5858
5859 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5860 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5861
5862 delete soundThreadManager;
5863 soundThreadManager = NULL;
5864 }
5865
5866 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5867 SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5868
5869 return 0;
5870 }
5871
5872 #if defined(__GNUC__) && !defined(__DragonFly__) && !defined(BSD)
handleSIGSEGV(int sig)5873 void handleSIGSEGV(int sig) {
5874 char szBuf[8096]="";
5875 snprintf(szBuf, 8096,"In [%s::%s Line: %d] Error detected: signal %d:\n",__FILE__,__FUNCTION__,__LINE__, sig);
5876 printf("%s",szBuf);
5877 //abort();
5878
5879 ExceptionHandler::handleRuntimeError(szBuf,true);
5880 }
5881 #endif
5882
5883 #if defined(HAVE_GOOGLE_BREAKPAD)
5884
5885 #if defined(WIN32)
5886 // Callback when minidump written.
MinidumpCallback(const wchar_t * dump_path,const wchar_t * minidump_id,void * context,EXCEPTION_POINTERS * exinfo,MDRawAssertionInfo * assertion,bool succeeded)5887 static bool MinidumpCallback(const wchar_t *dump_path,
5888 const wchar_t *minidump_id,
5889 void *context,
5890 EXCEPTION_POINTERS* exinfo,
5891 MDRawAssertionInfo* assertion,
5892 bool succeeded) {
5893 printf("\n======= In MinidumpCallback...\n");
5894 wprintf(L"\n***ERROR details captured:\nCrash minidump folder: %s\nfile: %s.dmp\nSucceeded: %d\n", (dump_path != NULL ? dump_path : L"(null)"),(minidump_id != NULL ? minidump_id : L"(null)"),succeeded);
5895
5896 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5897 wchar_t szBuf[8096];
5898 int bufBytes = _snwprintf(szBuf,8096,L"An unhandled error was detected.\n\nA crash dump file has been created in the folder:\n%s\nCrash dump filename is: %s.dmp",dump_path,minidump_id);
5899 szBuf[bufBytes] = '\0';
5900 MessageBox(NULL, szBuf, L"Unhandled error", MB_OK|MB_SYSTEMMODAL);
5901 }
5902
5903 return succeeded;
5904 }
5905
5906 #else
5907
5908 // Callback when minidump written.
MinidumpCallback(const google_breakpad::MinidumpDescriptor & descriptor,void * context,bool succeeded)5909 static bool MinidumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
5910 void* context,
5911 bool succeeded) {
5912 printf("\n======= In MinidumpCallback...\n");
5913 printf("\n***ERROR details captured:\nCrash minidump folder: %s\nfile: %s\nSucceeded: %d\n", descriptor.directory().c_str(),descriptor.path(),succeeded);
5914
5915 if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
5916 char szBuf[8096];
5917 snprintf(szBuf,8096,"An unhandled error was detected.\n\nA crash dump file has been created in the folder:\n%s\nCrash dump filename is: %s",descriptor.directory().c_str(),descriptor.path());
5918 message(szBuf,GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
5919 }
5920
5921 return succeeded;
5922 }
5923
5924 #endif
5925
5926 #endif
5927
5928 #ifdef WIN32
EnableCrashingOnCrashes()5929 void EnableCrashingOnCrashes() {
5930 typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
5931 typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
5932 const DWORD EXCEPTION_SWALLOWING = 0x1;
5933
5934 HMODULE kernel32 = LoadLibraryA("kernel32.dll");
5935 if(kernel32 != 0) {
5936 tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");
5937 tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");
5938 if (pGetPolicy && pSetPolicy) {
5939 DWORD dwFlags;
5940 if (pGetPolicy(&dwFlags)) {
5941 // Turn off the filter
5942 pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
5943 }
5944 }
5945 }
5946 }
5947 #endif
5948
glestMainSEHWrapper(int argc,char ** argv)5949 int glestMainSEHWrapper(int argc, char** argv) {
5950
5951 #ifdef WIN32_STACK_TRACE
5952 //printf("Hooking up WIN32_STACK_TRACE...\n");
5953 __try {
5954 #endif
5955
5956 //application_binary= executable_path(argv[0],true);
5957 //printf("\n\nargv0 [%s] application_binary [%s]\n\n",argv[0],application_binary.c_str());
5958
5959 #if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__DragonFly__) && !defined(BSD)
5960
5961 if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_DISABLE_SIGSEGV_HANDLER])) == false) {
5962 signal(SIGSEGV, handleSIGSEGV);
5963 }
5964
5965 // http://developerweb.net/viewtopic.php?id=3013
5966 //signal(SIGPIPE, SIG_IGN);
5967 #endif
5968
5969 initSpecialStrings();
5970 int result = 0;
5971
5972 IRCThread::setGlobalCacheContainerName(GameConstants::ircClientCacheLookupKey);
5973 result = glestMain(argc, argv);
5974
5975 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5976 cleanupProcessObjects();
5977
5978 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5979
5980 #ifdef WIN32
5981 //delete winSockManager;
5982 //winSockManager = NULL;
5983 #endif
5984
5985 if(sdl_quitCalled == false) {
5986 sdl_quitCalled = true;
5987 SDL_Quit();
5988 }
5989
5990 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
5991 return result;
5992 #ifdef WIN32_STACK_TRACE
5993 } __except(stackdumper(0, GetExceptionInformation(),true), EXCEPTION_CONTINUE_SEARCH) { return 0; }
5994 #endif
5995
5996 }
5997
glestMainWrapper(int argc,char ** argv)5998 int glestMainWrapper(int argc, char** argv) {
5999 //setlocale(LC_ALL, "zh_TW.UTF-8");
6000 //setlocale(LC_ALL, "");
6001
6002 #ifdef WIN32
6003 EnableCrashingOnCrashes();
6004 #endif
6005
6006 #if defined(HAVE_GOOGLE_BREAKPAD)
6007 /*
6008 handler = new ExceptionHandler(const wstring& dump_path,
6009 FilterCallback filter,
6010 MinidumpCallback callback,
6011 void* callback_context,
6012 int handler_types,
6013 MINIDUMP_TYPE dump_type,
6014 const wchar_t* pipe_name,
6015 const CustomClientInfo* custom_info);
6016 */
6017
6018 // See this link about swallowed exceptions in Win 7: http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/
6019 //DWORD dwFlags;
6020 //if (GetProcessUserModeExceptionPolicy(&dwFlags)) {
6021 // SetProcessUserModeExceptionPolicy(dwFlags & ~PROCESS_CALLBACK_FILTER_ENABLED); // turn off bit 1
6022 //}
6023
6024 //if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Hooking up google_breakpad::ExceptionHandler...\n");
6025
6026 #if defined(WIN32)
6027 wstring dumpfilepath = utf8_decode(".");
6028 //google_breakpad::ExceptionHandler handler(dumpfilepath, NULL, MinidumpCallback, NULL, true);
6029 errorHandlerPtr.reset(new google_breakpad::ExceptionHandler(dumpfilepath, NULL, MinidumpCallback,
6030 NULL, google_breakpad::ExceptionHandler::HANDLER_ALL));
6031 #else
6032 google_breakpad::MinidumpDescriptor descriptor(".");
6033 errorHandlerPtr.reset(new google_breakpad::ExceptionHandler(descriptor, NULL, MinidumpCallback, NULL, true,-1));
6034 #endif
6035
6036 // ExceptionHandler(const wstring& dump_path,
6037 // FilterCallback filter,
6038 // MinidumpCallback callback,
6039 // void* callback_context,
6040 // int handler_types);
6041
6042 #endif
6043
6044 #if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__DragonFly__) && !defined(BSD)
6045 //#ifdef DEBUG
6046 //printf("MTRACE will be called...\n");
6047 //mtrace ();
6048 //#endif
6049 #endif
6050
6051 #ifdef WIN32
6052 //winSockManager = new SocketManager();
6053 SocketManager winSockManager;
6054 #endif
6055
6056 int result = glestMainSEHWrapper(argc, argv);
6057 return result;
6058 }
6059
6060 }}//end namespace
6061
6062 MAIN_FUNCTION(Glest::Game::glestMainWrapper)
6063