CLIENT PREFS ARE GO!!1!shiftone!!1!

Fully implemented amb734 - Including console interface and menu for clients to use.

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402140
This commit is contained in:
Matt Woodrow 2008-05-12 08:06:47 +00:00
parent 6e91780e73
commit d88ba02fde
22 changed files with 1177 additions and 112 deletions

View File

@ -3,6 +3,7 @@ CREATE TABLE sm_cookies
id INTEGER unsigned NOT NULL auto_increment,
name varchar(30) NOT NULL UNIQUE,
description varchar(255),
access INTEGER,
PRIMARY KEY (id)
);

View File

@ -2,7 +2,8 @@ CREATE TABLE sm_cookies
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name varchar(30) NOT NULL UNIQUE,
description varchar(255)
description varchar(255),
access INTEGER
);
CREATE TABLE sm_cookie_cache

View File

@ -17,7 +17,7 @@ PROJECT = clientprefs
#Uncomment for Metamod: Source enabled extension
#USEMETA = true
OBJECTS = sdk/smsdk_ext.cpp extension.cpp query.cpp cookie.cpp natives.cpp
OBJECTS = sdk/smsdk_ext.cpp extension.cpp query.cpp cookie.cpp natives.cpp menus.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
@ -59,7 +59,8 @@ ifeq "$(USEMETA)" "true"
-I$(METAMOD) -I$(METAMOD)/sourcehook -I$(METAMOD)/sourcemm -I$(SMSDK)/public \
-I$(SMSDK)/public/sourcepawn
else
INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SOURCEMM16)/sourcehook
INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SOURCEMM16)/sourcehook \
-I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1
endif
LINK += -static-libgcc

View File

@ -30,6 +30,7 @@
*/
#include "cookie.h"
#include "menus.h"
#include "query.h"
CookieManager g_CookieManager;
@ -42,7 +43,8 @@ CookieManager::CookieManager()
statsLoaded[i] = false;
}
cookiesLoadedForward = NULL;
cookieDataLoadedForward = NULL;
clientMenu = NULL;
}
CookieManager::~CookieManager(){}
@ -97,26 +99,45 @@ Cookie *CookieManager::FindCookie(const char *name)
}
Cookie *CookieManager::CreateCookie(const char *name, const char *description)
Cookie *CookieManager::CreateCookie(const char *name, const char *description, CookieAccess access)
{
Cookie *pCookie = FindCookie(name);
/* Check if cookie already exists */
if (pCookie != NULL)
{
/* Update data fields to the provided values */
strncpy(pCookie->description, description, MAX_DESC_LENGTH);
pCookie->description[MAX_DESC_LENGTH-1] = '\0';
pCookie->access = access;
return pCookie;
}
/* First time cookie - Create from scratch */
pCookie = new Cookie(name, description);
pCookie = new Cookie(name, description, access);
cookieTrie.insert(name, pCookie);
cookieList.push_back(pCookie);
char quotedname[2 * MAX_NAME_LENGTH + 1];
char quoteddesc[2 * MAX_DESC_LENGTH + 1];
g_ClientPrefs.Database->QuoteString(pCookie->name, quotedname, sizeof(quotedname), NULL);
g_ClientPrefs.Database->QuoteString(pCookie->description, quoteddesc, sizeof(quoteddesc), NULL);
/* Attempt to load cookie from the db and get its ID num */
g_ClientPrefs.Query_InsertCookie->BindParamString(0, name, true);
g_ClientPrefs.Query_InsertCookie->BindParamString(1, description, true);
TQueryOp *op = new TQueryOp(g_ClientPrefs.Database, g_ClientPrefs.Query_InsertCookie, Query_InsertCookie, pCookie);
/* Attempt to insert cookie into the db and get its ID num */
char query[300];
if (driver == DRIVER_SQLITE)
{
UTIL_Format(query, sizeof(query), "INSERT OR IGNORE INTO sm_cookies(name, description, access) VALUES('%s', '%s', %i)", quotedname, quoteddesc, access);
}
else
{
UTIL_Format(query, sizeof(query), "INSERT IGNORE INTO sm_cookies(name, description, access) VALUES('%s', '%s', %i)", quotedname, quoteddesc, access);
}
TQueryOp *op = new TQueryOp(g_ClientPrefs.Database, query, Query_InsertCookie, pCookie);
dbi->AddToThreadQueue(op, PrioQueue_Normal);
return pCookie;
@ -177,8 +198,10 @@ void CookieManager::OnClientAuthorized(int client, const char *authstring)
{
connected[client] = true;
g_ClientPrefs.Query_SelectData->BindParamString(0, authstring, true);
TQueryOp *op = new TQueryOp(g_ClientPrefs.Database, g_ClientPrefs.Query_SelectData, Query_SelectData, client);
char query[300];
/* Assume that the authstring doesn't need to be quoted */
UTIL_Format(query, sizeof(query), "SELECT sm_cookies.name, sm_cookie_cache.value, sm_cookies.description, sm_cookies.access FROM sm_cookies JOIN sm_cookie_cache ON sm_cookies.id = sm_cookie_cache.cookie_id WHERE player = '%s'", authstring);
TQueryOp *op = new TQueryOp(g_ClientPrefs.Database, query, Query_SelectData, client);
dbi->AddToThreadQueue(op, PrioQueue_Normal);
}
@ -220,18 +243,20 @@ void CookieManager::OnClientDisconnecting(int client)
return;
}
g_ClientPrefs.Query_InsertData->BindParamString(0, player->GetAuthString(), true);
g_ClientPrefs.Query_InsertData->BindParamInt(1, dbId, false);
g_ClientPrefs.Query_InsertData->BindParamString(2, current->value, true);
g_ClientPrefs.Query_InsertData->BindParamInt(3, time(NULL), false);
char quotedvalue[2 * MAX_VALUE_LENGTH + 1];
g_ClientPrefs.Database->QuoteString(current->value, quotedvalue, sizeof(quotedvalue), NULL);
if (driver == DRIVER_MYSQL)
char query[300];
if (driver == DRIVER_SQLITE)
{
g_ClientPrefs.Query_InsertData->BindParamString(4, current->value, true);
g_ClientPrefs.Query_InsertData->BindParamInt(5, time(NULL), false);
UTIL_Format(query, sizeof(query), "INSERT OR REPLACE INTO sm_cookie_cache(player,cookie_id, value, timestamp) VALUES('%s', %i, '%s', %i)", player->GetAuthString(), dbId, quotedvalue, time(NULL));
}
else
{
UTIL_Format(query, sizeof(query), "INSERT INTO sm_cookie_cache(player,cookie_id, value, timestamp) VALUES('%s', %i, '%s', %i) ON DUPLICATE KEY UPDATE value = '%s', timestamp = %i", player->GetAuthString(), dbId, quotedvalue, time(NULL), quotedvalue, time(NULL));
}
TQueryOp *op = new TQueryOp(g_ClientPrefs.Database, g_ClientPrefs.Query_InsertData, Query_InsertData, client);
TQueryOp *op = new TQueryOp(g_ClientPrefs.Database, query, Query_InsertData, client);
dbi->AddToThreadQueue(op, PrioQueue_Normal);
current->parent->data[client] = NULL;
@ -241,7 +266,7 @@ void CookieManager::OnClientDisconnecting(int client)
}
}
void CookieManager::ClientConnectCallback(int client, IPreparedQuery *data)
void CookieManager::ClientConnectCallback(int client, IQuery *data)
{
IResultSet *results = data->GetResultSet();
if (results == NULL)
@ -274,7 +299,10 @@ void CookieManager::ClientConnectCallback(int client, IPreparedQuery *data)
const char *desc;
row->GetString(2, &desc, NULL);
parent = CreateCookie(name, desc);
CookieAccess access = CookieAccess_Public;
row->GetInt(3, (int *)&access);
parent = CreateCookie(name, desc, access);
cookieTrie.insert(name, parent);
cookieList.push_back(parent);
}
@ -286,15 +314,47 @@ void CookieManager::ClientConnectCallback(int client, IPreparedQuery *data)
} while (results->MoreRows());
statsLoaded[client] = true;
cookiesLoadedForward->PushCell(client);
cookiesLoadedForward->Execute(NULL);
cookieDataLoadedForward->PushCell(client);
cookieDataLoadedForward->Execute(NULL);
}
void CookieManager::InsertCookieCallback(Cookie *pCookie, int dbId)
{
pCookie->dbid = dbId;
if (dbId > 0)
{
pCookie->dbid = dbId;
return;
}
char quotedname[2 * MAX_NAME_LENGTH + 1];
g_ClientPrefs.Database->QuoteString(pCookie->name, quotedname, sizeof(quotedname), NULL);
char query[300];
UTIL_Format(query, sizeof(query), "SELECT id FROM sm_cookies WHERE name='%s'", quotedname);
TQueryOp *op = new TQueryOp(g_ClientPrefs.Database, query, Query_SelectId, pCookie);
dbi->AddToThreadQueue(op, PrioQueue_Normal);
}
void CookieManager::SelectIdCallback(Cookie *pCookie, IQuery *data)
{
IResultSet *results = data->GetResultSet();
if (results == NULL)
{
return;
}
IResultRow *row = results->FetchRow();
if (row == NULL)
{
return;
}
row->GetInt(0, &pCookie->dbid);
}
bool CookieManager::AreClientCookiesCached(int client)
@ -302,3 +362,51 @@ bool CookieManager::AreClientCookiesCached(int client)
return statsLoaded[client];
}
void CookieManager::OnPluginDestroyed(IPlugin *plugin)
{
SourceHook::List<char *> *pList;
if (plugin->GetProperty("SettingsMenuItems", (void **)&pList, true))
{
SourceHook::List<char *>::iterator p_iter = pList->begin();
char *name;
while (p_iter != pList->end())
{
name = (char *)*p_iter;
p_iter = pList->erase(p_iter); //remove from this plugins list
ItemDrawInfo draw;
for (unsigned int i=0; i<clientMenu->GetItemCount(); i++)
{
const char *info = clientMenu->GetItemInfo(i, &draw);
if (info == NULL)
{
continue;
}
if (strcmp(draw.display, name) == 0)
{
ItemDrawInfo draw;
const char *info = clientMenu->GetItemInfo(i, &draw);
AutoMenuData *data = (AutoMenuData *)strtol(info, NULL, 16);
if (data->handler->forward != NULL)
{
forwards->ReleaseForward(data->handler->forward);
}
delete data->handler;
delete data;
clientMenu->RemoveItem(i);
break;
}
}
delete name;
}
}
}

View File

@ -41,6 +41,13 @@
#define MAX_DESC_LENGTH 255
#define MAX_VALUE_LENGTH 100
enum CookieAccess
{
CookieAccess_Public, /**< Visible and Changeable by users */
CookieAccess_Protected, /**< Read only to users */
CookieAccess_Private, /**< Completely hidden cookie */
};
struct Cookie;
struct CookieData
@ -58,13 +65,15 @@ struct CookieData
struct Cookie
{
Cookie(const char *name, const char *description)
Cookie(const char *name, const char *description, CookieAccess access)
{
strncpy(this->name, name, MAX_NAME_LENGTH);
this->name[MAX_NAME_LENGTH-1] = '\0';
strncpy(this->description, description, MAX_DESC_LENGTH);
this->description[MAX_DESC_LENGTH-1] = '\0';
this->access = access;
dbid = -1;
for (int i=0; i<=MAXCLIENTS; i++)
@ -88,10 +97,10 @@ struct Cookie
char description[MAX_DESC_LENGTH];
int dbid;
CookieData *data[MAXCLIENTS+1];
CookieAccess access;
};
class CookieManager : public IClientListener
class CookieManager : public IClientListener, public IPluginsListener
{
public:
CookieManager();
@ -105,18 +114,24 @@ public:
void Unload();
void ClientConnectCallback(int client, IPreparedQuery *data);
void ClientConnectCallback(int client, IQuery *data);
void InsertCookieCallback(Cookie *pCookie, int dbId);
void SelectIdCallback(Cookie *pCookie, IQuery *data);
Cookie *FindCookie(const char *name);
Cookie *CreateCookie(const char *name, const char *description);
Cookie *CreateCookie(const char *name, const char *description, CookieAccess access);
bool AreClientCookiesCached(int client);
IForward *cookiesLoadedForward;
IForward *cookieDataLoadedForward;
SourceHook::List<Cookie *> cookieList;
IBaseMenu *clientMenu;
void OnPluginDestroyed(IPlugin *plugin);
private:
SourceHook::List<Cookie *> cookieList;
KTrie<Cookie *> cookieTrie;
SourceHook::List<CookieData *> clientData[MAXCLIENTS];

View File

@ -43,6 +43,9 @@ SMEXT_LINK(&g_ClientPrefs);
HandleType_t g_CookieType = 0;
CookieTypeHandler g_CookieTypeHandler;
HandleType_t g_CookieIterator = 0;
CookieIteratorHandler g_CookieIteratorHandler;
int driver = 0;
@ -100,44 +103,9 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
return false;
}
if (driver == DRIVER_SQLITE)
{
Query_InsertCookie = Database->PrepareQuery("INSERT OR IGNORE INTO sm_cookies(name, description) VALUES(?, ?)", error, maxlength);
}
else
{
Query_InsertCookie = Database->PrepareQuery("INSERT IGNORE INTO sm_cookies(name, description) VALUES(?, ?)", error, maxlength);
}
if (Query_InsertCookie == NULL)
{
return false;
}
Query_SelectData = Database->PrepareQuery("SELECT sm_cookies.name, sm_cookie_cache.value, sm_cookies.description FROM sm_cookies JOIN sm_cookie_cache ON sm_cookies.id = sm_cookie_cache.cookie_id WHERE player = ?", error, maxlength);
if (Query_SelectData == NULL)
{
return false;
}
if (driver == DRIVER_SQLITE)
{
Query_InsertData = Database->PrepareQuery("INSERT OR REPLACE INTO sm_cookie_cache(player,cookie_id, value, timestamp) VALUES(?, ?, ?, ?)", error, maxlength);
}
else
{
Query_InsertData = Database->PrepareQuery("INSERT INTO sm_cookie_cache(player,cookie_id, value, timestamp) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE value = ?, timestamp = ?", error, maxlength);
}
if (Query_InsertData == NULL)
{
return false;
}
sharesys->AddNatives(myself, g_ClientPrefNatives);
sharesys->RegisterLibrary(myself, "clientprefs");
g_CookieManager.cookiesLoadedForward = forwards->CreateForward("OnClientCookiesLoaded", ET_Ignore, 1, NULL, Param_Cell);
g_CookieManager.cookieDataLoadedForward = forwards->CreateForward("OnClientCookiesCached", ET_Ignore, 1, NULL, Param_Cell);
g_CookieType = handlesys->CreateType("Cookie",
&g_CookieTypeHandler,
@ -147,6 +115,25 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
myself->GetIdentity(),
NULL);
g_CookieIterator = handlesys->CreateType("CookieIterator",
&g_CookieIteratorHandler,
0,
NULL,
NULL,
myself->GetIdentity(),
NULL);
IMenuStyle *style = menus->GetDefaultStyle();
g_CookieManager.clientMenu = style->CreateMenu(&g_Handler, NULL);
g_CookieManager.clientMenu->SetDefaultTitle("Client Settings:");
plsys->AddPluginsListener(&g_CookieManager);
phrases = translator->CreatePhraseCollection();
phrases->AddPhraseFile("clientprefs.phrases");
phrases->AddPhraseFile("common.phrases");
return true;
}
@ -161,13 +148,78 @@ void ClientPrefs::SDK_OnUnload()
g_CookieManager.Unload();
Query_InsertCookie->Destroy();
Query_InsertData->Destroy();
Query_SelectData->Destroy();
Database->Close();
forwards->ReleaseForward(g_CookieManager.cookiesLoadedForward);
forwards->ReleaseForward(g_CookieManager.cookieDataLoadedForward);
g_CookieManager.clientMenu->Destroy();
}
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
va_end(ap);
if (len >= maxlength)
{
buffer[maxlength - 1] = '\0';
return (maxlength - 1);
}
else
{
return len;
}
}
bool Translate(char *buffer,
size_t maxlength,
const char *format,
unsigned int numparams,
size_t *pOutLength,
...)
{
va_list ap;
unsigned int i;
const char *fail_phrase;
void *params[MAX_TRANSLATE_PARAMS];
if (numparams > MAX_TRANSLATE_PARAMS)
{
assert(false);
return false;
}
va_start(ap, pOutLength);
for (i = 0; i < numparams; i++)
{
params[i] = va_arg(ap, void *);
}
va_end(ap);
if (!g_ClientPrefs.phrases->FormatString(buffer,
maxlength,
format,
params,
numparams,
pOutLength,
&fail_phrase))
{
if (fail_phrase != NULL)
{
g_pSM->LogError(myself, "[SM] Could not find core phrase: %s", fail_phrase);
}
else
{
g_pSM->LogError(myself, "[SM] Unknown fatal error while translating a core phrase.");
}
return false;
}
return true;
}

View File

@ -35,11 +35,16 @@
#define MAXCLIENTS 64
#include "smsdk_ext.h"
#include "sh_list.h"
#include "cookie.h"
#include "menus.h"
#define DRIVER_MYSQL 1
#define DRIVER_SQLITE 0
#define MAX_TRANSLATE_PARAMS 32
/**
* @brief Sample implementation of the SDK Extension.
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
@ -117,10 +122,7 @@ public:
public:
IDBDriver *Driver;
IDatabase *Database;
IPreparedQuery *Query_InsertCookie;
IPreparedQuery *Query_SelectData;
IPreparedQuery *Query_InsertData;
IPhraseCollection *phrases;
};
class CookieTypeHandler : public IHandleTypeDispatch
@ -128,16 +130,37 @@ class CookieTypeHandler : public IHandleTypeDispatch
public:
void OnHandleDestroy(HandleType_t type, void *object)
{
/* No delete needed since this Cookies are persistant */
/* No delete needed since Cookies are persistant */
}
};
class CookieIteratorHandler : public IHandleTypeDispatch
{
public:
void OnHandleDestroy(HandleType_t type, void *object)
{
delete (SourceHook::List<Cookie *>::iterator *)object;
}
};
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
extern sp_nativeinfo_t g_ClientPrefNatives[];
extern ClientPrefs g_ClientPrefs;
extern HandleType_t g_CookieType;
extern CookieTypeHandler g_CookieTypeHandler;
extern HandleType_t g_CookieIterator;
extern CookieIteratorHandler g_CookieIteratorHandler;
bool Translate(char *buffer,
size_t maxlength,
const char *format,
unsigned int numparams,
size_t *pOutLength,
...);
extern int driver;
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_

View File

@ -0,0 +1,179 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Client Preferences 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 "menus.h"
ClientMenuHandler g_Handler;
AutoMenuHandler g_AutoHandler;
void ClientMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
{
ItemDrawInfo draw;
const char *info = menu->GetItemInfo(item, &draw);
AutoMenuData *data = (AutoMenuData *)strtol(info, NULL, 16);
if (data->handler->forward != NULL)
{
data->handler->forward->PushCell(client);
data->handler->forward->PushCell(CookieMenuAction_SelectOption);
data->handler->forward->PushCell(data->datavalue);
data->handler->forward->PushString("");
data->handler->forward->PushCell(0);
data->handler->forward->Execute(NULL);
}
if (!data->handler->isAutoMenu)
{
return;
}
IBaseMenu *submenu = menus->GetDefaultStyle()->CreateMenu(&g_AutoHandler, NULL);
char message[256];
Translate(message, sizeof(message), "%T:", 2, NULL, "Choose Option", &client);
submenu->SetDefaultTitle(message);
if (data->type == CookieMenu_YesNo || data->type == CookieMenu_YesNo_Int)
{
Translate(message, sizeof(message), "%T", 2, NULL, "Yes", &client);
submenu->AppendItem(info, message);
Translate(message, sizeof(message), "%T", 2, NULL, "No", &client);
submenu->AppendItem(info, message);
}
else if (data->type == CookieMenu_OnOff || data->type == CookieMenu_OnOff_Int)
{
Translate(message, sizeof(message), "%T", 2, NULL, "On", &client);
submenu->AppendItem(info, message);
Translate(message, sizeof(message), "%T", 2, NULL, "Off", &client);
submenu->AppendItem(info, message);
}
submenu->Display(client, 0, NULL);
}
unsigned int ClientMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
int client,
IMenuPanel *panel,
unsigned int item,
const ItemDrawInfo &dr)
{
ItemDrawInfo draw;
const char *info = menu->GetItemInfo(item, &draw);
AutoMenuData *data = (AutoMenuData *)strtol(info, NULL, 16);
if (data->handler->forward != NULL)
{
char buffer[100];
UTIL_Format(buffer, sizeof(buffer), "%s", dr.display);
data->handler->forward->PushCell(client);
data->handler->forward->PushCell(CookieMenuAction_DisplayOption);
data->handler->forward->PushCell(data->datavalue);
data->handler->forward->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
data->handler->forward->PushCell(sizeof(buffer));
data->handler->forward->Execute(NULL);
ItemDrawInfo newdraw(buffer, draw.style);
return panel->DrawItem(newdraw);
}
return 0;
}
void AutoMenuHandler::OnMenuSelect(SourceMod::IBaseMenu *menu, int client, unsigned int item)
{
ItemDrawInfo draw;
const char *info = menu->GetItemInfo(item, &draw);
AutoMenuData *data = (AutoMenuData *)strtol(info, NULL, 16);
switch (data->type)
{
case CookieMenu_YesNo:
{
if (item == 0)
{
g_CookieManager.SetCookieValue(data->pCookie, client, "yes");
}
else
{
g_CookieManager.SetCookieValue(data->pCookie, client, "no");
}
break;
}
case CookieMenu_YesNo_Int:
case CookieMenu_OnOff_Int:
{
if (item == 0)
{
g_CookieManager.SetCookieValue(data->pCookie, client, "1");
}
else
{
g_CookieManager.SetCookieValue(data->pCookie, client, "0");
}
break;
}
case CookieMenu_OnOff:
{
if (item == 0)
{
g_CookieManager.SetCookieValue(data->pCookie, client, "on");
}
else
{
g_CookieManager.SetCookieValue(data->pCookie, client, "off");
}
break;
}
}
char message[255];
char *value;
g_CookieManager.GetCookieValue(data->pCookie, client, &value);
Translate(message, sizeof(message), "[SM] %T", 4, NULL, "Cookie Changed Value", &client, &(data->pCookie->name), value);
gamehelpers->TextMsg(client, 3, message);
}
void AutoMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
{
menu->Destroy(true);
}

View File

@ -0,0 +1,103 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Client Preferences 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$
*/
#ifndef _INCLUDE_SOURCEMOD_CLIENTPREFS_MENUS_H_
#define _INCLUDE_SOURCEMOD_CLIENTPREFS_MENUS_H_
#include "extension.h"
#include "cookie.h"
enum CookieMenuAction
{
/**
* An option is being drawn for a menu.
*
* INPUT : Client index and any data if available.
* OUTPUT: Buffer for rendering, maxlength of buffer.
*/
CookieMenuAction_DisplayOption = 0,
/**
* A menu option has been selected.
*
* INPUT : Client index and any data if available.
*/
CookieMenuAction_SelectOption = 1,
};
enum CookieMenu
{
CookieMenu_YesNo, /**< Yes/No menu with "yes"/"no" results saved into the cookie */
CookieMenu_YesNo_Int, /**< Yes/No menu with 1/0 saved into the cookie */
CookieMenu_OnOff, /**< On/Off menu with "on"/"off" results saved into the cookie */
CookieMenu_OnOff_Int, /**< On/Off menu with 1/0 saved into the cookie */
};
struct ItemHandler
{
bool isAutoMenu;
IChangeableForward *forward;
CookieMenu autoMenuType;
};
class ClientMenuHandler : public IMenuHandler
{
void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
unsigned int OnMenuDisplayItem(IBaseMenu *menu,
int client,
IMenuPanel *panel,
unsigned int item,
const ItemDrawInfo &dr);
};
class AutoMenuHandler : public IMenuHandler
{
void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
};
extern ClientMenuHandler g_Handler;
extern AutoMenuHandler g_AutoHandler;
/* Something went wrong with the includes and made me do this */
struct Cookie;
enum CookieMenu;
struct ItemHandler;
struct AutoMenuData
{
ItemHandler *handler;
Cookie *pCookie;
CookieMenu type;
cell_t datavalue;
};
#endif // _INCLUDE_SOURCEMOD_CLIENTPREFS_MENUS_H_

View File

@ -675,6 +675,10 @@
RelativePath="..\extension.cpp"
>
</File>
<File
RelativePath="..\menus.cpp"
>
</File>
<File
RelativePath="..\natives.cpp"
>
@ -697,6 +701,10 @@
RelativePath="..\extension.h"
>
</File>
<File
RelativePath="..\menus.h"
>
</File>
<File
RelativePath="..\query.h"
>

View File

@ -31,6 +31,7 @@
#include "extension.h"
#include "cookie.h"
#include "menus.h"
cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{
@ -45,7 +46,7 @@ cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
char *desc;
pContext->LocalToString(params[2], &desc);
Cookie *pCookie = g_CookieManager.CreateCookie(name, desc);
Cookie *pCookie = g_CookieManager.CreateCookie(name, desc, (CookieAccess)params[3]);
if (!pCookie)
{
@ -153,12 +154,208 @@ cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params)
return g_CookieManager.AreClientCookiesCached(client);
}
cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
Cookie *pCookie;
if ((err = handlesys->ReadHandle(hndl, g_CookieType, &sec, (void **)&pCookie))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid Cookie handle %x (error %d)", hndl, err);
}
return pCookie->access;
}
static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params)
{
SourceHook::List<Cookie *>::iterator *iter = new SourceHook::List<Cookie *>::iterator;
*iter = g_CookieManager.cookieList.begin();
Handle_t hndl = handlesys->CreateHandle(g_CookieIterator, iter, pContext->GetIdentity(), myself->GetIdentity(), NULL);
if (hndl == BAD_HANDLE)
{
delete iter;
}
return hndl;
}
static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params)
{
SourceHook::List<Cookie *>::iterator *iter;
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
if ((err = handlesys->ReadHandle(hndl, g_CookieIterator, &sec, (void **)&iter))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid Cookie iterator handle %x (error %d)", hndl, err);
}
if (*iter == g_CookieManager.cookieList.end())
{
return 0;
}
Cookie *pCookie = (Cookie *)**iter;
(*iter)++;
pContext->StringToLocalUTF8(params[2], params[3], pCookie->name, NULL);
pContext->StringToLocalUTF8(params[5], params[6], pCookie->description, NULL);
cell_t *addr;
pContext->LocalToPhysAddr(params[4], &addr);
*addr = pCookie->access;
return 1;
}
cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params)
{
char message[256];
Translate(message, sizeof(message), "%T:", 2, NULL, "Client Settings", &params[1]);
g_CookieManager.clientMenu->SetDefaultTitle(message);
g_CookieManager.clientMenu->Display(params[1], 0, NULL);
return 0;
}
cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
{
char *display;
pContext->LocalToString(params[3], &display);
/* Register a callback */
ItemHandler *pItem = new ItemHandler;
pItem->isAutoMenu = false;
pItem->forward = forwards->CreateForwardEx(NULL, ET_Ignore, 5, NULL, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell);
pItem->forward->AddFunction(pContext, static_cast<funcid_t>(params[1]));
char info[20];
AutoMenuData *data = new AutoMenuData;
data->datavalue = params[2];
data->handler = pItem;
UTIL_Format(info, sizeof(info), "%x", data);
ItemDrawInfo draw(display, 0);
g_CookieManager.clientMenu->AppendItem(info, draw);
/* Track this in case the plugin unloads */
IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
SourceHook::List<char *> *pList = NULL;
if (!pPlugin->GetProperty("SettingsMenuItems", (void **)&pList, false) || !pList)
{
pList = new SourceHook::List<char *>;
pPlugin->SetProperty("SettingsMenuItems", pList);
}
char *copyarray = new char[strlen(display)+1];
UTIL_Format(copyarray, strlen(display)+1, "%s", display);
pList->push_back(copyarray);
return 0;
}
cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
{
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
HandleSecurity sec;
sec.pOwner = NULL;
sec.pIdentity = myself->GetIdentity();
Cookie *pCookie;
if ((err = handlesys->ReadHandle(hndl, g_CookieType, &sec, (void **)&pCookie))
!= HandleError_None)
{
return pContext->ThrowNativeError("Invalid Cookie handle %x (error %d)", hndl, err);
}
/* Register a callback */
ItemHandler *pItem = new ItemHandler;
pItem->isAutoMenu = true;
pItem->autoMenuType = (CookieMenu)params[2];
/* User passed a function id for a callback */
if (params[4] != -1)
{
pItem->forward = forwards->CreateForwardEx(NULL, ET_Ignore, 5, NULL, Param_Cell, Param_Cell, Param_Cell, Param_String, Param_Cell);
pItem->forward->AddFunction(pContext, static_cast<funcid_t>(params[4]));
}
else
{
pItem->forward = NULL;
}
char *display;
pContext->LocalToString(params[3], &display);
ItemDrawInfo draw(display, 0);
char info[20];
AutoMenuData *data = new AutoMenuData;
data->datavalue = params[5];
data->pCookie = pCookie;
data->type = (CookieMenu)params[2];
data->handler = pItem;
UTIL_Format(info, sizeof(info), "%x", data);
g_CookieManager.clientMenu->AppendItem(info, draw);
/* Track this in case the plugin unloads */
IPlugin *pPlugin = plsys->FindPluginByContext(pContext->GetContext());
SourceHook::List<char *> *pList = NULL;
if (!pPlugin->GetProperty("SettingsMenuItems", (void **)&pList, false) || !pList)
{
pList = new SourceHook::List<char *>;
pPlugin->SetProperty("SettingsMenuItems", pList);
}
char *copyarray = new char[strlen(display)+1];
UTIL_Format(copyarray, strlen(display)+1, "%s", display);
pList->push_back(copyarray);
return 0;
}
sp_nativeinfo_t g_ClientPrefNatives[] =
{
{"RegClientPrefCookie", RegClientPrefCookie},
{"FindClientPrefCookie", FindClientPrefCookie},
{"SetClientPrefCookie", SetClientPrefCookie},
{"GetClientPrefCookie", GetClientPrefCookie},
{"RegClientCookie", RegClientPrefCookie},
{"FindClientCookie", FindClientPrefCookie},
{"SetClientCookie", SetClientPrefCookie},
{"GetClientCookie", GetClientPrefCookie},
{"AreClientCookiesCached", AreClientCookiesCached},
{"GetCookieAccess", GetCookieAccess},
{"ReadCookieIterator", ReadCookieIterator},
{"GetCookieIterator", GetCookieIterator},
{"ShowCookieMenu", ShowSettingsMenu},
{"SetCookieMenuItem", AddSettingsMenuItem},
{"SetCookiePrefabMenu", AddSettingsPrefabMenuItem},
{NULL, NULL}
};

View File

@ -47,28 +47,34 @@ void TQueryOp::RunThinkPart()
g_CookieManager.ClientConnectCallback(m_client, m_pQuery);
break;
case Query_InsertData:
g_pSM->LogMessage(myself, "Inserted data into table");
//No specific handling
break;
case Query_SelectId:
g_CookieManager.SelectIdCallback(pCookie, m_pQuery);
break;
default:
break;
}
m_pQuery->Destroy();
}
else
{
g_pSM->LogError(myself,"Failed SQL Query Error: \"%s\"- Ref Id: %i, Client num: %i",error ,m_type, m_client);
g_pSM->LogError(myself,"Failed SQL Query, Error: \"%s\" (Query id %i - client %i)", error, m_type, m_client);
}
}
void TQueryOp::RunThreadPart()
{
m_pDatabase->LockForFullAtomicOperation();
if (!m_pQuery->Execute())
m_pQuery = m_pDatabase->DoQuery(m_Query.c_str());
if (!m_pQuery)
{
g_pSM->LogError(myself, m_pQuery->GetError());
g_pSM->LogError(myself, "Failed SQL Query, Error: \"%s\" (Query id %i - client %i)", m_pDatabase->GetError(), m_type, m_client);
}
m_insertId = m_pQuery->GetInsertID();
m_insertId = g_ClientPrefs.Database->GetInsertID();
m_pDatabase->UnlockFromFullAtomicOperation();
}
@ -86,20 +92,20 @@ void TQueryOp::Destroy()
delete this;
}
TQueryOp::TQueryOp(IDatabase *db, IPreparedQuery *query, enum querytype type, int client)
TQueryOp::TQueryOp(IDatabase *db, const char *query, enum querytype type, int client)
{
m_pDatabase = db;
m_pQuery = query;
m_Query = query;
m_type = type;
m_client = client;
m_pDatabase->IncReferenceCount();
}
TQueryOp::TQueryOp(IDatabase *db, IPreparedQuery *query, enum querytype type, Cookie *cookie)
TQueryOp::TQueryOp(IDatabase *db, const char *query, enum querytype type, Cookie *cookie)
{
m_pDatabase = db;
m_pQuery = query;
m_Query = query;
m_type = type;
pCookie = cookie;

View File

@ -41,13 +41,14 @@ enum querytype
Query_InsertCookie = 0,
Query_SelectData,
Query_InsertData,
Query_SelectId,
};
class TQueryOp : public IDBThreadOperation
{
public:
TQueryOp(IDatabase *db, IPreparedQuery *query, enum querytype type, int client);
TQueryOp(IDatabase *db, IPreparedQuery *query, enum querytype type, Cookie *cookie);
TQueryOp(IDatabase *db, const char *query, enum querytype type, int client);
TQueryOp(IDatabase *db, const char *query, enum querytype type, Cookie *cookie);
~TQueryOp() {}
IDBDriver *GetDriver();
@ -64,7 +65,8 @@ public:
private:
IDatabase *m_pDatabase;
IPreparedQuery *m_pQuery;
IQuery *m_pQuery;
SourceHook::String m_Query;
char error[255];
enum querytype m_type;
int m_client;

View File

@ -40,7 +40,7 @@
#include "svn_version.h"
/* Basic information exposed publicly */
#define SMEXT_CONF_NAME "Client Preferences Extension"
#define SMEXT_CONF_NAME "Client Preferences"
#define SMEXT_CONF_DESCRIPTION "Saves client preference settings"
#define SMEXT_CONF_VERSION SVN_FULL_VERSION
#define SMEXT_CONF_AUTHOR "AlliedModders"
@ -67,15 +67,16 @@
#define SMEXT_ENABLE_DBMANAGER
//#define SMEXT_ENABLE_GAMECONF
//#define SMEXT_ENABLE_MEMUTILS
//#define SMEXT_ENABLE_GAMEHELPERS
#define SMEXT_ENABLE_GAMEHELPERS
//#define SMEXT_ENABLE_TIMERSYS
//#define SMEXT_ENABLE_THREADER
//#define SMEXT_ENABLE_LIBSYS
//#define SMEXT_ENABLE_MENUS
#define SMEXT_ENABLE_MENUS
//#define SMEXT_ENABLE_ADTFACTORY
//#define SMEXT_ENABLE_PLUGINSYS
#define SMEXT_ENABLE_PLUGINSYS
//#define SMEXT_ENABLE_ADMINSYS
//#define SMEXT_ENABLE_TEXTPARSERS
//#define SMEXT_ENABLE_USERMSGS
#define SMEXT_ENABLE_TRANSLATOR
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_

View File

@ -94,6 +94,9 @@ ITextParsers *textparsers = NULL;
#if defined SMEXT_ENABLE_USERMSGS
IUserMessages *usermsgs = NULL;
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
ITranslator *translator = NULL;
#endif
/** Exports the main interface */
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
@ -179,6 +182,9 @@ bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error,
#if defined SMEXT_ENABLE_USERMSGS
SM_GET_IFACE(USERMSGS, usermsgs);
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
SM_GET_IFACE(TRANSLATOR, translator);
#endif
if (SDK_OnLoad(error, maxlength, late))
{

View File

@ -88,6 +88,9 @@
#if defined SMEXT_ENABLE_USERMSGS
#include <IUserMessages.h>
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
#include <ITranslator.h>
#endif
#if defined SMEXT_CONF_METAMOD
#include <ISmmPlugin.h>
@ -283,6 +286,9 @@ extern IAdminSystem *adminsys;
#if defined SMEXT_ENABLE_USERMSGS
extern IUserMessages *usermsgs;
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
extern ITranslator *translator;
#endif
#if defined SMEXT_CONF_METAMOD
PLUGIN_GLOBALVARS();

150
plugins/clientprefs.sp Normal file
View File

@ -0,0 +1,150 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Map Management Plugin
* Provides all map related functionality, including map changing, map voting,
* and nextmap.
*
* SourceMod (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$
*/
#pragma semicolon 1
#include <sourcemod>
#include <clientprefs>
public Plugin:myinfo =
{
name = "Client Preferences",
author = "AlliedModders LLC",
description = "Client peferences and settings menu",
version = SOURCEMOD_VERSION,
url = "http://www.sourcemod.net/"
};
public OnPluginStart()
{
LoadTranslations("clientprefs.phrases");
RegConsoleCmd("sm_cookie", Command_Cookie, "sm_cookie <name> [value]");
RegConsoleCmd("sm_settings", Command_Settings);
}
public Action:Command_Cookie(client, args)
{
if (args == 0)
{
ReplyToCommand(client, "[SM] Usage: sm_cookie <name> [value]");
ReplyToCommand(client, "[SM] %t", "Printing Cookie List");
/* Show list of cookies */
new Handle:iter = GetCookieIterator();
decl String:name[30];
name[0] = '\0';
decl String:description[255];
description[0] = '\0';
PrintToConsole(client, "%t:", "Cookie List");
new CookieAccess:access;
while (ReadCookieIterator(iter,
name,
sizeof(name),
access,
description,
sizeof(description)) != false)
{
if (access < CookieAccess_Private)
{
PrintToConsole(client, "%s - %s", name, description);
}
}
return Plugin_Handled;
}
decl String:name[30];
name[0] = '\0';
GetCmdArg(1, name, sizeof(name));
new Handle:cookie = FindClientCookie(name);
if (cookie == INVALID_HANDLE)
{
ReplyToCommand(client, "[SM] %t", "Cookie not Found", name);
return Plugin_Handled;
}
new CookieAccess:access = GetCookieAccess(cookie);
if (access == CookieAccess_Private)
{
ReplyToCommand(client, "[SM] %t", "Cookie not Found", name);
return Plugin_Handled;
}
decl String:value[100];
value[0] = '\0';
if (args == 1)
{
GetClientCookie(client, cookie, value, sizeof(value));
ReplyToCommand(client, "[SM] %t", "Cookie Value", name, value);
return Plugin_Handled;
}
if (access == CookieAccess_Protected)
{
ReplyToCommand(client, "[SM] %t", "Protected Cookie", name);
return Plugin_Handled;
}
/* Set the new value of the cookie */
GetCmdArg(2, value, sizeof(value));
SetClientCookie(client, cookie, value);
ReplyToCommand(client, "[SM] %t", "Cookie Changed Value", name, value);
return Plugin_Handled;
}
public Action:Command_Settings(client, args)
{
if (client == 0)
{
PrintToServer("%T", "No Console", LANG_SERVER);
return Plugin_Handled;
}
ShowCookieMenu(client);
return Plugin_Handled;
}

View File

@ -35,15 +35,55 @@
#endif
#define _clientprefs_included
/**
* Cookie access types for client viewing
*/
enum CookieAccess
{
CookieAccess_Public, /**< Visible and Changeable by users */
CookieAccess_Protected, /**< Read only to users */
CookieAccess_Private, /**< Completely hidden cookie */
};
/**
* Cookie Prefab menu types
*/
enum CookieMenu
{
CookieMenu_YesNo, /**< Yes/No menu with "yes"/"no" results saved into the cookie */
CookieMenu_YesNo_Int, /**< Yes/No menu with 1/0 saved into the cookie */
CookieMenu_OnOff, /**< On/Off menu with "on"/"off" results saved into the cookie */
CookieMenu_OnOff_Int, /**< On/Off menu with 1/0 saved into the cookie */
};
enum CookieMenuAction
{
/**
* An option is being drawn for a menu.
*
* INPUT : Client index and data if available.
* OUTPUT: Buffer for rendering, maxlength of buffer.
*/
CookieMenuAction_DisplayOption = 0,
/**
* A menu option has been selected.
*
* INPUT : Client index and any data if available.
*/
CookieMenuAction_SelectOption = 1,
};
/**
* Creates a new Client preference cookie.
*
* @param name Name of the new preference cookie.
* @param description Optional description of the preference cookie.
* @param access What CookieAccess level to assign to this cookie.
* @return A handle to the newly created cookie. If the cookie already exists, a handle to it will still be returned.
* @error Cookie name is blank.
*/
native Handle:RegClientPrefCookie(const String:name[], const String:description[]);
native Handle:RegClientCookie(const String:name[], const String:description[], CookieAccess:access);
/**
* Searches for a Client preference cookie.
@ -51,7 +91,7 @@ native Handle:RegClientPrefCookie(const String:name[], const String:description[
* @param name Name of cookie to find.
* @return A handle to the cookie if it is found. INVALID_HANDLE otherwise.
*/
native Handle:FindClientPrefCookie(const String:name[]);
native Handle:FindClientCookie(const String:name[]);
/**
* Set the value of a Client preference cookie.
@ -62,7 +102,7 @@ native Handle:FindClientPrefCookie(const String:name[]);
* @noreturn
* @error Invalid cookie handle or invalid client index.
*/
native SetClientPrefCookie(client, Handle:cookie, const String:value[]);
native SetClientCookie(client, Handle:cookie, const String:value[]);
/**
* Retrieve the value of a Client preference cookie.
@ -71,9 +111,10 @@ native SetClientPrefCookie(client, Handle:cookie, const String:value[]);
* @param cookie Client preference cookie handle.
* @param buffer Copyback buffer for value.
* @param maxlen Maximum length of the buffer.
* @noreturn
* @error Invalid cookie handle or invalid client index.
*/
native GetClientPrefCookie(client, Handle:cookie, String:buffer[], maxlen);
native GetClientCookie(client, Handle:cookie, String:buffer[], maxlen);
/**
* Checks if a clients cookies have been loaded from the database.
@ -89,8 +130,89 @@ native bool:AreClientCookiesCached(client);
*
* @param client Client index.
*/
forward OnClientCookiesLoaded(client);
forward OnClientCookiesCached(client);
/**
* Cookie Menu Callback prototype
*
* @param client Client index.
* @param action CookeMenuAction being performed.
* @param data Info data passed.
* @param buffer Outbut buffer.
* @param maxlen Max length of the output buffer.
*/
functag CookieMenuHandler public(client, CookieMenuAction:action, any:info, String:buffer[], maxlen);
/**
* Add a new prefab item to the client cookie settings menu.
*
* Note: This handles everything automatically and does not require a callback
*
* @param cookie Client preference cookie handle.
* @param type A CookieMenu prefab menu type.
* @param display Text to show on the menu.
* @param handler Optional handler callback for translations and output on selection
* @param info Info data to pass to the callback.
* @noreturn
* @error Invalid cookie handle.
*/
native SetCookiePrefabMenu(Handle:cookie, CookieMenu:type, const String:display[], CookieMenuHandler:handler=CookieMenuHandler:-1, info=0);
/**
* Adds a new item to the client cookie settings menu.
*
* Note: This only adds the top level menu item. You need to handle any submenus from the callback.
*
* @param handler A MenuHandler callback function.
* @param info Data to pass to the callback.
* @param display Text to show on the menu.
* @noreturn
* @error Invalid cookie handle.
*/
native SetCookieMenuItem(CookieMenuHandler:handler, any:info, const String:display[]);
/**
* Displays the settings menu to a client.
*
* @param client Client index.
* @noreturn
*/
native ShowCookieMenu(client);
/**
* Gets a cookie iterator. Must be freed with CloseHandle().
*
* @return A new cookie iterator.
*/
native Handle:GetCookieIterator();
/**
* Reads a cookie iterator, then advances to the next cookie if any.
*
* @param iter Cookie iterator Handle.
* @param name Name buffer.
* @param nameLen Name buffer size.
* @param access Access level of the cookie.
* @param desc Cookie description buffer.
* @param descLen Cookie description buffer size.
* @param
* @return True on success, false if there are no more commands.
*/
native bool:ReadCookieIterator(Handle:iter,
String:name[],
nameLen,
&CookieAccess:access,
String:desc[]="",
descLen=0);
/**
* Returns the access level of a cookie
*
* @param cookie Client preference cookie handle.
* @return CookieAccess access level.
* @error Invalid cookie handle.
*/
native CookieAccess:GetCookieAccess(Handle:cookie);
/**
* Do not edit below this line!

View File

@ -1,26 +1,59 @@
#include <sourcemod>
#include "../include/clientprefs.inc"
#include <clientprefs.inc>
new Handle:g_Cookie;
new Handle:g_Cookie2;
new Handle:g_Cookie3;
new Handle:g_Cookie4;
new Handle:g_Cookie5;
public OnPluginStart()
{
g_Cookie = RegClientPrefCookie("test-cookie", "A basic testing cookie");
g_Cookie = RegClientCookie("test-cookie", "A basic testing cookie", CookieAccess_Public);
g_Cookie2 = RegClientCookie("test-cookie2", "A basic testing cookie", CookieAccess_Protected);
g_Cookie3 = RegClientCookie("test-cookie3", "A basic testing cookie", CookieAccess_Public);
g_Cookie4 = RegClientCookie("test-cookie4", "A basic testing cookie", CookieAccess_Private);
g_Cookie5 = RegClientCookie("test-cookie5", "A basic testing cookie", CookieAccess_Public);
SetCookiePrefabMenu(g_Cookie, CookieMenu_YesNo, "Cookie 1", CookieSelected, any:g_Cookie);
SetCookiePrefabMenu(g_Cookie2, CookieMenu_YesNo_Int, "Cookie 2");
SetCookiePrefabMenu(g_Cookie3, CookieMenu_OnOff, "Cookie 3");
SetCookiePrefabMenu(g_Cookie4, CookieMenu_OnOff_Int, "Cookie 4");
SetCookieMenuItem(CookieSelected, g_Cookie5, "Get Cookie 5 value");
}
public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
public CookieSelected(client, CookieMenuAction:action, any:info, String:buffer[], maxlen)
{
if (action == CookieMenuAction_DisplayOption)
{
PrintToChat(client, "About to draw item. Current text is : %s", buffer);
Format(buffer, maxlen, "HELLLLLLLLLLO");
}
else
{
LogMessage("SELECTED!");
new String:value[100];
GetClientCookie(client, info, value, sizeof(value));
PrintToChat(client, "Value is : %s", value);
}
}
public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
{
LogMessage("Connect Cookie state: %s", AreClientCookiesCached(client) ? "YES" : "NO");
}
public OnClientCookiesLoaded(client)
public OnClientCookiesCached(client)
{
LogMessage("Loaded Cookie state: %s", AreClientCookiesCached(client) ? "YES" : "NO");
new String:hi[100];
GetClientPrefCookie(client, g_Cookie, hi, sizeof(hi));
GetClientCookie(client, g_Cookie, hi, sizeof(hi));
LogMessage("Test: %s",hi);
SetClientPrefCookie(client, g_Cookie, "somethingsomething");
GetClientPrefCookie(client, g_Cookie, hi, sizeof(hi));
SetClientCookie(client, g_Cookie, "somethingsomething");
GetClientCookie(client, g_Cookie, hi, sizeof(hi));
LogMessage("Test: %s",hi);
}
}

View File

@ -0,0 +1,43 @@
"Phrases"
{
"Cookie List"
{
"en" "Sourcemod Cookie List"
}
"Printing Cookie List"
{
"en" "Printing cookie list to console"
}
"Cookie not Found"
{
"#format" "{1:s}"
"en" "Could not find cookie \"{1}\""
}
"Cookie Value"
{
"#format" "{1:s},{2:s}"
"en" "{1}'s value is {2}"
}
"Protected Cookie"
{
"#format" "{1:s}"
"en" "Cannot change the value of protected cookie \"{1}\""
}
"Cookie Changed Value"
{
"#format" "{1:s},{2:s}"
"en" "Changed the value of cookie \"{1}\" to \"{2}\""
}
"No Console"
{
"en" "Cannot display settings menu to console"
}
"Choose Option"
{
"en" "Choose Option"
}
"Client Settings"
{
"en" "Client Settings"
}
}

View File

@ -249,4 +249,12 @@
"#format" "{1:s}"
"en" "Kicked player '{1}'"
}
"On"
{
"en" "On"
}
"Off"
{
"en" "Off"
}
}