diff --git a/extensions/clientprefs/extension.cpp b/extensions/clientprefs/extension.cpp index 255f53f9..a797ecdb 100644 --- a/extensions/clientprefs/extension.cpp +++ b/extensions/clientprefs/extension.cpp @@ -365,6 +365,32 @@ void ClientPrefs::ProcessQueryCache() queryMutex->Unlock(); } +size_t IsAuthIdConnected(char *authID) +{ + IGamePlayer *player; + int maxPlayers = playerhelpers->GetMaxClients(); + + for (int playerIndex = 1; playerIndex <= maxPlayers; playerIndex++) + { + player = playerhelpers->GetGamePlayer(playerIndex); + if (!player || !player->IsConnected()) + { + continue; + } + const char *authString = player->GetAuthString(); + if (!authString || authString[0] == '\0') + { + continue; + } + + if (strcmp(authString, authID) == 0) + { + return playerIndex; + } + } + return 0; +} + size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) { va_list ap; diff --git a/extensions/clientprefs/extension.h b/extensions/clientprefs/extension.h index 8cd05465..22df6128 100644 --- a/extensions/clientprefs/extension.h +++ b/extensions/clientprefs/extension.h @@ -170,6 +170,8 @@ public: } }; +size_t IsAuthIdConnected(char *authID); + size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); extern sp_nativeinfo_t g_ClientPrefNatives[]; diff --git a/extensions/clientprefs/natives.cpp b/extensions/clientprefs/natives.cpp index d3848c06..525cd2f4 100644 --- a/extensions/clientprefs/natives.cpp +++ b/extensions/clientprefs/natives.cpp @@ -89,6 +89,63 @@ cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params) NULL); } +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"); + } + + char *steamID; + pContext->LocalToString(params[1], &steamID); + + // convert cookie handle to Cookie* + Handle_t hndl = static_cast(params[2]); + 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); + } + + int i_dbId = pCookie->dbid; + char *value; + pContext->LocalToString(params[3], &value); + + // make sure the steamID isn't currently connected + if (int client = IsAuthIdConnected(steamID)) + { + // use regular code for connected players + return g_CookieManager.SetCookieValue(pCookie, client, value); + } + + // constructor calls strncpy for us + CookieData *payload = new CookieData(value); + + // set changed so players connecting later in during the same map will have the correct value + payload->changed = true; + payload->timestamp = time(NULL); + + // 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'; + op->m_params.cookieId = i_dbId; + op->m_params.data = payload; + + g_ClientPrefs.AddQueryToQueue(op); + + return 1; +} + cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params) { if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) @@ -436,6 +493,7 @@ sp_nativeinfo_t g_ClientPrefNatives[] = {"RegClientCookie", RegClientPrefCookie}, {"FindClientCookie", FindClientPrefCookie}, {"SetClientCookie", SetClientPrefCookie}, + {"SetAuthIdCookie", SetAuthIdCookie}, {"GetClientCookie", GetClientPrefCookie}, {"AreClientCookiesCached", AreClientCookiesCached}, {"GetCookieAccess", GetCookieAccess}, diff --git a/plugins/include/clientprefs.inc b/plugins/include/clientprefs.inc index 9f4faaa9..ffb7030b 100644 --- a/plugins/include/clientprefs.inc +++ b/plugins/include/clientprefs.inc @@ -131,6 +131,17 @@ native SetClientCookie(client, Handle:cookie, const String:value[]); */ native GetClientCookie(client, Handle:cookie, String:buffer[], maxlen); +/** + * Sets the value of a Client preference cookie based on an authID string. + * + * @param authID String Auth/STEAM ID of player to set. + * @param cookie Client preference cookie handle. + * @param value String value to set. + * @noreturn + * @error Invalid cookie handle. + */ +native SetAuthIdCookie(const String:authID[], Handle:cookie, const String:value[]); + /** * Checks if a clients cookies have been loaded from the database. *