MegaGlest/source/glest_game/main/main.cpp

6128 lines
236 KiB
C++

// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifdef WIN32
#include <winsock2.h>
#include <winsock.h>
#include <process.h>
#include <io.h>
#endif
#ifdef HAVE_GOOGLE_BREAKPAD
#include "handler/exception_handler.h"
#endif
#include "math_wrapper.h"
#include "main.h"
#include <string>
#include <cstdlib>
#include "steamshim_child.h"
#include "steam.h"
#include "game.h"
#include "main_menu.h"
#include "program.h"
#include "config.h"
#include "metrics.h"
#include "game_util.h"
#include "platform_util.h"
#include "platform_main.h"
#include "network_interface.h"
#include "ImageReaders.h"
#include "renderer.h"
#include "simple_threads.h"
//#include <memory>
#include "font.h"
#include <curl/curl.h>
#include "menu_state_masterserver.h"
#include "checksum.h"
#include <algorithm>
#include "sound_renderer.h"
#include "font_gl.h"
#include "FileReader.h"
#include "cache_manager.h"
#include <iterator>
#include "core_data.h"
#include "font_text.h"
#include <locale.h>
#include "string_utils.h"
#include "auto_test.h"
#include "lua_script.h"
#include "interpolation.h"
#include "common_scoped_ptr.h"
// To handle signal catching
#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__FreeBSD__) && !defined(BSD)
#include <signal.h>
#endif
#if defined WIN32 && !defined(HAVE_GOOGLE_BREAKPAD)
#if defined(__WIN32__) && !defined(__GNUC__)
#include <eh.h>
#endif
#include <dbghelp.h>
#endif
#ifndef WIN32
#include <poll.h>
#define stricmp strcasecmp
#define strnicmp strncasecmp
#define _strnicmp strncasecmp
#endif
#include <stdlib.h>
#include "network_message.h"
#include "network_protocol.h"
#include "conversion.h"
#include "gen_uuid.h"
//#include "intro.h"
#include "leak_dumper.h"
#if defined(WIN32)
#ifndef _DEBUG
#ifndef __GNUC__
#define WIN32_STACK_TRACE
#endif
#endif
#endif
using namespace std;
using namespace Shared::Platform;
using namespace Shared::Util;
using namespace Shared::Graphics;
using namespace Shared::Graphics::Gl;
using namespace Shared::Xml;
using namespace Shared;
/**
* @namespace Glest
* Namespace used for all %Glest related code.
*/
/**
* @namespace Game
* Namespace used for game related code.
*/
namespace Glest { namespace Game {
static string tempDataLocation = getUserHome();
static string mg_app_name = "";
static string mailStringSupport = "";
static bool sdl_quitCalled = false;
static bool disableheadless_console = false;
static bool disableBacktrace = false;
static bool gameInitialized = false;
static Program *mainProgram = NULL;
static FileCRCPreCacheThread *preCacheThread = NULL;
#ifdef WIN32
static string runtimeErrorMsg = "";
// keeps in scope for duration of the application
//SocketManager *winSockManager = NULL;
#endif
#ifdef HAVE_GOOGLE_BREAKPAD
auto_ptr<google_breakpad::ExceptionHandler> errorHandlerPtr;
#endif
class NavtiveLanguageNameListCacheGenerator : public SimpleTaskCallbackInterface {
virtual void simpleTask(BaseThread *callingThread,void *userdata) {
Lang &lang = Lang::getInstance();
lang.getDiscoveredLanguageList(true);
}
};
// =====================================================
// class ExceptionHandler
// =====================================================
class ExceptionHandler: public PlatformExceptionHandler{
public:
#if defined(__WIN32__) && !defined(__GNUC__)
virtual void handle(LPEXCEPTION_POINTERS pointers);
#endif
virtual void handle();
static void logError(const char *msg, bool confirmToConsole);
static void handleRuntimeError(const megaglest_runtime_error &ex);
static void handleRuntimeError(const char *msg, bool getStackTraceString);
static int DisplayMessage(const char *msg, bool exitApp);
};
void cleanupCRCThread() {
if(preCacheThread != NULL) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
const double MAX_THREAD_WAIT = 60;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("START - shutting down crc threads\n");
time_t elapsed = time(NULL);
preCacheThread->signalQuit();
for(;preCacheThread->canShutdown(false) == false &&
difftime((long int)time(NULL),elapsed) <= MAX_THREAD_WAIT;) {
}
if(difftime((long int)time(NULL),elapsed) <= MAX_THREAD_WAIT) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("B - shutting down crc threads\n");
for(;preCacheThread->shutdownAndWait() == false &&
difftime((long int)time(NULL),elapsed) <= MAX_THREAD_WAIT;) {
}
if(preCacheThread->getRunningStatus() == false) {
delete preCacheThread;
preCacheThread=NULL;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("C - shutting down crc threads\n");
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
else {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("D - shutting down crc threads\n");
if(preCacheThread->canShutdown(false) == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete preCacheThread;
preCacheThread=NULL;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("E - shutting down crc threads\n");
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("F - shutting down crc threads\n");
preCacheThread = NULL;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
static void cleanupProcessObjects() {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
showCursor(true);
restoreVideoMode(::Shared::Platform::Window::getSDLWindow(), true);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#1 IRCCLient Cache SHUTDOWN\n");
IRCThread * &ircClient = CacheManager::getCachedItem< IRCThread * >(GameConstants::ircClientCacheLookupKey);
if(ircClient != NULL) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#2 IRCCLient Cache SHUTDOWN\n");
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ircClient->disconnect();
ircClient->signalQuit();
ircClient = NULL;
sleep(0);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#4 IRCCLient Cache SHUTDOWN\n");
cleanupCRCThread();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(Renderer::isEnded() == false) {
Renderer::getInstance().end();
CoreData &coreData= CoreData::getInstance();
coreData.cleanup();
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::Close();
SystemFlags::SHUTDOWN_PROGRAM_MODE=true;
//printf("Closing IRC CLient %d\n",__LINE__);
Thread::shutdownThreads();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("start running threads = " MG_SIZE_T_SPECIFIER "\n",Thread::getThreadList().size());
time_t elapsed = time(NULL);
int lastLazyThreadDump = 0;
for(;Thread::getThreadList().size() > 0 &&
difftime((long int)time(NULL),elapsed) <= 10;) {
if(difftime((long int)time(NULL),elapsed) > 1) {
if(lastLazyThreadDump != (int)difftime((long int)time(NULL),elapsed)) {
lastLazyThreadDump = difftime((long int)time(NULL),elapsed);
printf("Waiting for the following threads to exit [" MG_SIZE_T_SPECIFIER "]:\n",Thread::getThreadList().size());
for(int i = 0; i < (int)Thread::getThreadList().size(); ++i) {
BaseThread *baseThread = dynamic_cast<BaseThread *>(Thread::getThreadList()[i]);
printf("Thread index: %d ptr [%p] isBaseThread: %d, Name: [%s]\n",i,baseThread,(baseThread != NULL ? 1 : 0),(baseThread != NULL ? baseThread->getUniqueID().c_str() : "<na>"));
}
}
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("end running threads = " MG_SIZE_T_SPECIFIER "\n",Thread::getThreadList().size());
Thread::shutdownThreads();
std::map<int,Texture2D *> &crcPlayerTextureCache = CacheManager::getCachedItem< std::map<int,Texture2D *> >(GameConstants::playerTextureCacheLookupKey);
crcPlayerTextureCache.clear();
std::map<string,Texture2D *> &crcFactionPreviewTextureCache = CacheManager::getCachedItem< std::map<string,Texture2D *> >(GameConstants::factionPreviewTextureCacheLookupKey);
crcFactionPreviewTextureCache.clear();
std::map<string, vector<FileReader<Pixmap2D> const * >* > &list2d = FileReader<Pixmap2D>::getFileReadersMap();
deleteMapValues(list2d.begin(),list2d.end());
std::map<string, vector<FileReader<Pixmap3D> const * >* > &list3d = FileReader<Pixmap3D>::getFileReadersMap();
deleteMapValues(list3d.begin(),list3d.end());
#if defined(WANT_XERCES)
XmlIo::getInstance().cleanup();
#endif
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::globalCleanupHTTP();
CacheManager::cleanupMutexes();
}
#if defined(WIN32) && !defined(__GNUC__)
void fatal(const char *s, ...) // failure exit
{
static int errors = 0;
errors++;
if(errors <= 5) { // print up to two extra recursive errors
defvformatstring(msg,s,s);
string errText = string(msg) + " [" + runtimeErrorMsg + "]";
//puts(msg);
string sErr = string(mg_app_name) + " fatal error";
SystemFlags::OutputDebug(SystemFlags::debugError,"%s\n",errText.c_str());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",errText.c_str());
if(errors <= 1) { // avoid recursion
if(SDL_WasInit(SDL_INIT_VIDEO)) {
SDL_SetRelativeMouseMode(SDL_FALSE);
}
#ifdef WIN32
LPWSTR wstr = Ansi2WideString(errText.c_str());
LPWSTR wstr1 = Ansi2WideString(sErr.c_str());
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
MessageBox(NULL, wstr, wstr1, MB_OK|MB_SYSTEMMODAL);
}
if(wstr) delete [] wstr;
if(wstr1) delete [] wstr1;
#endif
}
}
// Now try to shutdown threads if possible
delete mainProgram;
mainProgram = NULL;
// END
if(sdl_quitCalled == false) {
sdl_quitCalled = true;
SDL_Quit();
}
exit(EXIT_FAILURE);
}
std::string get_module_path(HMODULE module = 0) {
char path_name[MAX_PATH] = {};
DWORD size = GetModuleFileNameA(module, path_name, MAX_PATH);
return std::string(path_name, size);
}
void write_module_name(string &out, HANDLE process, DWORD64 program_counter) {
DWORD64 module_base = SymGetModuleBase64(process, program_counter);
if (module_base) {
std::string module_name = get_module_path(reinterpret_cast<HMODULE>(module_base));
if (!module_name.empty())
out += module_name + "|";
else
out += "Unknown module|";
} else {
out += "Unknown module|";
}
}
void write_function_name(string &out, HANDLE process, DWORD64 program_counter) {
SYMBOL_INFO_PACKAGE sym = { sizeof(sym) };
sym.si.MaxNameLen = MAX_SYM_NAME;
if (SymFromAddr(process, program_counter, 0, &sym.si)) {
out += string(sym.si.Name) + "()";
} else {
out += "Unknown function";
}
}
void write_file_and_line(string & out, HANDLE process, DWORD64 program_counter) {
IMAGEHLP_LINE64 ih_line = { sizeof(IMAGEHLP_LINE64) };
DWORD dummy = 0;
if (SymGetLineFromAddr64(process, program_counter, &dummy, &ih_line)) {
out += string("|") + string(ih_line.FileName) + ":" + intToStr(ih_line.LineNumber);
}
}
void generate_stack_trace(string &out, CONTEXT ctx, int skip) {
STACKFRAME64 sf = {};
#if !defined(_WIN64)
sf.AddrPC.Offset = ctx.Eip;
#else
sf.AddrPC.Offset = ctx.Rip;
#endif
sf.AddrPC.Mode = AddrModeFlat;
#if !defined(_WIN64)
sf.AddrStack.Offset = ctx.Esp;
#else
sf.AddrStack.Offset = ctx.Rsp;
#endif
sf.AddrStack.Mode = AddrModeFlat;
#if !defined(_WIN64)
sf.AddrFrame.Offset = ctx.Ebp;
#else
sf.AddrFrame.Offset = ctx.Rbp;
#endif
sf.AddrFrame.Mode = AddrModeFlat;
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
bool tryThreadContext = true;
CONTEXT threadContext;
memset(&threadContext, 0, sizeof(CONTEXT));
threadContext.ContextFlags = CONTEXT_FULL;
for (;;) {
SetLastError(0);
#if !defined(_WIN64)
BOOL stack_walk_ok = StackWalk64(IMAGE_FILE_MACHINE_I386,
#else
BOOL stack_walk_ok = StackWalk64(IMAGE_FILE_MACHINE_AMD64,
#endif
process, thread, &sf,
(tryThreadContext == false ? &threadContext : &ctx),
0, &SymFunctionTableAccess64,
&SymGetModuleBase64, 0);
if (!stack_walk_ok || !sf.AddrFrame.Offset) {
if(tryThreadContext == true) {
tryThreadContext = false;
if(GetThreadContext(thread, &threadContext) != 0) {
#if !defined(_WIN64)
sf.AddrPC.Offset = threadContext.Eip;
#else
sf.AddrPC.Offset = threadContext.Rip;
#endif
sf.AddrPC.Mode = AddrModeFlat;
#if !defined(_WIN64)
sf.AddrStack.Offset = threadContext.Esp;
#else
sf.AddrStack.Offset = threadContext.Rsp;
#endif
sf.AddrStack.Mode = AddrModeFlat;
#if !defined(_WIN64)
sf.AddrFrame.Offset = threadContext.Ebp;
#else
sf.AddrFrame.Offset = threadContext.Rbp;
#endif
sf.AddrFrame.Mode = AddrModeFlat;
}
else {
return;
}
}
else {
return;
}
}
if (skip) {
--skip;
}
else {
// write the address
out += intToStr(sf.AddrPC.Offset) + "|";
write_module_name(out, process, sf.AddrPC.Offset);
write_function_name(out, process, sf.AddrPC.Offset);
write_file_and_line(out, process, sf.AddrPC.Offset);
out += "\n";
}
}
}
struct UntypedException {
explicit UntypedException(const EXCEPTION_RECORD & er)
: exception_object(reinterpret_cast<void *>(er.ExceptionInformation[1])),
type_array(reinterpret_cast<_ThrowInfo *>(er.ExceptionInformation[2])->pCatchableTypeArray)
{}
void * exception_object;
_CatchableTypeArray * type_array;
};
void * exception_cast_worker(const UntypedException & e, const type_info & ti) {
for (int i = 0; i < e.type_array->nCatchableTypes; ++i) {
_CatchableType & type_i = *e.type_array->arrayOfCatchableTypes[i];
const std::type_info & ti_i = *reinterpret_cast<std::type_info *>(type_i.pType);
if (ti_i == ti) {
char * base_address = reinterpret_cast<char *>(e.exception_object);
base_address += type_i.thisDisplacement.mdisp;
return base_address;
}
}
return 0;
}
template <typename T>
T * exception_cast(const UntypedException & e) {
const std::type_info & ti = typeid(T);
return reinterpret_cast<T *>(exception_cast_worker(e, ti));
}
void stackdumper(unsigned int type, EXCEPTION_POINTERS *ep, bool fatalExit) {
#ifdef HAVE_GOOGLE_BREAKPAD
if(errorHandlerPtr.get() != NULL) {
errorHandlerPtr->WriteMinidump();
}
#endif
if(!ep) {
fatal("unknown type");
return;
}
EXCEPTION_RECORD *er = ep->ExceptionRecord;
CONTEXT *context = ep->ContextRecord;
string out="";
int skip = 0;
switch (er->ExceptionCode) {
case 0xE06D7363: { // C++ exception
UntypedException ue(*er);
if (std::exception * e = exception_cast<std::exception>(ue)) {
const std::type_info & ti = typeid(*e);
out += string(ti.name()) + ":" + string(e->what());
}
else {
out += "Unknown C++ exception thrown.";
}
skip = 2; // skip RaiseException and _CxxThrowException
} break;
case EXCEPTION_ACCESS_VIOLATION: {
out += string("Access violation. Illegal ")
+ (er->ExceptionInformation[0] ? "write" : "read")
+ string(" by ")
+ intToStr((int)er->ExceptionAddress)
+ string(" at ")
+ intToStr(er->ExceptionInformation[1]);
} break;
default: {
out += "SEH exception thrown. Exception code: "
+ er->ExceptionCode
+ string(" at ")
+ intToStr((int)er->ExceptionAddress);
}
}
generate_stack_trace(out, *context, skip);
if(fatalExit == true) {
fatal(out.c_str());
}
else {
ExceptionHandler::logError(out.c_str(), true);
}
}
#endif
// =====================================================
// class ExceptionHandler
// =====================================================
#if defined(WIN32) && !defined(__GNUC__)
void ExceptionHandler::handle(LPEXCEPTION_POINTERS pointers) {
string msg = "#1 An error occurred and " + string(mg_app_name) + " will close.\nPlease report this bug to: " + string(mailString);
msg += ", attaching the generated " + getCrashDumpFileName()+ " file.";
SystemFlags::OutputDebug(SystemFlags::debugError,"%s\n",msg.c_str());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",msg.c_str());
stackdumper(0, pointers, false);
if(mainProgram && gameInitialized == true) {
mainProgram->showMessage(msg.c_str());
}
message(msg.c_str(),GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
}
#endif
void ExceptionHandler::handle() {
string msg = "#1 An error occurred and " + string(mg_app_name) + " will close.\nPlease report this bug to: " + string(mailString);
#ifdef WIN32
msg += ", attaching the generated " + getCrashDumpFileName()+ " file.";
#endif
SystemFlags::OutputDebug(SystemFlags::debugError,"%s\n",msg.c_str());
SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",msg.c_str());
if(mainProgram && gameInitialized == true) {
mainProgram->showMessage(msg.c_str());
}
message(msg.c_str(),GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
}
void ExceptionHandler::logError(const char *msg, bool confirmToConsole) {
string errorLogFile = "error.log";
if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
errorLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + errorLogFile;
}
else {
string userData = Config::getInstance().getString("UserData_Root","");
if(userData != "") {
endPathWithSlash(userData);
}
errorLogFile = userData + errorLogFile;
}
#if defined(WIN32) && !defined(__MINGW32__)
FILE *fp = _wfopen(utf8_decode(errorLogFile).c_str(), L"w");
std::ofstream logFile(fp);
#else
std::ofstream logFile;
logFile.open(errorLogFile.c_str(), ios_base::out | ios_base::trunc);
#endif
if(logFile.is_open() == true) {
//time_t curtime = time (NULL);
//struct tm *loctime = localtime (&curtime);
struct tm loctime = threadsafe_localtime(systemtime_now());
char szBuf2[100]="";
strftime(szBuf2,100,"%Y-%m-%d %H:%M:%S",&loctime);
logFile << "[" << szBuf2 << "] Runtime Error information:" << std::endl;
logFile << "======================================================" << std::endl;
logFile << (msg != NULL ? msg : "null") << std::endl;
logFile.close();
#if defined(WIN32) && !defined(__MINGW32__)
if(fp) {
fclose(fp);
}
#endif
if(confirmToConsole == true) {
printf("Error saved to logfile [%s]\n",errorLogFile.c_str());
fflush(stdout);
}
}
else {
if(confirmToConsole == true) {
printf("COULD NOT SAVE TO ERROR logfile [%s]\n",errorLogFile.c_str());
fflush(stdout);
}
}
}
void ExceptionHandler::handleRuntimeError(const megaglest_runtime_error &ex) {
const char *msg = ex.what();
handleRuntimeError(msg,false);
}
void ExceptionHandler::handleRuntimeError(const char *msg, bool getStackTraceString) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
static bool inErrorNow = false;
if(inErrorNow == true) {
printf("\n=====================================\n");
printf("\n** Already in error handler aborting, msg [%s]\n",msg);
fflush(stdout);
abort();
//return;
}
inErrorNow = true;
logError(msg,true);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] program = %p gameInitialized = %d msg [%s]\n",__FILE__,__FUNCTION__,__LINE__,mainProgram,gameInitialized,msg);
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] [%s] gameInitialized = %d, program = %p\n",__FILE__,__FUNCTION__,__LINE__,msg,gameInitialized,mainProgram);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%s] gameInitialized = %d, program = %p\n",__FILE__,__FUNCTION__,__LINE__,msg,gameInitialized,mainProgram);
string errMsg = (msg != NULL ? msg : "null");
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
bool gotStackTrace = false;
if(getStackTraceString == true && disableBacktrace == false && sdl_quitCalled == false) {
string stackTrace = getStackTrace();
errMsg += stackTrace;
gotStackTrace = true;
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
logError(errMsg.c_str(),false);
if(gotStackTrace == true) {
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] [%s]\n",__FILE__,__FUNCTION__,__LINE__,errMsg.c_str());
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%s]\n",__FILE__,__FUNCTION__,__LINE__,errMsg.c_str());
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//abort();
if(mainProgram && gameInitialized == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(mainProgram->getState() != NULL) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
mainProgram->showMessage(errMsg.c_str());
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(glActiveTexture != NULL) {
for(;GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false && mainProgram->isMessageShowing();) {
::Shared::Platform::Window::handleEvent();
try {
mainProgram->loop();
}
catch(const exception &e) {
printf("\n=====================================\n");
printf("\n** Already in error handler exiting error rendering, msg [%s]\n",e.what());
fflush(stdout);
break;
}
}
}
}
else {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
mainProgram->showMessage(errMsg.c_str());
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(glActiveTexture != NULL) {
for(;GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false && mainProgram->isMessageShowing();) {
::Shared::Platform::Window::handleEvent();
try {
mainProgram->loop();
}
catch(const exception &e) {
printf("\n=====================================\n");
printf("\n** Already in error handler exiting error rendering, msg [%s]\n",e.what());
fflush(stdout);
break;
}
}
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
else {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
string err = "#2 An error occurred and ";
if(sdl_quitCalled == false) {
err += mg_app_name;
}
err += " will close.\nError msg = [" + errMsg + "]\n\nPlease report this bug to ";
if(sdl_quitCalled == false) {
err += mailStringSupport;
}
#ifdef WIN32
err += string(", attaching the generated ") + getCrashDumpFileName() + string(" file.");
#endif
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
message(err,GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
// Now try to shutdown threads if possible
delete mainProgram;
mainProgram = NULL;
// END
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
#ifdef WIN32
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
showCursor(true);
restoreVideoMode(::Shared::Platform::Window::getSDLWindow(), true);
}
runtimeErrorMsg = errMsg;
inErrorNow = false;
throw runtimeErrorMsg;
#endif
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
cleanupProcessObjects();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(sdl_quitCalled == false) {
sdl_quitCalled = true;
SDL_Quit();
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
inErrorNow = false;
abort();
}
int ExceptionHandler::DisplayMessage(const char *msg, bool exitApp) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
if(mainProgram && gameInitialized == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
mainProgram->showMessage(msg);
}
else {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
message(msg,GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
if(exitApp == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s\n",msg);
// Now try to shutdown threads if possible
delete mainProgram;
mainProgram = NULL;
// END
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
cleanupProcessObjects();
if(sdl_quitCalled == false) {
sdl_quitCalled = true;
SDL_Quit();
}
exit(-1);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] msg [%s] exitApp = %d\n",__FILE__,__FUNCTION__,__LINE__,msg,exitApp);
return 0;
}
// =====================================================
// class MainWindow
// =====================================================
MainWindow::MainWindow(Program *program) : WindowGl(), popupMenu("MainWindow", "popupMenu") {
this->program= program;
//this->popupMenu.registerGraphicComponentOnlyFontCallbacks("MainWindow", "popupMenu");
this->popupMenu.setEnabled(false);
this->popupMenu.setVisible(false);
this->triggerLanguageToggle = false;
this->triggerLanguage = "";
this->cancelLanguageSelection = -1;
}
MainWindow::~MainWindow(){
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete program;
program = NULL;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
int MainWindow::getDesiredScreenWidth() {
Config &config= Config::getInstance();
return config.getInt("ScreenWidth");
}
int MainWindow::getDesiredScreenHeight() {
Config &config= Config::getInstance();
return config.getInt("ScreenHeight");
}
void MainWindow::eventToggleFullScreen(bool isFullscreen) {
WindowGl::eventToggleFullScreen(isFullscreen);
if(isFullscreen) {
Metrics::reload(this->program->getWindow()->getScreenWidth(),
this->program->getWindow()->getScreenHeight());
}
else {
Config &config= Config::getInstance();
Metrics::reload(config.getInt("ScreenWidth"),config.getInt("ScreenHeight"));
//window->setText(config.getString("WindowTitle","MegaGlest"));
//this->mainMenu->init();
}
}
void MainWindow::eventMouseDown(int x, int y, MouseButton mouseButton){
const Metrics &metrics = Metrics::getInstance();
int vx = metrics.toVirtualX(x);
int vy = metrics.toVirtualY(getH() - y);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventMouseDown] ERROR, program == NULL!");
}
if(popupMenu.getVisible() == true && popupMenu.mouseClick(vx, vy)) {
std::pair<int,string> result = popupMenu.mouseClickedMenuItem(vx, vy);
popupMenu.setEnabled(false);
popupMenu.setVisible(false);
// Exit game
if(result.first != cancelLanguageSelection) {
Lang &lang= Lang::getInstance();
map<string,string> languageList = lang.getDiscoveredLanguageList(true);
for(map<string,string>::iterator iterMap = languageList.begin();
iterMap != languageList.end(); ++iterMap) {
string matchLanguage = iterMap->first + "-" + iterMap->second;
if(matchLanguage == result.second) {
this->triggerLanguageToggle = true;
this->triggerLanguage = iterMap->first;
break;
}
}
}
return;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
switch(mouseButton) {
case mbLeft:
program->mouseDownLeft(vx, vy);
break;
case mbRight:
//program->mouseDownRight(vx, vy);
break;
case mbCenter:
//program->mouseDownCenter(vx, vy);
break;
default:
break;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ProgramState *programState = program->getState();
if(programState != NULL) {
switch(mouseButton) {
case mbLeft:
programState->mouseDownLeft(vx, vy);
break;
case mbRight:
programState->mouseDownRight(vx, vy);
break;
case mbCenter:
programState->mouseDownCenter(vx, vy);
break;
default:
break;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void MainWindow::eventMouseUp(int x, int y, MouseButton mouseButton){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
const Metrics &metrics = Metrics::getInstance();
int vx = metrics.toVirtualX(x);
int vy = metrics.toVirtualY(getH() - y);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventMouseUp] ERROR, program == NULL!");
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ProgramState *programState = program->getState();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(programState != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
switch(mouseButton) {
case mbLeft:
programState->mouseUpLeft(vx, vy);
break;
case mbRight:
programState->mouseUpRight(vx, vy);
break;
case mbCenter:
programState->mouseUpCenter(vx, vy);
break;
default:
break;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void MainWindow::eventMouseDoubleClick(int x, int y, MouseButton mouseButton) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
const Metrics &metrics= Metrics::getInstance();
int vx = metrics.toVirtualX(x);
int vy = metrics.toVirtualY(getH() - y);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventMouseDoubleClick] ERROR, program == NULL!");
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ProgramState *programState = program->getState();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(programState != NULL) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
switch(mouseButton){
case mbLeft:
programState->mouseDoubleClickLeft(vx, vy);
break;
case mbRight:
programState->mouseDoubleClickRight(vx, vy);
break;
case mbCenter:
programState->mouseDoubleClickCenter(vx, vy);
break;
default:
break;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void MainWindow::eventMouseMove(int x, int y, const MouseState *ms){
const Metrics &metrics= Metrics::getInstance();
int vx = metrics.toVirtualX(x);
int vy = metrics.toVirtualY(getH() - y);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventMouseMove] ERROR, program == NULL!");
}
program->eventMouseMove(vx, vy, ms);
ProgramState *programState = program->getState();
if(programState != NULL) {
programState->mouseMove(vx, vy, ms);
}
}
void MainWindow::eventMouseWheel(int x, int y, int zDelta) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
const Metrics &metrics= Metrics::getInstance();
int vx = metrics.toVirtualX(x);
int vy = metrics.toVirtualY(getH() - y);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventMouseMove] ERROR, program == NULL!");
}
ProgramState *programState = program->getState();
if(programState != NULL) {
programState->eventMouseWheel(vx, vy, zDelta);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void MainWindow::render() {
if(popupMenu.getVisible() == true) {
Renderer &renderer= Renderer::getInstance();
renderer.renderPopupMenu(&popupMenu);
}
}
void MainWindow::showLanguages() {
Lang &lang= Lang::getInstance();
std::vector<string> menuItems;
map<string,string> languageList = lang.getDiscoveredLanguageList(true);
for(map<string,string>::iterator iterMap = languageList.begin();
iterMap != languageList.end(); ++iterMap) {
menuItems.push_back(iterMap->first + "-" + iterMap->second);
}
menuItems.push_back(lang.getString("Exit"));
cancelLanguageSelection = (int)menuItems.size()-1;
popupMenu.setW(100);
popupMenu.setH(100);
popupMenu.init(lang.getString("GameMenuTitle"),menuItems);
popupMenu.setEnabled(true);
popupMenu.setVisible(true);
}
void MainWindow::toggleLanguage(string language) {
popupMenu.setEnabled(false);
popupMenu.setVisible(false);
this->triggerLanguageToggle = false;
this->triggerLanguage = "";
Lang &lang= Lang::getInstance();
string currentLanguage = lang.getLanguage();
string newLanguageSelected = language;
if(language == "") {
newLanguageSelected = currentLanguage;
vector<string> langResults;
string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
string userDataPath = getGameCustomCoreDataPath(data_path, "");
findAll(userDataPath + "data/lang/*.lng", langResults, true, false);
vector<string> langResults2;
findAll(data_path + "data/lang/*.lng", langResults2, true);
if(langResults2.empty() && langResults.empty()) {
throw megaglest_runtime_error("There are no lang files");
}
for(unsigned int i = 0; i < langResults2.size(); ++i) {
string testLanguage = langResults2[i];
if(std::find(langResults.begin(),langResults.end(),testLanguage) == langResults.end()) {
langResults.push_back(testLanguage);
}
}
for(unsigned int i = 0; i < langResults.size(); ++i) {
string testLanguage = langResults[i];
if(testLanguage == currentLanguage) {
if( i+1 < langResults.size()) {
newLanguageSelected = langResults[i+1];
}
else {
newLanguageSelected = langResults[0];
}
break;
}
}
}
if(newLanguageSelected != currentLanguage) {
lang.loadGameStrings(newLanguageSelected);
program->reloadUI();
program->consoleAddLine(lang.getString("Language") + " " + newLanguageSelected);
}
}
bool MainWindow::eventTextInput(std::string text) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%s]\n",__FILE__,__FUNCTION__,__LINE__,text.c_str());
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventKeyDown] ERROR, program == NULL!");
}
bool result = program->textInput(text);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] result = %d\n",__FILE__,__FUNCTION__,__LINE__,result);
return result;
}
bool MainWindow::eventSdlKeyDown(SDL_KeyboardEvent key) {
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventKeyDown] ERROR, program == NULL!");
}
return program->sdlKeyDown(key);
}
void MainWindow::eventKeyDown(SDL_KeyboardEvent key) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym);
//printf("In mainwindow checking keypress for key [%d]\n",key.keysym.sym);
SDL_keysym keystate = key.keysym;
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c][%d]\n",__FILE__,__FUNCTION__,__LINE__,key,key);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventKeyDown] ERROR, program == NULL!");
}
if(popupMenu.getVisible() == true && isKeyPressed(SDLK_ESCAPE,key) == true) {
this->popupMenu.setEnabled(false);
this->popupMenu.setVisible(false);
return;
}
program->keyDown(key);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(keystate.mod & (KMOD_LALT | KMOD_RALT)) {
//if(key == vkReturn) {
if(isKeyPressed(SDLK_RETURN,key) == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] ALT-ENTER pressed\n",__FILE__,__FUNCTION__,__LINE__);
// This stupidity only required in win32.
// We reload the textures so that the canvas paints textures properly
#ifdef WIN32
if(Window::getAllowAltEnterFullscreenToggle() == true) {
Renderer &renderer= Renderer::getInstance();
renderer.reinitAll();
}
#endif
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
}
//printf("In mainwindow checking keypress for key [%d] mod [%d] modvalue: %d\n",key.keysym.sym,keystate.mod,(keystate.mod & (KMOD_LCTRL | KMOD_RCTRL)));
if(program != NULL && program->isInSpecialKeyCaptureEvent() == false) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
vector<int> modifiersToCheck;
modifiersToCheck.push_back(KMOD_LCTRL);
modifiersToCheck.push_back(KMOD_RCTRL);
modifiersToCheck.push_back(KMOD_LALT);
modifiersToCheck.push_back(KMOD_RALT);
modifiersToCheck.push_back(KMOD_LSHIFT);
modifiersToCheck.push_back(KMOD_RSHIFT);
Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
if(isKeyPressed(configKeys.getSDLKey("HotKeyShowDebug"),key) == true) {
Renderer &renderer= Renderer::getInstance();
if(keystate.mod & (KMOD_LALT | KMOD_RALT)) {
renderer.cycleShowDebugUILevel();
printf("**Cycled Debug UI level to: %d\n",renderer.getShowDebugUILevel());
}
else {
bool showDebugUI = renderer.getShowDebugUI();
renderer.setShowDebugUI(!showDebugUI);
}
}
else if((keystate.mod & (KMOD_LCTRL | KMOD_RCTRL)) &&
isKeyPressed(configKeys.getSDLKey("SwitchLanguage"),key) == true) {
if((keystate.mod & (KMOD_LSHIFT | KMOD_RSHIFT))) {
this->triggerLanguageToggle = true;
this->triggerLanguage = "";
}
else {
showLanguages();
}
}
else if(isKeyPressed(configKeys.getSDLKey("ReloadINI"),key,modifiersToCheck) == true) {
Config &config = Config::getInstance();
config.reload();
}
else if(isKeyPressed(configKeys.getSDLKey("Screenshot"),key,modifiersToCheck) == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot key pressed\n");
string userData = Config::getInstance().getString("UserData_Root","");
if(userData != "") {
endPathWithSlash(userData);
}
string path = userData + GameConstants::folder_path_screenshots;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot checking path [%s]\n",path.c_str());
if(isdir(path.c_str()) == false) {
createDirectoryPaths(path);
}
if(isdir(path.c_str()) == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot path [%s]\n",path.c_str());
Config &config= Config::getInstance();
string fileFormat = config.getString("ScreenShotFileType","jpg");
unsigned int queueSize = Renderer::getInstance().getSaveScreenQueueSize();
for(int i=0; i < 5000; ++i) {
path = userData + GameConstants::folder_path_screenshots;
path += string("screen") + intToStr(i + queueSize) + string(".") + fileFormat;
#ifdef WIN32
FILE *f= _wfopen(utf8_decode(path).c_str(), L"rb");
#else
FILE *f= fopen(path.c_str(), "rb");
#endif
if(f == NULL) {
Lang &lang= Lang::getInstance();
char szBuf[8096]="";
if(lang.getString("ScreenshotSavedTo").length() > 0 && lang.getString("ScreenshotSavedTo")[0] != '?') {
snprintf(szBuf,8096,lang.getString("ScreenshotSavedTo").c_str(),path.c_str());
}
else {
snprintf(szBuf,8096,"Screenshot will be saved to: %s",path.c_str());
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf);
bool showScreenshotSavedMsg = Config::getInstance().getBool("DisableScreenshotConsoleText","false");
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot console showScreenshotSavedMsg = %d\n",showScreenshotSavedMsg);
if(showScreenshotSavedMsg == false) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot console [%s]\n",szBuf);
program->consoleAddLine(szBuf);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Screenshot save to [%s]\n",path.c_str());
Renderer::getInstance().saveScreen(path);
break;
}
else {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CANNOT save Screenshot [%s]\n",path.c_str());
fclose(f);
}
}
}
}
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
void MainWindow::eventKeyUp(SDL_KeyboardEvent key) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventKeyUp] ERROR, program == NULL!");
}
program->keyUp(key);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key);
}
void MainWindow::eventKeyPress(SDL_KeyboardEvent c) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,c);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventKeyPress] ERROR, program == NULL!");
}
program->keyPress(c);
if(program != NULL && program->isInSpecialKeyCaptureEvent() == false) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Config &configKeys = Config::getInstance(std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys));
if(isKeyPressed(configKeys.getSDLKey("HotKeyToggleOSMouseEnabled"),c) == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
bool showCursorState = false;
int state = SDL_ShowCursor(SDL_QUERY);
if(state == SDL_DISABLE) {
showCursorState = true;
}
showCursor(showCursorState);
Renderer &renderer= Renderer::getInstance();
renderer.setNo2DMouseRendering(showCursorState);
Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
}
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,c);
}
void MainWindow::eventWindowEvent(SDL_WindowEvent event) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,event.event);
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventKeyPress] ERROR, program == NULL!");
}
// if(program->getState() != NULL && dynamic_cast<Intro *>(program->getState()) != NULL) {
// printf("In eventWindowEvent skip\n");
// return;
// }
//Renderer &renderer= Renderer::getInstance();
switch(event.event) {
case SDL_WINDOWEVENT_ENTER:
{
//printf("In SDL_WINDOWEVENT_ENTER\n");
// bool showCursorState = Window::lastShowMouseState;
// showCursor(showCursorState);
// renderer.setNo2DMouseRendering(showCursorState);
//
// Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
}
break;
case SDL_WINDOWEVENT_LEAVE:
{
//printf("In SDL_WINDOWEVENT_LEAVE\n");
// bool showCursorState = false;
// int state = SDL_ShowCursor(SDL_QUERY);
// if(state == SDL_DISABLE) {
// showCursorState = true;
// }
// showCursor(showCursorState);
// renderer.setNo2DMouseRendering(showCursorState);
//
// Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
}
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
{
//printf("SDL_WINDOWEVENT_FOCUS_GAINED\n");
// bool showCursorState = Window::lastShowMouseState;
// showCursor(showCursorState);
// renderer.setNo2DMouseRendering(showCursorState);
//
// Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
}
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
{
//printf("SDL_WINDOWEVENT_FOCUS_LOST\n");
// bool showCursorState = false;
// int state = SDL_ShowCursor(SDL_QUERY);
// if(state == SDL_DISABLE) {
// showCursorState = true;
// }
// showCursor(showCursorState);
// renderer.setNo2DMouseRendering(showCursorState);
//
// Window::lastShowMouseState = SDL_ShowCursor(SDL_QUERY);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Window::lastShowMouseState = %d\n",__FILE__,__FUNCTION__,__LINE__,Window::lastShowMouseState);
}
break;
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] [%d]\n",__FILE__,__FUNCTION__,__LINE__,event.event);
}
void MainWindow::eventActivate(bool active) {
if(!active){
//minimize();
}
}
void MainWindow::eventResize(SizeState sizeState) {
if(program == NULL) {
throw megaglest_runtime_error("In [MainWindow::eventResize] ERROR, program == NULL!");
}
program->resize(sizeState);
}
void MainWindow::eventClose(){
delete program;
program= NULL;
}
void MainWindow::setProgram(Program *program) {
this->program= program;
}
// =====================================================
// Main
// =====================================================
SystemFlags debugger;
void print_SDL_version(const char *preamble, SDL_version *v) {
printf("%s %u.%u.%u\n", preamble, v->major, v->minor, v->patch);
}
int setupGameItemPaths(int argc, char** argv, Config *config) {
// Setup path cache for files and folders used in the game
std::map<string,string> &pathCache = CacheManager::getCachedItem< std::map<string,string> >(GameConstants::pathCacheLookupKey);
Properties devProperties;
string devPropertyFile = Properties::getApplicationPath() + "glest-dev.ini";
if(fileExists(devPropertyFile) == true) {
devProperties.load(devPropertyFile);
if(devProperties.hasString("ServerListPath") == true) {
string devItem = devProperties.getString("ServerListPath");
if(devItem != "") {
endPathWithSlash(devItem);
}
if(config != NULL) {
config->setString("ServerListPath",devItem,true);
}
}
if(devProperties.hasString("GlestKeysIniPath") == true) {
string devItem = devProperties.getString("GlestKeysIniPath");
if(devItem != "") {
endPathWithSlash(devItem);
}
if(config != NULL) {
config->setString("GlestKeysIniPath",devItem,true);
}
}
}
//GAME_ARG_DATA_PATH
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DATA_PATH]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_DATA_PATH]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_DATA_PATH]),&foundParamIndIndex);
}
string customPath = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(customPath,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string customPathValue = paramPartTokens[1];
Properties::applyTagsToValue(customPathValue);
if(customPathValue != "") {
endPathWithSlash(customPathValue);
}
pathCache[GameConstants::path_data_CacheLookupKey] = customPathValue;
Properties::setApplicationDataPath(pathCache[GameConstants::path_data_CacheLookupKey]);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom data path [%s]\n",customPathValue.c_str());
}
else {
printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],false);
return 1;
}
}
else if(config != NULL) {
bool foundPath = false;
string customPathValue = "";
if(fileExists(devPropertyFile) == true && devProperties.hasString("DataPath") == true) {
foundPath = true;
customPathValue = devProperties.getString("DataPath","");
}
else if(config->getString("DataPath","") != "") {
foundPath = true;
customPathValue = config->getString("DataPath","");
}
if(foundPath == true) {
pathCache[GameConstants::path_data_CacheLookupKey] = customPathValue;
if(customPathValue != "") {
endPathWithSlash(customPathValue);
}
Properties::setApplicationDataPath(pathCache[GameConstants::path_data_CacheLookupKey]);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using ini specified data path [%s]\n",config->getString("DataPath","").c_str());
}
}
//GAME_ARG_INI_PATH
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_INI_PATH]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_INI_PATH]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_INI_PATH]),&foundParamIndIndex);
}
string customPath = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(customPath,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string customPathValue = paramPartTokens[1];
Properties::applyTagsToValue(customPathValue);
pathCache[GameConstants::path_ini_CacheLookupKey]=customPathValue;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom ini path [%s]\n",customPathValue.c_str());
}
else {
printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],false);
return 1;
}
}
//GAME_ARG_LOG_PATH
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LOG_PATH]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOG_PATH]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOG_PATH]),&foundParamIndIndex);
}
string customPath = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(customPath,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string customPathValue = paramPartTokens[1];
Properties::applyTagsToValue(customPathValue);
pathCache[GameConstants::path_logs_CacheLookupKey]=customPathValue;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom logs path [%s]\n",customPathValue.c_str());
}
else {
printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],false);
return 1;
}
}
else if(config != NULL) {
bool foundPath = false;
string customPathValue = "";
if(fileExists(devPropertyFile) == true && devProperties.hasString("LogPath") == true) {
foundPath = true;
customPathValue = devProperties.getString("LogPath","");
}
else if(config->getString("LogPath","") != "") {
foundPath = true;
customPathValue = config->getString("LogPath","");
}
if(foundPath == true) {
pathCache[GameConstants::path_logs_CacheLookupKey] = customPathValue;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using ini specified logs path [%s]\n",config->getString("LogPath","").c_str());
}
}
Text::DEFAULT_FONT_PATH = pathCache[GameConstants::path_data_CacheLookupKey];
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_FONT_PATH]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_PATH]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_PATH]),&foundParamIndIndex);
}
string customPath = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(customPath,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string customPathValue = paramPartTokens[1];
Properties::applyTagsToValue(customPathValue);
Text::DEFAULT_FONT_PATH_ABSOLUTE = customPathValue;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Using custom fonts path [%s]\n",customPathValue.c_str());
}
else {
printf("\nInvalid path specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],false);
return 1;
}
}
return 0;
}
void setupLogging(Config &config, bool haveSpecialOutputCommandLineOption) {
SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled = config.getBool("DebugMode","false");
SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled = config.getBool("DebugNetwork","false");
SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled = config.getBool("DebugPerformance","false");
SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled = config.getBool("DebugWorldSynch","false");
SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled = config.getBool("DebugUnitCommands","false");
SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled = config.getBool("DebugPathFinder","false");
SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled = config.getBool("DebugLUA","false");
LuaScript::setDebugModeEnabled(SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled);
SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled = config.getBool("DebugSound","false");
SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled = config.getBool("DebugError","true");
string userData = config.getString("UserData_Root","");
if(userData != "") {
endPathWithSlash(userData);
}
#ifdef HAVE_GOOGLE_BREAKPAD
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#1 In setting up errorHandlerPtr->set_dump_path [%p]...\n",errorHandlerPtr.get());
if(errorHandlerPtr.get() != NULL) {
string dumpFilePath;
if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
dumpFilePath = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey);
}
else {
dumpFilePath = userData;
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("#2 In setting up errorHandlerPtr->set_dump_path...\n");
#if defined(WIN32)
wstring dumpfilepath = utf8_decode(dumpFilePath);
if(SystemFlags::VERBOSE_MODE_ENABLED) wprintf(L"Hooking up google_breakpad::ExceptionHandler to save dmp files to [%s]...\n",dumpfilepath.c_str());
errorHandlerPtr->set_dump_path(dumpfilepath);
#else
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Hooking up google_breakpad::ExceptionHandler to save dmp files to [%s]...\n",dumpFilePath.c_str());
//errorHandlerPtr->set_dump_path(dumpfilepath);
google_breakpad::MinidumpDescriptor descriptor(dumpFilePath);
errorHandlerPtr->set_minidump_descriptor(descriptor);
#endif
}
#endif
string debugLogFile = config.getString("DebugLogFile","");
if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugLogFile;
}
else {
debugLogFile = userData + debugLogFile;
}
string debugWorldSynchLogFile = config.getString("DebugLogFileWorldSynch","");
if(debugWorldSynchLogFile == "") {
debugWorldSynchLogFile = debugLogFile;
}
else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugWorldSynchLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugWorldSynchLogFile;
}
else {
debugWorldSynchLogFile = userData + debugWorldSynchLogFile;
}
string debugPerformanceLogFile = config.getString("DebugLogFilePerformance","");
if(debugPerformanceLogFile == "") {
debugPerformanceLogFile = debugLogFile;
}
else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugPerformanceLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugPerformanceLogFile;
}
else {
debugPerformanceLogFile = userData + debugPerformanceLogFile;
}
string debugNetworkLogFile = config.getString("DebugLogFileNetwork","");
if(debugNetworkLogFile == "") {
debugNetworkLogFile = debugLogFile;
}
else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugNetworkLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugNetworkLogFile;
}
else {
debugNetworkLogFile = userData + debugNetworkLogFile;
}
string debugUnitCommandsLogFile = config.getString("DebugLogFileUnitCommands","");
if(debugUnitCommandsLogFile == "") {
debugUnitCommandsLogFile = debugLogFile;
}
else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugUnitCommandsLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugUnitCommandsLogFile;
}
else {
debugUnitCommandsLogFile = userData + debugUnitCommandsLogFile;
}
string debugPathFinderLogFile = config.getString("DebugLogFilePathFinder","");
if(debugPathFinderLogFile == "") {
debugPathFinderLogFile = debugLogFile;
}
else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugPathFinderLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugPathFinderLogFile;
}
else {
debugPathFinderLogFile = userData + debugPathFinderLogFile;
}
string debugLUALogFile = config.getString("DebugLogFileLUA","");
if(debugLUALogFile == "") {
debugLUALogFile = debugLogFile;
}
else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugLUALogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugLUALogFile;
}
else {
debugLUALogFile = userData + debugLUALogFile;
}
string debugSoundLogFile = config.getString("DebugLogFileSound","");
if(debugSoundLogFile == "") {
debugSoundLogFile = debugLogFile;
}
else if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
debugSoundLogFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + debugSoundLogFile;
}
else {
debugSoundLogFile = userData + debugSoundLogFile;
}
string debugErrorLogFile = config.getString("DebugLogFileError","");
SystemFlags::getSystemSettingType(SystemFlags::debugSystem).debugLogFileName = debugLogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).debugLogFileName = debugNetworkLogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).debugLogFileName = debugPerformanceLogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).debugLogFileName = debugWorldSynchLogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).debugLogFileName = debugUnitCommandsLogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).debugLogFileName = debugPathFinderLogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugLUA).debugLogFileName = debugLUALogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugSound).debugLogFileName = debugSoundLogFile;
SystemFlags::getSystemSettingType(SystemFlags::debugError).debugLogFileName = debugErrorLogFile;
if(haveSpecialOutputCommandLineOption == false) {
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",
SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled,
debugLogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled,
debugNetworkLogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled,
debugPerformanceLogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled,
debugWorldSynchLogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugUnitCommands).enabled,
debugUnitCommandsLogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled,
debugPathFinderLogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugLUA).enabled,
debugLUALogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugSound).enabled,
debugSoundLogFile.c_str(),
SystemFlags::getSystemSettingType(SystemFlags::debugError).enabled,
debugErrorLogFile.c_str());
}
}
void runTilesetValidationForPath(string tilesetPath, string tilesetName,
World &world, bool purgeUnusedFiles,bool purgeDuplicateFiles,
bool showDuplicateFiles, bool gitPurgeFiles,double &purgedMegaBytes) {
Checksum checksum;
//bool techtree_errors = false;
std::map<string,vector<pair<string, string> > > loadedFileList;
vector<string> pathList;
pathList.push_back(tilesetPath);
world.loadTileset(pathList, tilesetName,&checksum, loadedFileList);
// Fixup paths with ..
{
std::map<string,vector<pair<string, string> > > newLoadedFileList;
for( std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
iterMap != loadedFileList.end(); ++iterMap) {
string loadedFile = iterMap->first;
replaceAll(loadedFile,"//","/");
replaceAll(loadedFile,"\\\\","\\");
updatePathClimbingParts(loadedFile);
if(newLoadedFileList.find(loadedFile) != newLoadedFileList.end()) {
for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
pair<string, string> &newVal = iterMap->second[xx1];
replaceAll(newVal.first,"//","/");
replaceAll(newVal.first,"\\\\","\\");
updatePathClimbingParts(newVal.first);
replaceAll(newVal.second,"//","/");
replaceAll(newVal.second,"\\\\","\\");
updatePathClimbingParts(newVal.second);
newLoadedFileList[loadedFile].push_back(newVal);
}
}
else {
for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
pair<string, string> &newVal = iterMap->second[xx1];
replaceAll(newVal.first,"//","/");
replaceAll(newVal.first,"\\\\","\\");
updatePathClimbingParts(newVal.first);
replaceAll(newVal.second,"//","/");
replaceAll(newVal.second,"\\\\","\\");
updatePathClimbingParts(newVal.second);
}
newLoadedFileList[loadedFile] = iterMap->second;
}
}
loadedFileList = newLoadedFileList;
}
// Validate the faction setup to ensure we don't have any bad associations
// std::vector<std::string> resultErrors = world.validateFactionTypes();
// Now check for unused files in the techtree
std::map<string,vector<pair<string, string> > > foundFileList;
for(unsigned int i = 0; i < pathList.size(); ++i) {
string path = pathList[i];
endPathWithSlash(path);
path = path + tilesetName + "/";
replaceAll(path, "//", "/");
replaceAll(path, "\\\\", "\\");
vector<string> foundFiles = getFolderTreeContentsListRecursively(path + "*.", "");
for(unsigned int j = 0; j < foundFiles.size(); ++j) {
string file = foundFiles[j];
replaceAll(file, "//", "/");
replaceAll(file, "\\\\", "\\");
replaceAll(file,"//","/");
replaceAll(file,"\\\\","\\");
foundFileList[file].push_back(make_pair(path,path));
}
}
printf("Found tileset filecount = " MG_SIZE_T_SPECIFIER ", used = " MG_SIZE_T_SPECIFIER "\n",foundFileList.size(),loadedFileList.size());
int purgeCount = 0;
bool foundUnusedFile = false;
for( std::map<string,vector<pair<string, string> > >::iterator iterMap = foundFileList.begin();
iterMap != foundFileList.end(); ++iterMap) {
string foundFile = iterMap->first;
replaceAll(foundFile, "//", "/");
replaceAll(foundFile, "\\\\", "\\");
if(loadedFileList.find(foundFile) == loadedFileList.end() &&
foundFile.find("lang/") == foundFile.npos) {
if(foundUnusedFile == false) {
printf("\nLine ref: %d, Warning, unused files were detected - START:\n=====================\n",__LINE__);
}
foundUnusedFile = true;
printf("[%s]\n",foundFile.c_str());
string fileName = extractFileFromDirectoryPath(foundFile);
if(loadedFileList.find(fileName) != loadedFileList.end()) {
printf("possible match on [%s] ?\n",loadedFileList.find(fileName)->first.c_str());
}
else if(purgeUnusedFiles == true) {
off_t fileSize = getFileSize(foundFile);
// convert to MB
purgedMegaBytes += ((double)fileSize / 1048576.0);
purgeCount++;
if(gitPurgeFiles == true) {
char szBuf[8096]="";
snprintf(szBuf,8096,"git rm \"%s\"",foundFile.c_str());
bool gitOk = executeShellCommand(szBuf,0);
if(gitOk == false) {
throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
}
}
else {
removeFile(foundFile);
}
}
}
}
if(foundUnusedFile == true) {
if(purgedMegaBytes > 0) {
printf("Purged %.2f MB (%d) in files\n",purgedMegaBytes,purgeCount);
}
printf("\nLine ref: %d, Warning, unused files were detected - END:\n",__LINE__);
}
if(showDuplicateFiles == true) {
std::map<uint32,vector<string> > mapDuplicateFiles;
// Now check for duplicate data content
for(std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
iterMap != loadedFileList.end(); ++iterMap) {
string fileName = iterMap->first;
Checksum checksum;
checksum.addFile(fileName);
uint32 crcValue = checksum.getSum();
mapDuplicateFiles[crcValue].push_back(fileName);
}
double duplicateMegaBytesPurged=0;
int duplicateCountPurged=0;
double duplicateMegaBytes=0;
int duplicateCount=0;
bool foundDuplicates = false;
for(std::map<uint32,vector<string> >::iterator iterMap = mapDuplicateFiles.begin();
iterMap != mapDuplicateFiles.end(); ++iterMap) {
vector<string> &fileList = iterMap->second;
if(fileList.size() > 1) {
if(foundDuplicates == false) {
foundDuplicates = true;
printf("\nWarning, duplicate files were detected - START:\n=====================\n");
}
map<string,int> parentList;
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
if(idx > 0) {
off_t fileSize = getFileSize(duplicateFile);
// convert to MB
duplicateMegaBytes += ((double)fileSize / 1048576.0);
duplicateCount++;
}
else {
printf("\n");
}
printf("[%s]\n",duplicateFile.c_str());
std::map<string,vector<pair<string, string> > >::iterator iterFind = loadedFileList.find(duplicateFile);
if(iterFind != loadedFileList.end()) {
for(unsigned int jdx = 0; jdx < iterFind->second.size(); jdx++) {
parentList[iterFind->second[jdx].first]++;
}
}
}
for(map<string,int>::iterator iterMap1 = parentList.begin();
iterMap1 != parentList.end(); ++iterMap1) {
if(iterMap1 == parentList.begin()) {
printf("\tParents:\n");
}
printf("\t[%s]\n",iterMap1->first.c_str());
}
if(purgeDuplicateFiles == true) {
string newCommonFileName = "";
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
off_t fileSize = getFileSize(duplicateFile);
if(idx == 0) {
newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
string expandedNewCommonFileName = newCommonFileName;
std::map<string,string> mapExtraTagReplacementValues;
mapExtraTagReplacementValues = Properties::getTagReplacementValues(&mapExtraTagReplacementValues);
Properties::applyTagsToValue(expandedNewCommonFileName,&mapExtraTagReplacementValues);
replaceAll(expandedNewCommonFileName, "//", "/");
createDirectoryPaths(extractDirectoryPathFromFile(expandedNewCommonFileName));
if(gitPurgeFiles == true) {
copyFileTo(duplicateFile, expandedNewCommonFileName);
char szBuf[8096]="";
snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
bool gitOk = executeShellCommand(szBuf,0);
if(gitOk == false) {
throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
}
printf("*** Duplicate file:\n[%s]\nwas git rm and copied to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
}
else {
//int result = 0;
int result = rename(duplicateFile.c_str(),expandedNewCommonFileName.c_str());
if(result != 0) {
char szBuf[8096]="";
char *errmsg = strerror(errno);
snprintf(szBuf,8096,"!!! Error [%s] Could not rename [%s] to [%s]!",errmsg,duplicateFile.c_str(),expandedNewCommonFileName.c_str());
throw megaglest_runtime_error(szBuf);
}
else {
printf("*** Duplicate file:\n[%s]\nwas renamed to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
}
}
}
else {
if(gitPurgeFiles == true) {
char szBuf[8096]="";
snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
bool gitOk = executeShellCommand(szBuf,0);
if(gitOk == false) {
throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
}
printf("*** Duplicate file:\n[%s]\nwas git rm\n",duplicateFile.c_str());
}
else {
removeFile(duplicateFile);
}
printf("*** Duplicate file:\n[%s]\nwas removed\n",duplicateFile.c_str());
// convert to MB
duplicateMegaBytesPurged += ((double)fileSize / 1048576.0);
duplicateCountPurged++;
}
}
}
std::map<string,int> mapUniqueParentList;
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
std::map<string,vector<pair<string, string> > >::iterator iterFind2 = loadedFileList.find(duplicateFile);
if(iterFind2 != loadedFileList.end()) {
for(unsigned int jdx1 = 0; jdx1 < iterFind2->second.size(); jdx1++) {
string parentFile = iterFind2->second[jdx1].first;
string searchText = iterFind2->second[jdx1].second;
if(mapUniqueParentList.find(parentFile) == mapUniqueParentList.end()) {
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());
bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, false);
printf("foundText = %d\n",foundText);
if(foundText == false) {
char szBuf[8096]="";
snprintf(szBuf,8096,"Line ref = %d, Error finding text [%s] in file [%s]",__LINE__,searchText.c_str(),parentFile.c_str());
throw megaglest_runtime_error(szBuf);
}
mapUniqueParentList[parentFile]++;
}
}
}
}
}
}
else {
string newCommonFileName = "";
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
//off_t fileSize = getFileSize(duplicateFile);
if(idx == 0) {
newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
break;
}
}
}
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
std::map<string,vector<pair<string, string> > >::iterator iterFind4 = loadedFileList.find(duplicateFile);
if(iterFind4 != loadedFileList.end()) {
for(unsigned int jdx = 0; jdx < iterFind4->second.size(); jdx++) {
string parentFile = iterFind4->second[jdx].first;
string searchText = iterFind4->second[jdx].second;
bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, true);
if(foundText == false) {
char szBuf[8096]="";
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());
printf("\n\n=================================================\n%s",szBuf);
throw megaglest_runtime_error(szBuf);
}
}
}
}
}
}
}
}
if(foundDuplicates == true) {
printf("Duplicates %.2f MB (%d) in files\n",duplicateMegaBytes,duplicateCount);
printf("Duplicates purged %.2f MB (%d) in files\n",duplicateMegaBytesPurged,duplicateCountPurged);
printf("\nWarning, duplicate files were detected - END:\n");
}
}
//if(techtree_errors == false) {
printf("\nValidation found NO ERRORS for tilesetPath [%s] tilesetName [%s]:\n",tilesetPath.c_str(), tilesetName.c_str());
//}
printf("----------------------------------------------------------------");
}
void runTechValidationForPath(string techPath, string techName,
const std::vector<string> &filteredFactionList, World &world,
bool purgeUnusedFiles,bool purgeDuplicateFiles, bool showDuplicateFiles,
bool gitPurgeFiles,double &purgedMegaBytes) {
string techTreeFolder = techPath + techName;
string techTreeFactionFolder = techTreeFolder + "/factions/";
vector<string> factionsList;
findDirs(techTreeFactionFolder, factionsList, false, false);
if(factionsList.empty() == false) {
Checksum checksum;
set<string> factions;
for(int j = 0; j < (int)factionsList.size(); ++j) {
if( filteredFactionList.empty() == true ||
std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
factions.insert(factionsList[j]);
}
}
printf("\n----------------------------------------------------------------");
printf("\nChecking techPath [%s] techName [%s] total faction count = %d\n",techPath.c_str(), techName.c_str(),(int)factionsList.size());
for(int j = 0; j < (int)factionsList.size(); ++j) {
if( filteredFactionList.empty() == true ||
std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
printf("Using faction [%s]\n",factionsList[j].c_str());
}
}
if(factions.empty() == false) {
bool techtree_errors = false;
std::map<string,vector<pair<string, string> > > loadedFileList;
vector<string> pathList;
pathList.push_back(techPath);
Config &config = Config::getInstance();
vector<string> otherTechPaths = config.getPathListForType(ptTechs,"");
pathList.insert(pathList.end(), otherTechPaths.begin(), otherTechPaths.end());
try {
world.loadTech(pathList, techName, factions, &checksum, loadedFileList, true);
// Fixup paths with ..
{
std::map<string,vector<pair<string, string> > > newLoadedFileList;
for( std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
iterMap != loadedFileList.end(); ++iterMap) {
string loadedFile = iterMap->first;
replaceAll(loadedFile,"//","/");
replaceAll(loadedFile,"\\\\","\\");
updatePathClimbingParts(loadedFile);
if(newLoadedFileList.find(loadedFile) != newLoadedFileList.end()) {
for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
pair<string, string> &newVal = iterMap->second[xx1];
replaceAll(newVal.first,"//","/");
replaceAll(newVal.first,"\\\\","\\");
updatePathClimbingParts(newVal.first);
replaceAll(newVal.second,"//","/");
replaceAll(newVal.second,"\\\\","\\");
updatePathClimbingParts(newVal.second);
newLoadedFileList[loadedFile].push_back(newVal);
}
}
else {
for(unsigned int xx1 = 0; xx1 < iterMap->second.size(); ++xx1) {
pair<string, string> &newVal = iterMap->second[xx1];
replaceAll(newVal.first,"//","/");
replaceAll(newVal.first,"\\\\","\\");
updatePathClimbingParts(newVal.first);
replaceAll(newVal.second,"//","/");
replaceAll(newVal.second,"\\\\","\\");
updatePathClimbingParts(newVal.second);
}
newLoadedFileList[loadedFile] = iterMap->second;
}
}
loadedFileList = newLoadedFileList;
}
// Validate the faction setup to ensure we don't have any bad associations
std::vector<std::string> resultErrors = world.validateFactionTypes();
if(resultErrors.empty() == false) {
techtree_errors = true;
// Display the validation errors
string errorText = "\nErrors were detected:\n=====================\n";
for(int i = 0; i < (int)resultErrors.size(); ++i) {
if(i > 0) {
errorText += "\n";
}
errorText = errorText + resultErrors[i];
}
errorText += "\n=====================\n";
printf("%s",errorText.c_str());
}
// Validate the faction resource setup to ensure we don't have any bad associations
printf("\nChecking resources, count = %d\n",world.getTechTree()->getResourceTypeCount());
for(int i = 0; i < world.getTechTree()->getResourceTypeCount(); ++i) {
printf("Found techtree resource [%s]\n",world.getTechTree()->getResourceType(i)->getName().c_str());
}
resultErrors = world.validateResourceTypes();
if(resultErrors.empty() == false) {
techtree_errors = true;
// Display the validation errors
string errorText = "\nErrors were detected:\n=====================\n";
for(int i = 0; i < (int)resultErrors.size(); ++i) {
if(i > 0) {
errorText += "\n";
}
errorText = errorText + resultErrors[i];
}
errorText += "\n=====================\n";
printf("%s",errorText.c_str());
}
// Now check for unused files in the techtree
std::map<string,vector<pair<string, string> > > foundFileList;
for(unsigned int i = 0; i < pathList.size(); ++i) {
string path = pathList[i];
endPathWithSlash(path);
path = path + techName + "/";
replaceAll(path, "//", "/");
replaceAll(path, "\\\\", "\\");
vector<string> foundFiles = getFolderTreeContentsListRecursively(path + "*.", "");
for(unsigned int j = 0; j < foundFiles.size(); ++j) {
string file = foundFiles[j];
replaceAll(file, "//", "/");
replaceAll(file, "\\\\", "\\");
// ignore loading screen, preview screen and hud
if( file.find(GameConstants::LOADING_SCREEN_FILE) != string::npos ||
file.find(GameConstants::PREVIEW_SCREEN_FILE) != string::npos ||
file.find(GameConstants::HUD_SCREEN_FILE) != string::npos) {
continue;
}
// ignore commondata since we are not loading all factions
if(filteredFactionList.size() > 0) {
if( file.find("/commondata/") != string::npos) {
continue;
}
}
if(file.find("/factions/") != string::npos) {
bool includeFaction = false;
for ( set<string>::iterator it = factions.begin(); it != factions.end(); ++it ) {
string currentFaction = *it;
if(file.find("/factions/" + currentFaction) != string::npos) {
includeFaction = true;
break;
}
}
if(includeFaction == false) {
continue;
}
}
replaceAll(file,"//","/");
replaceAll(file,"\\\\","\\");
foundFileList[file].push_back(make_pair(path,path));
}
}
printf("Found techtree filecount = " MG_SIZE_T_SPECIFIER ", used = " MG_SIZE_T_SPECIFIER "\n",foundFileList.size(),loadedFileList.size());
int purgeCount = 0;
bool foundUnusedFile = false;
for( std::map<string,vector<pair<string, string> > >::iterator iterMap = foundFileList.begin();
iterMap != foundFileList.end(); ++iterMap) {
string foundFile = iterMap->first;
replaceAll(foundFile, "//", "/");
replaceAll(foundFile, "\\\\", "\\");
if(loadedFileList.find(foundFile) == loadedFileList.end() &&
foundFile.find("lang/") == foundFile.npos) {
if(foundUnusedFile == false) {
printf("\nLine ref: %d, Warning, unused files were detected - START:\n=====================\n",__LINE__);
}
foundUnusedFile = true;
printf("[%s]\n",foundFile.c_str());
string fileName = extractFileFromDirectoryPath(foundFile);
if(loadedFileList.find(fileName) != loadedFileList.end()) {
printf("possible match on [%s] ?\n",loadedFileList.find(fileName)->first.c_str());
}
else if(purgeUnusedFiles == true) {
off_t fileSize = getFileSize(foundFile);
// convert to MB
purgedMegaBytes += ((double)fileSize / 1048576.0);
purgeCount++;
if(gitPurgeFiles == true) {
char szBuf[8096]="";
snprintf(szBuf,8096,"git rm \"%s\"",foundFile.c_str());
bool gitOk = executeShellCommand(szBuf,0);
if(gitOk == false) {
throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
}
}
else {
removeFile(foundFile);
}
}
}
}
if(foundUnusedFile == true) {
if(purgedMegaBytes > 0) {
printf("Purged %.2f MB (%d) in files\n",purgedMegaBytes,purgeCount);
}
printf("\nLine ref: %d, Warning, unused files were detected - END:\n",__LINE__);
}
if(showDuplicateFiles == true) {
std::map<uint32,vector<string> > mapDuplicateFiles;
// Now check for duplicate data content
for(std::map<string,vector<pair<string, string> > >::iterator iterMap = loadedFileList.begin();
iterMap != loadedFileList.end(); ++iterMap) {
string fileName = iterMap->first;
Checksum checksum;
checksum.addFile(fileName);
uint32 crcValue = checksum.getSum();
if(crcValue == 0) {
char szBuf[8096]="";
snprintf(szBuf,8096,"Error calculating CRC for file [%s]",fileName.c_str());
throw megaglest_runtime_error(szBuf);
}
mapDuplicateFiles[crcValue].push_back(fileName);
}
double duplicateMegaBytesPurged=0;
int duplicateCountPurged=0;
double duplicateMegaBytes=0;
int duplicateCount=0;
bool foundDuplicates = false;
for(std::map<uint32,vector<string> >::iterator iterMap = mapDuplicateFiles.begin();
iterMap != mapDuplicateFiles.end(); ++iterMap) {
vector<string> &fileList = iterMap->second;
if(fileList.size() > 1) {
if(foundDuplicates == false) {
foundDuplicates = true;
printf("\nWarning, duplicate files were detected - START:\n=====================\n");
}
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());
map<string,int> parentList;
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
if(idx > 0) {
off_t fileSize = getFileSize(duplicateFile);
// convert to MB
duplicateMegaBytes += ((double)fileSize / 1048576.0);
duplicateCount++;
}
else {
printf("\n");
}
printf("[%s]\n",duplicateFile.c_str());
std::map<string,vector<pair<string, string> > >::iterator iterFind = loadedFileList.find(duplicateFile);
if(iterFind != loadedFileList.end()) {
for(unsigned int jdx = 0; jdx < iterFind->second.size(); jdx++) {
parentList[iterFind->second[jdx].first]++;
}
}
string newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
string expandedNewCommonFileName = newCommonFileName;
std::map<string,string> mapExtraTagReplacementValues;
string techCommonData = techPath + techName + "/commondata/";
replaceAll(techCommonData, "//", "/");
mapExtraTagReplacementValues["$COMMONDATAPATH"] = techCommonData;
mapExtraTagReplacementValues = Properties::getTagReplacementValues(&mapExtraTagReplacementValues);
Properties::applyTagsToValue(expandedNewCommonFileName,&mapExtraTagReplacementValues);
replaceAll(expandedNewCommonFileName, "//", "/");
}
printf("----- Finding parents for duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
for(map<string,int>::iterator iterMap1 = parentList.begin();
iterMap1 != parentList.end(); ++iterMap1) {
if(iterMap1 == parentList.begin()) {
printf("\tParents:\n");
}
printf("\t[%s]\n",iterMap1->first.c_str());
}
if(purgeDuplicateFiles == true) {
printf("----- move / remove duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
// First move first duplicate to commondata and delete all other copies
string newCommonFileName = "";
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
off_t fileSize = getFileSize(duplicateFile);
printf("#1 [%u / " MG_SIZE_T_SPECIFIER "] removing duplicate [%s]\n",idx,fileList.size(),duplicateFile.c_str());
if(idx == 0) {
newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
string expandedNewCommonFileName = newCommonFileName;
std::map<string,string> mapExtraTagReplacementValues;
string techCommonData = techPath + techName + "/commondata/";
replaceAll(techCommonData, "//", "/");
mapExtraTagReplacementValues["$COMMONDATAPATH"] = techCommonData;
mapExtraTagReplacementValues = Properties::getTagReplacementValues(&mapExtraTagReplacementValues);
Properties::applyTagsToValue(expandedNewCommonFileName,&mapExtraTagReplacementValues);
replaceAll(expandedNewCommonFileName, "//", "/");
createDirectoryPaths(extractDirectoryPathFromFile(expandedNewCommonFileName));
if(gitPurgeFiles == true) {
copyFileTo(duplicateFile, expandedNewCommonFileName);
char szBuf[8096]="";
snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
bool gitOk = executeShellCommand(szBuf,0);
if(gitOk == false) {
throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
}
printf("*** Duplicate file:\n[%s]\nwas git rm and copied to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
}
else {
printf("moving duplicate [%s] to common data [%s] expanded to [%s]\n",duplicateFile.c_str(),newCommonFileName.c_str(),expandedNewCommonFileName.c_str());
int result = rename(duplicateFile.c_str(),expandedNewCommonFileName.c_str());
if(result != 0) {
char szBuf[8096]="";
char *errmsg = strerror(errno);
snprintf(szBuf,8096,"!!! Error [%s] Could not rename [%s] to [%s]!",errmsg,duplicateFile.c_str(),expandedNewCommonFileName.c_str());
throw megaglest_runtime_error(szBuf);
}
else {
printf("*** Duplicate file:\n[%s]\nwas renamed to:\n[%s]\n",duplicateFile.c_str(),expandedNewCommonFileName.c_str());
}
}
}
else {
if(gitPurgeFiles == true) {
char szBuf[8096]="";
snprintf(szBuf,8096,"git rm \"%s\"",duplicateFile.c_str());
bool gitOk = executeShellCommand(szBuf,0);
if(gitOk == false) {
throw megaglest_runtime_error("Call to command failed [" + string(szBuf) + "]");
}
printf("*** Duplicate file:\n[%s]\nwas git rm\n",duplicateFile.c_str());
}
else {
printf("removing duplicate [%s]\n",duplicateFile.c_str());
removeFile(duplicateFile);
}
printf("*** Duplicate file:\n[%s]\nwas removed\n",duplicateFile.c_str());
// convert to MB
duplicateMegaBytesPurged += ((double)fileSize / 1048576.0);
duplicateCountPurged++;
}
}
}
printf("----- update XML files for duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
std::map<string,int> mapUniqueParentList;
// Update the XML files to point to the new single copy in commondata
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
std::map<string,vector<pair<string, string> > >::iterator iterFind2 = loadedFileList.find(duplicateFile);
if(iterFind2 != loadedFileList.end()) {
for(unsigned int jdx1 = 0; jdx1 < iterFind2->second.size(); jdx1++) {
string parentFile = iterFind2->second[jdx1].first;
string searchText = iterFind2->second[jdx1].second;
if(mapUniqueParentList.find(parentFile) == mapUniqueParentList.end()) {
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());
bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, false);
printf("foundText = %d\n",foundText);
if(foundText == false) {
string techCommonData = techPath + techName + "/commondata/";
replaceAll(techCommonData, "//", "/");
if(StartsWith(searchText, techCommonData) == true) {
printf("WARNING #1 [%d] techCommonData check\n[%s]\n[%s]\n[%s]\n[%s]\n",
foundText,parentFile.c_str(),techCommonData.c_str(),searchText.c_str(),newCommonFileName.c_str());
replaceAll(searchText, techCommonData, "$COMMONDATAPATH/");
foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, false);
printf("WARNING #2 [%d] techCommonData check\n[%s]\n[%s]\n[%s]\n[%s]\n",
foundText,parentFile.c_str(),techCommonData.c_str(),searchText.c_str(),newCommonFileName.c_str());
}
if(foundText == false) {
char szBuf[8096]="";
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());
printf("\n\n=================================================\n%s",szBuf);
throw megaglest_runtime_error(szBuf);
}
}
mapUniqueParentList[parentFile]++;
}
}
}
}
}
}
else {
string newCommonFileName = "";
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
//off_t fileSize = getFileSize(duplicateFile);
if(idx == 0) {
newCommonFileName = "$COMMONDATAPATH/sounds/" + extractFileFromDirectoryPath(duplicateFile);
break;
}
}
}
for(unsigned int idx = 0; idx < fileList.size(); ++idx) {
string duplicateFile = fileList[idx];
string fileExt = extractExtension(duplicateFile);
if(fileExt == "wav" || fileExt == "ogg") {
std::map<string,vector<pair<string, string> > >::iterator iterFind4 = loadedFileList.find(duplicateFile);
if(iterFind4 != loadedFileList.end()) {
for(unsigned int jdx = 0; jdx < iterFind4->second.size(); jdx++) {
string parentFile = iterFind4->second[jdx].first;
string searchText = iterFind4->second[jdx].second;
bool foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, true);
if(foundText == false) {
string techCommonData = techPath + techName + "/commondata/";
replaceAll(techCommonData, "//", "/");
if(StartsWith(searchText, techCommonData) == true) {
replaceAll(searchText, techCommonData, "$COMMONDATAPATH/");
foundText = searchAndReplaceTextInFile(parentFile, searchText, newCommonFileName, true);
}
if(foundText == false) {
// Check if the sound file already references commandata
foundText = searchAndReplaceTextInFile(parentFile, newCommonFileName, newCommonFileName, true);
if(foundText == false) {
char szBuf[8096]="";
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());
printf("\n\n=================================================\n%s",szBuf);
throw megaglest_runtime_error(szBuf);
}
}
}
}
}
}
}
}
printf("----- END duplicate files [" MG_SIZE_T_SPECIFIER "] first file is [%s]\n",fileList.size(),fileList[0].c_str());
}
}
if(foundDuplicates == true) {
printf("Duplicates %.2f MB (%d) in files\n",duplicateMegaBytes,duplicateCount);
printf("Duplicates purged %.2f MB (%d) in files\n",duplicateMegaBytesPurged,duplicateCountPurged);
printf("\nWarning, duplicate files were detected - END:\n");
}
}
}
catch(const megaglest_runtime_error &ex) {
techtree_errors = true;
printf("\n\n****ERROR**** detected while validating the techName: %s\nMESSAGE: %s\n",techName.c_str(),ex.what());
}
if(techtree_errors == false) {
printf("\nValidation found NO ERRORS for techPath [%s] techName [%s] factions checked (count = %d):\n",techPath.c_str(), techName.c_str(),(int)factions.size());
for ( set<string>::iterator it = factions.begin(); it != factions.end(); ++it ) {
printf("Faction [%s]\n",(*it).c_str());
}
}
}
printf("----------------------------------------------------------------");
}
else if(folderExists(techTreeFolder) == true) {
printf("\nWarning, No factions were found for the techtree located in: [%s]\n",techTreeFolder.c_str());
}
}
void runTechTranslationExtractionForPath(string techPath, string techName,
const std::vector<string> &filteredFactionList, World &world) {
vector<string> factionsList;
findDirs(techPath + techName + "/factions/", factionsList, false, false);
if(factionsList.empty() == false) {
Checksum checksum;
set<string> factions;
for(int j = 0; j < (int)factionsList.size(); ++j) {
if( filteredFactionList.empty() == true ||
std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
factions.insert(factionsList[j]);
}
}
printf("\n----------------------------------------------------------------");
printf("\nChecking techPath [%s] techName [%s] total faction count = %d\n",techPath.c_str(), techName.c_str(),(int)factionsList.size());
for(int j = 0; j < (int)factionsList.size(); ++j) {
if( filteredFactionList.empty() == true ||
std::find(filteredFactionList.begin(),filteredFactionList.end(),factionsList[j]) != filteredFactionList.end()) {
printf("Using faction [%s]\n",factionsList[j].c_str());
}
}
if(factions.empty() == false) {
std::map<string,vector<pair<string, string> > > loadedFileList;
vector<string> pathList;
pathList.push_back(techPath);
Config &config = Config::getInstance();
vector<string> otherTechPaths = config.getPathListForType(ptTechs,"");
pathList.insert(pathList.end(), otherTechPaths.begin(), otherTechPaths.end());
try {
world.loadTech(pathList, techName, factions, &checksum, loadedFileList, true);
const TechTree *techtree = world.getTechTree();
string translationFile = techtree->getPath();
endPathWithSlash(translationFile);
translationFile += "lang/" + techName + "_default.lng";
if(fileExists(translationFile) == false) {
string txFilePath = extractDirectoryPathFromFile(translationFile);
createDirectoryPaths(txFilePath);
#if defined(WIN32) && !defined(__MINGW32__)
FILE *fp = _wfopen(utf8_decode(translationFile).c_str(), L"w");
std::ofstream txFile(fp);
#else
std::ofstream txFile;
txFile.open(translationFile.c_str(), ios_base::out | ios_base::trunc);
#endif
if(txFile.is_open() == true) {
string _transl_TechTreeName = techName;
replaceAll(_transl_TechTreeName,"_"," ");
txFile << "; TechTree" << std::endl;
txFile << "TechTreeName=" << _transl_TechTreeName << std::endl;
txFile << "; -------------------------------------" << std::endl;
txFile << "; Types of Armor" << std::endl;
for(int index = 0; index < techtree->getArmorTypeCount(); ++index) {
const ArmorType *at = techtree->getArmorTypeByIndex(index);
string _transl_ArmorTypeName = at->getName(false);
replaceAll(_transl_ArmorTypeName,"_"," ");
txFile << "ArmorTypeName_" << at->getName(false) << "=" << _transl_ArmorTypeName << std::endl;
}
txFile << "; --------------------" << std::endl;
txFile << "; Types of Attack" << std::endl;
for(int index = 0; index < techtree->getAttackTypeCount(); ++index) {
const AttackType *at = techtree->getAttackTypeByIndex(index);
string _transl_AttackTypeName = at->getName(false);
replaceAll(_transl_AttackTypeName,"_"," ");
txFile << "AttackTypeName_" << at->getName(false) << "=" << _transl_AttackTypeName << std::endl;
}
txFile << "; --------------------" << std::endl;
txFile << "; Types of Resources" << std::endl;
for(int index = 0; index < techtree->getResourceTypeCount(); ++index) {
const ResourceType *rt = techtree->getResourceType(index);
string _transl_ResourceTypeName = rt->getName(false);
replaceAll(_transl_ResourceTypeName,"_"," ");
txFile << "ResourceTypeName_" << rt->getName(false) << "=" << _transl_ResourceTypeName << std::endl;
}
//txFile << "FactionName_" << GameConstants::OBSERVER_SLOTNAME << "=" << GameConstants::OBSERVER_SLOTNAME << std::endl;
//txFile << "FactionName_" << GameConstants::RANDOMFACTION_SLOTNAME << "=" << GameConstants::RANDOMFACTION_SLOTNAME << std::endl;
for(int index = 0; index < techtree->getTypeCount(); ++index) {
const FactionType *ft = techtree->getType(index);
string _transl_FactionName = ft->getName(false);
replaceAll(_transl_FactionName,"_"," ");
txFile << "; -----------------------------------------------------------------------------" << std::endl;
txFile << "; Faction" << std::endl;
txFile << "FactionName_" << ft->getName(false) << "=" << _transl_FactionName << std::endl;
txFile << "; -------------------------------------" << std::endl;
txFile << "; Types of Upgrades for this Faction" << std::endl;
for(int upgradeIndex = 0; upgradeIndex < ft->getUpgradeTypeCount(); ++upgradeIndex) {
const UpgradeType *upt = ft->getUpgradeType(upgradeIndex);
string _transl_UpgradeTypeName = upt->getName(false);
replaceAll(_transl_UpgradeTypeName,"_"," ");
txFile << "UpgradeTypeName_" << upt->getName(false) << "=" << _transl_UpgradeTypeName << std::endl;
}
for(int unitIndex = 0; unitIndex < ft->getUnitTypeCount(); ++unitIndex) {
const UnitType *ut = ft->getUnitType(unitIndex);
string _transl_UnitTypeName = ut->getName(false);
replaceAll(_transl_UnitTypeName,"_"," ");
txFile << "; -------------------------------------" << std::endl;
txFile << "; Unit" << std::endl;
txFile << "UnitTypeName_" << ut->getName(false) << "=" << _transl_UnitTypeName << std::endl;
txFile << "; --------------------" << std::endl;
txFile << "; Levels for this Unit" << std::endl;
for(int levelIndex = 0; levelIndex < ut->getLevelCount(); ++levelIndex) {
const Level *level = ut->getLevel(levelIndex);
string _transl_LevelName = level->getName(false);
replaceAll(_transl_LevelName,"_"," ");
txFile << "LevelName_" << level->getName(false) << "=" << _transl_LevelName << std::endl;
}
txFile << "; --------------------" << std::endl;
txFile << "; Types of Commands for this Unit" << std::endl;
for(int commandIndex = 0; commandIndex < ut->getCommandTypeCount(); ++commandIndex) {
const CommandType *ct = ut->getCommandType(commandIndex);
string _transl_CommandName = ct->getName(false);
replaceAll(_transl_CommandName,"_"," ");
txFile << "CommandName_" << ct->getName(false) << "=" << _transl_CommandName << std::endl;
}
}
}
txFile << "; -------------------------------------" << std::endl;
}
txFile.close();
#if defined(WIN32) && !defined(__MINGW32__)
if(fp) {
fclose(fp);
}
#endif
}
else {
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());
}
}
catch(const megaglest_runtime_error &ex) {
printf("\n\n****ERROR**** detected while loading the techName: %s\nMESSAGE: %s\n",techName.c_str(),ex.what());
}
}
printf("----------------------------------------------------------------");
}
}
void runTechTranslationExtraction(int argc, char** argv) {
printf("====== Started Translation Extraction ======\n");
Config &config = Config::getInstance();
// Did the user pass a specific list of factions to validate?
std::vector<string> filteredFactionList;
vector<string> results;
findDirs(config.getPathListForType(ptTechs), results);
vector<string> techTreeFiles = results;
// Did the user pass a specific list of techtrees to validate?
std::vector<string> filteredTechTreeList;
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) + string("=")) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) + string("="),&foundParamIndIndex);
string filterList = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(filterList,paramPartTokens,"=");
if(paramPartTokens.size() >= 2) {
string techtreeList = paramPartTokens[1];
Tokenize(techtreeList,filteredTechTreeList,",");
if(filteredTechTreeList.empty() == false) {
printf("Filtering techtrees and only looking for the following:\n");
for(int idx = 0; idx < (int)filteredTechTreeList.size(); ++idx) {
filteredTechTreeList[idx] = trim(filteredTechTreeList[idx]);
printf("%s\n",filteredTechTreeList[idx].c_str());
}
}
}
}
{
printf("\n---------------- Loading factions inside world ----------------");
World world;
vector<string> techPaths = config.getPathListForType(ptTechs);
for(int idx = 0; idx < (int)techPaths.size(); idx++) {
string &techPath = techPaths[idx];
endPathWithSlash(techPath);
for(int idx2 = 0; idx2 < (int)techTreeFiles.size(); idx2++) {
string &techName = techTreeFiles[idx2];
if( filteredTechTreeList.empty() == true ||
std::find(filteredTechTreeList.begin(),filteredTechTreeList.end(),techName) != filteredTechTreeList.end()) {
runTechTranslationExtractionForPath(techPath, techName,
filteredFactionList,world);
}
}
}
printf("\n====== Finished Translation ======\n");
}
}
void runTechValidationReport(int argc, char** argv) {
printf("====== Started Validation ======\n");
bool purgeDuplicateFiles = false;
bool showDuplicateFiles = true;
bool purgeUnusedFiles = false;
bool gitPurgeFiles = false;
double purgedMegaBytes=0;
Config &config = Config::getInstance();
// Did the user pass a specific scenario to validate?
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) + string("=")) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) + string("="),&foundParamIndIndex);
string filterList = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(filterList,paramPartTokens,"=");
if(paramPartTokens.size() >= 2) {
string validateScenarioName = paramPartTokens[1];
printf("Filtering scenario: %s\n",validateScenarioName.c_str());
if(paramPartTokens.size() >= 3) {
if(paramPartTokens[2] == "purgeunused") {
purgeUnusedFiles = true;
printf("*NOTE All unused scenario files will be deleted!\n");
}
}
{
printf("\n---------------- Loading scenario inside world ----------------\n");
bool scenarioFound = false;
World world;
std::vector<string> filteredFactionList;
vector<string> scenarioPaths = config.getPathListForType(ptScenarios);
for(int idx = 0; idx < (int)scenarioPaths.size(); idx++) {
string &scenarioPath = scenarioPaths[idx];
endPathWithSlash(scenarioPath);
vector<string> scenarioList;
findDirs(scenarioPath, scenarioList, false, false);
for(int idx2 = 0; idx2 < (int)scenarioList.size(); idx2++) {
string &scenarioName = scenarioList[idx2];
if(scenarioName == validateScenarioName) {
scenarioFound = true;
string file = scenarioPath + scenarioName + "/" + scenarioName + ".xml";
XmlTree xmlTree;
xmlTree.load(file,Properties::getTagReplacementValues());
const XmlNode *scenarioNode= xmlTree.getRootNode();
string techName = scenarioNode->getChild("tech-tree")->getAttribute("value")->getValue();
// Self Contained techtree?
string scenarioTechtree = scenarioPath + scenarioName + "/" + techName + "/" + techName + ".xml";
printf("\nFound Scenario [%s] looking for techtree [%s]...\n",scenarioName.c_str(),scenarioTechtree.c_str());
if(fileExists(scenarioTechtree) == true) {
string techPath = scenarioPath + scenarioName + "/";
printf("\nFound Scenario [%s] with custom techtree [%s] validating...\n",scenarioName.c_str(),techName.c_str());
runTechValidationForPath(techPath, techName, filteredFactionList,
world, purgeUnusedFiles, showDuplicateFiles, false, false, purgedMegaBytes);
}
else {
vector<string> techPaths = config.getPathListForType(ptTechs);
for(int idx = 0; idx < (int)techPaths.size(); idx++) {
string &techPath = techPaths[idx];
endPathWithSlash(techPath);
scenarioTechtree = techPath + "/" + techName + "/" + techName + ".xml";
if(fileExists(scenarioTechtree) == true) {
printf("\nFound Scenario [%s] with techtree [%s] validating...\n",scenarioName.c_str(),techName.c_str());
runTechValidationForPath(techPath, techName, filteredFactionList,
world, purgeUnusedFiles, showDuplicateFiles, false, false, purgedMegaBytes);
break;
}
}
}
}
}
}
if(scenarioFound == false) {
printf("\nWARNING, the scenario [%s] was NOT FOUND!\n",validateScenarioName.c_str());
}
printf("\n====== Finished Validation ======\n");
}
return;
}
else {
printf("\nInvalid missing scenario specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return;
}
}
// Did the user pass a specific list of factions to validate?
std::vector<string> filteredFactionList;
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) + string("=")) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) + string("="),&foundParamIndIndex);
string filterList = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(filterList,paramPartTokens,"=");
if(paramPartTokens.size() >= 2) {
string factionList = paramPartTokens[1];
Tokenize(factionList,filteredFactionList,",");
if(filteredFactionList.empty() == false) {
printf("Filtering factions and only looking for the following:\n");
for(int idx = 0; idx < (int)filteredFactionList.size(); ++idx) {
filteredFactionList[idx] = trim(filteredFactionList[idx]);
printf("%s\n",filteredFactionList[idx].c_str());
}
}
if(paramPartTokens.size() >= 3) {
if(paramPartTokens[2] == "purgeunused") {
purgeUnusedFiles = true;
printf("*NOTE All unused faction files will be deleted!\n");
}
}
}
}
vector<string> results;
findDirs(config.getPathListForType(ptTechs), results);
vector<string> techTreeFiles = results;
// Did the user pass a specific list of techtrees to validate?
std::vector<string> filteredTechTreeList;
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) + string("=")) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) + string("="),&foundParamIndIndex);
string filterList = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(filterList,paramPartTokens,"=");
if(paramPartTokens.size() >= 2) {
string techtreeList = paramPartTokens[1];
Tokenize(techtreeList,filteredTechTreeList,",");
if(filteredTechTreeList.empty() == false) {
printf("Filtering techtrees and only looking for the following:\n");
for(int idx = 0; idx < (int)filteredTechTreeList.size(); ++idx) {
filteredTechTreeList[idx] = trim(filteredTechTreeList[idx]);
printf("%s\n",filteredTechTreeList[idx].c_str());
}
}
if(paramPartTokens.size() >= 3) {
if(paramPartTokens[2] == "purgeunused") {
purgeUnusedFiles = true;
printf("*NOTE All unused techtree files will be deleted!\n");
}
else if(paramPartTokens[2] == "purgeduplicates") {
purgeDuplicateFiles = true;
printf("*NOTE All duplicate techtree files will be merged!\n");
}
else if(paramPartTokens[2] == "gitdelete") {
gitPurgeFiles = true;
printf("*NOTE All unused / duplicate techtree files will be removed from git!\n");
}
else if(paramPartTokens[2] == "hideduplicates") {
showDuplicateFiles = false;
printf("*NOTE All duplicate techtree files will NOT be shown!\n");
}
}
if(paramPartTokens.size() >= 4) {
if(paramPartTokens[3] == "purgeunused") {
purgeUnusedFiles = true;
printf("*NOTE All unused techtree files will be deleted!\n");
}
else if(paramPartTokens[3] == "purgeduplicates") {
purgeDuplicateFiles = true;
printf("*NOTE All duplicate techtree files will be merged!\n");
}
else if(paramPartTokens[3] == "gitdelete") {
gitPurgeFiles = true;
printf("*NOTE All unused / duplicate techtree files will be removed from git!\n");
}
else if(paramPartTokens[3] == "hideduplicates") {
showDuplicateFiles = false;
printf("*NOTE All duplicate techtree files will NOT be shown!\n");
}
}
if(paramPartTokens.size() >= 5) {
if(paramPartTokens[4] == "purgeunused") {
purgeUnusedFiles = true;
printf("*NOTE All unused techtree files will be deleted!\n");
}
else if(paramPartTokens[4] == "purgeduplicates") {
purgeDuplicateFiles = true;
printf("*NOTE All duplicate techtree files will be merged!\n");
}
else if(paramPartTokens[4] == "gitdelete") {
gitPurgeFiles = true;
printf("*NOTE All unused / duplicate techtree files will be removed from git!\n");
}
else if(paramPartTokens[4] == "hideduplicates") {
showDuplicateFiles = false;
printf("*NOTE All duplicate techtree files will NOT be shown!\n");
}
}
}
}
{
printf("\n---------------- Loading factions inside world ----------------");
World world;
vector<string> techPaths = config.getPathListForType(ptTechs);
for(int idx = 0; idx < (int)techPaths.size(); idx++) {
string &techPath = techPaths[idx];
endPathWithSlash(techPath);
for(int idx2 = 0; idx2 < (int)techTreeFiles.size(); idx2++) {
string &techName = techTreeFiles[idx2];
if( filteredTechTreeList.empty() == true ||
std::find(filteredTechTreeList.begin(),filteredTechTreeList.end(),techName) != filteredTechTreeList.end()) {
runTechValidationForPath(techPath, techName, filteredFactionList,
world, purgeUnusedFiles,purgeDuplicateFiles,
showDuplicateFiles,gitPurgeFiles,purgedMegaBytes);
}
}
}
printf("\n====== Finished Validation ======\n");
}
}
void runTilesetValidationReport(int argc, char** argv) {
printf("====== Started Validation ======\n");
Config &config = Config::getInstance();
// Did the user pass a specific tileset to validate?
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) + string("=")) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) + string("="),&foundParamIndIndex);
string filterList = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(filterList,paramPartTokens,"=");
if(paramPartTokens.size() >= 2) {
string validateTilesetName = paramPartTokens[1];
printf("Filtering tileset: %s\n",validateTilesetName.c_str());
bool purgeUnusedFiles = false;
if(paramPartTokens.size() >= 3) {
if(paramPartTokens[2] == "purgeunused") {
purgeUnusedFiles = true;
printf("*NOTE All unused tileset files will be deleted!\n");
}
}
{
printf("\n---------------- Loading tileset inside world ----------------\n");
World world;
double purgedMegaBytes=0;
bool showDuplicateFiles = true;
bool tilesetFound = false;
vector<string> tilesetPaths = config.getPathListForType(ptTilesets);
for(int idx = 0; idx < (int)tilesetPaths.size(); idx++) {
string &tilesetPath = tilesetPaths[idx];
endPathWithSlash(tilesetPath);
vector<string> tilesetList;
findDirs(tilesetPath, tilesetList, false, false);
for(int idx2 = 0; idx2 < (int)tilesetList.size(); idx2++) {
string &tilesetName = tilesetList[idx2];
if(tilesetName == validateTilesetName) {
tilesetFound = true;
runTilesetValidationForPath(tilesetPath, tilesetName,
world, purgeUnusedFiles, showDuplicateFiles,
false, false, purgedMegaBytes);
}
}
}
if(tilesetFound == false) {
printf("*ERROR The specified tileset [%s] was NOT FOUND!\n",validateTilesetName.c_str());
}
printf("\n====== Finished Validation ======\n");
}
return;
}
else {
printf("\nInvalid missing tileset specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return;
}
}
else {
printf("\nInvalid missing tileset specified on commandline\n\n");
return;
}
}
void ShowINISettings(int argc, char **argv,Config &config,Config &configKeys) {
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true) {
vector<string> filteredPropertyList;
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) + string("=")) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) + string("="),&foundParamIndIndex);
string filterList = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(filterList,paramPartTokens,"=");
if(paramPartTokens.size() >= 2) {
string tokenList = paramPartTokens[1];
Tokenize(tokenList,filteredPropertyList,",");
if(filteredPropertyList.empty() == false) {
printf("Filtering properties and only looking for the following:\n");
for(int idx = 0; idx < (int)filteredPropertyList.size(); ++idx) {
filteredPropertyList[idx] = trim(filteredPropertyList[idx]);
printf("%s\n",filteredPropertyList[idx].c_str());
}
}
}
}
printf("\nMain settings report\n");
printf("====================\n");
vector<pair<string,string> > mergedMainSettings = config.getMergedProperties();
vector<pair<string,string> > mergedKeySettings = configKeys.getMergedProperties();
// Figure out the max # of tabs we need to format display nicely
int tabCount = 1;
for(int i = 0; i < (int)mergedMainSettings.size(); ++i) {
const pair<string,string> &nameValue = mergedMainSettings[i];
bool displayProperty = false;
if(filteredPropertyList.empty() == false) {
if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
displayProperty = true;
}
}
else {
displayProperty = true;
}
if(displayProperty == true) {
int requredTabs = ((int)nameValue.first.length() / 8)+1;
if(nameValue.first.length() % 8) {
requredTabs++;
}
if(requredTabs > tabCount) {
tabCount = requredTabs;
}
}
}
for(int i = 0; i < (int)mergedKeySettings.size(); ++i) {
const pair<string,string> &nameValue = mergedKeySettings[i];
bool displayProperty = false;
if(filteredPropertyList.empty() == false) {
if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
displayProperty = true;
}
}
else {
displayProperty = true;
}
if(displayProperty == true) {
int requredTabs = ((int)nameValue.first.length() / 8)+1;
if(nameValue.first.length() % 8) {
requredTabs++;
}
if(requredTabs > tabCount) {
tabCount = requredTabs;
}
}
}
// Output the properties
for(int i = 0; i < (int)mergedMainSettings.size(); ++i) {
const pair<string,string> &nameValue = mergedMainSettings[i];
bool displayProperty = false;
if(filteredPropertyList.empty() == false) {
if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
displayProperty = true;
}
}
else {
displayProperty = true;
}
if(displayProperty == true) {
printf("Property Name [%s]",nameValue.first.c_str());
int tabs = ((int)nameValue.first.length() / 8) + 1;
for(int j = 0; j < (tabCount - tabs); ++j) {
printf("\t");
}
string displayValue = nameValue.second;
if(nameValue.first == "TranslationGetURLPassword") {
displayValue = "*****";
}
printf("Value [%s]\n",displayValue.c_str());
}
}
printf("\n\nMain key binding settings report\n");
printf("====================================\n");
for(int i = 0; i < (int)mergedKeySettings.size(); ++i) {
const pair<string,string> &nameValue = mergedKeySettings[i];
bool displayProperty = false;
if(filteredPropertyList.empty() == false) {
if(find(filteredPropertyList.begin(),filteredPropertyList.end(),nameValue.first) != filteredPropertyList.end()) {
displayProperty = true;
}
}
else {
displayProperty = true;
}
if(displayProperty == true) {
printf("Property Name [%s]",nameValue.first.c_str());
int tabs = ((int)nameValue.first.length() / 8) + 1;
for(int j = 0; j < (tabCount - tabs); ++j) {
printf("\t");
}
printf("Value [%s]\n",nameValue.second.c_str());
}
}
}
}
Steam & initSteamInstance() {
Steam *&steamInstance = CacheManager::getCachedItem< Steam *>(GameConstants::steamCacheInstanceKey);
if(steamInstance == NULL) {
steamInstance = new Steam();
}
return *steamInstance;
}
void setupSteamSettings(bool steamEnabled, bool steamResetStats, bool debugEnabled) {
Config &config = Config::getInstance();
config.setBool("SteamEnabled",steamEnabled,true);
if(steamEnabled) {
printf("*NOTE: Steam Integration Enabled.\n");
if(debugEnabled) {
printf("*NOTE: Steam Debugging Enabled.\n");
}
Steam::setDebugEnabled(debugEnabled);
Steam &steam = initSteamInstance();
// For Debugging purposes:
if(steamResetStats) {
printf("*WARNING: Steam Stats / Achievements are being RESET by request!\n");
steam.resetStats(true);
}
string steamPlayerName = steam.userName();
string steamLang = steam.lang();
printf("Steam Integration Enabled!\nSteam User Name is [%s] Language is [%s]\n", steamPlayerName.c_str(), steamLang.c_str());
bool needToSaveConfig=false;
string currentPLayerName = config.getString("NetPlayerName","");
if( currentPLayerName == "newbie" || currentPLayerName == "" ) {
config.setString("NetPlayerName",steamPlayerName);
needToSaveConfig=true;
}
if( needToSaveConfig == true ) {
config.save();
}
}
}
void CheckForDuplicateData() {
Config &config = Config::getInstance();
string duplicateWarnings="";
try {
{
string scenarioDir = "";
vector<string> pathList = config.getPathListForType(ptMaps,scenarioDir);
vector<string> invalidMapList;
vector<string> maps = MapPreview::findAllValidMaps(pathList,scenarioDir,false,true,&invalidMapList);
std::sort(maps.begin(),maps.end());
if(maps.empty() == true) {
throw megaglest_runtime_error("No maps were found!",true);
}
else if(invalidMapList.empty() == false) {
string errorMsg = "Warning invalid maps were detected (will be ignored):\n";
for(int i = 0; i < (int)invalidMapList.size(); ++i) {
char szBuf[8096]="";
snprintf(szBuf,8096,"map [%s]\n",invalidMapList[i].c_str());
errorMsg += szBuf;
}
duplicateWarnings += errorMsg;
}
vector<string> duplicateMapsToRename;
for(int i = 0; i < (int)maps.size(); ++i) {
string map1 = maps[i];
for(int j = 0; j < (int)maps.size(); ++j) {
if(i != j) {
string map2 = maps[j];
if(map1 == map2) {
if(std::find(duplicateMapsToRename.begin(),duplicateMapsToRename.end(),map1) == duplicateMapsToRename.end()) {
duplicateMapsToRename.push_back(map1);
}
}
}
}
}
if(duplicateMapsToRename.empty() == false) {
string errorMsg = "Warning duplicate maps were detected and renamed:\n";
for(int i = 0; i < (int)duplicateMapsToRename.size(); ++i) {
string currentPath = pathList[1];
endPathWithSlash(currentPath);
string oldFile = currentPath + duplicateMapsToRename[i];
string newFile = currentPath + duplicateMapsToRename[i];
string ext = extractExtension(newFile);
newFile = newFile.substr( 0, newFile.length()-ext.length()-1);
newFile = newFile + "_custom." + ext;
char szBuf[8096]="";
int result = rename(oldFile.c_str(),newFile.c_str());
if(result != 0) {
char *errmsg = strerror(errno);
snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
throw megaglest_runtime_error(szBuf,true);
}
else {
snprintf(szBuf,8096,"map [%s] in [%s]\nwas renamed to [%s]",duplicateMapsToRename[i].c_str(),oldFile.c_str(),newFile.c_str());
}
errorMsg += szBuf;
}
duplicateWarnings += errorMsg;
}
}
{
//tilesets
std::vector<std::string> tileSets;
vector<string> tilesetPaths = config.getPathListForType(ptTilesets);
findDirs(tilesetPaths, tileSets, false, true);
if (tileSets.empty()) {
throw megaglest_runtime_error("No tilesets were found!",true);
}
vector<string> duplicateTilesetsToRename;
for(int i = 0; i < (int)tileSets.size(); ++i) {
string tileSet1 = tileSets[i];
for(int j = 0; j < (int)tileSets.size(); ++j) {
if(i != j) {
string tileSet2= tileSets[j];
if(tileSet1 == tileSet2) {
if(std::find(duplicateTilesetsToRename.begin(),duplicateTilesetsToRename.end(),tileSet1) == duplicateTilesetsToRename.end()) {
duplicateTilesetsToRename.push_back(tileSet1);
}
}
}
}
}
if(duplicateTilesetsToRename.empty() == false) {
string errorMsg = "Warning duplicate tilesets were detected and renamed:\n";
for(int i = 0; i < (int)duplicateTilesetsToRename.size(); ++i) {
string currentPath = tilesetPaths[1];
endPathWithSlash(currentPath);
string oldFile = currentPath + duplicateTilesetsToRename[i];
string newFile = currentPath + duplicateTilesetsToRename[i];
newFile = newFile + "_custom";
char szBuf[8096]="";
int result = rename(oldFile.c_str(),newFile.c_str());
if(result != 0) {
char *errmsg = strerror(errno);
snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
throw megaglest_runtime_error(szBuf,true);
}
else {
snprintf(szBuf,8096,"tileset [%s] in [%s]\nwas renamed to [%s]",duplicateTilesetsToRename[i].c_str(),oldFile.c_str(),newFile.c_str());
string tilesetName = extractFileFromDirectoryPath(oldFile);
oldFile = newFile + "/" + tilesetName + ".xml";
newFile = newFile + "/" + tilesetName + "_custom.xml";
result = rename(oldFile.c_str(),newFile.c_str());
if(result != 0) {
char *errmsg = strerror(errno);
snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
throw megaglest_runtime_error(szBuf,true);
}
}
errorMsg += szBuf;
}
duplicateWarnings += errorMsg;
}
}
{
vector<string> techPaths = config.getPathListForType(ptTechs);
vector<string> techTrees;
findDirs(techPaths, techTrees, false, true);
if(techTrees.empty()) {
throw megaglest_runtime_error("No tech-trees were found (dup)!",true);
}
vector<string> duplicateTechtreesToRename;
for(int i = 0; i < (int)techTrees.size(); ++i) {
string techtree1 = techTrees[i];
for(int j = 0; j < (int)techTrees.size(); ++j) {
if(i != j) {
string techtree2 = techTrees[j];
if(techtree1 == techtree2) {
if(std::find(duplicateTechtreesToRename.begin(),duplicateTechtreesToRename.end(),techtree1) == duplicateTechtreesToRename.end()) {
duplicateTechtreesToRename.push_back(techtree1);
}
}
}
}
}
if(duplicateTechtreesToRename.empty() == false) {
string errorMsg = "Warning duplicate techtrees were detected and renamed:\n";
for(int i = 0; i < (int)duplicateTechtreesToRename.size(); ++i) {
string currentPath = techPaths[1];
endPathWithSlash(currentPath);
string oldFile = currentPath + duplicateTechtreesToRename[i];
string newFile = currentPath + duplicateTechtreesToRename[i];
newFile = newFile + "_custom";
char szBuf[8096]="";
int result = rename(oldFile.c_str(),newFile.c_str());
if(result != 0) {
char *errmsg = strerror(errno);
snprintf(szBuf,8096,"Error [%s]\nCould not rename [%s] to [%s]!",errmsg,oldFile.c_str(),newFile.c_str());
throw megaglest_runtime_error(szBuf,true);
}
else {
snprintf(szBuf,8096,"techtree [%s] in [%s]\nwas renamed to [%s]",duplicateTechtreesToRename[i].c_str(),oldFile.c_str(),newFile.c_str());
string tilesetName = extractFileFromDirectoryPath(oldFile);
oldFile = newFile + "/" + tilesetName + ".xml";
newFile = newFile + "/" + tilesetName + "_custom.xml";
int rename_result = rename(oldFile.c_str(),newFile.c_str());
if(rename_result != 0) {
printf("Error renaming [%s] to [%s]\n",oldFile.c_str(),newFile.c_str());
}
}
errorMsg += szBuf;
}
duplicateWarnings += errorMsg;
}
}
}
catch(const megaglest_runtime_error &ex) {
if(mainProgram) {
mainProgram->getState()->setForceMouseRender(true);
}
ExceptionHandler::DisplayMessage(ex.what(), false);
}
if(duplicateWarnings != "") {
if(mainProgram) {
mainProgram->getState()->setForceMouseRender(true);
}
ExceptionHandler::DisplayMessage(duplicateWarnings.c_str(), false);
}
}
int handleCreateDataArchivesCommand(int argc, char** argv) {
int return_value = 1;
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string compress_item = paramPartTokens[1];
bool includeMainData = false;
if(paramPartTokens.size() >= 3 && paramPartTokens[2] == "include_main") {
includeMainData = true;
}
Config &config = Config::getInstance();
string fileArchiveExtension = config.getString("FileArchiveExtension","");
string fileArchiveCompressCommand = config.getString("FileArchiveCompressCommand","");
string fileArchiveCompressCommandParameters = config.getString("FileArchiveCompressCommandParameters","");
int32 fileArchiveCompressCommandSuccessResult = config.getInt("FileArchiveCompressCommandSuccessResult","0");
string userData = config.getString("UserData_Root","");
if(userData != "") {
endPathWithSlash(userData);
}
int typesSelected = 0;
if(compress_item == "techtrees" || compress_item == "all") {
typesSelected++;
vector<string> pathList = config.getPathListForType(ptTechs,"");
vector<string> results;
findDirs(pathList, results);
printf("Techtrees found:\n===========================================\n");
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
for(unsigned int j = 0; j < pathList.size(); ++j) {
string techPath = pathList[j];
if(techPath != "") {
endPathWithSlash(techPath);
}
vector<string> results2;
findDirs(techPath + name + "/factions", results2, false,true);
if(results2.empty() == false) {
string techtreePath = techPath + name;
if(includeMainData == false) {
if(techtreePath.find(userData) == techPath.npos) {
printf("Skipping techtree: [%s]\n",techtreePath.c_str());
continue;
}
}
string downloadArchive = techtreePath + fileArchiveExtension;
if(fileExists(downloadArchive) == true) {
bool removed = removeFile(downloadArchive);
if(removed == false) {
printf("Error could not remove old file: [%s]\n",downloadArchive.c_str());
}
}
string compressCmd = getFullFileArchiveCompressCommand(
fileArchiveCompressCommand,
fileArchiveCompressCommandParameters,
downloadArchive,techtreePath );
printf("Running compression command: %s\n",compressCmd.c_str());
if(executeShellCommand(compressCmd,fileArchiveCompressCommandSuccessResult) == false) {
printf("Error could not create new file: [%s]\n",downloadArchive.c_str());
}
if(fileExists(downloadArchive) == true) {
off_t fileSize = getFileSize(downloadArchive);
// convert to MB
double megaBytes = ((double)fileSize / 1048576.0);
printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
}
}
}
}
printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
}
if(compress_item == "tilesets" || compress_item == "all") {
typesSelected++;
vector<string> pathList = config.getPathListForType(ptTilesets,"");
vector<string> results;
findDirs(pathList, results);
printf("Tilesets found:\n===========================================\n");
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
for(unsigned int j = 0; j < pathList.size(); ++j) {
string tilesetPath = pathList[j];
if(tilesetPath != "") {
endPathWithSlash(tilesetPath);
}
if(fileExists(tilesetPath + name + "/" + name + ".xml") == true) {
string tilesetDataPath = tilesetPath + name;
if(includeMainData == false) {
if(tilesetPath.find(userData) == tilesetPath.npos) {
printf("Skipping tileset data: [%s]\n",tilesetDataPath.c_str());
continue;
}
}
string downloadArchive = tilesetDataPath + fileArchiveExtension;
if(fileExists(downloadArchive) == true) {
bool removed = removeFile(downloadArchive);
if(removed == false) {
printf("Error could not remove old file: [%s]\n",downloadArchive.c_str());
}
}
string compressCmd = getFullFileArchiveCompressCommand(
fileArchiveCompressCommand,
fileArchiveCompressCommandParameters,
downloadArchive,tilesetDataPath );
printf("Running compression command: %s\n",compressCmd.c_str());
if(executeShellCommand(compressCmd,fileArchiveCompressCommandSuccessResult) == false) {
printf("Error could not create new file: [%s]\n",downloadArchive.c_str());
}
if(fileExists(downloadArchive) == true) {
off_t fileSize = getFileSize(downloadArchive);
// convert to MB
double megaBytes = ((double)fileSize / 1048576.0);
printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
}
break;
}
}
}
printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
}
if(typesSelected == 0) {
printf("Compress item [%s] is not valid!\n",compress_item.c_str());
return_value = 1;
}
else
return_value = 0;
}
else {
printf("\nInvalid missing map specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return_value = 1;
}
}
return return_value;
}
int handleShowCRCValuesCommand(int argc, char** argv) {
int return_value = 1;
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemName = paramPartTokens[1];
string file = Config::getMapPath(itemName,"",false);
if(file != "") {
Checksum checksum;
checksum.addFile(file);
uint32 crcValue = checksum.getSum();
printf("CRC value for map [%s] file [%s] is [%u]\n",itemName.c_str(),file.c_str(),crcValue);
return_value = 0;
}
else {
printf("Map [%s] was NOT FOUND\n",itemName.c_str());
return_value = 1;
}
}
else {
printf("\nInvalid missing map specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return_value = 1;
}
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemName = paramPartTokens[1];
Config &config = Config::getInstance();
uint32 crcValue = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,""), string("/") + itemName + string("/*"), ".xml", NULL, true);
if(crcValue != 0) {
printf("CRC value for tileset [%s] is [%u]\n",itemName.c_str(),crcValue);
return_value = 0;
}
else {
printf("Tileset [%s] was NOT FOUND\n",itemName.c_str());
return_value = 1;
}
}
else {
printf("\nInvalid missing tileset specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return_value = 1;
}
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemName = paramPartTokens[1];
Config &config = Config::getInstance();
uint32 crcValue = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,""), "/" + itemName + "/*", ".xml", NULL, true);
if(crcValue != 0) {
printf("CRC value for techtree [%s] is [%u]\n",itemName.c_str(),crcValue);
return_value = 0;
}
else {
printf("Techtree [%s] was NOT FOUND\n",itemName.c_str());
return_value = 1;
}
}
else {
printf("\nInvalid missing techtree specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return_value = 1;
}
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemName = paramPartTokens[1];
Config &config = Config::getInstance();
uint32 crcValue = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptScenarios,""), "/" + itemName + "/*", ".xml", NULL, true);
if(crcValue != 0) {
printf("CRC value for scenario [%s] is [%u]\n",itemName.c_str(),crcValue);
return_value = 0;
}
else {
printf("Scenario [%s] was NOT FOUND\n",itemName.c_str());
return_value = 1;
}
}
else {
printf("\nInvalid missing scenario specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return_value = 0;
}
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 3 && paramPartTokens[1].length() > 0) {
string itemName = paramPartTokens[1];
string itemNameFilter = paramPartTokens[2];
uint32 crcValue = getFolderTreeContentsCheckSumRecursively(itemName, itemNameFilter, NULL, true);
printf("CRC value for path [%s] filter [%s] is [%u]\n",itemName.c_str(),itemNameFilter.c_str(),crcValue);
return_value = 0;
}
else {
if(paramPartTokens.size() < 2) {
printf("\nInvalid missing path and filter specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
}
if(paramPartTokens.size() < 3) {
printf("\nInvalid missing filter specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 3 ? paramPartTokens[2].c_str() : NULL));
}
return_value = 1;
}
}
return return_value;
}
int handleListDataCommand(int argc, char** argv) {
int return_value = 1;
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_MAPS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_MAPS]),&foundParamIndIndex);
}
Config &config = Config::getInstance();
vector<string> pathList = config.getPathListForType(ptMaps,"");
vector<string> maps = MapPreview::findAllValidMaps(pathList,"",false,true);
std::sort(maps.begin(),maps.end());
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemNameFilter = paramPartTokens[1];
printf("Using filter for maps list [%s]\n",itemNameFilter.c_str());
vector<string> filteredMaps;
for(unsigned int i = 0; i < maps.size(); ++i) {
string mapName = maps[i];
if(itemNameFilter.find("*") != itemNameFilter.npos) {
if(StartsWith(mapName, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
filteredMaps.push_back(mapName);
}
}
else if(mapName == itemNameFilter) {
filteredMaps.push_back(mapName);
}
}
maps = filteredMaps;
}
printf("Maps found:\n===========================================\n");
for(unsigned int i = 0; i < maps.size(); ++i) {
string mapName = maps[i];
printf("%s\n",mapName.c_str());
}
printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",maps.size());
return_value = 0;
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TECHTRESS]),&foundParamIndIndex);
}
Config &config = Config::getInstance();
vector<string> pathList = config.getPathListForType(ptTechs,"");
vector<string> results;
findDirs(pathList, results);
bool showfactions=false;
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string cmd = paramPartTokens[1];
if(cmd == "showfactions") {
showfactions = true;
}
else {
throw megaglest_runtime_error("unknown command for techtreelist [" + cmd + "]");
}
printf("Using special command for techtree list [%s]\n",cmd.c_str());
}
printf("Techtrees found:\n===========================================\n");
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
for(unsigned int j = 0; j < pathList.size(); ++j) {
string techPath = pathList[j];
if(techPath != "") {
endPathWithSlash(techPath);
}
vector<string> results2;
findDirs(techPath + name + "/factions", results2, false,true);
if(results2.empty() == false) {
string downloadArchive = techPath + name + ".7z";
if(fileExists(downloadArchive) == true) {
off_t fileSize = getFileSize(downloadArchive);
// convert to MB
double megaBytes = ((double)fileSize / 1048576.0);
printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
}
else {
printf("%s\n",name.c_str());
}
if(showfactions == true) {
printf("--> Factions:\n");
for(unsigned int k = 0; k < results2.size(); ++k) {
string name2 = results2[k];
printf("--> %s\n",name2.c_str());
}
printf("--> Total Factions: " MG_SIZE_T_SPECIFIER "\n",results2.size());
break;
}
}
}
}
printf("===========================================\nTotal Techtrees: " MG_SIZE_T_SPECIFIER "\n",results.size());
return_value = 0;
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_SCENARIOS]),&foundParamIndIndex);
}
Config &config = Config::getInstance();
vector<string> pathList = config.getPathListForType(ptScenarios,"");
vector<string> results;
findDirs(pathList, results);
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemNameFilter = paramPartTokens[1];
printf("Using filter for scenarios list [%s]\n",itemNameFilter.c_str());
vector<string> filtered;
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
if(itemNameFilter.find("*") != itemNameFilter.npos) {
if(StartsWith(name, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
filtered.push_back(name);
}
}
else if(name == itemNameFilter) {
filtered.push_back(name);
}
}
results = filtered;
}
printf("Scenarios found:\n===========================================\n");
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
printf("%s\n",name.c_str());
}
printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
return_value = 0;
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TILESETS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TILESETS]),&foundParamIndIndex);
}
Config &config = Config::getInstance();
vector<string> pathList = config.getPathListForType(ptTilesets,"");
vector<string> results;
findDirs(pathList, results);
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemNameFilter = paramPartTokens[1];
printf("Using filter for tilesets list [%s]\n",itemNameFilter.c_str());
vector<string> filtered;
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
if(itemNameFilter.find("*") != itemNameFilter.npos) {
if(StartsWith(name, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
filtered.push_back(name);
}
}
else if(name == itemNameFilter) {
filtered.push_back(name);
}
}
results = filtered;
}
printf("Tilesets found:\n===========================================\n");
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
for(unsigned int j = 0; j < pathList.size(); ++j) {
string tilesetPath = pathList[j];
if(tilesetPath != "") {
endPathWithSlash(tilesetPath);
}
if(fileExists(tilesetPath + name + "/" + name + ".xml") == true) {
string downloadArchive = tilesetPath + name + ".7z";
if(fileExists(downloadArchive) == true) {
off_t fileSize = getFileSize(downloadArchive);
// convert to MB
double megaBytes = ((double)fileSize / 1048576.0);
printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
}
else {
printf("%s\n",name.c_str());
}
break;
}
}
}
printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
return_value = 0;
}
else if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LIST_TUTORIALS]),&foundParamIndIndex);
}
Config &config = Config::getInstance();
vector<string> pathList = config.getPathListForType(ptTutorials,"");
vector<string> results;
findDirs(pathList, results);
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string itemNameFilter = paramPartTokens[1];
printf("Using filter for tutorials list [%s]\n",itemNameFilter.c_str());
vector<string> filtered;
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
if(itemNameFilter.find("*") != itemNameFilter.npos) {
if(StartsWith(name, itemNameFilter.substr(0,itemNameFilter.find("*"))) == true) {
filtered.push_back(name);
}
}
else if(name == itemNameFilter) {
filtered.push_back(name);
}
}
results = filtered;
}
printf("Tutorials found:\n===========================================\n");
for(unsigned int i = 0; i < results.size(); ++i) {
string name = results[i];
for(unsigned int j = 0; j < pathList.size(); ++j) {
string tutorialsPath = pathList[j];
if(tutorialsPath != "") {
endPathWithSlash(tutorialsPath);
}
if(fileExists(tutorialsPath + name + "/" + name + ".xml") == true) {
string downloadArchive = tutorialsPath + name + ".7z";
if(fileExists(downloadArchive) == true) {
off_t fileSize = getFileSize(downloadArchive);
// convert to MB
double megaBytes = ((double)fileSize / 1048576.0);
printf("%s [download archive %.2fMB]\n",name.c_str(),megaBytes);
}
else {
printf("%s\n",name.c_str());
}
break;
}
}
}
printf("===========================================\nTotal: " MG_SIZE_T_SPECIFIER "\n",results.size());
return_value = 0;
}
return return_value;
}
int glestMain(int argc, char** argv) {
#ifdef SL_LEAK_DUMP
//AllocInfo::set_application_binary(executable_path(argv[0],true));
string &app = AllocInfo::get_application_binary();
app = executable_path(argv[0],true);
//want_full_leak_stacktrace = true;
//want_full_leak_stacktrace_line_numbers = true;
#endif
Thread::setMainThreadId();
// printf("START ALLOC char 200\n");
//char *ptr = new char[200];
// printf("END ALLOC char 200\n");
// return -1;
SystemFlags::VERBOSE_MODE_ENABLED = false;
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERBOSE_MODE]) == true) {
SystemFlags::VERBOSE_MODE_ENABLED = true;
Thread::setEnableVerboseMode(true);
//LuaScript::setDebugModeEnabled(true);
}
// DEbug testing threads
//Thread::setEnableVerboseMode(true);
PlatformExceptionHandler::application_binary= executable_path(argv[0],true);
mg_app_name = GameConstants::application_name;
mailStringSupport = mailString;
SystemFlags::ENABLE_THREADED_LOGGING = false;
disableBacktrace = false;
bool foundInvalidArgs = false;
preCacheThread=NULL;
Properties::setApplicationPath(executable_path(argv[0]));
Properties::setApplicationDataPath(executable_path(argv[0]));
Properties::setGameVersion(glestVersionString);
ServerSocket::setMaxPlayerCount(GameConstants::maxPlayers);
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_BACKTRACE]) == true) {
disableBacktrace = true;
}
PlatformExceptionHandler::disableBacktrace= disableBacktrace;
#if defined(CUSTOM_DATA_INSTALL_PATH)
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n\nCUSTOM_DATA_INSTALL_PATH = [%s]\n\n",formatPath(TOSTRING(CUSTOM_DATA_INSTALL_PATH)).c_str());
#endif
const int knownArgCount = sizeof(GAME_ARGS) / sizeof(GAME_ARGS[0]);
for(int idx = 1; idx < argc; ++idx) {
if( hasCommandArgument(knownArgCount, (char **)&GAME_ARGS[0], argv[idx], NULL, 0, true) == false) {
foundInvalidArgs = true;
printf("\nInvalid argument: %s",argv[idx]);
}
}
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_HELP]) == true ||
foundInvalidArgs == true) {
printParameterHelp(argv[0],foundInvalidArgs);
return 2;
}
if( hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
//isMasterServerModeEnabled = true;
//Window::setMasterserverMode(isMasterServerModeEnabled);
GlobalStaticFlags::setIsNonGraphicalModeEnabled(true);
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string headless_command_list = paramPartTokens[1];
vector<string> paramHeadlessCommandList;
Tokenize(headless_command_list,paramHeadlessCommandList,",");
for(unsigned int i = 0; i < paramHeadlessCommandList.size(); ++i) {
string headless_command = paramHeadlessCommandList[i];
if(headless_command == "exit") {
printf("Forcing quit after game has completed [%s]\n",headless_command.c_str());
Program::setWantShutdownApplicationAfterGame(true);
}
else if(headless_command == "vps") {
printf("Disabled reading from console [%s]\n",headless_command.c_str());
disableheadless_console = true;
}
else if(headless_command == "lan") {
printf("Forcing local LAN mode [%s]\n",headless_command.c_str());
GlobalStaticFlags::setFlag(gsft_lan_mode);
}
}
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SERVER_TITLE]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SERVER_TITLE]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SERVER_TITLE]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
Config &config = Config::getInstance();
string serverTitle = paramPartTokens[1];
printf("Forcing serverTitle[%s]\n",serverTitle.c_str());
config.setString("ServerTitle",serverTitle,true);
}
else {
printf("\nInvalid missing server title specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
//#ifdef WIN32
//SocketManager winSockManager;
//#endif
bool haveSpecialOutputCommandLineOption = false;
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
haveSpecialOutputCommandLineOption = true;
}
if( haveSpecialOutputCommandLineOption == false ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true) {
printf("%s %s",extractFileFromDirectoryPath(argv[0]).c_str(),getNetworkPlatformFreeVersionString().c_str());
// 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"));
printf("\nCompiled using: %s platform: %s endianness: %s",getCompilerNameString().c_str(),getPlatformNameString().c_str(),(::Shared::PlatformByteOrder::isBigEndian() == true ? "big" : "little"));
// 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));
//
// Config::getInstance().setBool("DebugNetworkPackets",true,true);
// NetworkMessageIntro data(424336, "mg_version_x","player_x", 3, nmgstOk,444444, 555555, "english");
// unsigned char *buf = data.packMessage();
// printf("\nSend packet size = %u\n%s\n",data.getPackedSize(),data.toString().c_str());
// data.dump_packet("Send data", buf, data.getPackedSize());
// //delete [] buf;
//
// NetworkMessageIntro data2;
// data2.unpackMessage(buf);
// printf("\nReceive packet size = %u\n%s\n",data2.getPackedSize(),data2.toString().c_str());
// data2.dump_packet("nReceive data", buf, data2.getPackedSize());
// delete [] buf;
// SwitchSetupRequest data("factionname", 3,-1,2,"softcoder",10, 11,"eng");
//
// unsigned char *buf = data.packMessage();
// 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());
// //delete [] buf;
//
// data.unpackMessage(buf);
// 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());
// delete [] buf;
// int8 a = 1;
// uint8 b = 2;
// int16 c = 3;
// uint16 d = 4;
// int32 e = 5;
// uint32 f = 6;
//
// printf("\nPack test #1: [%d][%u][%d][%u][%d][%u]\n,",a,b,c,d,e,f);
//
// unsigned char *buf = new unsigned char[100];
// unsigned int packedsize = pack(buf, "cChHlL",
// a,
// b,
// c,
// d,
// e,
// f);
//
// printf("Pack test #2: [%u][%s]\n,",packedsize,buf);
//
// int8 a1 = 0;
// uint8 b1 = 0;
// int16 c1 = 0;
// uint16 d1 = 0;
// int32 e1 = 0;
// uint32 f1 = 0;
//
// unpack(buf, "cChHlL",
// &a1,
// &b1,
// &c1,
// &d1,
// &e1,
// &f1);
//
// printf("UnPack test #3: [%d][%u][%d][%u][%d][%u]\n,",a1,b1,c1,d1,e1,f1);
if(SystemFlags::VERBOSE_MODE_ENABLED == true) {
int8 testVar = 111;
printf("\nEndian value = %d",testVar);
testVar = ::Shared::PlatformByteOrder::toCommonEndian(testVar);
printf("\nEndian to common value = %d",testVar);
testVar = ::Shared::PlatformByteOrder::fromCommonEndian(testVar);
printf("\nEndian from common value = %d",testVar);
printf("\nint8 sizeof = " MG_SIZE_T_SPECIFIER "",sizeof(int8));
printf("\nSwitchSetupRequest sizeof = " MG_SIZE_T_SPECIFIER "",SwitchSetupRequest().getDataSize());
}
printf("\nGIT: [%s]",getGITRevisionString().c_str());
#ifdef USE_STREFLOP
#if defined(STREFLOP_SSE)
const char *instruction_set = "[SSE]";
#elif defined(STREFLOP_X87)
const char *instruction_set = "[X87]";
#elif defined(STREFLOP_SOFT)
const char *instruction_set = "[SOFTFLOAT]";
#else
const char *instruction_set = "[none]";
#endif
#if defined(STREFLOP_NO_DENORMALS)
const char *denormals = "[no-denormals]";
#else
const char *denormals = "[denormals]";
#endif
printf(" - using STREFLOP %s - %s\n",instruction_set,denormals);
#else
printf("\n");
#endif
}
setGameVersion(glestVersionString);
setGameGITVersion(getRAWGITRevisionString());
#ifdef WIN32
CheckPacketThrottling();
#endif
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
VideoPlayer::setDisabled(true);
}
//throw megaglest_runtime_error("Test!");
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true) {
SDL_version ver;
// Prints the compile time version
SDL_VERSION(&ver);
print_SDL_version("SDL compile-time version", &ver);
// Prints the run-time version
SDL_GetVersion(&ver);
print_SDL_version("SDL runtime version", &ver);
//const SDL_VideoInfo *vidInfo = SDL_GetVideoInfo();
//printf("Video card Memory: %u\n",vidInfo->video_mem);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true) {
printf("LUA version: %s\n", LUA_RELEASE);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true) {
curl_version_info_data *curlVersion= curl_version_info(CURLVERSION_NOW);
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));
if(curlVersion->protocols != NULL && curlVersion->protocols[0] != NULL) {
printf("protocols: ");
for(unsigned int i = 0; curlVersion->protocols != NULL && curlVersion->protocols[i] != NULL; ++i) {
printf("%s ", curlVersion->protocols[i]);
if(i > 0 && i % 10 == 0) {
printf("\n ");
}
}
printf("\n");
}
}
#if defined(WANT_XERCES)
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true) {
printf("XERCES version: %s\n", XERCES_FULLVERSIONDOT);
}
#endif
if( (hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VERSION]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SDL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CURL_INFO]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_XERCES_INFO]) == true) &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == false &&
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == false) {
return 0;
}
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MOD])) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MOD]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MOD]),&foundParamIndIndex);
}
string scenarioName = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(scenarioName,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string autoloadModName = paramPartTokens[1];
if(Properties::applyTagsToValue(autoloadModName) == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Property key [%s] now has value [%s]\n",Config::ACTIVE_MOD_PROPERTY_NAME,autoloadModName.c_str());
}
Config::setCustomRuntimeProperty(Config::ACTIVE_MOD_PROPERTY_NAME,autoloadModName);
printf("Setting mod active [%s]\n",autoloadModName.c_str());
}
else {
printf("\nInvalid mod pathname specified on commandline [%s] mod [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],foundInvalidArgs);
return 1;
}
}
SystemFlags::init(haveSpecialOutputCommandLineOption);
//SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled = true;
//SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled = true;
MainWindow *mainWindow= NULL;
Program *program= NULL;
ExceptionHandler exceptionHandler;
exceptionHandler.install( getCrashDumpFileName() );
int shutdownFadeSoundMilliseconds = 1000;
Chrono chronoshutdownFadeSound;
SimpleTaskThread *soundThreadManager = NULL;
try {
// Setup paths to game items (like data, logs, ini etc)
int setupResult = setupGameItemPaths(argc, argv, NULL);
if(setupResult != 0) {
return setupResult;
}
// Attempt to read ini files
Config &config = Config::getInstance();
setupGameItemPaths(argc, argv, &config);
setupSteamSettings(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_STEAM]),
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_STEAM_RESET_STATS]),
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_STEAM_DEBUG]));
if(config.getString("PlayerId","") == "") {
char uuid_str[38];
get_uuid_string(uuid_str,sizeof(uuid_str));
config.setString("PlayerId",uuid_str);
config.save();
}
//printf("Players UUID: [%s]\n",config.getString("PlayerId","").c_str());
if(config.getBool("DisableLuaSandbox","false") == true) {
LuaScript::setDisableSandbox(true);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DEBUG_NETWORK_PACKETS]) == true) {
printf("*NOTE: debugging network packets.\n");
config.setBool("DebugNetworkPackets",true,true);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DEBUG_NETWORK_PACKET_SIZES]) == true) {
printf("*NOTE: debugging network packet SIZES.\n");
config.setBool("DebugNetworkPacketSizes",true,true);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DEBUG_NETWORK_PACKET_STATS]) == true) {
printf("*NOTE: debugging network packet STATISTICS.\n");
config.setBool("DebugNetworkPacketStats",true,true);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_ENABLE_NEW_PROTOCOL]) == true) {
printf("*NOTE: enabling new network protocol.\n");
NetworkMessage::useOldProtocol = false;
}
Socket::setBroadCastPort(config.getInt("BroadcastPort",intToStr(Socket::getBroadCastPort()).c_str()));
Socket::disableNagle = config.getBool("DisableNagle","false");
if(Socket::disableNagle) {
printf("*WARNING users wants to disable the socket nagle algorithm.\n");
}
Socket::DEFAULT_SOCKET_SENDBUF_SIZE = config.getInt("DefaultSocketSendBufferSize",intToStr(Socket::DEFAULT_SOCKET_SENDBUF_SIZE).c_str());
if(Socket::DEFAULT_SOCKET_SENDBUF_SIZE >= 0) {
printf("*WARNING users wants to set default socket send buffer size to: %d\n",Socket::DEFAULT_SOCKET_SENDBUF_SIZE);
}
Socket::DEFAULT_SOCKET_RECVBUF_SIZE = config.getInt("DefaultSocketReceiveBufferSize",intToStr(Socket::DEFAULT_SOCKET_RECVBUF_SIZE).c_str());
if(Socket::DEFAULT_SOCKET_RECVBUF_SIZE >= 0) {
printf("*WARNING users wants to set default socket receive buffer size to: %d\n",Socket::DEFAULT_SOCKET_RECVBUF_SIZE);
}
shutdownFadeSoundMilliseconds = config.getInt("ShutdownFadeSoundMilliseconds",intToStr(shutdownFadeSoundMilliseconds).c_str());
string userData = config.getString("UserData_Root","");
if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
userData = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey);
}
if(userData != "") {
endPathWithSlash(userData);
}
string data_path_check = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
string userDataPath_check = getGameCustomCoreDataPath(data_path_check, "");
if(data_path_check == userDataPath_check) {
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());
throw megaglest_runtime_error("Regular and User data paths cannot have the same value [" + userDataPath_check + "]");
}
if(userData != "") {
if(isdir(userData.c_str()) == false) {
createDirectoryPaths(userData);
}
}
string crcCachePath = userData + "cache/";
if(isdir(crcCachePath.c_str()) == false) {
createDirectoryPaths(crcCachePath);
}
setCRCCacheFilePath(crcCachePath);
string savedGamePath = userData + "saved/";
if(isdir(savedGamePath.c_str()) == false) {
createDirectoryPaths(savedGamePath);
}
string tempDataPath = userData + "temp/";
tempDataLocation = tempDataPath;
if(isdir(tempDataPath.c_str()) == true) {
removeFolder(tempDataPath);
}
createDirectoryPaths(tempDataPath);
string binaryNameOld = Properties::getApplicationPath() + extractFileFromDirectoryPath(PlatformExceptionHandler::application_binary) + "__REMOVE";
if(fileExists(binaryNameOld)) {
removeFile(binaryNameOld);
}
string netInterfaces = config.getString("NetworkInterfaces","");
if(netInterfaces != "") {
//printf("Using network interfaces: %s\n",netInterfaces.c_str());
std::vector<std::string> intfList;
Tokenize(netInterfaces,intfList,",");
Socket::setIntfTypes(intfList);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_PORTS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_PORTS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_PORTS]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string portsToUse = paramPartTokens[1];
vector<string> paramPartPortsTokens;
Tokenize(portsToUse,paramPartPortsTokens,",");
if(paramPartPortsTokens.size() >= 2 && paramPartPortsTokens[1].length() > 0) {
int internalPort = strToInt(paramPartPortsTokens[0]);
int externalPort = strToInt(paramPartPortsTokens[1]);
printf("Forcing internal port# %d, external port# %d\n",internalPort,externalPort);
config.setInt("PortServer",internalPort,true);
config.setInt("PortExternal",externalPort,true);
config.setInt("FTPServerPort",internalPort+1,true);
if(paramPartPortsTokens.size() >= 3 && paramPartPortsTokens[2].length() > 0) {
int statusPort = strToInt(paramPartPortsTokens[2]);
printf("Forcing status port# %d\n",statusPort);
config.setInt("ServerAdminPort",statusPort,true);
}
}
else {
printf("\nInvalid ports specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
else {
printf("\nInvalid missing ports specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_STATUS])) == true) {
Ip ip("localhost");
int port = Config::getInstance().getInt("ServerAdminPort", intToStr(GameConstants::serverAdminPort).c_str());
ClientSocket clientSocket;
clientSocket.setBlock(false);
clientSocket.connect(ip, port);
if(clientSocket.isConnected() == true) {
clientSocket.setBlock(true);
char szBuf[8096]="";
clientSocket.receive(&szBuf[0],8095,false);
std::cout << szBuf << std::endl;
}
else {
std::cout << "Could not connect (possibly no clients connected) to host: " << ip.getString() << " port: " << port << std::endl;
}
return 0;
}
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_SOUND]) == true ||
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
config.setString("FactorySound","None",true);
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
//Logger::getInstance().setMasterserverMode(true);
//Model::setMasterserverMode(true);
//Shared::Sound::Sound::setMasterserverMode(true);
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_OPENGL_CAPS_CHECK]) == true ||
config.getBool("CheckGlCaps") == false) {
printf("**WARNING** disabling opengl capability checking...\n");
config.setBool("CheckGlCaps",false,true);
}
bool enableATIHacks = config.getBool("EnableATIHacks","false");
if(enableATIHacks == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**WARNING** Enabling ATI video card hacks\n");
TextureGl::setEnableATIHacks(enableATIHacks);
}
Renderer::renderText3DEnabled = config.getBool("Enable3DFontRendering",intToStr(Renderer::renderText3DEnabled).c_str());
if(config.getBool("EnableLegacyFonts","false") == true || hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_ENABLE_LEGACYFONTS]) == true) {
::Shared::Graphics::Font::forceLegacyFonts = true;
Renderer::renderText3DEnabled = false;
printf("**WARNING** Forcing Legacy Fonts Enabled\n");
}
else {
Renderer::renderText3DEnabled = config.getBool("Enable3DFontRendering",intToStr(Renderer::renderText3DEnabled).c_str());
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_RESOLUTION]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_RESOLUTION]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_RESOLUTION]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string settings = paramPartTokens[1];
printf("Forcing resolution [%s]\n",settings.c_str());
paramPartTokens.clear();
Tokenize(settings,paramPartTokens,"x");
if(paramPartTokens.size() >= 2) {
int newScreenWidth = strToInt(paramPartTokens[0]);
config.setInt("ScreenWidth",newScreenWidth,true);
int newScreenHeight = strToInt(paramPartTokens[1]);
config.setInt("ScreenHeight",newScreenHeight,true);
}
else {
printf("\nInvalid missing resolution settings specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
else {
printf("\nInvalid missing resolution setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_COLORBITS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_COLORBITS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_COLORBITS]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string settings = paramPartTokens[1];
printf("Forcing colorbits [%s]\n",settings.c_str());
int newColorBits = strToInt(settings);
config.setInt("ColorBits",newColorBits,true);
}
else {
printf("\nInvalid missing colorbits settings specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_DEPTHBITS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_DEPTHBITS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_DEPTHBITS]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string settings = paramPartTokens[1];
printf("Forcing depthbits [%s]\n",settings.c_str());
int newDepthBits = strToInt(settings);
config.setInt("DepthBits",newDepthBits,true);
}
else {
printf("\nInvalid missing depthbits setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_FULLSCREEN]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FULLSCREEN]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FULLSCREEN]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string settings = paramPartTokens[1];
printf("Forcing fullscreen [%s]\n",settings.c_str());
bool newFullScreenMode = strToBool(settings);
config.setBool("Windowed",!newFullScreenMode,true);
}
else {
printf("\nInvalid missing fullscreen setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SET_GAMMA]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SET_GAMMA]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_SET_GAMMA]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string settings = paramPartTokens[1];
printf("Forcing gamma [%s]\n",settings.c_str());
float newGammaValue = strToFloat(settings);
config.setFloat("GammaValue",newGammaValue,true);
}
else {
printf("\nInvalid missing gamma setting specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_VIDEOS]) == true) {
VideoPlayer::setDisabled(true);
}
else if(config.getBool("EnableVideos","true") == false) {
VideoPlayer::setDisabled(true);
}
// Set some statics based on ini entries
SystemFlags::ENABLE_THREADED_LOGGING = config.getBool("ThreadedLogging","true");
FontGl::setDefault_fontType(config.getString("DefaultFont",FontGl::getDefault_fontType().c_str()));
UPNP_Tools::isUPNP = !config.getBool("DisableUPNP","false");
Texture::useTextureCompression = config.getBool("EnableTextureCompression","false");
// 256 for English
// 30000 for Chinese
::Shared::Graphics::Font::charCount = config.getInt("FONT_CHARCOUNT",intToStr(::Shared::Graphics::Font::charCount).c_str());
::Shared::Graphics::Font::fontTypeName = config.getString("FONT_TYPENAME",::Shared::Graphics::Font::fontTypeName.c_str());
::Shared::Graphics::Font::fontIsMultibyte = config.getBool("FONT_MULTIBYTE",intToStr(::Shared::Graphics::Font::fontIsMultibyte).c_str());
::Shared::Graphics::Font::fontIsRightToLeft = config.getBool("FONT_RIGHTTOLEFT",intToStr(::Shared::Graphics::Font::fontIsRightToLeft).c_str());
::Shared::Graphics::Font::baseSize = config.getInt("FONT_BASE_SIZE",intToStr(::Shared::Graphics::Font::baseSize).c_str());
::Shared::Graphics::Font::scaleFontValue = config.getFloat("FONT_SCALE_SIZE",floatToStr(::Shared::Graphics::Font::scaleFontValue).c_str());
::Shared::Graphics::Font::scaleFontValueCenterHFactor = config.getFloat("FONT_SCALE_CENTERH_FACTOR",floatToStr(::Shared::Graphics::Font::scaleFontValueCenterHFactor).c_str());
::Shared::Graphics::Font::langHeightText = config.getString("FONT_HEIGHT_TEXT",::Shared::Graphics::Font::langHeightText.c_str());
::Shared::Graphics::Font::fontSupportMixedRightToLeft = config.getBool("FONT_RIGHTTOLEFT_MIXED_SUPPORT",intToStr(::Shared::Graphics::Font::fontSupportMixedRightToLeft).c_str());
// Example values:
// DEFAULT_CHARSET (English) = 1
// GB2312_CHARSET (Chinese) = 134
::Shared::Platform::PlatformContextGl::charSet = config.getInt("FONT_CHARSET",intToStr(::Shared::Platform::PlatformContextGl::charSet).c_str());
if(config.getBool("No2DMouseRendering","false") == false) {
showCursor(false);
//showWindowCursorState = false;
}
if(config.getInt("DEFAULT_HTTP_TIMEOUT",intToStr(SystemFlags::DEFAULT_HTTP_TIMEOUT).c_str()) >= 0) {
SystemFlags::DEFAULT_HTTP_TIMEOUT = config.getInt("DEFAULT_HTTP_TIMEOUT",intToStr(SystemFlags::DEFAULT_HTTP_TIMEOUT).c_str());
}
bool allowAltEnterFullscreenToggle = config.getBool("AllowAltEnterFullscreenToggle",boolToStr(::Shared::Platform::Window::getAllowAltEnterFullscreenToggle()).c_str());
::Shared::Platform::Window::setAllowAltEnterFullscreenToggle(allowAltEnterFullscreenToggle);
if(config.getBool("noTeamColors","false") == true) {
MeshCallbackTeamColor::noTeamColors = true;
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LUA_DEBUG]) == true) {
printf("Forcing LUA debugging enabled!\n");
config.setBool("DebugLUA",true, true);
}
// Setup debug logging etc
setupLogging(config, haveSpecialOutputCommandLineOption);
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);
NetworkInterface::setDisplayMessageFunction(ExceptionHandler::DisplayMessage);
MenuStateMasterserver::setDisplayMessageFunction(ExceptionHandler::DisplayMessage);
#ifdef USE_STREFLOP
SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s, STREFLOP enabled.\n",getNetworkVersionString().c_str());
#else
SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s, STREFLOP NOT enabled.\n",getNetworkVersionString().c_str());
#endif
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"START\n");
SystemFlags::OutputDebug(SystemFlags::debugPathFinder,"START\n");
// Setup hotkeys from key ini files
Config &configKeys = Config::getInstance(
std::pair<ConfigType,ConfigType>(cfgMainKeys,cfgUserKeys),
std::pair<string,string>(Config::glestkeys_ini_filename,Config::glestuserkeys_ini_filename),
std::pair<bool,bool>(true,false),config.getString("GlestKeysIniPath",""));
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_INI_SETTINGS]) == true) {
ShowINISettings(argc,argv,config,configKeys);
return 0;
}
// Explicitly disable VBO's
if(config.getBool("DisableVBO","false") == true || hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_VBO]) == true) {
setVBOSupported(false);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**INFO** Disabling VBOs\n");
}
if(config.getBool("DisableVertexInterpolation","false") || hasCommandArgument(argc, argv, GAME_ARGS[GAME_ARG_DISABLE_VERTEX_INTERPOLATION])) {
InterpolationData::setEnableInterpolation(false);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**INFO** Disabling Interpolation\n");
}
if(config.getBool("EnableVSynch","false") == true) {
::Shared::Platform::Window::setTryVSynch(true);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**ENABLED OPENGL VSYNCH**\n");
}
//float pingTime = Socket::getAveragePingMS("soft-haus.com");
//printf("Ping time = %f\n",pingTime);
// Load the language strings
Lang &lang= Lang::getInstance();
string language = config.getString("Lang");
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_LANGUAGE]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_LANGUAGE]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_LANGUAGE]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
language = paramPartTokens[1];
printf("Forcing language [%s]\n",language.c_str());
}
else {
printf("\nInvalid missing language specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
else {
#ifdef _WIN32
int localeBufferSize = GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, NULL, 0);
wchar_t *sysLocale = new wchar_t[localeBufferSize];
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SISO639LANGNAME, sysLocale,localeBufferSize);
//String langValue(sysLocale);
//const char *lang_locale = langValue.c_str();
char langValue[1024]="";
wcstombs(langValue,sysLocale, 1023);
const char *lang_locale = &langValue[0];
delete [] sysLocale;
#else
const char *lang_locale = setlocale(LC_ALL,"");
#endif
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Locale is: [%s]\n", lang_locale);
if(lang_locale != NULL && strlen(lang_locale) >= 2) {
if(config.getBool("AutoLocaleLanguageDetect","true") == true) {
language = lang_locale;
language = language.substr(0,2);
printf("Auto setting language [%s]\n",language.c_str());
config.setString("AutoLocaleLanguageDetect","false");
config.save();
}
}
}
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST])) == true ||
Config::getInstance().getBool("AutoTest","false") == true) {
printf("Running in auto test mode\n");
}
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST])) == true) {
Config::getInstance().setBool("AutoTest",true,true);
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTO_TEST]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
vector<string> paramPartTokens2;
Tokenize(paramPartTokens[1],paramPartTokens2,",");
if(paramPartTokens2.empty() == false && paramPartTokens2[0].length() > 0) {
string newMaxSeconds = paramPartTokens2[0];
time_t newTimeMaxSeconds = strToInt(newMaxSeconds);
AutoTest::setMaxGameTime(newTimeMaxSeconds);
printf("Forcing maximum game time to [%ld] seconds (%.2f minutes)\n",(long int)newTimeMaxSeconds,((double)newTimeMaxSeconds / 60.0));
}
if(paramPartTokens2.size() >= 3 && paramPartTokens2[2].length() > 0) {
string autoTestCmd = paramPartTokens2[2];
if(autoTestCmd == "exit") {
printf("Detected auto test command [%s], will exit after game.\n",autoTestCmd.c_str());
AutoTest::setWantExitGameWhenDone(true);
}
else {
printf("WARNING: Detected and UNKNOWN auto test command [%s].\n",autoTestCmd.c_str());
}
}
if(paramPartTokens2.size() >= 2 && paramPartTokens2[1].length() > 0) {
string newGameSettingsFileToLoad = paramPartTokens2[1];
printf("About to auto test using game settings file [%s]\n",newGameSettingsFileToLoad.c_str());
AutoTest::setLoadGameSettingsFile(newGameSettingsFileToLoad);
}
}
}
Renderer &renderer= Renderer::getInstance();
lang.loadGameStrings(language,false, true);
if( lang.hasString("FONT_HEIGHT_TEXT")) {
::Shared::Graphics::Font::langHeightText = config.getString("FONT_HEIGHT_TEXT",::Shared::Graphics::Font::langHeightText.c_str());
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_FONT_BASESIZE]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_BASESIZE]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_FONT_BASESIZE]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string newfontBaseSize = paramPartTokens[1];
printf("Forcing font base size[%s]\n",newfontBaseSize.c_str());
::Shared::Graphics::Font::baseSize = strToInt(newfontBaseSize);
}
else {
printf("\nInvalid missing font base size specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
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);
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);
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_USE_FONT]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FONT]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_USE_FONT]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string newfont = paramPartTokens[1];
Properties::applyTagsToValue(newfont);
printf("Forcing font [%s]\n",newfont.c_str());
#if defined(WIN32)
string newEnvValue = "MEGAGLEST_FONT=" + newfont;
_putenv(newEnvValue.c_str());
#else
setenv("MEGAGLEST_FONT",newfont.c_str(),1);
#endif
}
else {
printf("\nInvalid missing font specified on commandline [%s] value [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
return 1;
}
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CREATE_DATA_ARCHIVES]) == true) {
return handleCreateDataArchivesCommand(argc, argv);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_MAP_CRC]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TILESET_CRC]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_TECHTREE_CRC]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_SCENARIO_CRC]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SHOW_PATH_CRC]) == true) {
return handleShowCRCValuesCommand(argc, argv);
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_MAPS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TECHTRESS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_SCENARIOS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TILESETS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_LIST_TUTORIALS]) == true) {
return handleListDataCommand(argc, argv);
}
program= new Program();
mainProgram = program;
renderer.setProgram(program);
if(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled == true) {
renderer.setAllowRenderUnitTitles(SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled);
SystemFlags::OutputDebug(SystemFlags::debugPathFinder,"In [%s::%s Line: %d] renderer.setAllowRenderUnitTitles = %d\n",__FILE__,__FUNCTION__,__LINE__,SystemFlags::getSystemSettingType(SystemFlags::debugPathFinder).enabled);
}
renderer.setAllowRenderUnitTitles(true);
string screenShotsPath = userData + GameConstants::folder_path_screenshots;
if(isdir(screenShotsPath.c_str()) == false) {
createDirectoryPaths(screenShotsPath);
}
// Cache Player textures - START
string data_path = getGameReadWritePath(GameConstants::path_data_CacheLookupKey);
std::map<int,Texture2D *> &crcPlayerTextureCache = CacheManager::getCachedItem< std::map<int,Texture2D *> >(GameConstants::playerTextureCacheLookupKey);
for(int index = 0; index < GameConstants::maxPlayers; ++index) {
string playerTexture = getGameCustomCoreDataPath(data_path, "data/core/faction_textures/faction" + intToStr(index) + ".tga");
if(fileExists(playerTexture) == true) {
Texture2D *texture = Renderer::getInstance().newTexture2D(rsGlobal);
if(texture) {
texture->load(playerTexture);
}
crcPlayerTextureCache[index] = texture;
}
else {
crcPlayerTextureCache[index] = NULL;
}
}
// Cache Player textures - END
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
mainWindow= new MainWindow(program);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
GameSettings startupGameSettings;
//parse command line
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_SERVER]) == true) {
program->initServer(mainWindow,false,true);
gameInitialized = true;
}
else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_MASTERSERVER_MODE])) == true) {
program->initServer(mainWindow,false,true,true);
gameInitialized = true;
}
else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LASTGAME])) == true) {
program->initServer(mainWindow,true,false);
gameInitialized = true;
}
else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LAST_SAVED_GAME])) == true) {
string fileName = "";
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_AUTOSTART_LAST_SAVED_GAME]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex >= 0) {
string loadfileName = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(loadfileName,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
fileName = paramPartTokens[1];
if(fileExists(fileName) == false) {
// Save the file now
string saveGameFile = "saved/" + fileName;
if(getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) != "") {
saveGameFile = getGameReadWritePath(GameConstants::path_logs_CacheLookupKey) + saveGameFile;
}
else {
saveGameFile = userData + saveGameFile;
}
if(fileExists(saveGameFile) == true) {
fileName = saveGameFile;
}
}
if(fileExists(fileName) == false) {
char szBuf[8096]="";
snprintf(szBuf,8096,"File specified for loading a saved game cannot be found: [%s]",fileName.c_str());
printf("\n\n======================================================================================\n%s\n======================================================================================\n\n\n",szBuf);
throw megaglest_runtime_error(szBuf);
}
}
}
program->initSavedGame(mainWindow,false,fileName);
gameInitialized = true;
}
else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP])) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_PREVIEW_MAP]),&foundParamIndIndex);
}
string mapName = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(mapName,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
vector<string> paramPartTokens2;
string tileset="forest";
Tokenize(paramPartTokens[1],paramPartTokens2,",");
if(paramPartTokens2.size() >= 2 && paramPartTokens2[1].length() > 0) {
tileset = paramPartTokens2[1];
}
string autoloadMapName = paramPartTokens2[0];
GameSettings *gameSettings = &startupGameSettings;
gameSettings->setMap(autoloadMapName);
gameSettings->setTileset(tileset);
gameSettings->setTech("megapack");
gameSettings->setDefaultUnits(false);
gameSettings->setDefaultResources(false);
gameSettings->setDefaultVictoryConditions(true);
gameSettings->setFogOfWar(false);
gameSettings->setAllowObservers(true);
gameSettings->setPathFinderType(pfBasic);
for(int i = 0; i < GameConstants::maxPlayers; ++i) {
ControlType ct= ctClosed;
gameSettings->setNetworkPlayerStatuses(i, npst_None);
gameSettings->setFactionControl(i, ct);
gameSettings->setStartLocationIndex(i, i);
gameSettings->setResourceMultiplierIndex(i, 10);
gameSettings->setNetworkPlayerName(i, GameConstants::NETWORK_SLOT_CLOSED_SLOTNAME);
}
ControlType ct= ctHuman;
gameSettings->setNetworkPlayerStatuses(0, npst_None);
gameSettings->setFactionControl(0, ct);
gameSettings->setFactionTypeName(0, formatString(GameConstants::OBSERVER_SLOTNAME));
gameSettings->setTeam(0, GameConstants::maxPlayers + fpt_Observer - 1);
gameSettings->setStartLocationIndex(0, 0);
gameSettings->setNetworkPlayerName(0, GameConstants::OBSERVER_SLOTNAME);
gameSettings->setFactionCount(1);
Config &config = Config::getInstance();
gameSettings->setEnableServerControlledAI(config.getBool("ServerControlledAI","true"));
gameSettings->setNetworkFramePeriod(config.getInt("NetworkSendFrameCount","20"));
program->initServer(mainWindow,gameSettings);
gameInitialized = true;
}
else {
printf("\nInvalid map name specified on commandline [%s] map [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],foundInvalidArgs);
delete mainWindow;
mainWindow=NULL;
return 1;
}
}
else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONNECT])) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONNECT]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONNECT]),&foundParamIndIndex);
}
string serverToConnectTo = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(serverToConnectTo,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string autoConnectServer = paramPartTokens[1];
int port = config.getInt("PortServer",intToStr(GameConstants::serverPort).c_str());
vector<string> paramPartTokens2;
Tokenize(autoConnectServer,paramPartTokens2,":");
autoConnectServer = paramPartTokens2[0];
if(paramPartTokens2.size() >= 2 && paramPartTokens2[1].length() > 0) {
port = strToInt(paramPartTokens2[1]);
}
printf("Connecting to host [%s] using port: %d\n",autoConnectServer.c_str(),port);
if(autoConnectServer == "auto-connect") {
program->initClientAutoFindHost(mainWindow);
}
else {
program->initClient(mainWindow, autoConnectServer,port);
}
gameInitialized = true;
}
else {
printf("\nInvalid host specified on commandline [%s] host [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],foundInvalidArgs);
delete mainWindow;
mainWindow=NULL;
return 1;
}
}
else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CLIENT])) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CLIENT]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CLIENT]),&foundParamIndIndex);
}
string serverToConnectTo = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(serverToConnectTo,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string autoConnectServer = paramPartTokens[1];
if(autoConnectServer == "auto-connect") {
program->initClientAutoFindHost(mainWindow);
}
else {
program->initClient(mainWindow, autoConnectServer);
}
gameInitialized = true;
}
else {
printf("\nInvalid host specified on commandline [%s] host [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],foundInvalidArgs);
delete mainWindow;
mainWindow=NULL;
return 1;
}
}
else if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOADSCENARIO])) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOADSCENARIO]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_LOADSCENARIO]),&foundParamIndIndex);
}
string scenarioName = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(scenarioName,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string autoloadScenarioName = paramPartTokens[1];
program->initScenario(mainWindow, autoloadScenarioName);
gameInitialized = true;
}
else {
printf("\nInvalid scenario name specified on commandline [%s] scenario [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],foundInvalidArgs);
delete mainWindow;
mainWindow=NULL;
return 1;
}
}
else {
program->initNormal(mainWindow);
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] OpenGL Info:\n%s\n",__FILE__,__FUNCTION__,__LINE__,renderer.getGlInfo().c_str());
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_OPENGL_INFO]) == true) {
printf("%s",renderer.getGlInfo().c_str());
printf("%s",renderer.getGlMoreInfo().c_str());
delete mainWindow;
mainWindow=NULL;
return 0;
}
if(hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_CONVERT_MODELS]) == true) {
int foundParamIndIndex = -1;
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONVERT_MODELS]) + string("="),&foundParamIndIndex);
if(foundParamIndIndex < 0) {
hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_CONVERT_MODELS]),&foundParamIndIndex);
}
string paramValue = argv[foundParamIndIndex];
vector<string> paramPartTokens;
Tokenize(paramValue,paramPartTokens,"=");
if(paramPartTokens.size() >= 2 && paramPartTokens[1].length() > 0) {
string modelFile = paramPartTokens[1];
printf("About to convert model(s) [%s]\n",modelFile.c_str());
string textureFormat = "";
if(paramPartTokens.size() >= 3 && paramPartTokens[1].length() > 0) {
textureFormat = paramPartTokens[2];
printf("About to convert using texture format [%s]\n",textureFormat.c_str());
}
bool keepsmallest = false;
if(paramPartTokens.size() >= 4 && paramPartTokens[1].length() > 0) {
keepsmallest = (paramPartTokens[3] == "keepsmallest");
printf("About to convert using keepsmallest = %d\n",keepsmallest);
}
showCursor(true);
const Metrics &metrics= Metrics::getInstance();
renderer.clearBuffers();
renderer.clearZBuffer();
renderer.reset2d();
if(CoreData::getInstance().getMenuFontBig3D() != NULL) {
renderer.renderText3D(
"Please wait, converting models...",
CoreData::getInstance().getMenuFontBig3D(),
Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
(metrics.getScreenH() / 2), true);
}
else {
renderer.renderText(
"Please wait, converting models...",
CoreData::getInstance().getMenuFontBig(),
Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
(metrics.getScreenH() / 2), true);
}
renderer.swapBuffers();
std::vector<string> models;
if(isdir(modelFile.c_str()) == true) {
models = getFolderTreeContentsListRecursively(modelFile, ".g3d");
}
else {
models.push_back(modelFile);
}
sleep(0);
::Shared::Platform::Window::handleEvent();
SDL_PumpEvents();
int result = 0;
char szTextBuf[8096]="";
for(unsigned int i =0; i < models.size(); ++i) {
string &file = models[i];
renderer.clearBuffers();
renderer.clearZBuffer();
renderer.reset2d();
snprintf(szTextBuf,8096,"Please wait, converting models [%u of " MG_SIZE_T_SPECIFIER "] ...",i,models.size());
if(CoreData::getInstance().getMenuFontBig3D() != NULL) {
renderer.renderText3D(
szTextBuf,
CoreData::getInstance().getMenuFontBig3D(),
Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
(metrics.getScreenH() / 2), true);
}
else {
renderer.renderText(
szTextBuf,
CoreData::getInstance().getMenuFontBig(),
Vec3f(1.f, 1.f, 0.f), (metrics.getScreenW() / 2) - 400,
(metrics.getScreenH() / 2), true);
}
renderer.swapBuffers();
sleep(0);
::Shared::Platform::Window::handleEvent();
SDL_PumpEvents();
try {
printf("About to load model [%s] [%u of " MG_SIZE_T_SPECIFIER "]\n",file.c_str(),i,models.size());
Model *model = renderer.newModel(rsGlobal, file);
printf("About to save converted model [%s]\n",file.c_str());
model->save(file,textureFormat,keepsmallest);
Renderer::getInstance().endModel(rsGlobal, model);
}
catch(const exception &ex) {
result = 1;
printf("ERROR loading model [%s] message [%s]\n",file.c_str(),ex.what());
}
}
delete mainWindow;
mainWindow=NULL;
return result;
}
else {
printf("\nInvalid model specified on commandline [%s] texture [%s]\n\n",argv[foundParamIndIndex],(paramPartTokens.size() >= 2 ? paramPartTokens[1].c_str() : NULL));
printParameterHelp(argv[0],foundInvalidArgs);
delete mainWindow;
mainWindow=NULL;
return 1;
}
}
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TECHTREES]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_FACTIONS]) == true ||
hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_SCENARIO]) == true) {
runTechValidationReport(argc, argv);
delete mainWindow;
mainWindow=NULL;
return 0;
}
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_TRANSLATE_TECHTREES]) == true) {
runTechTranslationExtraction(argc, argv);
delete mainWindow;
mainWindow=NULL;
return 0;
}
if( hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_VALIDATE_TILESET]) == true) {
runTilesetValidationReport(argc, argv);
delete mainWindow;
mainWindow=NULL;
return 0;
}
gameInitialized = true;
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
CheckForDuplicateData();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//throw "BLAH!";
// START Test out SIGSEGV error handling
//int *foo = (int*)-1; // make a bad pointer
//printf("%d\n", *foo); // causes segfault
// END
bool startCRCPrecacheThread = config.getBool("PreCacheCRCThread","true");
//printf("### In [%s::%s Line: %d] precache thread enabled = %d SystemFlags::VERBOSE_MODE_ENABLED = %d\n",__FILE__,__FUNCTION__,__LINE__,startCRCPrecacheThread,SystemFlags::VERBOSE_MODE_ENABLED);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] precache thread enabled = %d\n",__FILE__,__FUNCTION__,__LINE__,startCRCPrecacheThread);
if (startCRCPrecacheThread == true
&& GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
static string mutexOwnerId = string(extractFileFromDirectoryPath(__FILE__).c_str()) + string("_") + intToStr(__LINE__);
vector<string> techDataPaths = config.getPathListForType(ptTechs);
FileCRCPreCacheThread::setPreCacheThreadCacheLookupKey(GameConstants::preCacheThreadCacheLookupKey);
FileCRCPreCacheThread * &preCacheCRCThreadPtr = CacheManager::getCachedItem< FileCRCPreCacheThread * >(GameConstants::preCacheThreadCacheLookupKey);
if(preCacheCRCThreadPtr == NULL) {
preCacheCRCThreadPtr = new FileCRCPreCacheThread();
}
preCacheThread = preCacheCRCThreadPtr;
preCacheThread->setUniqueID(mutexOwnerId);
preCacheThread->setTechDataPaths(techDataPaths);
//preCacheThread->setFileCRCPreCacheThreadCallbackInterface(&preCacheThreadGame);
preCacheThread->start();
}
auto_ptr<NavtiveLanguageNameListCacheGenerator> lngCacheGen;
auto_ptr<SimpleTaskThread> languageCacheGen;
bool startNativeLanguageNamesPrecacheThread = config.getBool("PreCacheNativeLanguageNamesThread","true");
if(startNativeLanguageNamesPrecacheThread == true &&
GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
lngCacheGen.reset(new NavtiveLanguageNameListCacheGenerator());
languageCacheGen.reset(new SimpleTaskThread(lngCacheGen.get(),1));
languageCacheGen->start();
}
// test
//Shared::Platform::MessageBox(NULL,"Mark's test.","Test",0);
//throw megaglest_runtime_error("test!");
//ExceptionHandler::DisplayMessage("test!", false);
// Check for commands being input from stdin
string command="";
#ifndef WIN32
pollfd cinfd[1];
#else
HANDLE h = 0;
#endif
if(disableheadless_console == false) {
#ifndef WIN32
// Theoretically this should always be 0, but one fileno call isn't going to hurt, and if
// we try to run somewhere that stdin isn't fd 0 then it will still just work
cinfd[0].fd = fileno(stdin);
cinfd[0].events = POLLIN;
#else
h = GetStdHandle(STD_INPUT_HANDLE);
//DWORD dwMode;
//GetConsoleMode(h, &dwMode);
//SetConsoleMode(h, dwMode & ~ENABLE_MOUSE_INPUT);
FlushConsoleInputBuffer(h);
#endif
}
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
printf("Headless server is now running...\n");
printf("To shutdown type: quit\n");
printf("All commands require you to press ENTER\n");
}
//throw megaglest_runtime_error("Test!");
//printf("About to throw an exception...\n");
//throw 123;
//main loop
while(program->isShutdownApplicationEnabled() == false && ::Shared::Platform::Window::handleEvent()) {
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
if(disableheadless_console == false) {
#ifndef WIN32
int pollresult = poll(cinfd, 1, 0);
int pollerror = errno;
if(pollresult)
#else
// This is problematic because input on Windows is not line-buffered so this will return
// even if getline may block. I haven't found a good way to fix it, so for the moment
// I just strongly suggest only running the server from the Python frontend, which does
// line buffer input. This does work okay as long as the user doesn't enter characters
// without pressing enter, and then try to end the server another way (say a remote
// console command), in which case we'll still be waiting for the stdin EOL and hang.
DWORD saveMode;
GetConsoleMode(h, &saveMode);
DWORD dwMode = saveMode;
dwMode &= ~ENABLE_MOUSE_INPUT;
dwMode &= ~ENABLE_WINDOW_INPUT;
SetConsoleMode(h, dwMode);
bool gotData = (WaitForSingleObject(h, 0) == WAIT_OBJECT_0);
SetConsoleMode(h, saveMode);
if(gotData == true)
#endif
{
#ifdef WIN32
bool skip = true;
DWORD nNumberOfCharsToRead = 1024;
DWORD nRead = 0;
INPUT_RECORD irInRec[1025];
PeekConsoleInput(h,&irInRec[0],nNumberOfCharsToRead,&nRead);
for(int i = 0; i < nRead; ++i) {
INPUT_RECORD &inr = irInRec[i];
//printf("inr.EventType = %d\n",inr.EventType);
if(inr.EventType == KEY_EVENT) {
if(inr.Event.KeyEvent.bKeyDown) {
char cHoldKey = inr.Event.KeyEvent.uChar.AsciiChar;
if(cHoldKey == '\r') {
skip = false;
break;
}
}
}
}
#else
bool skip = false;
#endif
if(skip == false) {
getline(cin, command);
cin.clear();
printf("server command [%s]\n",command.c_str());
if(command == "quit") {
break;
}
#ifndef WIN32
if (cinfd[0].revents & POLLNVAL) {
printf("invalid file descriptor\n");
}
if (cinfd[0].revents & POLLERR) {
printf("error in file descriptor\n");
}
if (cinfd[0].revents & POLLHUP) {
printf("hang up in file descriptor\n");
}
if(pollresult < 0) {
printf("pollresult = %d errno = %d [%s]\n",pollresult,pollerror,strerror(pollerror));
cinfd[0].fd = fileno(stdin);
cinfd[0].events = POLLIN;
}
#endif
}
}
}
//printf("looping\n");
}
program->loop();
// Because OpenGL really doesn't do multi-threading well
// if(difftime(time(NULL),lastTextureLoadEvent) >= 3) {
// lastTextureLoadEvent = time(NULL);
// vector<Texture2D *> textureList = preCacheThread->getPendingTextureList(1);
// for(unsigned int i = 0; i < textureList.size(); ++i) {
// Texture2D * factionLogo = textureList[i];
// if(factionLogo != NULL) {
// printf("\n\n\n\n|||||||||||||||||||||||||| Load texture [%s]\n",factionLogo->getPath().c_str());
// //Renderer::findTexture(factionLogo);
// renderer.initTexture(rsGlobal,factionLogo);
// }
// }
// }
}
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == true) {
printf("\nHeadless server is about to quit...\n");
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] starting normal application shutdown\n",__FILE__,__FUNCTION__,__LINE__);
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
soundThreadManager = program->getSoundThreadManager(true);
if(soundThreadManager) {
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
chronoshutdownFadeSound.start();
}
}
cleanupCRCThread();
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
showCursor(true);
//showWindowCursorState = true;
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
}
catch(const megaglest_runtime_error &e) {
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
if(soundThreadManager) {
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
chronoshutdownFadeSound.start();
}
if(program != NULL &&
program->getTryingRendererInit() == true &&
program->getRendererInitOk() == false) {
message(e.what(),GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
}
}
if(program == NULL || program->getTryingRendererInit() == false ||
(program->getTryingRendererInit() == true &&
program->getRendererInitOk() == true)) {
ExceptionHandler::handleRuntimeError(e);
}
}
catch(const exception &e) {
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
if(soundThreadManager) {
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
chronoshutdownFadeSound.start();
}
}
ExceptionHandler::handleRuntimeError(e.what(),true);
}
catch(const char *e) {
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
if(soundThreadManager) {
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
chronoshutdownFadeSound.start();
}
}
ExceptionHandler::handleRuntimeError(e,true);
}
catch(const string &ex) {
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
if(soundThreadManager) {
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
chronoshutdownFadeSound.start();
}
}
ExceptionHandler::handleRuntimeError(ex.c_str(),true);
}
#if !defined(HAVE_GOOGLE_BREAKPAD)
catch(...) {
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
soundThreadManager = (program != NULL ? program->getSoundThreadManager(true) : NULL);
if(soundThreadManager) {
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
soundRenderer.stopAllSounds(shutdownFadeSoundMilliseconds);
chronoshutdownFadeSound.start();
}
}
ExceptionHandler::handleRuntimeError("Unknown error [main]!",true);
}
#endif
cleanupCRCThread();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete mainWindow;
mainWindow = NULL;
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
GraphicComponent::clearRegisteredComponents();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(soundThreadManager) {
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
if( Config::getInstance().getString("FactorySound","") != "None" &&
soundRenderer.isVolumeTurnedOff() == false) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
for(;chronoshutdownFadeSound.getMillis() <= shutdownFadeSoundMilliseconds;) {
sleep(10);
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
BaseThread::shutdownAndWait(soundThreadManager);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
delete soundThreadManager;
soundThreadManager = NULL;
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
return 0;
}
#if defined(__GNUC__) && !defined(__FreeBSD__) && !defined(BSD)
void handleSIGSEGV(int sig) {
char szBuf[8096]="";
snprintf(szBuf, 8096,"In [%s::%s Line: %d] Error detected: signal %d:\n",__FILE__,__FUNCTION__,__LINE__, sig);
printf("%s",szBuf);
//abort();
ExceptionHandler::handleRuntimeError(szBuf,true);
}
#endif
#if defined(HAVE_GOOGLE_BREAKPAD)
#if defined(WIN32)
// Callback when minidump written.
static bool MinidumpCallback(const wchar_t *dump_path,
const wchar_t *minidump_id,
void *context,
EXCEPTION_POINTERS* exinfo,
MDRawAssertionInfo* assertion,
bool succeeded) {
printf("\n======= In MinidumpCallback...\n");
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);
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
wchar_t szBuf[8096];
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);
szBuf[bufBytes] = '\0';
MessageBox(NULL, szBuf, L"Unhandled error", MB_OK|MB_SYSTEMMODAL);
}
return succeeded;
}
#else
// Callback when minidump written.
static bool MinidumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* context,
bool succeeded) {
printf("\n======= In MinidumpCallback...\n");
printf("\n***ERROR details captured:\nCrash minidump folder: %s\nfile: %s\nSucceeded: %d\n", descriptor.directory().c_str(),descriptor.path(),succeeded);
if(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false) {
char szBuf[8096];
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());
message(szBuf,GlobalStaticFlags::getIsNonGraphicalModeEnabled(),tempDataLocation);
}
return succeeded;
}
#endif
#endif
#ifdef WIN32
void EnableCrashingOnCrashes() {
typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
const DWORD EXCEPTION_SWALLOWING = 0x1;
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
if(kernel32 != 0) {
tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, "GetProcessUserModeExceptionPolicy");
tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, "SetProcessUserModeExceptionPolicy");
if (pGetPolicy && pSetPolicy) {
DWORD dwFlags;
if (pGetPolicy(&dwFlags)) {
// Turn off the filter
pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
}
}
}
}
#endif
int glestMainSEHWrapper(int argc, char** argv) {
int result = 0;
#ifdef WIN32_STACK_TRACE
//printf("Hooking up WIN32_STACK_TRACE...\n");
__try {
#endif
//application_binary= executable_path(argv[0],true);
//printf("\n\nargv0 [%s] application_binary [%s]\n\n",argv[0],application_binary.c_str());
#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__FreeBSD__) && !defined(BSD)
if(hasCommandArgument(argc, argv,string(GAME_ARGS[GAME_ARG_DISABLE_SIGSEGV_HANDLER])) == false) {
signal(SIGSEGV, handleSIGSEGV);
}
// http://developerweb.net/viewtopic.php?id=3013
//signal(SIGPIPE, SIG_IGN);
#endif
initSpecialStrings();
IRCThread::setGlobalCacheContainerName(GameConstants::ircClientCacheLookupKey);
result = glestMain(argc, argv);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
cleanupProcessObjects();
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
#ifdef WIN32
//delete winSockManager;
//winSockManager = NULL;
#endif
if(sdl_quitCalled == false) {
sdl_quitCalled = true;
SDL_Quit();
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
#ifdef WIN32_STACK_TRACE
}
__except(stackdumper(0, GetExceptionInformation(),true), EXCEPTION_CONTINUE_SEARCH) {
return 0;
}
#endif
return result;
}
int glestMainWrapper(int argc, char** argv) {
//setlocale(LC_ALL, "zh_TW.UTF-8");
//setlocale(LC_ALL, "");
#ifdef WIN32
EnableCrashingOnCrashes();
#endif
#if defined(HAVE_GOOGLE_BREAKPAD)
/*
handler = new ExceptionHandler(const wstring& dump_path,
FilterCallback filter,
MinidumpCallback callback,
void* callback_context,
int handler_types,
MINIDUMP_TYPE dump_type,
const wchar_t* pipe_name,
const CustomClientInfo* custom_info);
*/
// 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/
//DWORD dwFlags;
//if (GetProcessUserModeExceptionPolicy(&dwFlags)) {
// SetProcessUserModeExceptionPolicy(dwFlags & ~PROCESS_CALLBACK_FILTER_ENABLED); // turn off bit 1
//}
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Hooking up google_breakpad::ExceptionHandler...\n");
#if defined(WIN32)
wstring dumpfilepath = utf8_decode(".");
//google_breakpad::ExceptionHandler handler(dumpfilepath, NULL, MinidumpCallback, NULL, true);
errorHandlerPtr.reset(new google_breakpad::ExceptionHandler(dumpfilepath, NULL, MinidumpCallback,
NULL, google_breakpad::ExceptionHandler::HANDLER_ALL));
#else
google_breakpad::MinidumpDescriptor descriptor(".");
errorHandlerPtr.reset(new google_breakpad::ExceptionHandler(descriptor, NULL, MinidumpCallback, NULL, true,-1));
#endif
// ExceptionHandler(const wstring& dump_path,
// FilterCallback filter,
// MinidumpCallback callback,
// void* callback_context,
// int handler_types);
#endif
#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__FreeBSD__) && !defined(BSD)
//#ifdef DEBUG
//printf("MTRACE will be called...\n");
//mtrace ();
//#endif
#endif
#ifdef WIN32
//winSockManager = new SocketManager();
SocketManager winSockManager;
#endif
bool isSteamMode = hasCommandArgument(argc, argv, GAME_ARGS[GAME_ARG_STEAM]);
if (isSteamMode == true) {
if (!STEAMSHIM_init()) {
printf("\nSteam API init failed, terminating.\n");
return 42;
}
}
int result = glestMainSEHWrapper(argc, argv);
if (isSteamMode == true) {
printf("\nSteam API deinit.\n");
STEAMSHIM_deinit();
}
return result;
}
}}//end namespace
MAIN_FUNCTION(Glest::Game::glestMainWrapper)