From 09b6c5ead158b6178a55af35ecdcf6722acb791c Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 20 Nov 2007 17:16:50 +0000 Subject: [PATCH] added new menu feature for old plugins --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401711 --- core/MenuStyle_Radio.cpp | 40 +++++++++++++++++++---- core/MenuStyle_Radio.h | 3 ++ core/smn_menus.cpp | 69 +++++++++++++++++++++++++++++++++++++++ plugins/include/menus.inc | 20 ++++++++++++ 4 files changed, 126 insertions(+), 6 deletions(-) diff --git a/core/MenuStyle_Radio.cpp b/core/MenuStyle_Radio.cpp index 1a5d033f..a1eee8ec 100644 --- a/core/MenuStyle_Radio.cpp +++ b/core/MenuStyle_Radio.cpp @@ -206,7 +206,9 @@ CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu) if (m_FreeDisplays.empty()) { display = new CRadioDisplay(); - } else { + } + else + { display = m_FreeDisplays.front(); m_FreeDisplays.pop(); display->Reset(); @@ -214,6 +216,15 @@ CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu) return display; } +IMenuPanel *CRadioStyle::MakeRadioDisplay(const char *str, int keys) +{ + CRadioDisplay *pPanel = MakeRadioDisplay(NULL); + + pPanel->DirectSet(str, keys); + + return pPanel; +} + void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display) { m_FreeDisplays.push(display); @@ -275,6 +286,13 @@ void CRadioDisplay::Reset() keys = 0; } +void CRadioDisplay::DirectSet(const char *str, int keymap) +{ + m_Title.clear(); + m_BufferText.assign(str); + keys = keymap; +} + unsigned int CRadioDisplay::GetCurrentKey() { return m_NextPos; @@ -391,11 +409,21 @@ bool CRadioMenuPlayer::Radio_NeedsRefresh() void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text) { - display_len = UTIL_Format(display_pkt, - sizeof(display_pkt), - "%s\n%s", - title, - text); + if (title[0] != '\0') + { + display_len = UTIL_Format(display_pkt, + sizeof(display_pkt), + "%s\n%s", + title, + text); + } + else + { + display_len = UTIL_Format(display_pkt, + sizeof(display_pkt), + "%s", + text); + } display_keys = keys; } diff --git a/core/MenuStyle_Radio.h b/core/MenuStyle_Radio.h index a1b8971b..e8ba85f5 100644 --- a/core/MenuStyle_Radio.h +++ b/core/MenuStyle_Radio.h @@ -92,6 +92,7 @@ public: CRadioDisplay *MakeRadioDisplay(CRadioMenu *menu=NULL); void FreeRadioDisplay(CRadioDisplay *display); CRadioMenuPlayer *GetRadioMenuPlayer(int client); + IMenuPanel *MakeRadioDisplay(const char *str, int keys); private: CRadioMenuPlayer *m_players; CStack m_FreeDisplays; @@ -118,6 +119,8 @@ public: //IMenuPanel unsigned int GetCurrentKey(); bool SetCurrentKey(unsigned int key); int GetAmountRemaining(); +public: + void DirectSet(const char *str, int keymap); private: String m_BufferText; String m_Title; diff --git a/core/smn_menus.cpp b/core/smn_menus.cpp index 4074c8df..22534c7e 100644 --- a/core/smn_menus.cpp +++ b/core/smn_menus.cpp @@ -37,6 +37,7 @@ #include "MenuStyle_Radio.h" #include "HandleSys.h" #include "PluginSys.h" +#include "PlayerManager.h" #include "sm_stringutil.h" #include "sourcemm_api.h" #if defined MENU_DEBUG @@ -1398,6 +1399,73 @@ static cell_t GetMenuSelectionPosition(IPluginContext *pContext, const cell_t *p return *s_CurSelectPosition; } +class EmptyMenuHandler : public IMenuHandler +{ +public: +} s_EmptyMenuHandler; + +static cell_t InternalShowMenu(IPluginContext *pContext, const cell_t *params) +{ + int client = params[1]; + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); + + if (pPlayer == NULL) + { + return pContext->ThrowNativeError("Invalid client index %d", client); + } + else if (!pPlayer->IsInGame()) + { + return pContext->ThrowNativeError("Client %d is not in game", client); + } + + if (!g_RadioMenuStyle.IsSupported()) + { + return pContext->ThrowNativeError("Radio menus are not supported on this mod"); + } + + char *str; + pContext->LocalToString(params[2], &str); + + IMenuPanel *pPanel = g_RadioMenuStyle.MakeRadioDisplay(str, params[4]); + + if (pPanel == NULL) + { + return 0; + } + + IMenuHandler *pHandler; + CPanelHandler *pActualHandler = NULL; + if (params[5] != -1) + { + IPluginFunction *pFunction = pContext->GetFunctionById(params[5]); + if (pFunction == NULL) + { + return pContext->ThrowNativeError("Invalid function index %x", params[5]); + } + pActualHandler = g_MenuHelpers.GetPanelHandler(pFunction); + } + + if (pActualHandler == NULL) + { + pHandler = &s_EmptyMenuHandler; + } + else + { + pHandler = pActualHandler; + } + + bool bSuccess = pPanel->SendDisplay(client, pHandler, params[3]); + + pPanel->DeleteThis(); + + if (!bSuccess && pActualHandler != NULL) + { + g_MenuHelpers.FreePanelHandler(pActualHandler); + } + + return bSuccess ? 1 : 0; +} + REGISTER_NATIVES(menuNatives) { {"AddMenuItem", AddMenuItem}, @@ -1430,6 +1498,7 @@ REGISTER_NATIVES(menuNatives) {"GetPanelCurrentKey", GetPanelCurrentKey}, {"GetPanelStyle", GetPanelStyle}, {"InsertMenuItem", InsertMenuItem}, + {"InternalShowMenu", InternalShowMenu}, {"IsVoteInProgress", IsVoteInProgress}, {"RedrawMenuItem", RedrawMenuItem}, {"RemoveAllMenuItems", RemoveAllMenuItems}, diff --git a/plugins/include/menus.inc b/plugins/include/menus.inc index 90559b0c..7bac6f76 100644 --- a/plugins/include/menus.inc +++ b/plugins/include/menus.inc @@ -732,6 +732,26 @@ native bool:SetPanelCurrentKey(Handle:panel, key); */ native RedrawMenuItem(const String:text[]); +/** + * This function is provided for legacy code only. Some older plugins may use + * network messages instead of the panel API. This function wraps the panel + * API for eased portability into the SourceMod menu system. + * + * This function is only usable with the Radio Menu style. You do not need to + * split up your menu into multiple packets; SourceMod will break the string + * up internally. + * + * @param client Client index. + * @param str Full menu string as would be passed over the network. + * @param time Time to hold the menu for. + * @param keys Selectable key bitstring. + * @param handler Optional handler function, with the same rules as + * SendPanelToClient(). + * @return True on success, false on failure. + * @error Invalid client index, or radio menus not supported. + */ +native bool:InternalShowMenu(client, const String:str[], time, keys=-1, MenuHandler:handler=MenuHandler:-1); + /** * Retrieves voting information from MenuAction_VoteEnd. *