Added SetUserInfo command to sdktools.
Added SetUserInfo command to sdktools.
1.1 --- a/extensions/sdktools/vnatives.cpp Fri Jun 06 04:55:27 2008 +0000
1.2 +++ b/extensions/sdktools/vnatives.cpp Mon Jun 09 07:12:32 2008 +0000
1.3 @@ -37,6 +37,8 @@
1.4 #include "vhelpers.h"
1.5 #include "vglobals.h"
1.6 #include "CellRecipientFilter.h"
1.7 +#include <inetchannel.h>
1.8 +#include <iclient.h>
1.9
1.10 SourceHook::List<ValveCall *> g_RegCalls;
1.11 SourceHook::List<ICallWrapper *> g_CallWraps;
1.12 @@ -916,6 +918,64 @@
1.13 return 1;
1.14 }
1.15
1.16 +static cell_t SetClientInfo(IPluginContext *pContext, const cell_t *params)
1.17 +{
1.18 + IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
1.19 + if (player == NULL)
1.20 + {
1.21 + return pContext->ThrowNativeError("Invalid client index %d", params[1]);
1.22 + }
1.23 + if (!player->IsConnected())
1.24 + {
1.25 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.26 + }
1.27 +
1.28 + static ValveCall *pCall = NULL;
1.29 + if (!pCall)
1.30 + {
1.31 + ValvePassInfo params[2];
1.32 + InitPass(params[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
1.33 + InitPass(params[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
1.34 +
1.35 + if (!CreateBaseCall("SetUserCvar", ValveCall_Entity, NULL, params, 2, &pCall))
1.36 + {
1.37 + return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod");
1.38 + }
1.39 + else if (!pCall)
1.40 + {
1.41 + return pContext->ThrowNativeError("\"SetUserCvar\" wrapper failed to initialized");
1.42 + }
1.43 + }
1.44 +
1.45 + static int changedOffset = -1;
1.46 +
1.47 + if (changedOffset == -1)
1.48 + {
1.49 + if (!g_pGameConf->GetOffset("InfoChanged", &changedOffset))
1.50 + {
1.51 + return pContext->ThrowNativeError("\"SetUserCvar\" not supported by this mod");
1.52 + }
1.53 + }
1.54 +
1.55 + INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(params[1]));
1.56 + IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
1.57 +
1.58 + unsigned char *CGameClient = (unsigned char *)pClient - 4;
1.59 +
1.60 + START_CALL();
1.61 + /* Not really a CBaseEntity* but this works */
1.62 + CBaseEntity **ebuf = (CBaseEntity **)vptr;
1.63 + *ebuf = (CBaseEntity *)CGameClient;
1.64 + DECODE_VALVE_PARAM(2, vparams, 0);
1.65 + DECODE_VALVE_PARAM(3, vparams, 1);
1.66 + FINISH_CALL_SIMPLE(NULL);
1.67 +
1.68 + uint8_t* changed = (uint8_t *)(CGameClient + changedOffset);
1.69 + *changed = 1;
1.70 +
1.71 + return 1;
1.72 +}
1.73 +
1.74 sp_nativeinfo_t g_Natives[] =
1.75 {
1.76 {"ExtinguishEntity", ExtinguishEntity},
1.77 @@ -942,5 +1002,6 @@
1.78 {"GetServerNetStats", GetServerNetStats},
1.79 {"EquipPlayerWeapon", WeaponEquip},
1.80 {"ActivateEntity", ActivateEntity},
1.81 + {"SetClientInfo", SetClientInfo},
1.82 {NULL, NULL},
1.83 };
2.1 --- a/gamedata/sdktools.games.ep2.txt Fri Jun 06 04:55:27 2008 +0000
2.2 +++ b/gamedata/sdktools.games.ep2.txt Mon Jun 09 07:12:32 2008 +0000
2.3 @@ -411,4 +411,34 @@
2.4 }
2.5 }
2.6 }
2.7 +
2.8 + /* SetUserInfo data */
2.9 + "#default"
2.10 + {
2.11 + "Offsets"
2.12 + {
2.13 + /**
2.14 + * CBaseClient::SetUserCVar(char const*,char const*);
2.15 + * Linux offset straight from VTable dump.
2.16 + * Windows offset is crazy. Found the windows 'SetName' function using string "(%d)%-0.*s"
2.17 + * Cross referenced back to the vtable and counted manually (SetUserCvar is 1 higher, offsets start from 1)
2.18 + */
2.19 + "SetUserCvar"
2.20 + {
2.21 + "windows" "17"
2.22 + "linux" "55"
2.23 + }
2.24 + /**
2.25 + * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made.
2.26 + * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end.
2.27 + * Linux: mov byte ptr [esi+98h], 0
2.28 + * Win: mov byte ptr [esi+0A4h], 0
2.29 + */
2.30 + "InfoChanged"
2.31 + {
2.32 + "windows" "164"
2.33 + "linux" "152"
2.34 + }
2.35 + }
2.36 + }
2.37 }
3.1 --- a/gamedata/sdktools.games.txt Fri Jun 06 04:55:27 2008 +0000
3.2 +++ b/gamedata/sdktools.games.txt Mon Jun 09 07:12:32 2008 +0000
3.3 @@ -1858,5 +1858,35 @@
3.4 }
3.5 }
3.6 }
3.7 +
3.8 + /* SetUserInfo data */
3.9 + "#default"
3.10 + {
3.11 + "Offsets"
3.12 + {
3.13 + /**
3.14 + * CBaseClient::SetUserCVar(char const*,char const*);
3.15 + * Linux offset straight from VTable dump.
3.16 + * Windows offset is crazy. Found the windows 'SetName' function using string "(%d)%-0.*s"
3.17 + * Cross referenced back to the vtable and counted manually (SetUserCvar is 1 higher, offsets start from 1)
3.18 + */
3.19 + "SetUserCvar"
3.20 + {
3.21 + "windows" "17"
3.22 + "linux" "53"
3.23 + }
3.24 + /**
3.25 + * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made.
3.26 + * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end.
3.27 + * Linux: mov byte ptr [esi+98h], 0
3.28 + * Win: mov byte ptr [esi+0A4h], 0
3.29 + */
3.30 + "InfoChanged"
3.31 + {
3.32 + "windows" "164"
3.33 + "linux" "152"
3.34 + }
3.35 + }
3.36 + }
3.37 }
3.38
4.1 --- a/plugins/include/sdktools_functions.inc Fri Jun 06 04:55:27 2008 +0000
4.2 +++ b/plugins/include/sdktools_functions.inc Mon Jun 09 07:12:32 2008 +0000
4.3 @@ -308,3 +308,15 @@
4.4 * @error Invalid entity or lack of mod support.
4.5 */
4.6 native ActivateEntity(entity);
4.7 +
4.8 +/**
4.9 + * Sets values to client info buffer keys and notifies the engine of the change.
4.10 + * The change does not get propogated to mods until the next frame.
4.11 + *
4.12 + * @param client Player's index.
4.13 + * @param key Key string.
4.14 + * @param value Value string.
4.15 + * @noreturn
4.16 + * @error Invalid client index, or client not connected.
4.17 + */
4.18 +native SetClientInfo(client, const String:key[], const String:value[]);