#include "StdAfx.h" #include "PythonApplication.h" #include "ProcessScanner.h" #include "PythonExceptionSender.h" #include "resource.h" #include "Version.h" #ifdef _DEBUG #include #endif #include "eterLib/Util.h" #include "EterLib/GameThreadPool.h" #include "EterBase/lzo.h" #include "PackLib/PackManager.h" #include "PackLib/M2PackRuntimeKeyProvider.h" #include #include #include #include #include #include #include #include "EterLib/FontManager.h" extern "C" { #if defined(__MINGW32__) int _fltused = 0; #else extern int _fltused; FILE __iob_func[3] = { *stdin, *stdout, *stderr }; #endif volatile int _AVOID_FLOATING_POINT_LIBRARY_BUG = _fltused; __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; }; #pragma comment(linker, "/NODEFAULTLIB:libci.lib") int Setup(LPSTR lpCmdLine); static const char * sc_apszPythonLibraryFilenames[] = { "UserDict.pyc", "__future__.pyc", "copy_reg.pyc", "linecache.pyc", "ntpath.pyc", "os.pyc", "site.pyc", "stat.pyc", "string.pyc", "traceback.pyc", "types.pyc", "\n", }; bool PackInitialize(const char * c_pszFolder) { if (_access(c_pszFolder, 0) != 0) return false; auto AddPreferredPack = [c_pszFolder](const std::string& packName, bool required) -> bool { const std::string m2Path = std::format("{}/{}.m2p", c_pszFolder, packName); const std::string legacyPath = std::format("{}/{}.pck", c_pszFolder, packName); if (_access(m2Path.c_str(), 0) == 0) { Tracef("PackInitialize: Loading %s\n", m2Path.c_str()); if (CPackManager::instance().AddPack(m2Path)) return true; TraceError("PackInitialize: Failed to load %s", m2Path.c_str()); return false; } if (_access(legacyPath.c_str(), 0) == 0) { Tracef("PackInitialize: Loading %s\n", legacyPath.c_str()); if (CPackManager::instance().AddPack(legacyPath)) return true; TraceError("PackInitialize: Failed to load %s", legacyPath.c_str()); } return !required; }; std::vector packFiles = { "patch1", "season3_eu", "patch2", "metin2_patch_snow", "metin2_patch_snow_dungeon", "metin2_patch_etc_costume1", "metin2_patch_pet1", "metin2_patch_pet2", "metin2_patch_ramadan_costume", "metin2_patch_flame", "metin2_patch_flame_dungeon", "metin2_patch_w21_etc", "metin2_patch_w21_mobs", "metin2_patch_w21_mobs_m", "metin2_patch_dss_box", "metin2_patch_costume_soccer", "metin2_patch_easter1", "metin2_patch_mineral", "metin2_patch_w20_sound", "metin2_patch_ds", "metin2_patch_5th_armor", "metin2_patch_w20_etc", "metin2_patch_dragon_rock", "metin2_patch_dragon_rock_mobs", "metin2_patch_dragon_rock_texcache", "metin2_patch_dragon_rock_mobs_texcache", "metin2_patch_etc", "metin2_patch_xmas", "metin2_patch_eu3", "metin2_patch_eu4", "metin2_patch_mundi", "metin2_patch_sd", "metin2_patch_halloween", "metin2_patch_party", "metin2_patch_dance", "pc", "pc2", "monster", "monster2", "effect", "zone", "terrain", "npc", "npc2", "tree", "guild", "item", "textureset", "property", "icon", "season1", "season2", "outdoora1", "outdoora2", "outdoora3", "outdoorb1", "outdoorb3", "outdoorc1", "outdoorc3", "outdoorsnow1", "outdoordesert1", "outdoorflame1", "outdoorfielddungeon1", "outdoort1", "outdoort2", "outdoort3", "outdoort4", "outdoorwedding", "outdoormilgyo1", "indoorspiderdungeon1", "indoordeviltower1", "indoormonkeydungeon1", "indoormonkeydungeon2", "indoormonkeydungeon3", "outdoortrent", "outdoortrent02", "outdoorguild1", "outdoorguild2", "outdoorguild3", "outdoorduel", "outdoorgmguildbuild", "sound", "sound_m", "sound2", // "bgm", // BGM files are loaded directly from disk, not from pack "locale", "uiscript", "ETC", "uiloading", }; DWORD dwStartTime = GetTickCount(); if (!AddPreferredPack("root", true)) { TraceError("Failed to load root pack"); return false; } Tracef("PackInitialize: Loading %d pack files...", packFiles.size()); for (const std::string& packFileName : packFiles) { AddPreferredPack(packFileName, false); } Tracef("PackInitialize: done. Time taken: %d ms\n", GetTickCount() - dwStartTime); return true; } bool RunMainScript(CPythonLauncher& pyLauncher, const char* lpCmdLine) { initpack(); initdbg(); initime(); initgrp(); initgrpImage(); initgrpText(); initwndMgr(); initapp(); initsystem(); initchr(); initchrmgr(); initPlayer(); initItem(); initNonPlayer(); initTrade(); initChat(); initTextTail(); initnet(); initMiniMap(); initProfiler(); initEvent(); initeffect(); initfly(); initsnd(); initeventmgr(); initshop(); initskill(); initquest(); initBackground(); initMessenger(); initsafebox(); initguild(); initServerStateChecker(); std::string stRegisterDebugFlag; #ifdef _DISTRIBUTE stRegisterDebugFlag = "__DEBUG__ = 0"; #else stRegisterDebugFlag = "__DEBUG__ = 1"; #endif if (!pyLauncher.RunLine(stRegisterDebugFlag.c_str())) { TraceError("RegisterDebugFlag Error"); return false; } if (!pyLauncher.RunFile("system.py")) { TraceError("RunMain Error"); return false; } return true; } static bool Main(HINSTANCE hInstance, LPSTR lpCmdLine) { DWORD dwRandSeed = (DWORD)time(NULL) ^ GetCurrentProcessId() ^ GetTickCount(); srandom(dwRandSeed); srand(random()); SetLogLevel(1); if (!Setup(lpCmdLine)) return false; #ifdef _DEBUG OpenConsoleWindow(); OpenLogFile(true); // true == uses syserr.txt and log.txt #else OpenLogFile(false); // false == uses syserr.txt only #endif if (sodium_init() < 0) { LogBox("sodium_init() failed"); return false; } if (!CFontManager::Instance().Initialize()) { LogBox("FreeType initialization failed"); return false; } static CLZO lzo; CPackManager packMgr; if (!PackInitialize("pack")) { LogBox("Pack Initialization failed. Check log.txt file.."); return false; } // Create game thread pool singleton before CPythonApplication static CGameThreadPool gameThreadPool; auto app = new CPythonApplication; app->Initialize (hInstance); CPythonLauncher pyLauncher; if (pyLauncher.Create()) { RunMainScript (pyLauncher, lpCmdLine); } app->Clear(); timeEndPeriod (1); pyLauncher.Clear(); app->Destroy(); delete app; CFontManager::Instance().Destroy(); return 0; } void __ErrorPythonLibraryIsNotExist() { LogBoxf("FATAL ERROR!! Python Library file not exist!"); } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { LoadConfig("config/locale.cfg"); int nArgc = 0; auto szArgv = CommandLineToArgv (lpCmdLine, &nArgc); Main (hInstance, lpCmdLine); ::CoUninitialize(); Clean: SAFE_FREE_GLOBAL (szArgv); return 0; } static void GrannyError(granny_log_message_type Type, granny_log_message_origin Origin, char const* File, granny_int32x Line, char const* Message, void* UserData) { TraceError("GRANNY: %s", Message); } int Setup(LPSTR lpCmdLine) { TIMECAPS tc; UINT wTimerRes; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) return 0; wTimerRes = MINMAX(tc.wPeriodMin, 1, tc.wPeriodMax); timeBeginPeriod(wTimerRes); granny_log_callback Callback; Callback.Function = nullptr; Callback.UserData = 0; GrannySetLogCallback(&Callback); InitializeM2PackRuntimeKeyProvider(lpCmdLine); return 1; }