From 8717ffe07ccafcd96de76a49f3bce2f967e5c998 Mon Sep 17 00:00:00 2001 From: Vincent Herbet Date: Fri, 28 Sep 2018 16:46:52 +0200 Subject: [PATCH] Implement menu_create "ml" param to allow menu title/item to be looked up as multilingual key (#593) * Clean up menu_create() internal code No code changes. Just modernizing code a little and tidying up things. * Implement menu_create() "ml" param * Include newmenu.inc to VS project files * Adjust documentation * Put back the quote in the log error message. --- amxmodx/msvc12/amxmodx_mm.vcxproj | 1 + amxmodx/msvc12/amxmodx_mm.vcxproj.filters | 7 +- amxmodx/newmenus.cpp | 91 ++++++++++++++++------- amxmodx/newmenus.h | 4 +- plugins/include/newmenus.inc | 5 +- 5 files changed, 75 insertions(+), 33 deletions(-) diff --git a/amxmodx/msvc12/amxmodx_mm.vcxproj b/amxmodx/msvc12/amxmodx_mm.vcxproj index 80fb9367..da893adc 100644 --- a/amxmodx/msvc12/amxmodx_mm.vcxproj +++ b/amxmodx/msvc12/amxmodx_mm.vcxproj @@ -457,6 +457,7 @@ md -p JIT 2>NUL + diff --git a/amxmodx/msvc12/amxmodx_mm.vcxproj.filters b/amxmodx/msvc12/amxmodx_mm.vcxproj.filters index f1c49446..946922c2 100644 --- a/amxmodx/msvc12/amxmodx_mm.vcxproj.filters +++ b/amxmodx/msvc12/amxmodx_mm.vcxproj.filters @@ -54,7 +54,7 @@ {04fab577-6f56-40d0-8f69-7ce1b8bf3bb9} - + {270f3524-564f-4154-bb35-242a6faac09e} @@ -693,10 +693,13 @@ Pawn Includes + + Pawn Includes + Assembly\Builds - + \ No newline at end of file diff --git a/amxmodx/newmenus.cpp b/amxmodx/newmenus.cpp index 9e07d356..59bdd7e6 100755 --- a/amxmodx/newmenus.cpp +++ b/amxmodx/newmenus.cpp @@ -10,6 +10,7 @@ #include "amxmodx.h" #include "CMenu.h" #include "newmenus.h" +#include "format.h" ke::Vector g_NewMenus; CStack g_MenuFreeStack; @@ -90,9 +91,9 @@ bool CloseNewMenus(CPlayer *pPlayer) return true; } -Menu::Menu(const char *title, AMX *amx, int fid) : m_Title(title), m_ItemColor("\\r"), +Menu::Menu(const char *title, AMX *amx, int fid, bool use_ml) : m_Title(title), m_ItemColor("\\r"), m_NeverExit(false), m_AutoColors(g_coloredmenus), thisId(0), func(fid), -isDestroying(false), pageCallback(-1), showPageNumber(true), items_per_page(7) +isDestroying(false), pageCallback(-1), showPageNumber(true), useMultilingual(use_ml), amx(amx), items_per_page(7) { CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(amx); menuId = g_menucmds.registerMenuId(title, amx); @@ -356,18 +357,32 @@ const char *Menu::GetTextString(int player, page_t page, int &keys) m_Text = nullptr; + + auto title = m_Title.chars(); + + if (this->useMultilingual) + { + const auto language = playerlang(player); + const auto definition = translate(this->amx, language, title); + + if (definition) + { + title = definition; + } + } + char buffer[255]; if (showPageNumber && items_per_page && (pages != 1)) { if (m_AutoColors) - ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s %d/%d\n\\w\n", m_Title.chars(), page + 1, pages); + ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s %d/%d\n\\w\n", title, page + 1, pages); else - ke::SafeSprintf(buffer, sizeof(buffer), "%s %d/%d\n\n", m_Title.chars(), page + 1, pages); + ke::SafeSprintf(buffer, sizeof(buffer), "%s %d/%d\n\n", title, page + 1, pages); } else { if (m_AutoColors) - ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s\n\\w\n", m_Title.chars()); + ke::SafeSprintf(buffer, sizeof(buffer), "\\y%s\n\\w\n", title); else - ke::SafeSprintf(buffer, sizeof(buffer), "%s\n\n", m_Title.chars()); + ke::SafeSprintf(buffer, sizeof(buffer), "%s\n\n", title); } m_Text = m_Text + buffer; @@ -462,24 +477,37 @@ const char *Menu::GetTextString(int player, page_t page, int &keys) option_display = 0; } + auto itemName = pItem->name.chars(); + + if (this->useMultilingual) + { + const auto language = playerlang(player); + const auto definition = translate(this->amx, language, itemName); + + if (definition) + { + itemName = definition; + } + } + if (pItem->isBlank) { - ke::SafeSprintf(buffer, sizeof(buffer), "%s\n", pItem->name.chars()); + ke::SafeSprintf(buffer, sizeof(buffer), "%s\n", itemName); } else if (enabled) { - if (m_AutoColors) + if (m_AutoColors) { - ke::SafeSprintf(buffer, sizeof(buffer), "%s%d.\\w %s\n", m_ItemColor.chars(),option_display, pItem->name.chars()); + ke::SafeSprintf(buffer, sizeof(buffer), "%s%d.\\w %s\n", m_ItemColor.chars(),option_display, itemName); } else { - ke::SafeSprintf(buffer, sizeof(buffer), "%d. %s\n", option_display, pItem->name.chars()); + ke::SafeSprintf(buffer, sizeof(buffer), "%d. %s\n", option_display, itemName); } } else { if (m_AutoColors) { - ke::SafeSprintf(buffer, sizeof(buffer), "\\d%d. %s\n\\w", option_display, pItem->name.chars()); + ke::SafeSprintf(buffer, sizeof(buffer), "\\d%d. %s\n\\w", option_display, itemName); } else { - ke::SafeSprintf(buffer, sizeof(buffer), "#. %s\n", pItem->name.chars()); + ke::SafeSprintf(buffer, sizeof(buffer), "#. %s\n", itemName); } } slots++; @@ -620,38 +648,45 @@ const char *Menu::GetTextString(int player, page_t page, int &keys) LogError(amx, AMX_ERR_NATIVE, "Invalid menu id %d(%d)", p, g_NewMenus.length()); \ return 0; } -//Makes a new menu handle (-1 for failure) -//native csdm_makemenu(title[]); +// native menu_create(const title[], const handler[], bool:ml = false); static cell AMX_NATIVE_CALL menu_create(AMX *amx, cell *params) { - int len; - char *title = get_amxstring(amx, params[1], 0, len); - validate_menu_text(title); - char *handler = get_amxstring(amx, params[2], 1, len); + enum args { arg_count, arg_title, arg_handler, arg_ml }; - int func = registerSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_CELL, FP_DONE); - - if (func == -1) + int length; + const auto title = get_amxstring(amx, params[arg_title], 0, length); + const auto handler = get_amxstring(amx, params[arg_handler], 1, length); + const auto callback = registerSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + + if (callback == -1) { - LogError(amx, AMX_ERR_NOTFOUND, "Invalid function \"%s\"", handler); + LogError(amx, AMX_ERR_NOTFOUND, R"(Invalid function "%s")", handler); return 0; } - Menu *pMenu = new Menu(title, amx, func); + validate_menu_text(title); + + auto pMenu = new Menu(title, amx, callback, params[arg_ml] != 0); if (g_MenuFreeStack.empty()) { g_NewMenus.append(pMenu); - pMenu->thisId = (int)g_NewMenus.length() - 1; - } else { - int pos = g_MenuFreeStack.front(); + + pMenu->thisId = static_cast(g_NewMenus.length()) - 1; + } + else + { + const auto position = g_MenuFreeStack.front(); + g_MenuFreeStack.pop(); - g_NewMenus[pos] = pMenu; - pMenu->thisId = pos; + g_NewMenus[position] = pMenu; + + pMenu->thisId = position; } return pMenu->thisId; } + static cell AMX_NATIVE_CALL menu_addblank(AMX *amx, cell *params) { GETMENU(params[1]); diff --git a/amxmodx/newmenus.h b/amxmodx/newmenus.h index df132df1..8b53a52a 100755 --- a/amxmodx/newmenus.h +++ b/amxmodx/newmenus.h @@ -95,7 +95,7 @@ typedef unsigned int page_t; class Menu { public: - Menu(const char *title, AMX *amx, int fid); + Menu(const char *title, AMX *amx, int fid, bool use_ml); ~Menu(); menuitem *GetMenuItem(item_t item); @@ -127,6 +127,8 @@ public: bool isDestroying; int pageCallback; bool showPageNumber; + bool useMultilingual; + AMX *amx; public: unsigned int items_per_page; }; diff --git a/plugins/include/newmenus.inc b/plugins/include/newmenus.inc index 9485ab2f..79a88f7b 100644 --- a/plugins/include/newmenus.inc +++ b/plugins/include/newmenus.inc @@ -117,13 +117,14 @@ * @param title Title the menu should use. * @param handler Name of the handler function. The function will be invoked * once and only once to every menu_display() call. - * @param ml Unused (should be 0). + * @param ml If true, the menu title and items will be looked up as multilingual keys + * when the menu displays. * @return Menu resource identifier which must be destroyed via * menu_destroy(). All menus are destroyed when the plugin * unloads. * @error Function name not found. */ -native menu_create(const title[], const handler[], ml=0); +native menu_create(const title[], const handler[], bool:ml = false); /** * Creates a menu item callback handler.