extensions/topmenus/smn_topmenus.cpp
author David Anderson <dvander@alliedmods.net>
Mon Oct 22 07:27:48 2007 +0000 (2007-10-22)
changeset 1635 e0c3f991ec94
parent 1634 241bf59d8f4d
child 1699 4368f4cc417b
child 1715 f9ecab642e25
permissions -rw-r--r--
fixed a compatibility bug in AddToTopMenu()
dvander@1495
     1
/**
dvander@1495
     2
 * vim: set ts=4 :
dvander@1495
     3
 * =============================================================================
dvander@1495
     4
 * SourceMod Sample Extension
dvander@1495
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
dvander@1495
     6
 * =============================================================================
dvander@1495
     7
 *
dvander@1495
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@1495
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@1495
    10
 * Free Software Foundation.
dvander@1495
    11
 * 
dvander@1495
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@1495
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@1495
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@1495
    15
 * details.
dvander@1495
    16
 *
dvander@1495
    17
 * You should have received a copy of the GNU General Public License along with
dvander@1495
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1495
    19
 *
dvander@1495
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@1495
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@1495
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@1495
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@1495
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@1495
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@1495
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@1495
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@1495
    28
 *
dvander@1495
    29
 * Version: $Id$
dvander@1495
    30
 */
dvander@1495
    31
dvander@1495
    32
#include "extension.h"
dvander@1495
    33
#include "TopMenuManager.h"
dvander@1495
    34
#include "TopMenu.h"
dvander@1495
    35
dvander@1495
    36
HandleType_t hTopMenuType;
dvander@1495
    37
dvander@1495
    38
class TopMenuHandle : public IHandleTypeDispatch
dvander@1495
    39
{
dvander@1495
    40
public: 
dvander@1495
    41
	void OnHandleDestroy(HandleType_t type, void *object)
dvander@1495
    42
	{
dvander@1495
    43
		ITopMenu *pTopMenu = (ITopMenu *)object;
dvander@1495
    44
		g_TopMenus.DestroyTopMenu(pTopMenu);
dvander@1495
    45
	}
dvander@1495
    46
} s_TopMenuHandle;
dvander@1495
    47
dvander@1495
    48
void Initialize_Natives()
dvander@1495
    49
{
dvander@1495
    50
	hTopMenuType = handlesys->CreateType("ITopMenu",
dvander@1495
    51
		&s_TopMenuHandle,
dvander@1495
    52
		0,
dvander@1495
    53
		NULL,
dvander@1495
    54
		NULL,
dvander@1495
    55
		myself->GetIdentity(),
dvander@1495
    56
		NULL);
dvander@1495
    57
}
dvander@1495
    58
dvander@1495
    59
void Shutdown_Natives()
dvander@1495
    60
{
dvander@1495
    61
	handlesys->RemoveType(hTopMenuType, myself->GetIdentity());
dvander@1495
    62
}
dvander@1495
    63
dvander@1495
    64
enum TopMenuAction
dvander@1495
    65
{
dvander@1526
    66
	TopMenuAction_DisplayOption = 0,
dvander@1526
    67
	TopMenuAction_DisplayTitle = 1,
dvander@1495
    68
	TopMenuAction_SelectOption = 2,
dvander@1526
    69
	TopMenuAction_DrawOption = 3,
dvander@1634
    70
	TopMenuAction_RemoveObject = 4,
dvander@1495
    71
};
dvander@1495
    72
dvander@1495
    73
class TopMenuCallbacks : public ITopMenuObjectCallbacks
dvander@1495
    74
{
dvander@1495
    75
public:
dvander@1495
    76
	TopMenuCallbacks(IPluginFunction *pFunction) : m_pFunction(pFunction)
dvander@1495
    77
	{		
dvander@1495
    78
	}
dvander@1495
    79
dvander@1495
    80
	unsigned int OnTopMenuDrawOption(ITopMenu *menu,
dvander@1526
    81
		int client,
dvander@1526
    82
		unsigned int object_id)
dvander@1526
    83
	{
dvander@1526
    84
		char buffer[2] = {ITEMDRAW_DEFAULT, 0x0};
dvander@1526
    85
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1526
    86
		m_pFunction->PushCell(TopMenuAction_DrawOption);
dvander@1526
    87
		m_pFunction->PushCell(object_id);
dvander@1526
    88
		m_pFunction->PushCell(client);
dvander@1527
    89
		m_pFunction->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
dvander@1526
    90
		m_pFunction->PushCell(sizeof(buffer));
dvander@1526
    91
		m_pFunction->Execute(NULL);
dvander@1526
    92
		return (unsigned int)buffer[0];
dvander@1526
    93
	}
dvander@1526
    94
dvander@1526
    95
	void OnTopMenuDisplayOption(ITopMenu *menu,
dvander@1495
    96
		int client, 
dvander@1495
    97
		unsigned int object_id,
dvander@1495
    98
		char buffer[], 
dvander@1495
    99
		size_t maxlength)
dvander@1495
   100
	{
dvander@1495
   101
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1526
   102
		m_pFunction->PushCell(TopMenuAction_DisplayOption);
dvander@1496
   103
		m_pFunction->PushCell(object_id);
dvander@1495
   104
		m_pFunction->PushCell(client);
dvander@1495
   105
		m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
dvander@1495
   106
		m_pFunction->PushCell(maxlength);
dvander@1526
   107
		m_pFunction->Execute(NULL);
dvander@1495
   108
	}
dvander@1495
   109
dvander@1526
   110
	void OnTopMenuDisplayTitle(ITopMenu *menu,
dvander@1495
   111
		int client,
dvander@1495
   112
		unsigned int object_id,
dvander@1495
   113
		char buffer[],
dvander@1495
   114
		size_t maxlength)
dvander@1495
   115
	{
dvander@1495
   116
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1526
   117
		m_pFunction->PushCell(TopMenuAction_DisplayTitle);
dvander@1496
   118
		m_pFunction->PushCell(object_id);
dvander@1495
   119
		m_pFunction->PushCell(client);
dvander@1495
   120
		m_pFunction->PushStringEx(buffer, maxlength, 0, SM_PARAM_COPYBACK);
dvander@1495
   121
		m_pFunction->PushCell(maxlength);
dvander@1495
   122
		m_pFunction->Execute(NULL);
dvander@1495
   123
	}
dvander@1495
   124
dvander@1495
   125
	void OnTopMenuSelectOption(ITopMenu *menu, 
dvander@1495
   126
		int client, 
dvander@1495
   127
		unsigned int object_id)
dvander@1495
   128
	{
dvander@1520
   129
		unsigned int old_reply = playerhelpers->SetReplyTo(SM_REPLY_CHAT);
dvander@1495
   130
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1496
   131
		m_pFunction->PushCell(TopMenuAction_SelectOption);
dvander@1496
   132
		m_pFunction->PushCell(object_id);
dvander@1495
   133
		m_pFunction->PushCell(client);
dvander@1495
   134
		m_pFunction->PushString("");
dvander@1495
   135
		m_pFunction->PushCell(0);
dvander@1495
   136
		m_pFunction->Execute(NULL);
dvander@1520
   137
		playerhelpers->SetReplyTo(old_reply);
dvander@1495
   138
	}
dvander@1495
   139
dvander@1495
   140
	void OnTopMenuObjectRemoved(ITopMenu *menu, unsigned int object_id)
dvander@1495
   141
	{
dvander@1634
   142
		m_pFunction->PushCell(m_hMenuHandle);
dvander@1634
   143
		m_pFunction->PushCell(TopMenuAction_RemoveObject);
dvander@1634
   144
		m_pFunction->PushCell(object_id);
dvander@1634
   145
		m_pFunction->PushCell(0);
dvander@1634
   146
		m_pFunction->PushString("");
dvander@1634
   147
		m_pFunction->PushCell(0);
dvander@1634
   148
		m_pFunction->Execute(NULL);
dvander@1634
   149
dvander@1495
   150
		delete this;
dvander@1495
   151
	}
dvander@1495
   152
dvander@1495
   153
	Handle_t m_hMenuHandle;
dvander@1495
   154
	IPluginFunction *m_pFunction;
dvander@1495
   155
};
dvander@1495
   156
dvander@1495
   157
static cell_t CreateTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1495
   158
{
dvander@1495
   159
	IPluginFunction *func = pContext->GetFunctionById(params[1]);
dvander@1495
   160
	if (func == NULL)
dvander@1495
   161
	{
dvander@1495
   162
		return pContext	->ThrowNativeError("Invalid function specified");
dvander@1495
   163
	}
dvander@1495
   164
dvander@1495
   165
	TopMenuCallbacks *cb = new TopMenuCallbacks(func);
dvander@1495
   166
dvander@1495
   167
	ITopMenu *pMenu = g_TopMenus.CreateTopMenu(cb);
dvander@1495
   168
dvander@1495
   169
	if (!pMenu)
dvander@1495
   170
	{
dvander@1495
   171
		delete cb;
dvander@1495
   172
		return BAD_HANDLE;
dvander@1495
   173
	}
dvander@1495
   174
dvander@1495
   175
	Handle_t hndl = handlesys->CreateHandle(hTopMenuType, 
dvander@1495
   176
		pMenu,
dvander@1495
   177
		pContext->GetIdentity(),
dvander@1495
   178
		myself->GetIdentity(),
dvander@1495
   179
		NULL);
dvander@1495
   180
	if (hndl == 0)
dvander@1495
   181
	{
dvander@1495
   182
		g_TopMenus.DestroyTopMenu(pMenu);
dvander@1495
   183
		return BAD_HANDLE;
dvander@1495
   184
	}
dvander@1495
   185
dvander@1496
   186
	cb->m_hMenuHandle = hndl;
dvander@1496
   187
dvander@1495
   188
	return hndl;
dvander@1495
   189
}
dvander@1495
   190
dvander@1495
   191
static cell_t LoadTopMenuConfig(IPluginContext *pContext, const cell_t *params)
dvander@1495
   192
{
dvander@1495
   193
	HandleError err;
dvander@1495
   194
	ITopMenu *pMenu;
dvander@1495
   195
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1495
   196
dvander@1495
   197
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1495
   198
		!= HandleError_None)
dvander@1495
   199
	{
dvander@1495
   200
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1495
   201
	}
dvander@1495
   202
dvander@1495
   203
	char *file, *err_buf;
dvander@1495
   204
	pContext->LocalToString(params[2], &file);
dvander@1495
   205
	pContext->LocalToString(params[3], &err_buf);
dvander@1495
   206
dvander@1495
   207
	char path[PLATFORM_MAX_PATH];
dvander@1495
   208
	g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
dvander@1495
   209
dvander@1495
   210
	return pMenu->LoadConfiguration(path, err_buf, params[4]) ? 1 : 0;
dvander@1495
   211
}
dvander@1495
   212
dvander@1495
   213
static cell_t AddToTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1495
   214
{
dvander@1495
   215
	HandleError err;
dvander@1495
   216
	ITopMenu *pMenu;
dvander@1495
   217
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1495
   218
dvander@1495
   219
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1495
   220
		!= HandleError_None)
dvander@1495
   221
	{
dvander@1495
   222
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1495
   223
	}
dvander@1495
   224
dvander@1497
   225
	IPluginFunction *func = pContext->GetFunctionById(params[4]);
dvander@1495
   226
	if (func == NULL)
dvander@1495
   227
	{
dvander@1495
   228
		return pContext	->ThrowNativeError("Invalid function specified");
dvander@1495
   229
	}
dvander@1495
   230
dvander@1495
   231
	TopMenuCallbacks *cb = new TopMenuCallbacks(func);
dvander@1495
   232
dvander@1635
   233
	char *name, *cmdname, *info_string = NULL;
dvander@1495
   234
	pContext->LocalToString(params[2], &name);
dvander@1496
   235
	pContext->LocalToString(params[6], &cmdname);
dvander@1495
   236
dvander@1634
   237
	if (params[0] >= 8)
dvander@1634
   238
	{
dvander@1634
   239
		pContext->LocalToString(params[8], &info_string);
dvander@1634
   240
	}
dvander@1634
   241
dvander@1495
   242
	TopMenuObjectType obj_type = (TopMenuObjectType)params[3];
dvander@1495
   243
	
dvander@1495
   244
	unsigned int object_id;
dvander@1634
   245
	if ((object_id = pMenu->AddToMenu2(name,
dvander@1495
   246
		obj_type,
dvander@1495
   247
		cb,
dvander@1495
   248
		pContext->GetIdentity(),
dvander@1496
   249
		cmdname,
dvander@1496
   250
		params[7], 
dvander@1634
   251
		params[5],
dvander@1634
   252
		info_string)) == 0)
dvander@1495
   253
	{
dvander@1495
   254
		delete cb;
dvander@1495
   255
		return 0;
dvander@1495
   256
	}
dvander@1495
   257
dvander@1520
   258
	cb->m_hMenuHandle = params[1];
dvander@1520
   259
dvander@1495
   260
	return object_id;
dvander@1495
   261
}
dvander@1495
   262
dvander@1495
   263
static cell_t RemoveFromTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1495
   264
{
dvander@1495
   265
	HandleError err;
dvander@1495
   266
	ITopMenu *pMenu;
dvander@1495
   267
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1495
   268
dvander@1495
   269
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1495
   270
		!= HandleError_None)
dvander@1495
   271
	{
dvander@1495
   272
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1495
   273
	}
dvander@1495
   274
dvander@1495
   275
	pMenu->RemoveFromMenu(params[2]);
dvander@1495
   276
dvander@1495
   277
	return 1;
dvander@1495
   278
}
dvander@1495
   279
dvander@1495
   280
static cell_t FindTopMenuCategory(IPluginContext *pContext, const cell_t *params)
dvander@1495
   281
{
dvander@1495
   282
	HandleError err;
dvander@1495
   283
	ITopMenu *pMenu;
dvander@1495
   284
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1495
   285
dvander@1495
   286
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1495
   287
		!= HandleError_None)
dvander@1495
   288
	{
dvander@1495
   289
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1495
   290
	}
dvander@1495
   291
dvander@1495
   292
	char *name;
dvander@1495
   293
	pContext->LocalToString(params[2], &name);
dvander@1495
   294
dvander@1495
   295
	return pMenu->FindCategory(name);
dvander@1495
   296
}
dvander@1495
   297
dvander@1496
   298
static cell_t DisplayTopMenu(IPluginContext *pContext, const cell_t *params)
dvander@1496
   299
{
dvander@1496
   300
	HandleError err;
dvander@1496
   301
	ITopMenu *pMenu;
dvander@1496
   302
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1496
   303
dvander@1496
   304
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1496
   305
		!= HandleError_None)
dvander@1496
   306
	{
dvander@1496
   307
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1496
   308
	}
dvander@1496
   309
dvander@1496
   310
	int client = params[2];
dvander@1496
   311
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
dvander@1496
   312
	if (!player)
dvander@1496
   313
	{
dvander@1496
   314
		return pContext->ThrowNativeError("Invalid client index %d", client);
dvander@1496
   315
	}
dvander@1496
   316
	else if (!player->IsInGame())
dvander@1496
   317
	{
dvander@1496
   318
		return pContext->ThrowNativeError("Client %d is not in game", client);
dvander@1496
   319
	}
dvander@1496
   320
dvander@1496
   321
	return pMenu->DisplayMenu(client, 0, (TopMenuPosition)params[3]);
dvander@1496
   322
}
dvander@1496
   323
dvander@1634
   324
static cell_t GetTopMenuInfoString(IPluginContext *pContext, const cell_t *params)
dvander@1634
   325
{
dvander@1634
   326
	HandleError err;
dvander@1634
   327
	ITopMenu *pMenu;
dvander@1634
   328
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@1634
   329
dvander@1634
   330
	if ((err = handlesys->ReadHandle(params[1], hTopMenuType, &sec, (void **)&pMenu))
dvander@1634
   331
		!= HandleError_None)
dvander@1634
   332
	{
dvander@1634
   333
		return pContext->ThrowNativeError("Invalid Handle %x (error: %d)", params[1], err);
dvander@1634
   334
	}
dvander@1634
   335
dvander@1634
   336
	const char *str;
dvander@1634
   337
	if ((str = pMenu->GetObjectInfoString(params[2])) == NULL)
dvander@1634
   338
	{
dvander@1634
   339
		return pContext->ThrowNativeError("Invalid menu object %d", params[2]);
dvander@1634
   340
	}
dvander@1634
   341
dvander@1634
   342
	char *buffer;
dvander@1634
   343
	pContext->LocalToString(params[3], &buffer);
dvander@1634
   344
dvander@1634
   345
	return strncopy(buffer, str, params[4]);
dvander@1634
   346
}
dvander@1634
   347
dvander@1495
   348
sp_nativeinfo_t g_TopMenuNatives[] = 
dvander@1495
   349
{
dvander@1634
   350
	{"AddToTopMenu",			AddToTopMenu},
dvander@1634
   351
	{"CreateTopMenu",			CreateTopMenu},
dvander@1634
   352
	{"DisplayTopMenu",			DisplayTopMenu},
dvander@1634
   353
	{"LoadTopMenuConfig",		LoadTopMenuConfig},
dvander@1634
   354
	{"RemoveFromTopMenu",		RemoveFromTopMenu},
dvander@1634
   355
	{"FindTopMenuCategory",		FindTopMenuCategory},
dvander@1634
   356
	{"GetTopMenuInfoString",	GetTopMenuInfoString},
dvander@1495
   357
	{NULL,					NULL},
dvander@1495
   358
};