From c4cc59a4f2a2a4e3aae329c60eabbc0910f6a0e9 Mon Sep 17 00:00:00 2001 From: rtw1x1 Date: Mon, 5 Jan 2026 18:55:36 +0000 Subject: [PATCH 1/2] ML: Hot reload locale system --- src/EterBase/Debug.cpp | 12 ++-- src/UserInterface/PythonApplicationModule.cpp | 58 ++++++++++++++++++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/EterBase/Debug.cpp b/src/EterBase/Debug.cpp index d9f77fd..a48dd9f 100644 --- a/src/EterBase/Debug.cpp +++ b/src/EterBase/Debug.cpp @@ -222,7 +222,7 @@ void Tracef(const char* c_szFormat, ...) void TraceError(const char* c_szFormat, ...) { -#ifndef _DISTRIBUTE +//#ifndef _DISTRIBUTE char szBuf[DEBUG_STRING_MAX_LEN + 2]; strncpy_s(szBuf, sizeof(szBuf), "SYSERR: ", _TRUNCATE); @@ -262,12 +262,12 @@ void TraceError(const char* c_szFormat, ...) if (isLogFile) LogFile(szBuf); -#endif +//#endif } void TraceErrorWithoutEnter(const char* c_szFormat, ...) { -#ifndef _DISTRIBUTE +//#ifndef _DISTRIBUTE char szBuf[DEBUG_STRING_MAX_LEN]; @@ -295,7 +295,7 @@ void TraceErrorWithoutEnter(const char* c_szFormat, ...) if (isLogFile) LogFile(szBuf); -#endif +//#endif } void LogBoxf(const char* c_szFormat, ...) @@ -349,7 +349,7 @@ void OpenLogFile(bool bUseLogFIle) std::filesystem::create_directory("log"); } -#ifndef _DISTRIBUTE +//#ifndef _DISTRIBUTE _wfreopen(L"log/syserr.txt", L"w", stderr); if (bUseLogFIle) @@ -357,7 +357,7 @@ void OpenLogFile(bool bUseLogFIle) isLogFile = true; CLogFile::Instance().Initialize(); } -#endif +//#endif } void OpenConsoleWindow() diff --git a/src/UserInterface/PythonApplicationModule.cpp b/src/UserInterface/PythonApplicationModule.cpp index 8454c22..fcefbbf 100644 --- a/src/UserInterface/PythonApplicationModule.cpp +++ b/src/UserInterface/PythonApplicationModule.cpp @@ -1073,6 +1073,60 @@ PyObject* appIsRTL(PyObject* poSelf, PyObject* poArgs) return Py_BuildValue("i", IsRTL() ? 1 : 0); } +PyObject* appReloadLocaleConfig(PyObject* poSelf, PyObject* poArgs) +{ + LoadConfig("config/locale.cfg"); + return Py_BuildNone(); +} + +PyObject* appReloadLocale(PyObject* poSelf, PyObject* poArgs) +{ + // Comprehensive locale reload - updates config, reloads data, and forces Python module reload + + TraceError("=== Starting Locale Reload ==="); + + LoadConfig("config/locale.cfg"); + TraceError("LoadConfig complete, new locale path: %s", GetLocalePath()); + + if (!LoadLocaleData(GetLocalePath())) + { + TraceError("LoadLocaleData FAILED for path: %s", GetLocalePath()); + return Py_BuildValue("i", 0); // Return False on failure + } + TraceError("LoadLocaleData succeeded"); + + PyObject* modulesDict = PyImport_GetModuleDict(); + TraceError("Got modules dict: %p, is dict: %d", modulesDict, modulesDict ? PyDict_Check(modulesDict) : 0); + + if (modulesDict && PyDict_Check(modulesDict)) + { + // List of locale-related modules to clear from cache + const char* modulesToReload[] = { + "localeInfo", + "localeinfo", + "uiScriptLocale", + "uiscriptlocale", + "serverInfo", + "serverinfo", + NULL + }; + + for (int i = 0; modulesToReload[i] != NULL; i++) + { + PyObject* moduleName = PyString_FromString(modulesToReload[i]); + if (PyDict_Contains(modulesDict, moduleName)) + { + TraceError("Removing module from cache: %s", modulesToReload[i]); + PyDict_DelItem(modulesDict, moduleName); + } + Py_DECREF(moduleName); + } + } + + TraceError("=== Locale Reload Complete ==="); + return Py_BuildValue("i", 1); // Return True on success +} + void initapp() { static PyMethodDef s_methods[] = @@ -1201,7 +1255,9 @@ void initapp() { "OnLogoRender", appLogoRender, METH_VARARGS }, { "OnLogoOpen", appLogoOpen, METH_VARARGS }, { "OnLogoClose", appLogoClose, METH_VARARGS }, - + + { "ReloadLocaleConfig", appReloadLocaleConfig, METH_VARARGS }, + { "ReloadLocale", appReloadLocale, METH_VARARGS }, { NULL, NULL }, }; From dfe2368c8f87f9645de8d11c83f98e8e2a333452 Mon Sep 17 00:00:00 2001 From: rtw1x1 Date: Wed, 7 Jan 2026 09:55:18 +0000 Subject: [PATCH 2/2] ML: Refactored Hot-Reload System --- src/UserInterface/PythonApplicationModule.cpp | 98 +++++++++++++------ 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/src/UserInterface/PythonApplicationModule.cpp b/src/UserInterface/PythonApplicationModule.cpp index fcefbbf..ab9c55d 100644 --- a/src/UserInterface/PythonApplicationModule.cpp +++ b/src/UserInterface/PythonApplicationModule.cpp @@ -1081,50 +1081,92 @@ PyObject* appReloadLocaleConfig(PyObject* poSelf, PyObject* poArgs) PyObject* appReloadLocale(PyObject* poSelf, PyObject* poArgs) { - // Comprehensive locale reload - updates config, reloads data, and forces Python module reload - - TraceError("=== Starting Locale Reload ==="); + /** + * Multi-language hot-reload system + * + * Reloads all locale-dependent data when the user changes language: + * 1. Reloads config/locale.cfg to get new locale path + * 2. Reloads C++ locale data (item_proto, mob_proto, etc.) + * 3. Calls Python modules to reload locale text files + * + * Returns 1 on success, 0 on failure + */ + // Step 1: Reload config to update locale path LoadConfig("config/locale.cfg"); - TraceError("LoadConfig complete, new locale path: %s", GetLocalePath()); + // Step 2: Reload C++ locale-dependent data (item_proto, mob_proto, etc.) if (!LoadLocaleData(GetLocalePath())) { - TraceError("LoadLocaleData FAILED for path: %s", GetLocalePath()); - return Py_BuildValue("i", 0); // Return False on failure + // TraceError("app.ReloadLocale: Failed to load C++ locale data from %s", GetLocalePath()); + return Py_BuildValue("i", 0); } - TraceError("LoadLocaleData succeeded"); + // Step 3: Reload Python locale text files PyObject* modulesDict = PyImport_GetModuleDict(); - TraceError("Got modules dict: %p, is dict: %d", modulesDict, modulesDict ? PyDict_Check(modulesDict) : 0); - - if (modulesDict && PyDict_Check(modulesDict)) + if (!modulesDict || !PyDict_Check(modulesDict)) { - // List of locale-related modules to clear from cache - const char* modulesToReload[] = { - "localeInfo", - "localeinfo", - "uiScriptLocale", - "uiscriptlocale", - "serverInfo", - "serverinfo", - NULL - }; + // TraceError("app.ReloadLocale: Failed to get Python modules dictionary"); + return Py_BuildValue("i", 0); + } - for (int i = 0; modulesToReload[i] != NULL; i++) + // Step 3a: Reload localeInfo module (locale_game.txt) + PyObject* localeInfoModule = PyDict_GetItemString(modulesDict, "localeinfo"); + if (!localeInfoModule) + localeInfoModule = PyDict_GetItemString(modulesDict, "localeInfo"); + + if (localeInfoModule && PyModule_Check(localeInfoModule)) + { + if (PyObject_HasAttrString(localeInfoModule, "LoadLocaleData")) { - PyObject* moduleName = PyString_FromString(modulesToReload[i]); - if (PyDict_Contains(modulesDict, moduleName)) + PyObject* loadFunc = PyObject_GetAttrString(localeInfoModule, "LoadLocaleData"); + if (loadFunc && PyCallable_Check(loadFunc)) { - TraceError("Removing module from cache: %s", modulesToReload[i]); - PyDict_DelItem(modulesDict, moduleName); + PyObject* result = PyObject_CallObject(loadFunc, NULL); + if (result) + Py_DECREF(result); + else + { + PyErr_Print(); + // TraceError("app.ReloadLocale: localeInfo.LoadLocaleData() failed"); + } + Py_DECREF(loadFunc); } - Py_DECREF(moduleName); } } - TraceError("=== Locale Reload Complete ==="); - return Py_BuildValue("i", 1); // Return True on success + // Step 3b: Reload uiScriptLocale module (locale_interface.txt) + PyObject* uiScriptLocaleModule = NULL; + const char* uiScriptModuleNames[] = {"uiscriptlocale", "uiScriptLocale", NULL}; + + for (int i = 0; uiScriptModuleNames[i] != NULL; i++) + { + uiScriptLocaleModule = PyDict_GetItemString(modulesDict, uiScriptModuleNames[i]); + if (uiScriptLocaleModule) + break; + } + + if (uiScriptLocaleModule && PyModule_Check(uiScriptLocaleModule)) + { + if (PyObject_HasAttrString(uiScriptLocaleModule, "LoadLocaleData")) + { + PyObject* loadFunc = PyObject_GetAttrString(uiScriptLocaleModule, "LoadLocaleData"); + if (loadFunc && PyCallable_Check(loadFunc)) + { + PyObject* result = PyObject_CallObject(loadFunc, NULL); + if (result) + Py_DECREF(result); + else + { + PyErr_Print(); + // TraceError("app.ReloadLocale: uiScriptLocale.LoadLocaleData() failed"); + } + Py_DECREF(loadFunc); + } + } + } + + return Py_BuildValue("i", 1); } void initapp()