2008-04-11 19:16:36 +02:00
|
|
|
/**
|
|
|
|
* vim: set ts=4 :
|
|
|
|
* =============================================================================
|
|
|
|
* SourceMod TopMenus Extension
|
|
|
|
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
|
|
|
* =============================================================================
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
|
|
* Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
|
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
|
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
|
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
|
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
|
|
* this exception to all derivative works. AlliedModders LLC defines further
|
|
|
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
|
|
* or <http://www.sourcemod.net/license.php>.
|
|
|
|
*
|
|
|
|
* Version: $Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "extension.h"
|
|
|
|
#include "TopMenuManager.h"
|
|
|
|
#include "TopMenu.h"
|
|
|
|
|
|
|
|
HandleType_t hTopMenuType;
|
|
|
|
|
|
|
|
class TopMenuHandle : public IHandleTypeDispatch
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void OnHandleDestroy(HandleType_t type, void *object)
|
|
|
|
{
|
|
|
|
ITopMenu *pTopMenu = (ITopMenu *)object;
|
|
|
|
g_TopMenus.DestroyTopMenu(pTopMenu);
|
|
|
|
}
|
|
|
|
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
|
|
|
|
{
|
|
|
|
*pSize = ((TopMenu *)object)->CalcMemUsage();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} s_TopMenuHandle;
|
|
|
|
|
|
|
|
void Initialize_Natives()
|
|
|
|
{
|
|
|
|
hTopMenuType = handlesys->CreateType("ITopMenu",
|
|
|
|
&s_TopMenuHandle,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
myself->GetIdentity(),
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shutdown_Natives()
|
|
|
|
{
|
|
|
|
handlesys->RemoveType(hTopMenuType, myself->GetIdentity());
|
|
|
|
}
|
|
|
|
|
|
|
|
enum TopMenuAction
|
|
|
|
{
|
|
|
|
TopMenuAction_DisplayOption = 0,
|
|
|
|
TopMenuAction_DisplayTitle = 1,
|
|
|
|
TopMenuAction_SelectOption = 2,
|
|
|
|
TopMenuAction_DrawOption = 3,
|
|
|
|
TopMenuAction_RemoveObject = 4,
|
|
|
|
};
|
|
|
|
|
|
|
|
class TopMenuCallbacks : public ITopMenuObjectCallbacks
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TopMenuCallbacks(IPluginFunction *pFunction) : m_pFunction(pFunction)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int OnTopMenuDrawOption(ITopMenu *menu,
|
|
|
|
int client,
|
|
|
|
unsigned int object_id)
|
|
|
|
{
|
|
|
|
char buffer[2] = {ITEMDRAW_DEFAULT, 0x0};
|
|
|
|
m_pFunction->PushCell(m_hMenuHandle);
|
|
|
|
m_pFunction->PushCell(TopMenuAction_DrawOption);
|
|
|
|
m_pFunction->PushCell(object_id);
|
|
|
|
m_pFunction->PushCell(client);
|
|
|
|
m_pFunction->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
|
|
|
m_pFunction->PushCell(sizeof(buffer));
|
|
|
|
m_pFunction->Execute(NULL);
|
|
|
|
return (unsigned int)buffer[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnTopMenuDisplayOption(ITopMenu *menu,
|
|
|
|
int client,
|
|
|
|
unsigned int object_id,
|
|
|
|
char buffer[],
|
|
|
|
size_t maxlength)
|
|
|
|
{
|
|
|
|
m_pFunction->PushCell(m_hMenuHandle);
|
|
|
|
m_pFunction->PushCell(TopMenuAction_DisplayOption);
|
|
|
|
m_pFunction->PushCell(object_id);
|
|
|
|
m_pFunction->PushCell(client);
|
|
|
|
m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
|
|
|
|
m_pFunction->PushCell(maxlength);
|
|
|
|
m_pFunction->Execute(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnTopMenuDisplayTitle(ITopMenu *menu,
|
|
|
|
int client,
|
|
|
|
unsigned int object_id,
|
|
|
|
char buffer[],
|
|
|
|
size_t maxlength)
|
|
|
|
{
|
|
|
|
m_pFunction->PushCell(m_hMenuHandle);
|
|
|
|
m_pFunction->PushCell(TopMenuAction_DisplayTitle);
|
|
|
|
m_pFunction->PushCell(object_id);
|
|
|
|
m_pFunction->PushCell(client);
|
|
|
|
m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
|
|
|
|
m_pFunction->PushCell(maxlength);
|
|
|
|
m_pFunction->Execute(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnTopMenuSelectOption(ITopMenu *menu,
|
|
|
|
int client,
|
|
|
|
unsigned int object_id)
|
|
|
|
{
|
|
|
|
unsigned int old_reply = playerhelpers->SetReplyTo(SM_REPLY_CHAT);
|
|
|
|
m_pFunction->PushCell(m_hMenuHandle);
|
|
|
|
m_pFunction->PushCell(TopMenuAction_SelectOption);
|
|
|
|
m_pFunction->PushCell(object_id);
|
|
|
|
m_pFunction->PushCell(client);
|
|
|
|
m_pFunction->PushString("");
|
|
|
|
m_pFunction->PushCell(0);
|
|
|
|
m_pFunction->Execute(NULL);
|
|
|
|
playerhelpers->SetReplyTo(old_reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnTopMenuObjectRemoved(ITopMenu *menu, unsigned int object_id)
|
|
|
|
{
|
|
|
|
m_pFunction->PushCell(m_hMenuHandle);
|
|
|
|
m_pFunction->PushCell(TopMenuAction_RemoveObject);
|
|
|
|
m_pFunction->PushCell(object_id);
|
|
|
|
m_pFunction->PushCell(0);
|
|
|
|
m_pFunction->PushString("");
|
|
|
|
m_pFunction->PushCell(0);
|
|
|
|
m_pFunction->Execute(NULL);
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle_t m_hMenuHandle;
|
|
|
|
IPluginFunction *m_pFunction;
|
|
|
|
};
|
|
|
|
|
|
|
|
static cell_t CreateTopMenu(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
IPluginFunction *func = pContext->GetFunctionById(params[1]);
|
|
|
|
if (func == NULL)
|
|
|
|
{
|
|
|
|
return pContext ->ThrowNativeError("Invalid function specified");
|
|
|
|
}
|
|
|
|
|
|
|
|
TopMenuCallbacks *cb = new TopMenuCallbacks(func);
|
|
|
|
|
|
|
|
ITopMenu *pMenu = g_TopMenus.CreateTopMenu(cb);
|
|
|
|
|
|
|
|
if (!pMenu)
|
|
|
|
{
|
|
|
|
delete cb;
|
|
|
|
return BAD_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Handle_t hndl = handlesys->CreateHandle(hTopMenuType,
|
|
|
|
pMenu,
|
|
|
|
pContext->GetIdentity(),
|
|
|
|
myself->GetIdentity(),
|
|
|
|
NULL);
|
|
|
|
if (hndl == 0)
|
|
|
|
{
|
|
|
|
g_TopMenus.DestroyTopMenu(pMenu);
|
|
|
|
return BAD_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb->m_hMenuHandle = hndl;
|
|
|
|
|
|
|
|
return hndl;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t LoadTopMenuConfig(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
ITopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *file, *err_buf;
|
|
|
|
pContext->LocalToString(params[2], &file);
|
|
|
|
pContext->LocalToString(params[3], &err_buf);
|
|
|
|
|
|
|
|
char path[PLATFORM_MAX_PATH];
|
|
|
|
g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
|
|
|
|
|
|
|
|
return pMenu->LoadConfiguration(path, err_buf, params[4]) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t AddToTopMenu(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
ITopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
IPluginFunction *func = pContext->GetFunctionById(params[4]);
|
|
|
|
if (func == NULL)
|
|
|
|
{
|
|
|
|
return pContext ->ThrowNativeError("Invalid function specified");
|
|
|
|
}
|
|
|
|
|
|
|
|
TopMenuCallbacks *cb = new TopMenuCallbacks(func);
|
|
|
|
|
|
|
|
char *name, *cmdname, *info_string = NULL;
|
|
|
|
pContext->LocalToString(params[2], &name);
|
|
|
|
pContext->LocalToString(params[6], &cmdname);
|
|
|
|
|
|
|
|
if (params[0] >= 8)
|
|
|
|
{
|
|
|
|
pContext->LocalToString(params[8], &info_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
TopMenuObjectType obj_type = (TopMenuObjectType)params[3];
|
|
|
|
|
|
|
|
unsigned int object_id;
|
|
|
|
if ((object_id = pMenu->AddToMenu2(name,
|
|
|
|
obj_type,
|
|
|
|
cb,
|
|
|
|
pContext->GetIdentity(),
|
|
|
|
cmdname,
|
|
|
|
params[7],
|
|
|
|
params[5],
|
|
|
|
info_string)) == 0)
|
|
|
|
{
|
|
|
|
delete cb;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cb->m_hMenuHandle = params[1];
|
|
|
|
|
|
|
|
return object_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t RemoveFromTopMenu(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
ITopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
pMenu->RemoveFromMenu(params[2]);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t FindTopMenuCategory(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
ITopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *name;
|
|
|
|
pContext->LocalToString(params[2], &name);
|
|
|
|
|
|
|
|
return pMenu->FindCategory(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t DisplayTopMenu(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
ITopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
int client = params[2];
|
|
|
|
IGamePlayer *player = playerhelpers->GetGamePlayer(client);
|
|
|
|
if (!player)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid client index %d", client);
|
|
|
|
}
|
|
|
|
else if (!player->IsInGame())
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Client %d is not in game", client);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pMenu->DisplayMenu(client, 0, (TopMenuPosition)params[3]);
|
|
|
|
}
|
|
|
|
|
2014-05-09 21:32:49 +02:00
|
|
|
static cell_t DisplayTopMenuCategory(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
TopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
int client = params[3];
|
|
|
|
IGamePlayer *player = playerhelpers->GetGamePlayer(client);
|
|
|
|
if (!player)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid client index %d", client);
|
|
|
|
}
|
|
|
|
else if (!player->IsInGame())
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Client %d is not in game", client);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pMenu->DisplayMenuAtCategory(client, params[2]);
|
|
|
|
}
|
|
|
|
|
2008-04-11 19:16:36 +02:00
|
|
|
static cell_t GetTopMenuInfoString(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
ITopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *str;
|
|
|
|
if ((str = pMenu->GetObjectInfoString(params[2])) == NULL)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid menu object %d", params[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *buffer;
|
|
|
|
pContext->LocalToString(params[3], &buffer);
|
|
|
|
|
|
|
|
return strncopy(buffer, str, params[4]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static cell_t GetTopMenuName(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
ITopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *str;
|
|
|
|
if ((str = pMenu->GetObjectName(params[2])) == NULL)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid menu object %d", params[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *buffer;
|
|
|
|
pContext->LocalToString(params[3], &buffer);
|
|
|
|
|
|
|
|
return strncopy(buffer, str, params[4]);
|
|
|
|
}
|
|
|
|
|
2014-05-09 21:30:52 +02:00
|
|
|
static cell_t SetTopMenuTitleCaching(IPluginContext *pContext, const cell_t *params)
|
|
|
|
{
|
|
|
|
HandleError err;
|
|
|
|
TopMenu *pMenu;
|
|
|
|
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
|
|
|
|
|
|
|
|
if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
|
|
|
|
!= HandleError_None)
|
|
|
|
{
|
|
|
|
return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cache_titles = params[2]==1?true:false;
|
|
|
|
pMenu->SetTitleCaching(cache_titles);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-11 19:16:36 +02:00
|
|
|
sp_nativeinfo_t g_TopMenuNatives[] =
|
|
|
|
{
|
|
|
|
{"AddToTopMenu", AddToTopMenu},
|
|
|
|
{"CreateTopMenu", CreateTopMenu},
|
|
|
|
{"DisplayTopMenu", DisplayTopMenu},
|
2014-05-09 21:32:49 +02:00
|
|
|
{"DisplayTopMenuCategory", DisplayTopMenuCategory},
|
2008-04-11 19:16:36 +02:00
|
|
|
{"LoadTopMenuConfig", LoadTopMenuConfig},
|
|
|
|
{"RemoveFromTopMenu", RemoveFromTopMenu},
|
|
|
|
{"FindTopMenuCategory", FindTopMenuCategory},
|
|
|
|
{"GetTopMenuInfoString", GetTopMenuInfoString},
|
|
|
|
{"GetTopMenuObjName", GetTopMenuName},
|
2014-05-09 21:30:52 +02:00
|
|
|
{"SetTopMenuTitleCaching", SetTopMenuTitleCaching},
|
2008-04-11 19:16:36 +02:00
|
|
|
{NULL, NULL},
|
|
|
|
};
|