Raised This Month: $ Target: $400
 0% 

YACCH: Simple ConCommand hooking...


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
XAD
Senior Member
Join Date: Mar 2004
Location: Sweden
Old 01-21-2005 , 11:37   YACCH: Simple ConCommand hooking...
Reply With Quote #1

Well, as people will need to hook ConCommand (due to autobuy) I thought I would share my version of hooking ConCommand, which make the coding a hook almost the same as a regular ConCommand...

Example to hook 'say'...
Code:
extern ICvar *g_pCVar;

PLUGIN_CON_COMMAND_F( say, "Display player message", FCVAR_GAMEDLL )
{
	... your code ...
	if( ... do not call original function ... )
		return PLUGIN_STOP;

	return PLUGIN_CONTINUE;
}
NOTE! If you create multiple hooks they will be called in the order declared. Between different server plugins I don't know as I haven't tested it.
NOTE2! I have only tested this on linux... please let me know if it works on windows...

/X

PS! The name of the class should probably be something else than plugin but that's what I started with...

The header file...
Code:
//-----------------------------------------------------------------------------
// Purpose: Support command hook, requires g_pCVar to be allocated.
// NOTE! Default ICvar allocation is 'g_pCVar'. 
//       To use a different pointer name define "ENGINEVAR" before
//       including this header file.
//-----------------------------------------------------------------------------
#ifndef ENGINECVAR
#define ENGINECVAR (g_pCVar)
#endif

extern ICvar *ENGINECVAR;

#define PLUGIN_CON_COMMAND( name, description ) \
   static PLUGIN_RESULT name(); \
   static PluginConCommand name##_command( #name, name, description ); \
   static PLUGIN_RESULT name()

#define PLUGIN_CON_COMMAND_F( name, description, flags ) \
   static PLUGIN_RESULT name(); \
   static PluginConCommand name##_command( #name, name, description, flags ); \
   static PLUGIN_RESULT name()

// Called when a ConCommand needs to execute 
// (return with PLUGIN_CONTINUE to call original function)
typedef PLUGIN_RESULT (*FnPluginCommandCallback)( void );

// Special ConCommand to hook commands
class PluginConCommand : public ConCommand
{ 
friend class ConCommandBaseMgr;
friend class CCvar;

public: 
	PluginConCommand( void ) : ConCommand() { Create(); }
	PluginConCommand( char const *pName, FnPluginCommandCallback fnCallback, 
	                  char const *pHelpString = 0, int flags = 0, 
	                  FnCommandCompletionCallback completionFunc = 0 )
	                : ConCommand( pName, NULL, pHelpString, flags, completionFunc )
	                { Create( pName, fnCallback ); }

	// Invoke the original function
	virtual void Dispatch( void )
	{
		if( m_fnPluginCommandCallback && (*m_fnPluginCommandCallback)() != PLUGIN_CONTINUE )
			return;
		if ( m_pConCommandOriginal && m_pConCommandOriginal->IsCommand() )
			m_pConCommandOriginal->Dispatch();
	}

protected:

	virtual void Create( const char *pName = NULL, FnPluginCommandCallback fnCallback = NULL )
	{
		m_fnPluginCommandCallback = fnCallback;
		m_pConCommandOriginal     = NULL;
	}

	// Override Init
	virtual void Init( void )
	{
		if( ! m_pConCommandOriginal )
		{
			const char *name = GetName();
			if( name && name[0] )
			{
				// Search the engine command list
				ConCommandBase const *cmd = NULL;
				if( ENGINECVAR )
					cmd = ENGINECVAR->GetCommands();
				for ( ; cmd && stricmp( name, cmd->GetName() ); cmd = cmd->GetNext() )
					{}
				if( cmd && cmd != this && cmd->IsCommand() )
				{
					m_pConCommandOriginal = (ConCommand*) cmd;
					Msg( "[%s] Plugin created hook on command \"%s\"\n",
					     VNAME, cmd->GetName() );
				}
			}
		}
		ConCommand::Init();
	}

protected:

	// This will hold the new callback pointer
	FnPluginCommandCallback     m_fnPluginCommandCallback;

	// This will hold a pointer to the original command
	ConCommand                 *m_pConCommandOriginal;
};
XAD is offline
vancelorgin
Senior Member
Join Date: Dec 2004
Location: san frandisco
Old 01-21-2005 , 15:36  
Reply With Quote #2

Nice stuff. I use this, but it's not as pretty Should work fine on windows.

Like I said before though I don't use this for my say hook as you'd need to hook engine->Cmd_Arg funcs to change the input of it or use some ugly hack.
__________________
Avoid like the plague.
vancelorgin is offline
megiddo
Junior Member
Join Date: Nov 2004
Old 01-20-2007 , 02:02   Re: YACCH: Simple ConCommand hooking...
Reply With Quote #3

<-Snip, sorry I'm an idiot ->

Last edited by megiddo; 01-20-2007 at 17:24.
megiddo is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 20:38.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode