diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp index ae3f1f38fb..ee20f487d5 100644 --- a/extensions/sdktools/extension.cpp +++ b/extensions/sdktools/extension.cpp @@ -50,6 +50,9 @@ */ SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); +#if SOURCE_ENGINE == SE_CSS +SH_DECL_HOOK1_void_vafmt(IVEngineServer, ClientCommand, SH_NOATTRIB, 0, edict_t *); +#endif SDKTools g_SdkTools; /**< Global singleton for extension's main interface */ IServerGameEnts *gameents = NULL; @@ -261,6 +264,10 @@ bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool #endif GET_V_IFACE_ANY(GetEngineFactory, soundemitterbase, ISoundEmitterSystemBase, SOUNDEMITTERSYSTEM_INTERFACE_VERSION); +#if SOURCE_ENGINE == SE_CSS + SH_ADD_HOOK(IVEngineServer, ClientCommand, engine, SH_MEMBER(this, &SDKTools::OnSendClientCommand), false); +#endif + gpGlobals = ismm->GetCGlobals(); enginePatch = SH_GET_CALLCLASS(engine); enginesoundPatch = SH_GET_CALLCLASS(engsound); @@ -268,6 +275,14 @@ bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool return true; } +bool SDKTools::SDK_OnMetamodUnload(char *error, size_t maxlen) +{ +#if SOURCE_ENGINE == SE_CSS + SH_REMOVE_HOOK(IVEngineServer, ClientCommand, engine, SH_MEMBER(this, &SDKTools::OnSendClientCommand), false); +#endif + return true; +} + void SDKTools::SDK_OnAllLoaded() { SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools); @@ -456,6 +471,21 @@ void SDKTools::OnClientPutInServer(int client) g_Hooks.OnClientPutInServer(client); } +#if SOURCE_ENGINE == SE_CSS +void SDKTools::OnSendClientCommand(edict_t *pPlayer, const char *szFormat) +{ + // Due to legacy code, CS:S still sends "name \"newname\"" to the client after a + // name change. The engine has a change hook on name causing it to reset to the + // player's Steam name. This quashes that to make SetClientName work properly. + if (!strncmp(szFormat, "name ", 5)) + { + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} +#endif + class SDKTools_API : public ISDKTools { public: diff --git a/extensions/sdktools/extension.h b/extensions/sdktools/extension.h index 00144e4f9a..381eeb0d44 100644 --- a/extensions/sdktools/extension.h +++ b/extensions/sdktools/extension.h @@ -83,7 +83,7 @@ class SDKTools : public: #if defined SMEXT_CONF_METAMOD virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late); - //virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen); + virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen); //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen); #endif public: //IConCommandBaseAccessor @@ -101,6 +101,9 @@ class SDKTools : #else void OnClientCommand(edict_t *pEntity); #endif +#if SOURCE_ENGINE == SE_CSS + void OnSendClientCommand(edict_t *pPlayer, const char *szFormat); +#endif public: //ICommandTargetProcessor bool ProcessCommandTarget(cmd_target_info_t *info); diff --git a/extensions/sdktools/vnatives.cpp b/extensions/sdktools/vnatives.cpp index 3539ccb666..ff1ebe607f 100644 --- a/extensions/sdktools/vnatives.cpp +++ b/extensions/sdktools/vnatives.cpp @@ -2,7 +2,7 @@ * vim: set ts=4 : * ============================================================================= * SourceMod SDKTools Extension -* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -1267,6 +1267,61 @@ static cell_t ActivateEntity(IPluginContext *pContext, const cell_t *params) return 1; } +static cell_t SetClientName(IPluginContext *pContext, const cell_t *params) +{ + if (iserver == NULL) + { + return pContext->ThrowNativeError("IServer interface not supported, file a bug report."); + } + + IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]); + IClient *pClient = iserver->GetClient(params[1] - 1); + + if (player == NULL || pClient == NULL) + { + return pContext->ThrowNativeError("Invalid client index %d", params[1]); + } + if (!player->IsConnected()) + { + return pContext->ThrowNativeError("Client %d is not connected", params[1]); + } + + static ValveCall *pCall = NULL; + if (!pCall) + { + ValvePassInfo params[1]; + InitPass(params[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL); + + if (!CreateBaseCall("SetClientName", ValveCall_Entity, NULL, params, 1, &pCall)) + { + return pContext->ThrowNativeError("\"SetClientName\" not supported by this mod"); + } + else if (!pCall) + { + return pContext->ThrowNativeError("\"SetClientName\" wrapper failed to initialize"); + } + } + + // The IClient vtable is +4 from the CBaseClient vtable due to multiple inheritance. + void *pGameClient = (void *)((intptr_t)pClient - 4); + + // Change the name in the engine. + START_CALL(); + void **ebuf = (void **)vptr; + *ebuf = pGameClient; + DECODE_VALVE_PARAM(2, vparams, 0); + FINISH_CALL_SIMPLE(NULL); + + // Notify the server of the change. +#if SOURCE_ENGINE == SE_DOTA + serverClients->ClientSettingsChanged(player->GetIndex()); +#else + serverClients->ClientSettingsChanged(player->GetEdict()); +#endif + + return 1; +} + static cell_t SetClientInfo(IPluginContext *pContext, const cell_t *params) { if (iserver == NULL) @@ -1418,6 +1473,7 @@ sp_nativeinfo_t g_Natives[] = {"EquipPlayerWeapon", WeaponEquip}, {"ActivateEntity", ActivateEntity}, {"SetClientInfo", SetClientInfo}, + {"SetClientName", SetClientName}, {"GetPlayerResourceEntity", GetPlayerResourceEntity}, {"GivePlayerAmmo", GivePlayerAmmo}, {NULL, NULL}, diff --git a/gamedata/sdktools.games/engine.bgt.txt b/gamedata/sdktools.games/engine.bgt.txt index fe4accc08b..be6d718ecb 100644 --- a/gamedata/sdktools.games/engine.bgt.txt +++ b/gamedata/sdktools.games/engine.bgt.txt @@ -156,6 +156,15 @@ "windows" "17" } + /** + * CBaseClient::SetName(char const*); + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + } + /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.blade.txt b/gamedata/sdktools.games/engine.blade.txt index 5dbe09d569..32da0ee075 100644 --- a/gamedata/sdktools.games/engine.blade.txt +++ b/gamedata/sdktools.games/engine.blade.txt @@ -210,6 +210,17 @@ "linux" "64" "mac" "64" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + "linux" "63" + "mac" "63" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.contagion.txt b/gamedata/sdktools.games/engine.contagion.txt index 3695d25e11..28f21532bc 100644 --- a/gamedata/sdktools.games/engine.contagion.txt +++ b/gamedata/sdktools.games/engine.contagion.txt @@ -205,6 +205,17 @@ "linux" "63" "mac" "63" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + "linux" "62" + "mac" "62" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.csgo.txt b/gamedata/sdktools.games/engine.csgo.txt index 893ffe1abb..bed7e1d0d1 100644 --- a/gamedata/sdktools.games/engine.csgo.txt +++ b/gamedata/sdktools.games/engine.csgo.txt @@ -220,6 +220,17 @@ "SetUserCvar" { /* Not 100% sure on this, why would windows change and not linux - TEST ME */ + "windows" "28" + "linux" "65" + "mac" "65" + } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { "windows" "27" "linux" "64" "mac" "64" diff --git a/gamedata/sdktools.games/engine.css.txt b/gamedata/sdktools.games/engine.css.txt index 9c6aa7776b..b4178ae677 100644 --- a/gamedata/sdktools.games/engine.css.txt +++ b/gamedata/sdktools.games/engine.css.txt @@ -193,6 +193,17 @@ "linux" "58" "mac" "58" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "17" + "linux" "57" + "mac" "57" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.darkm.txt b/gamedata/sdktools.games/engine.darkm.txt index fc54a665bd..957d2c6ca7 100644 --- a/gamedata/sdktools.games/engine.darkm.txt +++ b/gamedata/sdktools.games/engine.darkm.txt @@ -224,6 +224,15 @@ { "windows" "17" } + + /** + * CBaseClient::SetName(char const*); + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + } "UpdateUserSettings" { diff --git a/gamedata/sdktools.games/engine.dota.txt b/gamedata/sdktools.games/engine.dota.txt index 74c9657746..a46a263077 100644 --- a/gamedata/sdktools.games/engine.dota.txt +++ b/gamedata/sdktools.games/engine.dota.txt @@ -250,6 +250,17 @@ "SetUserCvar" { "windows" "26" + "linux" "63" + "mac" "63" + } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "25" "linux" "62" "mac" "62" } diff --git a/gamedata/sdktools.games/engine.ep1.txt b/gamedata/sdktools.games/engine.ep1.txt index 04b52146c0..b00e6615fb 100644 --- a/gamedata/sdktools.games/engine.ep1.txt +++ b/gamedata/sdktools.games/engine.ep1.txt @@ -256,6 +256,16 @@ "windows" "17" "linux" "53" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + "linux" "52" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.ep2.txt b/gamedata/sdktools.games/engine.ep2.txt index 07e9c9b2d0..887b21858e 100644 --- a/gamedata/sdktools.games/engine.ep2.txt +++ b/gamedata/sdktools.games/engine.ep2.txt @@ -219,6 +219,16 @@ "windows" "17" "linux" "55" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + "linux" "54" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.ep2valve.txt b/gamedata/sdktools.games/engine.ep2valve.txt index 47772302eb..4c1a989562 100644 --- a/gamedata/sdktools.games/engine.ep2valve.txt +++ b/gamedata/sdktools.games/engine.ep2valve.txt @@ -237,6 +237,17 @@ "linux" "58" "mac" "58" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "17" + "linux" "57" + "mac" "57" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.eye.txt b/gamedata/sdktools.games/engine.eye.txt index d203e71bd8..b451122519 100644 --- a/gamedata/sdktools.games/engine.eye.txt +++ b/gamedata/sdktools.games/engine.eye.txt @@ -183,6 +183,14 @@ { "windows" "17" } + /** + * CBaseClient::SetName(char const*); + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.insurgency.txt b/gamedata/sdktools.games/engine.insurgency.txt index b057d84dfe..13c0b89681 100644 --- a/gamedata/sdktools.games/engine.insurgency.txt +++ b/gamedata/sdktools.games/engine.insurgency.txt @@ -177,6 +177,17 @@ "linux" "67" "mac" "67" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "19" + "linux" "66" + "mac" "66" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.l4d.txt b/gamedata/sdktools.games/engine.l4d.txt index e053407d89..e1a931a2bd 100644 --- a/gamedata/sdktools.games/engine.l4d.txt +++ b/gamedata/sdktools.games/engine.l4d.txt @@ -225,6 +225,17 @@ "linux" "63" "mac" "63" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + "linux" "62" + "mac" "62" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.l4d2.txt b/gamedata/sdktools.games/engine.l4d2.txt index 1a0a3090d4..949ebcb1dc 100644 --- a/gamedata/sdktools.games/engine.l4d2.txt +++ b/gamedata/sdktools.games/engine.l4d2.txt @@ -102,6 +102,17 @@ "linux" "63" "mac" "63" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + "linux" "62" + "mac" "62" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.sdk2013.txt b/gamedata/sdktools.games/engine.sdk2013.txt index f6a1fbc36c..29c73df120 100644 --- a/gamedata/sdktools.games/engine.sdk2013.txt +++ b/gamedata/sdktools.games/engine.sdk2013.txt @@ -91,6 +91,17 @@ "linux" "58" "mac" "58" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "17" + "linux" "57" + "mac" "57" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/engine.swarm.txt b/gamedata/sdktools.games/engine.swarm.txt index 3c5e1954c2..9c12edc45f 100644 --- a/gamedata/sdktools.games/engine.swarm.txt +++ b/gamedata/sdktools.games/engine.swarm.txt @@ -180,6 +180,14 @@ /* Not 100% sure on this, why would windows change and not linux - TEST ME */ "windows" "17" } + /** + * CBaseClient::SetName(char const*); + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. diff --git a/gamedata/sdktools.games/game.nucleardawn.txt b/gamedata/sdktools.games/game.nucleardawn.txt index fefe5cd54c..7d94e50692 100644 --- a/gamedata/sdktools.games/game.nucleardawn.txt +++ b/gamedata/sdktools.games/game.nucleardawn.txt @@ -125,6 +125,17 @@ "linux" "63" "mac" "63" } + /** + * CBaseClient::SetName(char const*); + * Linux offset straight from VTable dump. + * Has string "(%d)%-0.*s" + */ + "SetClientName" + { + "windows" "16" + "linux" "62" + "mac" "62" + } /** * Offset into CBaseClient - Used by CBaseServer::UpdateUserSettings to determine when changes have been made. * Find CBaseClient::UpdateUserSettings (strings "net_maxroutable", "cl_updaterate" etc) and the offset is set to 0 near the end. @@ -248,4 +259,4 @@ } } } -} \ No newline at end of file +} diff --git a/plugins/include/sdktools_functions.inc b/plugins/include/sdktools_functions.inc index fc3f9c846b..63d3d1bef2 100644 --- a/plugins/include/sdktools_functions.inc +++ b/plugins/include/sdktools_functions.inc @@ -332,6 +332,15 @@ native ActivateEntity(entity); */ native SetClientInfo(client, const String:key[], const String:value[]); +/** + * Changes a client's name. + * + * @param client Player's index. + * @param name New name. + * @error Invalid client index, or client not connected. + */ +native void SetClientName(int client, const char[] name); + /** * Gives ammo of a certain type to a player. * This natives obeys the maximum amount of ammo a player can carry per ammo type. diff --git a/plugins/playercommands.sp b/plugins/playercommands.sp index 7ddcee54f5..ff14b5f76b 100644 --- a/plugins/playercommands.sp +++ b/plugins/playercommands.sp @@ -50,9 +50,6 @@ public Plugin:myinfo = TopMenu hTopMenu; /* Used to get the SDK / Engine version. */ -/* This is used in sm_rename and sm_changeteam */ -new EngineVersion:g_ModVersion = Engine_Unknown; - #include "playercommands/slay.sp" #include "playercommands/slap.sp" #include "playercommands/rename.sp" @@ -65,8 +62,6 @@ public OnPluginStart() RegAdminCmd("sm_slap", Command_Slap, ADMFLAG_SLAY, "sm_slap <#userid|name> [damage]"); RegAdminCmd("sm_slay", Command_Slay, ADMFLAG_SLAY, "sm_slay <#userid|name>"); RegAdminCmd("sm_rename", Command_Rename, ADMFLAG_SLAY, "sm_rename <#userid|name>"); - - g_ModVersion = GetEngineVersion(); /* Account for late loading */ TopMenu topmenu; diff --git a/plugins/playercommands/rename.sp b/plugins/playercommands/rename.sp index 2afd376502..5571444f8b 100644 --- a/plugins/playercommands/rename.sp +++ b/plugins/playercommands/rename.sp @@ -37,22 +37,8 @@ PerformRename(client, target) { LogAction(client, target, "\"%L\" renamed \"%L\" to \"%s\")", client, target, g_NewName[target]); - /* Used on OB / L4D engine */ - if (g_ModVersion != Engine_SourceSDK2006) - { - SetClientInfo(target, "name", g_NewName[target]); - } - else /* Used on CSS and EP1 / older engine */ - { - if (!IsPlayerAlive(target)) /* Lets tell them about the player renamed on the next round since they're dead. */ - { - decl String:m_TargetName[MAX_NAME_LENGTH]; + SetClientName(target, g_NewName[target]); - GetClientName(target, m_TargetName, sizeof(m_TargetName)); - ReplyToCommand(client, "[SM] %t", "Dead Player Rename", m_TargetName); - } - ClientCommand(target, "name %s", g_NewName[target]); - } g_NewName[target][0] = '\0'; } diff --git a/translations/playercommands.phrases.txt b/translations/playercommands.phrases.txt index 1adb848d07..a56b1ec99e 100644 --- a/translations/playercommands.phrases.txt +++ b/translations/playercommands.phrases.txt @@ -15,12 +15,6 @@ { "en" "Rename player" } - - "Dead Player Rename" - { - "#format" "{1:s}" - "en" "{1} will be renamed on the next round." - } "Slap player" {