Overhaul of ClientPrefs extension (bug 5538, r=asherkin).

This commit is contained in:
Kyle Sanderson 2013-02-28 21:51:49 +00:00
parent 6b07625192
commit 5d942265f9
9 changed files with 325 additions and 359 deletions

View File

@ -41,6 +41,7 @@ CookieManager::CookieManager()
{
connected[i] = false;
statsLoaded[i] = false;
statsPending[i] = false;
}
cookieDataLoadedForward = NULL;
@ -51,10 +52,7 @@ CookieManager::~CookieManager(){}
void CookieManager::Unload()
{
/* If clients are connected we should try save their data */
int maxclients = playerhelpers->GetMaxClients();
for (int i=1; i<=maxclients; i++)
for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
{
if (connected[i])
{
@ -63,20 +61,14 @@ void CookieManager::Unload()
}
/* Find all cookies and delete them */
SourceHook::List<Cookie *>::iterator _iter;
Cookie *current;
_iter = cookieList.begin();
while (_iter != cookieList.end())
for (SourceHook::List<Cookie *>::iterator _iter = cookieList.begin(); _iter != cookieList.end(); _iter++)
{
current = (Cookie *)*_iter;
if (current == NULL)
{
_iter++;
continue;
}
@ -91,9 +83,9 @@ void CookieManager::Unload()
g_ClientPrefs.cookieMutex->Unlock();
delete current;
}
_iter = cookieList.erase(_iter);
}
cookieList.clear();
}
Cookie *CookieManager::FindCookie(const char *name)
@ -116,9 +108,7 @@ Cookie *CookieManager::CreateCookie(const char *name, const char *description, C
if (pCookie != NULL)
{
/* Update data fields to the provided values */
strncpy(pCookie->description, description, MAX_DESC_LENGTH);
pCookie->description[MAX_DESC_LENGTH-1] = '\0';
UTIL_strncpy(pCookie->description, description, MAX_DESC_LENGTH);
pCookie->access = access;
return pCookie;
@ -126,17 +116,14 @@ Cookie *CookieManager::CreateCookie(const char *name, const char *description, C
/* First time cookie - Create from scratch */
pCookie = new Cookie(name, description, access);
cookieTrie.insert(name, pCookie);
cookieList.push_back(pCookie);
pCookie->usedInQuery++;
/* Attempt to insert cookie into the db and get its ID num */
TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
g_ClientPrefs.cookieMutex->Lock();
op->m_params.cookie = pCookie;
pCookie->usedInQuery++;
g_ClientPrefs.cookieMutex->Unlock();
cookieTrie.insert(name, pCookie);
cookieList.push_back(pCookie);
g_ClientPrefs.AddQueryToQueue(op);
@ -145,8 +132,6 @@ Cookie *CookieManager::CreateCookie(const char *name, const char *description, C
bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
{
assert(pCookie);
CookieData *data = pCookie->data[client];
/* Check if a value has been set before */
@ -156,8 +141,8 @@ bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
data->parent = pCookie;
clientData[client].push_back(data);
pCookie->data[client] = data;
data->changed = true;
data->timestamp = time(NULL);
data->changed = false;
data->timestamp = 0;
}
*value = &data->value[0];
@ -167,8 +152,6 @@ bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *value)
{
assert(pCookie);
CookieData *data = pCookie->data[client];
if (data == NULL)
@ -180,8 +163,7 @@ bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *valu
}
else
{
strncpy(data->value, value, MAX_VALUE_LENGTH);
data->value[MAX_VALUE_LENGTH-1] = '\0';
UTIL_strncpy(data->value, value, MAX_VALUE_LENGTH);
}
data->changed = true;
@ -200,9 +182,12 @@ void CookieManager::OnClientAuthorized(int client, const char *authstring)
}
connected[client] = true;
statsPending[client] = true;
g_ClientPrefs.AttemptReconnection();
TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial());
strcpy(op->m_params.steamId, authstring);
UTIL_strncpy(op->m_params.steamId, authstring, MAX_NAME_LENGTH);
g_ClientPrefs.AddQueryToQueue(op);
}
@ -211,105 +196,103 @@ void CookieManager::OnClientDisconnecting(int client)
{
connected[client] = false;
statsLoaded[client] = false;
SourceHook::List<CookieData *>::iterator _iter;
statsPending[client] = false;
CookieData *current;
_iter = clientData[client].begin();
g_ClientPrefs.AttemptReconnection();
while (_iter != clientData[client].end())
/* Save this cookie to the database */
IGamePlayer *player = playerhelpers->GetGamePlayer(client);
const char *pAuth = NULL;
int dbId;
if (player)
{
current = (CookieData *)*_iter;
pAuth = player->GetAuthString();
}
if (!current->changed)
g_ClientPrefs.ClearQueryCache(player->GetSerial());
for (SourceHook::List<CookieData *>::iterator _iter = clientData[client].begin();\
_iter != clientData[client].end(); _iter++)
{
if (player == NULL || pAuth == NULL)
{
/* panic! */
current->parent->data[client] = NULL;
delete current;
_iter = clientData[client].erase(_iter);
continue;
}
/* Save this cookie to the database */
IGamePlayer *player = playerhelpers->GetGamePlayer(client);
current = (CookieData *)*_iter;
dbId = current->parent->dbid;
if (player == NULL)
if (!current->changed || dbId == -1)
{
/* panic! */
return;
}
int dbId = current->parent->dbid;
if (dbId == -1)
{
/* Insert/Find Query must be still running or failed. */
return;
current->parent->data[client] = NULL;
delete current;
continue;
}
TQueryOp *op = new TQueryOp(Query_InsertData, client);
strcpy(op->m_params.steamId, player->GetAuthString());
UTIL_strncpy(op->m_params.steamId, pAuth, MAX_NAME_LENGTH);
op->m_params.cookieId = dbId;
op->m_params.data = current;
g_ClientPrefs.AddQueryToQueue(op);
current->parent->data[client] = NULL;
/* We don't delete here, it will be removed when the query is completed */
_iter = clientData[client].erase(_iter);
}
clientData[client].clear();
}
void CookieManager::ClientConnectCallback(int serial, IQuery *data)
{
int client;
IResultSet *results;
/* Check validity of client */
if ((client = playerhelpers->GetClientFromSerial(serial)) == 0)
{
return;
}
statsPending[client] = false;
IResultSet *results;
/* Check validity of results */
if (data == NULL || (results = data->GetResultSet()) == NULL)
{
return;
}
CookieData *pData;
IResultRow *row;
do
{
if ((row = results->FetchRow()) == NULL)
{
break;
}
unsigned int timestamp;
CookieAccess access;
const char *name;
while (results->MoreRows() && ((row = results->FetchRow()) != NULL))
{
const char *name = "";
row->GetString(0, &name, NULL);
const char *value;
const char *value = "";
row->GetString(1, &value, NULL);
CookieData *pData = new CookieData(value);
pData = new CookieData(value);
pData->changed = false;
unsigned int timestamp = 0;
row->GetInt(4, (int *)&timestamp);
pData->timestamp = timestamp;
pData->timestamp = (row->GetInt(4, (int *)&timestamp) == DBVal_Data) ? timestamp : 0;
Cookie *parent = FindCookie(name);
if (parent == NULL)
{
const char *desc;
const char *desc = "";
row->GetString(2, &desc, NULL);
CookieAccess access = CookieAccess_Public;
access = CookieAccess_Public;
row->GetInt(3, (int *)&access);
parent = CreateCookie(name, desc, access);
@ -317,10 +300,8 @@ void CookieManager::ClientConnectCallback(int serial, IQuery *data)
pData->parent = parent;
parent->data[client] = pData;
clientData[client].push_back(pData);
} while (results->MoreRows());
}
statsLoaded[client] = true;
@ -338,7 +319,7 @@ void CookieManager::InsertCookieCallback(Cookie *pCookie, int dbId)
TQueryOp *op = new TQueryOp(Query_SelectId, pCookie);
/* Put the cookie name into the steamId field to save space - Make sure we remember that it's there */
strcpy(op->m_params.steamId, pCookie->name);
UTIL_strncpy(op->m_params.steamId, pCookie->name, MAX_NAME_LENGTH);
g_ClientPrefs.AddQueryToQueue(op);
}
@ -366,26 +347,31 @@ bool CookieManager::AreClientCookiesCached(int client)
return statsLoaded[client];
}
bool CookieManager::AreClientCookiesPening(int client)
{
return statsPending[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;
ItemDrawInfo draw;
const char *info;
AutoMenuData * data;
unsigned itemcount;
while (p_iter != pList->end())
for (SourceHook::List<char *>::iterator p_iter = pList->begin(); p_iter != pList->end(); p_iter++)
{
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++)
itemcount = clientMenu->GetItemCount();
//remove from this plugins list
for (unsigned int i=0; i < itemcount; i++)
{
const char *info = clientMenu->GetItemInfo(i, &draw);
info = clientMenu->GetItemInfo(i, &draw);
if (info == NULL)
{
@ -394,9 +380,7 @@ void CookieManager::OnPluginDestroyed(IPlugin *plugin)
if (strcmp(draw.display, name) == 0)
{
ItemDrawInfo draw;
const char *info = clientMenu->GetItemInfo(i, &draw);
AutoMenuData *data = (AutoMenuData *)strtoul(info, NULL, 16);
data = (AutoMenuData *)strtoul(info, NULL, 16);
if (data->handler->forward != NULL)
{
@ -410,15 +394,15 @@ void CookieManager::OnPluginDestroyed(IPlugin *plugin)
}
}
delete name;
delete [] name;
}
pList->clear();
}
}
bool CookieManager::GetCookieTime(Cookie *pCookie, int client, time_t *value)
{
assert(pCookie);
CookieData *data = pCookie->data[client];
/* Check if a value has been set before */

View File

@ -54,11 +54,10 @@ struct CookieData
{
CookieData(const char *value)
{
strncpy(this->value, value, MAX_VALUE_LENGTH);
this->value[MAX_VALUE_LENGTH-1] = '\0';
UTIL_strncpy(this->value, value, MAX_VALUE_LENGTH);
}
char value[MAX_VALUE_LENGTH];
char value[MAX_VALUE_LENGTH+1];
bool changed;
time_t timestamp;
Cookie *parent;
@ -68,10 +67,8 @@ struct Cookie
{
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';
UTIL_strncpy(this->name, name, MAX_NAME_LENGTH);
UTIL_strncpy(this->description, description, MAX_DESC_LENGTH);
this->access = access;
@ -97,8 +94,8 @@ struct Cookie
}
}
char name[MAX_NAME_LENGTH];
char description[MAX_DESC_LENGTH];
char name[MAX_NAME_LENGTH+1];
char description[MAX_DESC_LENGTH+1];
int dbid;
CookieData *data[MAXCLIENTS+1];
CookieAccess access;
@ -134,6 +131,8 @@ public:
void OnPluginDestroyed(IPlugin *plugin);
bool AreClientCookiesPening(int client);
public:
IForward *cookieDataLoadedForward;
SourceHook::List<Cookie *> cookieList;
@ -145,6 +144,7 @@ private:
bool connected[MAXCLIENTS+1];
bool statsLoaded[MAXCLIENTS+1];
bool statsPending[MAXCLIENTS+1];
};
extern CookieManager g_CookieManager;

View File

@ -47,7 +47,6 @@ CookieTypeHandler g_CookieTypeHandler;
HandleType_t g_CookieIterator = 0;
CookieIteratorHandler g_CookieIteratorHandler;
DbDriver g_DriverType;
static const DatabaseInfo *storage_local = NULL;
bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
@ -60,28 +59,19 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
DBInfo = dbi->FindDatabaseConf("default");
if (DBInfo == NULL ||
(strcmp(DBInfo->host, "localhost") == 0 &&
strcmp(DBInfo->database, "sourcemod") == 0 &&
strcmp(DBInfo->user, "root") == 0 &&
strcmp(DBInfo->pass, "") == 0 &&
strcmp(DBInfo->driver, "") == 0))
{
storage_local = dbi->FindDatabaseConf("storage-local");
if (DBInfo == NULL)
{
DBInfo = storage_local;
}
}
if (DBInfo == NULL)
{
snprintf(error, maxlength, "Could not find \"clientprefs\" or \"default\" database configs");
return false;
DBInfo = dbi->FindDatabaseConf("storage-local");
}
}
if (DBInfo->driver[0] != '\0')
if (DBInfo == NULL)
{
snprintf(error, maxlength, "Could not find any suitable database configs");
return false;
}
if (DBInfo->driver && DBInfo->driver[0] != '\0')
{
Driver = dbi->FindOrLoadDriver(DBInfo->driver);
}
@ -96,7 +86,6 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
return false;
}
Database = NULL;
databaseLoading = true;
TQueryOp *op = new TQueryOp(Query_Connect, 0);
dbi->AddToThreadQueue(op, PrioQueue_High);
@ -136,19 +125,7 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
if (late)
{
int maxclients = playerhelpers->GetMaxClients();
for (int i = 1; i <= maxclients; i++)
{
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
if (!pPlayer || !pPlayer->IsAuthorized())
{
continue;
}
g_CookieManager.OnClientAuthorized(i, pPlayer->GetAuthString());
}
this->CatchLateLoadClients();
}
return true;
@ -188,20 +165,37 @@ void ClientPrefs::SDK_OnUnload()
if (Database != NULL)
{
Database->Close();
Database = NULL;
}
forwards->ReleaseForward(g_CookieManager.cookieDataLoadedForward);
HandleSecurity sec = HandleSecurity(identity, identity);
HandleError err = handlesys->FreeHandle(g_CookieManager.clientMenu->GetHandle(), &sec);
if (HandleError_None != err)
if (g_CookieManager.cookieDataLoadedForward != NULL)
{
g_pSM->LogError(myself, "Error %d when attempting to free client menu handle", err);
forwards->ReleaseForward(g_CookieManager.cookieDataLoadedForward);
g_CookieManager.cookieDataLoadedForward = NULL;
}
phrases->Destroy();
if (g_CookieManager.clientMenu != NULL)
{
Handle_t menuHandle = g_CookieManager.clientMenu->GetHandle();
sharesys->DestroyIdentity( identity );
if (menuHandle != BAD_HANDLE)
{
HandleSecurity sec = HandleSecurity(identity, identity);
HandleError err = handlesys->FreeHandle(menuHandle, &sec);
if (HandleError_None != err)
{
g_pSM->LogError(myself, "Error %d when attempting to free client menu handle", err);
}
}
g_CookieManager.clientMenu = NULL;
}
if (phrases != NULL)
{
phrases->Destroy();
phrases = NULL;
}
plsys->RemovePluginsListener(&g_CookieManager);
playerhelpers->RemoveClientListener(&g_CookieManager);
@ -212,15 +206,23 @@ void ClientPrefs::SDK_OnUnload()
void ClientPrefs::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
{
if (Database == NULL && !databaseLoading)
this->AttemptReconnection();
}
void ClientPrefs::AttemptReconnection()
{
if (Database || databaseLoading)
{
g_pSM->LogMessage(myself, "Attempting to reconnect to database...");
databaseLoading = true;
TQueryOp *op = new TQueryOp(Query_Connect, 0);
dbi->AddToThreadQueue(op, PrioQueue_High);
return; /* We're already loading, or have loaded. */
}
g_pSM->LogMessage(myself, "Attempting to reconnect to database...");
databaseLoading = true;
TQueryOp *op = new TQueryOp(Query_Connect, 0);
dbi->AddToThreadQueue(op, PrioQueue_High);
this->CatchLateLoadClients(); /* DB reconnection, we should check if we missed anyone... */
}
void ClientPrefs::DatabaseConnect()
@ -230,19 +232,10 @@ void ClientPrefs::DatabaseConnect()
Database = Driver->Connect(DBInfo, true, error, sizeof(error));
if (Database == NULL &&
DBInfo != storage_local &&
storage_local != NULL)
{
DBInfo = storage_local;
Database = Driver->Connect(DBInfo, true, error, sizeof(error));
}
if (Database == NULL)
{
g_pSM->LogError(myself, error);
databaseLoading = false;
ProcessQueryCache();
return;
}
@ -319,87 +312,76 @@ void ClientPrefs::DatabaseConnect()
databaseLoading = false;
ProcessQueryCache();
this->ProcessQueryCache();
return;
fatal_fail:
Database->Close();
Database = NULL;
databaseLoading = false;
ProcessQueryCache();
}
bool ClientPrefs::AddQueryToQueue( TQueryOp *query )
{
queryMutex->Lock();
if (Database == NULL && databaseLoading)
if (Database == NULL)
{
cachedQueries.push_back(query);
queryMutex->Unlock();
return true;
return false;
}
queryMutex->Unlock();
if (Database)
if (!cachedQueries.empty())
{
query->SetDatabase(Database);
dbi->AddToThreadQueue(query, PrioQueue_Normal);
return true;
queryMutex->Unlock();
this->ProcessQueryCache();
}
else
{
queryMutex->Unlock();
}
query->Destroy();
/* If Database is NULL and we're not in the loading phase it must have failed - Can't do much */
return false;
query->SetDatabase(Database);
dbi->AddToThreadQueue(query, PrioQueue_Normal);
return true;
}
void ClientPrefs::ProcessQueryCache()
{
SourceHook::List<TQueryOp *>::iterator iter;
if (Database == NULL)
{
return;
}
queryMutex->Lock();
iter = cachedQueries.begin();
while (iter != cachedQueries.end())
TQueryOp *op;
for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end(); iter++)
{
TQueryOp *op = *iter;
if (Database != NULL)
{
op->SetDatabase(Database);
dbi->AddToThreadQueue(op, PrioQueue_Normal);
}
else
{
op->Destroy();
}
iter++;
op = *iter;
op->SetDatabase(Database);
dbi->AddToThreadQueue(op, PrioQueue_Normal);
}
cachedQueries.clear();
queryMutex->Unlock();
}
size_t IsAuthIdConnected(char *authID)
{
IGamePlayer *player;
int maxPlayers = playerhelpers->GetMaxClients();
const char *authString;
for (int playerIndex = 1; playerIndex <= maxPlayers; playerIndex++)
for (int playerIndex = playerhelpers->GetMaxClients()+1; --playerIndex > 0;)
{
player = playerhelpers->GetGamePlayer(playerIndex);
if (!player || !player->IsConnected())
if (player == NULL || !player->IsConnected())
{
continue;
}
const char *authString = player->GetAuthString();
if (!authString || authString[0] == '\0')
authString = player->GetAuthString();
if (authString == NULL || authString[0] == '\0')
{
continue;
}
@ -412,22 +394,45 @@ size_t IsAuthIdConnected(char *authID)
return 0;
}
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
void ClientPrefs::CatchLateLoadClients()
{
va_list ap;
va_start(ap, fmt);
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
va_end(ap);
IGamePlayer *pPlayer;
for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
{
if (g_CookieManager.AreClientCookiesPening(i) || g_CookieManager.AreClientCookiesCached(i))
{
continue;
}
if (len >= maxlength)
{
buffer[maxlength - 1] = '\0';
return (maxlength - 1);
pPlayer = playerhelpers->GetGamePlayer(i);
if (!pPlayer || !pPlayer->IsAuthorized())
{
continue;
}
g_CookieManager.OnClientAuthorized(i, pPlayer->GetAuthString());
}
else
}
void ClientPrefs::ClearQueryCache(int serial)
{
queryMutex->Lock();
for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end();)
{
return len;
}
TQueryOp *op = *iter;
if (op && op->PullQueryType() == Query_SelectData && op->PullQuerySerial() == serial)
{
op->Destroy();
iter = cachedQueries.erase(iter);
}
else
{
iter++;
}
}
queryMutex->Unlock();
}
bool Translate(char *buffer,
@ -478,6 +483,30 @@ bool Translate(char *buffer,
return true;
}
char * UTIL_strncpy(char * destination, const char * source, size_t num)
{
if (source == NULL)
{
destination[0] = '\0';
return destination;
}
size_t req = strlen(source);
if (!req)
{
destination[0] = '\0';
return destination;
}
else if (req >= num)
{
req = num-1;
}
strncpy(destination, source, req);
destination[req] = '\0';
return destination;
}
IdentityToken_t *ClientPrefs::GetIdentity() const
{
return identity;
@ -493,3 +522,15 @@ const char *ClientPrefs::GetExtensionDateString()
return SM_BUILD_TIMESTAMP;
}
ClientPrefs::ClientPrefs()
{
Driver = NULL;
Database = NULL;
databaseLoading = false;
phrases = NULL;
DBInfo = NULL;
cookieMutex = NULL;
queryMutex = NULL;
identity = NULL;
}

View File

@ -38,6 +38,9 @@
#include <stdarg.h>
#include "smsdk_ext.h"
#include "sh_list.h"
char * UTIL_strncpy(char * destination, const char * source, size_t num);
#include "cookie.h"
#include "menus.h"
#include "query.h"
@ -58,6 +61,8 @@ class TQueryOp;
*/
class ClientPrefs : public SDKExtension
{
public:
ClientPrefs();
public:
/**
* @brief This is called after the initial loading sequence has been processed.
@ -94,6 +99,10 @@ public:
bool AddQueryToQueue(TQueryOp *query);
void ProcessQueryCache();
void AttemptReconnection();
void CatchLateLoadClients();
void ClearQueryCache(int serial);
/**
* @brief Called when the pause state is changed.
*/
@ -145,11 +154,11 @@ public:
public:
IDBDriver *Driver;
IDatabase *Database;
bool databaseLoading;
IPhraseCollection *phrases;
const DatabaseInfo *DBInfo;
IMutex *cookieMutex;
bool databaseLoading;
private:
SourceHook::List<TQueryOp *> cachedQueries;
@ -177,8 +186,6 @@ public:
size_t IsAuthIdConnected(char *authID);
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
extern sp_nativeinfo_t g_ClientPrefNatives[];
extern ClientPrefs g_ClientPrefs;

View File

@ -99,7 +99,7 @@ unsigned int ClientMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
if (data->handler->forward != NULL)
{
char buffer[100];
UTIL_Format(buffer, sizeof(buffer), "%s", dr.display);
g_pSM->Format(buffer, sizeof(buffer), "%s", dr.display);
data->handler->forward->PushCell(client);
data->handler->forward->PushCell(CookieMenuAction_DisplayOption);
@ -118,52 +118,14 @@ unsigned int ClientMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
void AutoMenuHandler::OnMenuSelect(SourceMod::IBaseMenu *menu, int client, unsigned int item)
{
static const char settings[CookieMenu_Elements][2][4] = { {"yes", "no"}, {"1", "0"}, {"on", "off"}, {"1", "0"} };
ItemDrawInfo draw;
const char *info = menu->GetItemInfo(item, &draw);
AutoMenuData *data = (AutoMenuData *)strtoul(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;
}
}
g_CookieManager.SetCookieValue(data->pCookie, client, settings[data->type][item]);
char message[255];
char *value;

View File

@ -59,13 +59,14 @@ enum CookieMenu
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 */
CookieMenu_Elements
};
struct ItemHandler
{
bool isAutoMenu;
IChangeableForward *forward;
CookieMenu autoMenuType;
bool isAutoMenu;
};
class ClientMenuHandler : public IMenuHandler
@ -96,8 +97,8 @@ struct AutoMenuData
{
ItemHandler *handler;
Cookie *pCookie;
CookieMenu type;
cell_t datavalue;
CookieMenu type;
};
#endif // _INCLUDE_SOURCEMOD_CLIENTPREFS_MENUS_H_

View File

@ -35,10 +35,7 @@
cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
char *name;
pContext->LocalToString(params[1], &name);
@ -67,10 +64,7 @@ cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
char *name;
pContext->LocalToString(params[1], &name);
@ -91,10 +85,7 @@ cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
char *steamID;
pContext->LocalToString(params[1], &steamID);
@ -136,8 +127,7 @@ cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
// edit database table
TQueryOp *op = new TQueryOp(Query_InsertData, pCookie);
// limit player auth length which doubles for cookie name length
strncpy(op->m_params.steamId, steamID, MAX_NAME_LENGTH);
op->m_params.steamId[MAX_NAME_LENGTH-1] = '\0';
UTIL_strncpy(op->m_params.steamId, steamID, MAX_NAME_LENGTH);
op->m_params.cookieId = i_dbId;
op->m_params.data = payload;
@ -148,10 +138,7 @@ cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
int client = params[1];
@ -183,10 +170,7 @@ cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t GetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
int client = params[1];
@ -221,10 +205,7 @@ cell_t GetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
int client = params[1];
@ -238,10 +219,7 @@ cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params)
cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
@ -263,10 +241,7 @@ cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params)
static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
SourceHook::List<Cookie *>::iterator *iter = new SourceHook::List<Cookie *>::iterator;
*iter = g_CookieManager.cookieList.begin();
@ -282,10 +257,7 @@ static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params)
static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
SourceHook::List<Cookie *>::iterator *iter;
@ -323,10 +295,7 @@ static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params)
cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
char message[256];
Translate(message, sizeof(message), "%T:", 2, NULL, "Client Settings", &params[1]);
@ -339,10 +308,7 @@ cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params)
cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
char *display;
pContext->LocalToString(params[3], &display);
@ -358,7 +324,7 @@ cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
AutoMenuData *data = new AutoMenuData;
data->datavalue = params[2];
data->handler = pItem;
UTIL_Format(info, sizeof(info), "%x", data);
g_pSM->Format(info, sizeof(info), "%x", data);
ItemDrawInfo draw(display, 0);
@ -376,7 +342,7 @@ cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
}
char *copyarray = new char[strlen(display)+1];
UTIL_Format(copyarray, strlen(display)+1, "%s", display);
g_pSM->Format(copyarray, strlen(display)+1, "%s", display);
pList->push_back(copyarray);
@ -385,10 +351,7 @@ cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err;
@ -433,7 +396,7 @@ cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
data->pCookie = pCookie;
data->type = (CookieMenu)params[2];
data->handler = pItem;
UTIL_Format(info, sizeof(info), "%x", data);
g_pSM->Format(info, sizeof(info), "%x", data);
g_CookieManager.clientMenu->AppendItem(info, draw);
@ -449,7 +412,7 @@ cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
}
char *copyarray = new char[strlen(display)+1];
UTIL_Format(copyarray, strlen(display)+1, "%s", display);
g_pSM->Format(copyarray, strlen(display)+1, "%s", display);
pList->push_back(copyarray);
@ -458,10 +421,7 @@ cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
cell_t GetClientCookieTime(IPluginContext *pContext, const cell_t *params)
{
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
g_ClientPrefs.AttemptReconnection();
Handle_t hndl = static_cast<Handle_t>(params[2]);
HandleError err;

View File

@ -35,12 +35,6 @@
void TQueryOp::RunThinkPart()
{
//handler for threaded sql queries
if (m_type == Query_Connect)
{
return;
}
switch (m_type)
{
case Query_InsertCookie:
@ -61,6 +55,11 @@ void TQueryOp::RunThinkPart()
break;
}
case Query_Connect:
{
return;
}
default:
{
break;
@ -73,31 +72,26 @@ void TQueryOp::RunThreadPart()
if (m_type == Query_Connect)
{
g_ClientPrefs.DatabaseConnect();
return;
}
else
{
assert(m_database != NULL);
/* I don't think this is needed anymore... keeping for now. */
m_database->LockForFullAtomicOperation();
assert(m_database != NULL);
/* I don't think this is needed anymore... keeping for now. */
m_database->LockForFullAtomicOperation();
if (!BindParamsAndRun())
{
g_pSM->LogError(myself,
"Failed SQL Query, Error: \"%s\" (Query id %i - serial %i)",
m_database->GetError(),
m_type,
m_serial);
}
m_database->UnlockFromFullAtomicOperation();
{
g_pSM->LogError(myself,
"Failed SQL Query, Error: \"%s\" (Query id %i - serial %i)",
m_database->GetError(),
m_type,
m_serial);
}
m_database->UnlockFromFullAtomicOperation();
}
IDBDriver *TQueryOp::GetDriver()
{
assert(m_database != NULL);
return m_database->GetDriver();
}
@ -131,6 +125,7 @@ TQueryOp::TQueryOp(enum querytype type, Cookie *cookie)
m_database = NULL;
m_insertId = -1;
m_pResult = NULL;
m_serial = 0;
}
void TQueryOp::SetDatabase(IDatabase *db)
@ -162,7 +157,7 @@ bool TQueryOp::BindParamsAndRun()
if (g_DriverType == Driver_MySQL)
{
UTIL_Format(query,
g_pSM->Format(query,
sizeof(query),
"INSERT IGNORE INTO sm_cookies (name, description, access) \
VALUES (\"%s\", \"%s\", %d)",
@ -172,7 +167,7 @@ bool TQueryOp::BindParamsAndRun()
}
else if (g_DriverType == Driver_SQLite)
{
UTIL_Format(query,
g_pSM->Format(query,
sizeof(query),
"INSERT OR IGNORE INTO sm_cookies (name, description, access) \
VALUES ('%s', '%s', %d)",
@ -197,7 +192,7 @@ bool TQueryOp::BindParamsAndRun()
m_database->QuoteString(m_params.steamId, safe_str, sizeof(safe_str), &ignore);
UTIL_Format(query,
g_pSM->Format(query,
sizeof(query),
"SELECT sm_cookies.name, sm_cookie_cache.value, sm_cookies.description, \
sm_cookies.access, sm_cookie_cache.timestamp \
@ -228,7 +223,7 @@ bool TQueryOp::BindParamsAndRun()
if (g_DriverType == Driver_MySQL)
{
UTIL_Format(query,
g_pSM->Format(query,
sizeof(query),
"INSERT INTO sm_cookie_cache (player, cookie_id, value, timestamp) \
VALUES (\"%s\", %d, \"%s\", %d) \
@ -243,7 +238,7 @@ bool TQueryOp::BindParamsAndRun()
}
else if (g_DriverType == Driver_SQLite)
{
UTIL_Format(query,
g_pSM->Format(query,
sizeof(query),
"INSERT OR REPLACE INTO sm_cookie_cache \
(player, cookie_id, value, timestamp) \
@ -274,7 +269,7 @@ bool TQueryOp::BindParamsAndRun()
sizeof(safe_name),
&ignore);
UTIL_Format(query,
g_pSM->Format(query,
sizeof(query),
"SELECT id FROM sm_cookies WHERE name = '%s'",
safe_name);
@ -296,6 +291,16 @@ bool TQueryOp::BindParamsAndRun()
return false;
}
querytype TQueryOp::PullQueryType()
{
return m_type;
}
int TQueryOp::PullQuerySerial()
{
return m_serial;
}
ParamData::~ParamData()
{
if (cookie)
@ -309,8 +314,10 @@ ParamData::~ParamData()
delete cookie;
cookie = NULL;
}
g_ClientPrefs.cookieMutex->Unlock();
else
{
g_ClientPrefs.cookieMutex->Unlock();
}
}
if (data)

View File

@ -94,6 +94,10 @@ public:
return m_database;
}
public:
querytype PullQueryType();
int PullQuerySerial();
private:
IDatabase *m_database;
IQuery *m_pResult;