--HG-- branch : refac-jit extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/refac-jit%402369
		
			
				
	
	
		
			389 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			389 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * 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]);
 | 
						|
}
 | 
						|
 | 
						|
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]);
 | 
						|
}
 | 
						|
 | 
						|
sp_nativeinfo_t g_TopMenuNatives[] = 
 | 
						|
{
 | 
						|
	{"AddToTopMenu",			AddToTopMenu},
 | 
						|
	{"CreateTopMenu",			CreateTopMenu},
 | 
						|
	{"DisplayTopMenu",			DisplayTopMenu},
 | 
						|
	{"LoadTopMenuConfig",		LoadTopMenuConfig},
 | 
						|
	{"RemoveFromTopMenu",		RemoveFromTopMenu},
 | 
						|
	{"FindTopMenuCategory",		FindTopMenuCategory},
 | 
						|
	{"GetTopMenuInfoString",	GetTopMenuInfoString},
 | 
						|
	{"GetTopMenuObjName",		GetTopMenuName},
 | 
						|
	{NULL,					NULL},
 | 
						|
};
 |