Alrighty, so using ClientPrefs is pretty straight forward. However, not a lot of plugins include support for it. Hopefully this helps someone.
The first thing you need to determine is what you need to store. Is it just a simple on off value? A name? In this case, let's store a simple bool.
PHP Code:
new bool:g_bClientPreference[MAXPLAYERS+1];
The next thing you need to do is
RegClientCookie. This is where you determine the internal (32 character) name of your cookie, a subsequently a description. This is also where you determine the
CookieAccess of a cookie. This can make or break you quite easily. If you make your cookie public, clients can raw set values using sm_cookies. This can provoke undefined behaviour, which can wreck you depending on your sanitation. In our case, we're making our cookie Private.
PHP Code:
new Handle:g_hClientCookie = INVALID_HANDLE;
public OnPluginStart()
{
g_hClientCookie = RegClientCookie("OurTestCookie", "A Test Cookie for use in our Tutorial", CookieAccess_Private);
}
In our case, we're going to add our Cookie to the sm_settings menu. Because we're using a simple on and off switch, we can easily use
SetCookiePrefabMenu. We're going to use
CookieMenu_OnOff_Int, because in our case we only want to store 1 or 0.
PHP Code:
public OnPluginStart()
{
g_hClientCookie = RegClientCookie("OurTestCookie", "A Test Cookie for use in our Tutorial", CookieAccess_Private);
SetCookiePrefabMenu(g_hClientCookie, CookieMenu_OnOff_Int, "TestCookie", TestCookieHandler);
}
Just with that one line, you have sm_settings support.
We now need to define our
CookieMenuHandler. The handler is pretty straight forward if you've used the menu API. If not, you may need to brush up on Menus. In this specific case, we only need to worry about the
CookieMenuAction_SelectOption. We need to simply cover setting the boolean so our internal state holds consistent. The major failure of the API is when the setting changes, buffer is always "", which makes me sad, but oh well.
PHP Code:
public TestCookieHandler(client, CookieMenuAction:action, any:info, String:buffer[], maxlen)
{
switch (action)
{
case CookieMenuAction_DisplayOption:
{
}
case CookieMenuAction_SelectOption:
{
OnClientCookiesCached(client);
}
}
}
The next gotcha with ClientPrefs (and SourceMod in general) is late-load support for plugins. You should probably support late-loading, because you can get into a weird state if you don't. It's pretty easy to do so with ClientPrefs.
PHP Code:
public OnPluginStart()
{
for (new i = MaxClients; i > 0; --i)
{
if (!AreClientCookiesCached(i))
{
continue;
}
OnClientCookiesCached(i);
}
}
Don't worry about bots/fake clients, they too have cookies.
Last but not least, the magical
OnClientCookiesCached forward. Here you're just reading a value out of a cookie. You can definitely register multiple cookies, or no cookies. OnClientCookiesCached has no defined order, and can happen before or after
OnClientPostAdminCheck. If you have a protected admin cookie, you're going to need to have your own custom handler, which is beyond the scope of this tutorial (at the moment). In our case, we're reading a simple one byte value from a String. In our case, we're going to use 8 bytes.
PHP Code:
public OnClientCookiesCached(client)
{
decl String:sValue[8];
GetClientCookie(client, g_hClientCookie, sValue, sizeof(sValue));
g_bClientPreference[client] = (sValue[0] != '\0' && StringToInt(sValue));
}
Hopefully this helped. There are more,
customized ways to handle Cookies. I tried to cover the basics, if you'd like me to go further into depth, just say so
EDIT: The final Plugin Looks Like:
PHP Code:
#pragma semicolon 1
#include <sourcemod>
#include <clientprefs>
new Handle:g_hClientCookie = INVALID_HANDLE;
new bool:g_bClientPreference[MAXPLAYERS+1];
public OnPluginStart()
{
g_hClientCookie = RegClientCookie("OurTestCookie", "A Test Cookie for use in our Tutorial", CookieAccess_Private);
SetCookiePrefabMenu(g_hClientCookie, CookieMenu_OnOff_Int, "TestCookie", TestCookieHandler);
for (new i = MaxClients; i > 0; --i)
{
if (!AreClientCookiesCached(i))
{
continue;
}
OnClientCookiesCached(i);
}
}
public TestCookieHandler(client, CookieMenuAction:action, any:info, String:buffer[], maxlen)
{
switch (action)
{
case CookieMenuAction_DisplayOption:
{
}
case CookieMenuAction_SelectOption:
{
OnClientCookiesCached(client);
}
}
}
public OnClientCookiesCached(client)
{
decl String:sValue[8];
GetClientCookie(client, g_hClientCookie, sValue, sizeof(sValue));
g_bClientPreference[client] = (sValue[0] != '\0' && StringToInt(sValue));
}