Fix recursion issue with show_menu and newmenus

This commit is contained in:
Arkshine 2016-01-14 17:50:25 +01:00
parent af0042b71d
commit e634e512c8
3 changed files with 36 additions and 25 deletions

View File

@ -1251,8 +1251,11 @@ static cell AMX_NATIVE_CALL show_menu(AMX *amx, cell *params) /* 3 param */
pPlayer->menu = 0; pPlayer->menu = 0;
// Fire newmenu callback so closing it can be handled by the plugin // Fire newmenu callback so closing it can be handled by the plugin
if (Menu *pMenu = get_menu_by_id(pPlayer->newmenu)) if (!CloseNewMenus(pPlayer))
pMenu->Close(pPlayer->index); {
LogError(amx, AMX_ERR_NATIVE, "Plugin called menu_display when item=MENU_EXIT");
return 0;
}
UTIL_FakeClientCommand(pPlayer->pEdict, "menuselect", "10", 0); UTIL_FakeClientCommand(pPlayer->pEdict, "menuselect", "10", 0);
} }
@ -1274,8 +1277,11 @@ static cell AMX_NATIVE_CALL show_menu(AMX *amx, cell *params) /* 3 param */
pPlayer->menu = 0; pPlayer->menu = 0;
// Fire newmenu callback so closing it can be handled by the plugin // Fire newmenu callback so closing it can be handled by the plugin
if (Menu *pMenu = get_menu_by_id(pPlayer->newmenu)) if (!CloseNewMenus(pPlayer))
pMenu->Close(pPlayer->index); {
LogError(amx, AMX_ERR_NATIVE, "Plugin called menu_display when item=MENU_EXIT");
return 0;
}
UTIL_FakeClientCommand(pPlayer->pEdict, "menuselect", "10", 0); UTIL_FakeClientCommand(pPlayer->pEdict, "menuselect", "10", 0);
} }

View File

@ -68,6 +68,28 @@ Menu *get_menu_by_id(int id)
return g_NewMenus[id]; return g_NewMenus[id];
} }
bool CloseNewMenus(CPlayer *pPlayer)
{
// If the stupid handler keeps drawing menus,
// We need to keep cancelling them. But we put in a quick infinite loop
// counter to prevent this from going nuts.
int loops = 0;
Menu *pMenu;
while ((pMenu = get_menu_by_id(pPlayer->newmenu)))
{
pMenu->Close(pPlayer->index);
if (++loops >= 10)
{
return false;
}
}
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) : m_Title(title), m_ItemColor("\\r"),
m_NeverExit(false), m_AutoColors(g_coloredmenus), thisId(0), func(fid), m_NeverExit(false), m_AutoColors(g_coloredmenus), thisId(0), func(fid),
isDestroying(false), items_per_page(7) isDestroying(false), items_per_page(7)
@ -792,29 +814,11 @@ static cell AMX_NATIVE_CALL menu_display(AMX *amx, cell *params)
int page = params[3]; int page = params[3];
CPlayer* pPlayer = GET_PLAYER_POINTER_I(player); CPlayer* pPlayer = GET_PLAYER_POINTER_I(player);
/* If the stupid handler keeps drawing menus, if (!CloseNewMenus(pPlayer))
* We need to keep cancelling them. But we put in a quick infinite loop
* counter to prevent this from going nuts.
*/
int menu;
int loops = 0;
while ((menu = pPlayer->newmenu) >= 0)
{
if ((size_t)menu >= g_NewMenus.length() || !g_NewMenus[menu])
{
break;
}
Menu *pOther = g_NewMenus[menu];
pOther->Close(pPlayer->index);
/* Infinite loop counter */
if (++loops >= 10)
{ {
LogError(amx, AMX_ERR_NATIVE, "Plugin called menu_display when item=MENU_EXIT"); LogError(amx, AMX_ERR_NATIVE, "Plugin called menu_display when item=MENU_EXIT");
return 0; return 0;
} }
}
int time = -1; int time = -1;
if (params[0] / sizeof(cell) >= 4) if (params[0] / sizeof(cell) >= 4)

View File

@ -129,6 +129,7 @@ public:
void ClearMenus(); void ClearMenus();
Menu *get_menu_by_id(int id); Menu *get_menu_by_id(int id);
bool CloseNewMenus(CPlayer *pPlayer);
extern ke::Vector<Menu *> g_NewMenus; extern ke::Vector<Menu *> g_NewMenus;
extern AMX_NATIVE_INFO g_NewMenuNatives[]; extern AMX_NATIVE_INFO g_NewMenuNatives[];