extensions/clientprefs/natives.cpp
author Matt Woodrow <pred@alliedmods.net>
Tue Jul 15 00:24:08 2008 +0000 (2008-07-15)
changeset 2207 3a97a56ded62
parent 2048 2454ff4d6afb
child 2668 a6c7e8d7f8c9
permissions -rw-r--r--
Fixed amb1810 - Clientprefs no longer blocks load.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod Client Preferences Extension
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "extension.h"
    33 #include "cookie.h"
    34 #include "menus.h"
    35 
    36 cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
    37 {
    38 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    39 	{
    40 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    41 	}
    42 
    43 	char *name;
    44 	pContext->LocalToString(params[1], &name);
    45 
    46 	if (name[0] == '\0')
    47 	{
    48 		return pContext->ThrowNativeError("Cannot create preference cookie with no name");
    49 	}
    50 
    51 	char *desc;
    52 	pContext->LocalToString(params[2], &desc);
    53 
    54 	Cookie *pCookie = g_CookieManager.CreateCookie(name, desc, (CookieAccess)params[3]);
    55 
    56 	if (!pCookie)
    57 	{
    58 		return BAD_HANDLE;
    59 	}
    60 
    61 	return handlesys->CreateHandle(g_CookieType, 
    62 		pCookie, 
    63 		pContext->GetIdentity(), 
    64 		myself->GetIdentity(), 
    65 		NULL);
    66 }
    67 
    68 cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params)
    69 {
    70 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    71 	{
    72 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    73 	}
    74 
    75 	char *name;
    76 	pContext->LocalToString(params[1], &name);
    77 
    78 	Cookie *pCookie = g_CookieManager.FindCookie(name);
    79 
    80 	if (!pCookie)
    81 	{
    82 		return BAD_HANDLE;
    83 	}
    84 
    85 	return handlesys->CreateHandle(g_CookieType, 
    86 		pCookie, 
    87 		pContext->GetIdentity(), 
    88 		myself->GetIdentity(), 
    89 		NULL);
    90 }
    91 
    92 cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
    93 {
    94 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    95 	{
    96 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    97 	}
    98 
    99 	int client = params[1];
   100 
   101 	if ((client < 1) || (client > playerhelpers->GetMaxClients()))
   102 	{
   103 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   104 	}
   105 
   106 	Handle_t hndl = static_cast<Handle_t>(params[2]);
   107 	HandleError err;
   108 	HandleSecurity sec;
   109  
   110 	sec.pOwner = NULL;
   111 	sec.pIdentity = myself->GetIdentity();
   112 
   113 	Cookie *pCookie;
   114 
   115 	if ((err = handlesys->ReadHandle(hndl, g_CookieType, &sec, (void **)&pCookie))
   116 	     != HandleError_None)
   117 	{
   118 		return pContext->ThrowNativeError("Invalid Cookie handle %x (error %d)", hndl, err);
   119 	}
   120 
   121 	char *value;
   122 	pContext->LocalToString(params[3], &value);
   123 
   124 	return g_CookieManager.SetCookieValue(pCookie, client, value);
   125 }
   126 
   127 cell_t GetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
   128 {
   129 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   130 	{
   131 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   132 	}
   133 
   134 	int client = params[1];
   135 
   136 	if ((client < 1) || (client > playerhelpers->GetMaxClients()))
   137 	{
   138 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   139 	}
   140 
   141 	Handle_t hndl = static_cast<Handle_t>(params[2]);
   142 	HandleError err;
   143 	HandleSecurity sec;
   144  
   145 	sec.pOwner = NULL;
   146 	sec.pIdentity = myself->GetIdentity();
   147 
   148 	Cookie *pCookie;
   149 
   150 	if ((err = handlesys->ReadHandle(hndl, g_CookieType, &sec, (void **)&pCookie))
   151 	     != HandleError_None)
   152 	{
   153 		return pContext->ThrowNativeError("Invalid Cookie handle %x (error %d)", hndl, err);
   154 	}
   155 	
   156 	char *value = NULL;
   157 
   158 	g_CookieManager.GetCookieValue(pCookie, client, &value);
   159 
   160 	pContext->StringToLocal(params[3], params[4], value);
   161 
   162 	return 1;
   163 }
   164 
   165 cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params)
   166 {
   167 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   168 	{
   169 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   170 	}
   171 
   172 	int client = params[1];
   173 
   174 	if ((client < 1) || (client > playerhelpers->GetMaxClients()))
   175 	{
   176 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   177 	}
   178 
   179 	return g_CookieManager.AreClientCookiesCached(client);
   180 }
   181 
   182 cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params)
   183 {
   184 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   185 	{
   186 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   187 	}
   188 
   189 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   190 	HandleError err;
   191 	HandleSecurity sec;
   192  
   193 	sec.pOwner = NULL;
   194 	sec.pIdentity = myself->GetIdentity();
   195 
   196 	Cookie *pCookie;
   197 
   198 	if ((err = handlesys->ReadHandle(hndl, g_CookieType, &sec, (void **)&pCookie))
   199 	     != HandleError_None)
   200 	{
   201 		return pContext->ThrowNativeError("Invalid Cookie handle %x (error %d)", hndl, err);
   202 	}
   203 
   204 	return pCookie->access;
   205 }
   206 
   207 static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params)
   208 {
   209 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   210 	{
   211 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   212 	}
   213 
   214 	SourceHook::List<Cookie *>::iterator *iter = new SourceHook::List<Cookie *>::iterator;
   215 	*iter = g_CookieManager.cookieList.begin();
   216 
   217 	Handle_t hndl = handlesys->CreateHandle(g_CookieIterator, iter, pContext->GetIdentity(), myself->GetIdentity(), NULL);
   218 	if (hndl == BAD_HANDLE)
   219 	{
   220 		delete iter;
   221 	}
   222 
   223 	return hndl;
   224 }
   225 
   226 static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params)
   227 {
   228 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   229 	{
   230 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   231 	}
   232 
   233 	SourceHook::List<Cookie *>::iterator *iter;
   234 
   235 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   236 	HandleError err;
   237 	HandleSecurity sec;
   238 
   239 	sec.pOwner = NULL;
   240 	sec.pIdentity = myself->GetIdentity();
   241 
   242 	if ((err = handlesys->ReadHandle(hndl, g_CookieIterator, &sec, (void **)&iter))
   243 	     != HandleError_None)
   244 	{
   245 		return pContext->ThrowNativeError("Invalid Cookie iterator handle %x (error %d)", hndl, err);
   246 	}
   247 
   248 	if (*iter == g_CookieManager.cookieList.end())
   249 	{
   250 		return 0;
   251 	}
   252 
   253 	Cookie *pCookie = (Cookie *)**iter;
   254 
   255 	(*iter)++;
   256 
   257 	pContext->StringToLocalUTF8(params[2], params[3], pCookie->name, NULL);
   258 	pContext->StringToLocalUTF8(params[5], params[6], pCookie->description, NULL);
   259 
   260 	cell_t *addr;
   261 	pContext->LocalToPhysAddr(params[4], &addr);
   262 	*addr = pCookie->access;
   263 
   264 	return 1;
   265 }
   266 
   267 cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params)
   268 {
   269 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   270 	{
   271 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   272 	}
   273 
   274 	char message[256];
   275 	Translate(message, sizeof(message), "%T:", 2, NULL, "Client Settings", &params[1]);
   276 
   277 	g_CookieManager.clientMenu->SetDefaultTitle(message);
   278 	g_CookieManager.clientMenu->Display(params[1], 0, NULL);
   279 
   280 	return 0;
   281 }
   282 
   283 cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
   284 {
   285 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   286 	{
   287 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   288 	}
   289 
   290 	char *display;
   291 	pContext->LocalToString(params[3], &display);
   292 
   293 	/* Register a callback */
   294 	ItemHandler *pItem = new ItemHandler;
   295 	pItem->isAutoMenu = false;
   296 	pItem->forward = forwards->CreateForwardEx(NULL, ET_Ignore, 5, NULL, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell);
   297 
   298 	pItem->forward->AddFunction(pContext, static_cast<funcid_t>(params[1]));
   299 
   300 	char info[20];
   301 	AutoMenuData *data = new AutoMenuData;
   302 	data->datavalue = params[2];
   303 	data->handler = pItem;
   304 	UTIL_Format(info, sizeof(info), "%x", data);
   305 
   306 	ItemDrawInfo draw(display, 0);
   307 
   308 	g_CookieManager.clientMenu->AppendItem(info, draw);
   309 
   310 	/* Track this in case the plugin unloads */
   311 
   312 	IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
   313 	SourceHook::List<char *> *pList = NULL;
   314 
   315 	if (!pPlugin->GetProperty("SettingsMenuItems", (void **)&pList, false) || !pList)
   316 	{
   317 		pList = new SourceHook::List<char *>;
   318 		pPlugin->SetProperty("SettingsMenuItems", pList);
   319 	}
   320 
   321 	char *copyarray = new char[strlen(display)+1];
   322 	UTIL_Format(copyarray, strlen(display)+1, "%s", display);
   323 
   324 	pList->push_back(copyarray);
   325 
   326 	return 0;
   327 }
   328 
   329 cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
   330 {
   331 	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   332 	{
   333 		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   334 	}
   335 
   336 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   337 	HandleError err;
   338 	HandleSecurity sec;
   339  
   340 	sec.pOwner = NULL;
   341 	sec.pIdentity = myself->GetIdentity();
   342 
   343 	Cookie *pCookie;
   344 
   345 	if ((err = handlesys->ReadHandle(hndl, g_CookieType, &sec, (void **)&pCookie))
   346 	     != HandleError_None)
   347 	{
   348 		return pContext->ThrowNativeError("Invalid Cookie handle %x (error %d)", hndl, err);
   349 	}
   350 
   351 	/* Register a callback */
   352 	ItemHandler *pItem = new ItemHandler;
   353 	pItem->isAutoMenu = true;
   354 	pItem->autoMenuType = (CookieMenu)params[2];
   355 
   356 
   357 	/* User passed a function id for a callback */
   358 	if (params[4] != -1)
   359 	{
   360 		pItem->forward = forwards->CreateForwardEx(NULL, ET_Ignore, 5, NULL, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell); 
   361 		pItem->forward->AddFunction(pContext, static_cast<funcid_t>(params[4]));
   362 	}
   363 	else
   364 	{
   365 		pItem->forward = NULL;
   366 	}
   367 
   368 	char *display;
   369 	pContext->LocalToString(params[3], &display);
   370 
   371 	ItemDrawInfo draw(display, 0);
   372 
   373 	char info[20];
   374 	AutoMenuData *data = new AutoMenuData;
   375 	data->datavalue = params[5];
   376 	data->pCookie = pCookie;
   377 	data->type = (CookieMenu)params[2];
   378 	data->handler = pItem;
   379 	UTIL_Format(info, sizeof(info), "%x", data);
   380 
   381 	g_CookieManager.clientMenu->AppendItem(info, draw);
   382 
   383 	/* Track this in case the plugin unloads */
   384 
   385 	IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
   386 	SourceHook::List<char *> *pList = NULL;
   387 
   388 	if (!pPlugin->GetProperty("SettingsMenuItems", (void **)&pList, false) || !pList)
   389 	{
   390 		pList = new SourceHook::List<char *>;
   391 		pPlugin->SetProperty("SettingsMenuItems", pList);
   392 	}
   393 
   394 	char *copyarray = new char[strlen(display)+1];
   395 	UTIL_Format(copyarray, strlen(display)+1, "%s", display);
   396 
   397 	pList->push_back(copyarray);
   398 
   399 	return 0;
   400 }
   401 
   402 sp_nativeinfo_t g_ClientPrefNatives[] = 
   403 {
   404 	{"RegClientCookie",				RegClientPrefCookie},
   405 	{"FindClientCookie",			FindClientPrefCookie},
   406 	{"SetClientCookie",				SetClientPrefCookie},
   407 	{"GetClientCookie",				GetClientPrefCookie},
   408 	{"AreClientCookiesCached",		AreClientCookiesCached},
   409 	{"GetCookieAccess",				GetCookieAccess},
   410 	{"ReadCookieIterator",			ReadCookieIterator},
   411 	{"GetCookieIterator",			GetCookieIterator},
   412 	{"ShowCookieMenu",				ShowSettingsMenu},
   413 	{"SetCookieMenuItem",			AddSettingsMenuItem},
   414 	{"SetCookiePrefabMenu",			AddSettingsPrefabMenuItem},
   415 	{NULL,							NULL}
   416 };