2024-09-23 19:11:46 +02:00
# include "CDetour/detours.h"
# include <iclient.h>
# include "extension.h"
/**
* @ file extension . cpp
* @ brief Implement extension code here .
*/
class CBaseEntity ;
2024-09-29 19:33:19 +02:00
//class CBasePlayer;
2024-09-23 19:11:46 +02:00
2024-10-04 13:12:19 +02:00
uint32_t g_ClientGiveNamedCounter [ SM_MAXPLAYERS + 1 ] ;
char g_ClientSteamIDMap [ SM_MAXPLAYERS + 1 ] [ 64 ] ;
char g_ClientNameMap [ SM_MAXPLAYERS + 1 ] [ 128 ] ;
2024-09-29 19:33:19 +02:00
int g_Capacity = 20 ;
2024-09-23 19:11:46 +02:00
//https://sm.alliedmods.net/doxygen/index.html
GiveNamedItemTracker g_Interface ; /**< Global singleton for extension's main interface */
SMEXT_LINK ( & g_Interface ) ;
ITimer * g_pGiveNamedItemTimer = NULL ;
GiveNamedItemTimer g_GiveNamedItemTracker ;
//taken from https://git.unloze.com/UNLOZE/sm-ext-connect/src/branch/master/extension.cpp
size_t strlcpy ( char * dst , const char * src , size_t dsize )
{
const char * osrc = src ;
size_t nleft = dsize ;
/* Copy as many bytes as will fit. */
if ( nleft ! = 0 ) {
while ( - - nleft ! = 0 ) {
if ( ( * dst + + = * src + + ) = = ' \0 ' )
break ;
}
}
/* Not enough room in dst, add NUL and traverse rest of src. */
if ( nleft = = 0 ) {
if ( dsize ! = 0 )
* dst = ' \0 ' ; /* NUL-terminate dst */
while ( * src + + )
;
}
return ( src - osrc - 1 ) ; /* count does not include NUL */
}
DETOUR_DECL_MEMBER2 ( GiveNamedItem , void , char * , pszName , int , iSubType )
{
2024-09-29 19:33:19 +02:00
CBaseEntity * pEntity = ( CBaseEntity * ) this ;
//int idx = gamehelpers->EntityToBCompatRef(pPlayer); //caused a crash
/*
# 0 0xeb7585a0 in CHalfLife2::EntityToBCompatRef (this=0xeb8605c0 <g_HL2>, pEntity=0x41)
at / home / gameservers / automate / sourcemod_1 .12 .0 .7137 / core / HalfLife2 . cpp : 1132
# 1 0xeb75867e in non-virtual thunk to CHalfLife2::EntityToBCompatRef(CBaseEntity*) ()
from / home / gameservers / css_ze / cstrike / addons / sourcemod / bin / sourcemod .2 . css . so
# 2 0xe15a9d6a in GiveNamedItem (pContext=0x9cc6170, params=0xdbf85114) at / home / gameservers / automate / sourcemod_1.12.0.7137 / extensions / sdktools / vnatives.cpp:327
*/
//CBasePlayer* pPlayer = (CBasePlayer*) this;
//CBasePlayer* pPlayer = CBasePlayer::GetLocalPlayer();
//CBasePlayer* pPlayer = ToBasePlayer(UTIL_GetCommandClient());
if ( pEntity )
2024-09-23 19:11:46 +02:00
{
2024-09-29 19:33:19 +02:00
cell_t entRef = gamehelpers - > EntityToReference ( pEntity ) ;
if ( entRef )
2024-09-23 19:11:46 +02:00
{
2024-09-29 19:33:19 +02:00
int idx = gamehelpers - > ReferenceToIndex ( entRef ) ;
if ( idx > 0 & & idx < = playerhelpers - > GetMaxClients ( ) ) //should be in the index range for clients.
{
IGamePlayer * gp = playerhelpers - > GetGamePlayer ( idx ) ;
if ( gp & & gp - > IsConnected ( ) & & gp - > IsInGame ( ) )
{
if ( gp - > IsFakeClient ( ) | | gp - > IsSourceTV ( ) )
{
DETOUR_MEMBER_CALL ( GiveNamedItem ) ( pszName , iSubType ) ;
}
else
{
g_ClientGiveNamedCounter [ idx ] + + ;
if ( g_ClientGiveNamedCounter [ idx ] < = g_Capacity )
{
smutils - > LogMessage ( myself , " DETOUR_DECL_MEMBER2. STEAMID: %s, name: %s. pszName: %s. iSubType: %i. counter: %i " ,
g_ClientSteamIDMap [ idx ] , g_ClientNameMap [ idx ] , pszName , iSubType , g_ClientGiveNamedCounter [ idx ] ) ;
DETOUR_MEMBER_CALL ( GiveNamedItem ) ( pszName , iSubType ) ;
}
else //log spammers
{
smutils - > LogMessage ( myself , " SPAMS A LOT. STEAMID: %s, name: %s. pszName: %s. iSubType: %i. counter: %i " ,
g_ClientSteamIDMap [ idx ] , g_ClientNameMap [ idx ] , pszName , iSubType , g_ClientGiveNamedCounter [ idx ] ) ;
}
}
}
}
2024-09-23 19:11:46 +02:00
}
}
}
GiveNamedItemTracker : : GiveNamedItemTracker ( )
{
m_GiveNamedItem = NULL ;
m_GiveNamedItemDetour = NULL ;
}
void GiveNamedItemTracker : : SDK_OnUnload ( )
{
if ( g_pGiveNamedItemTimer )
{
timersys - > KillTimer ( g_pGiveNamedItemTimer ) ;
}
}
bool GiveNamedItemTracker : : SDK_OnLoad ( char * error , size_t maxlength , bool late )
{
void * pBinary = dlopen ( " cstrike/bin/server_srv.so " , RTLD_NOW ) ;
2024-09-29 19:33:19 +02:00
if ( ! pBinary )
2024-09-23 19:11:46 +02:00
{
smutils - > LogError ( myself , " Could not dlopen cstrike/bin/server_srv.so " ) ;
return false ;
}
void * adrGiveNamedItem = NULL ;
//CBaseEntity *CCSPlayer::GiveNamedItem
adrGiveNamedItem = memutils - > ResolveSymbol ( pBinary , " _ZN9CCSPlayer13GiveNamedItemEPKci " ) ;
dlclose ( pBinary ) ;
// Setup GiveNamedItem detour.
CDetourManager : : Init ( g_pSM - > GetScriptingEngine ( ) , NULL ) ;
m_GiveNamedItemDetour = DETOUR_CREATE_MEMBER ( GiveNamedItem , adrGiveNamedItem ) ;
if ( ! m_GiveNamedItemDetour )
{
return false ;
}
m_GiveNamedItemDetour - > EnableDetour ( ) ;
playerhelpers - > AddClientListener ( this ) ; //needed so the OnClient forwards work.
//set up timer for reseting GiveNamedItemTracker counts.
g_pGiveNamedItemTimer = timersys - > CreateTimer ( & g_GiveNamedItemTracker , 2.0 , NULL , TIMER_FLAG_REPEAT ) ;
2024-10-04 13:12:19 +02:00
for ( int idx = 0 ; idx < = 65 ; idx + + )
{
g_ClientGiveNamedCounter [ idx ] = - 1 ;
}
2024-09-23 19:11:46 +02:00
return true ;
}
void GiveNamedItemTracker : : OnClientPostAdminCheck ( int client )
{
2024-09-29 19:33:19 +02:00
g_ClientGiveNamedCounter [ client ] = 0 ;
2024-09-23 19:11:46 +02:00
IGamePlayer * gp = playerhelpers - > GetGamePlayer ( client ) ;
strlcpy ( g_ClientSteamIDMap [ client ] , gp - > GetAuthString ( ) , sizeof ( * g_ClientSteamIDMap ) ) ;
strlcpy ( g_ClientNameMap [ client ] , gp - > GetName ( ) , sizeof ( * g_ClientNameMap ) ) ;
}
void GiveNamedItemTracker : : OnClientDisconnected ( int client )
{
2024-10-04 13:12:19 +02:00
g_ClientGiveNamedCounter [ client ] = - 1 ;
2024-09-23 19:11:46 +02:00
strlcpy ( g_ClientSteamIDMap [ client ] , " " , sizeof ( * g_ClientSteamIDMap ) ) ;
strlcpy ( g_ClientNameMap [ client ] , " " , sizeof ( * g_ClientNameMap ) ) ;
}
void GiveNamedItemTracker : : OnTimer ( )
{
2024-09-29 19:33:19 +02:00
for ( int idx = 0 ; idx < = playerhelpers - > GetMaxClients ( ) ; idx + + )
2024-09-23 19:11:46 +02:00
{
2024-10-04 13:12:19 +02:00
if ( g_ClientGiveNamedCounter [ idx ] = = - 1 )
{
continue ;
}
2024-09-29 19:33:19 +02:00
if ( strcmp ( g_ClientSteamIDMap [ idx ] , " " ) = = 0 )
2024-09-23 19:11:46 +02:00
{
2024-09-29 19:33:19 +02:00
//empty steamid. (null). idx: 2. name: mituju
//according to my logging does gp->GetAuthString() in DETOUR_DECL_MEMBER2 sometimes return null.
//therefore rerunning it here to try and re-assign them their steam ID if still missing.
IGamePlayer * gp = playerhelpers - > GetGamePlayer ( idx ) ;
if ( gp & & gp - > IsConnected ( ) & & gp - > IsInGame ( ) )
2024-09-23 19:11:46 +02:00
{
2024-10-04 13:12:19 +02:00
const char * steamID = gp - > GetAuthString ( ) ;
const char * name = gp - > GetName ( ) ;
if ( steamID )
{
strlcpy ( g_ClientSteamIDMap [ idx ] , steamID , sizeof ( * g_ClientSteamIDMap ) ) ;
}
//not too bad if we miss the name, just steam id is important
if ( name )
{
strlcpy ( g_ClientNameMap [ idx ] , name , sizeof ( * g_ClientNameMap ) ) ;
}
2024-09-23 19:11:46 +02:00
}
}
2024-09-29 19:33:19 +02:00
g_ClientGiveNamedCounter [ idx ] = 0 ;
2024-09-23 19:11:46 +02:00
}
}
ResultType GiveNamedItemTimer : : OnTimer ( ITimer * pTimer , void * pData )
{
g_Interface . OnTimer ( ) ;
return Pl_Continue ;
}
void GiveNamedItemTimer : : OnTimerEnd ( ITimer * pTimer , void * pData ) { }