Member
12-02-2020
, 16:31
Re: I need help in (player_disconnect)
#11
Quote:
Originally Posted by
Dragokas
I think we can do it by hooking
CBaseClient:: PerformDisconnection , responsible for logging the message in console.log:
PHP Code:
CBaseClient * __cdecl CBaseClient :: PerformDisconnection ( CBaseClient * this , const char * a2 )
{
...
ConMsg ( "Dropped %s from server (%s)\n" , v5 , a2 );
But I don't know how to do it correctly. Maybe, somebody help?
My attempt:
Spoiler
Code:
"Games"
{
"left4dead2"
{
"Functions"
{
"CBaseClient::PerformDisconnection"
{
"signature" "CBaseClient::PerformDisconnection"
"callconv" "cdecl"
"return" "int"
"this" "address"
"arguments"
{
"a2"
{
"type" "charptr"
}
}
}
}
"Signatures"
{
"CBaseClient::PerformDisconnection"
{
"library" "engine"
"linux" "@_ZN11CBaseClient20PerformDisconnectionEPKc"
/* Found by "Dropped %s from server" */
"windows" ""
}
}
}
}
PHP Code:
#define PLUGIN_VERSION "1.0"
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <dhooks>
#define DEBUG 0
#define GAMEDATA "disconnection.gamedata"
public Plugin myinfo =
{
name = "[L4D2] Get Disconnection Reason" ,
author = "Dragokas" ,
description = "Catches player's disconnection reason" ,
version = PLUGIN_VERSION ,
url = "https://github.com/dragokas"
}
Handle hDetour ;
public APLRes AskPluginLoad2 ( Handle myself , bool late , char [] error , int err_max )
{
EngineVersion test = GetEngineVersion ();
if( test != Engine_Left4Dead2 )
{
strcopy ( error , err_max , "Plugin only supports Left 4 Dead 2." );
return APLRes_SilentFailure ;
}
return APLRes_Success ;
}
public void OnPluginStart ()
{
char sPath [ PLATFORM_MAX_PATH ];
BuildPath ( Path_SM , sPath , sizeof ( sPath ), "gamedata/%s.txt" , GAMEDATA );
Handle hGameData = LoadGameConfigFile ( GAMEDATA );
if( hGameData == null ) SetFailState ( "Failed to load \"%s.txt\" gamedata." , GAMEDATA );
SetupDetour ( hGameData );
delete hGameData ;
}
public void OnPluginEnd ()
{
if( ! DHookDisableDetour ( hDetour , false , PerformDisconnection ) )
SetFailState ( "Failed to disable detour \"CBaseClient::PerformDisconnection\"." );
}
void SetupDetour ( Handle hGameData )
{
hDetour = DHookCreateFromConf ( hGameData , "CBaseClient::PerformDisconnection" );
if( ! hDetour )
SetFailState ( "Failed to find \"CBaseClient::PerformDisconnection\" signature." );
if( ! DHookEnableDetour ( hDetour , false , PerformDisconnection ) )
SetFailState ( "Failed to start detour \"CBaseClient::PerformDisconnection\"." );
}
public MRESReturn PerformDisconnection ( Address pThis , DHookParam hParams )
{
char reason [ 64 ];
if( pThis )
{
// this one crashes
int client = LoadFromAddress ( pThis , NumberType_Int32 );
// ok, this one also wrong. Need to deref firstly.
hParams . GetString ( 1 , reason , sizeof ( reason ));
LogError ( "Player # %i (%i) is disconnected (reason: '%s')" , pThis , client , reason );
}
return MRES_Ignored ;
}
Crashes on LoadFromAddress. Why address is incorrect?
Also, not sure what "return" type in gamedata is expected. Does Dhook Detours support class instance as a return at all? Any walkaround?
Sample of results coming to pThis:
Supposed struct:
PHP Code:
class CBaseClient : public IGameEventListener2 , public IClient , public IClientMessageHandler
{
typedef struct CustomFile_s
{
CRC32_t crc ; //file CRC
unsigned int reqID ; // download request ID
} CustomFile_t ;
public:
CBaseClient ();
virtual ~ CBaseClient ();
public:
int GetPlayerSlot () const { return m_nClientSlot ; };
int GetUserID () const { return m_UserID ; };
const USERID_t GetNetworkID () const;
const char * GetClientName () const { return m_Name ; };
INetChannel * GetNetChannel () { return m_NetChannel ; };
IServer * GetServer () { return ( IServer *) m_Server ; };
const char * GetUserSetting (const char * cvar ) const;
const char * GetNetworkIDString () const;
...
PS. The topic is marked "
Solved " when actually is not at all.
As you said, this question is difficult to answer.
Most likely, it just doesn't work in l4d2.
For me, this topic is no longer so important, since I went a different way to solve it. It was good to get an answer, but it probably won't be.
__________________