mirror of
https://github.com/alliedmodders/sourcemod.git
synced 2025-12-07 10:28:34 +00:00
DHooks Merge pt1
This commit is contained in:
parent
4f3c3175e6
commit
8fc0e6fd5a
@ -657,6 +657,7 @@ BuildScripts = [
|
||||
'extensions/tf2/AMBuilder',
|
||||
'extensions/topmenus/AMBuilder',
|
||||
'extensions/updater/AMBuilder',
|
||||
'extensions/dhooks/AMBuilder',
|
||||
]
|
||||
|
||||
if builder.backend == 'amb2':
|
||||
|
||||
39
extensions/dhooks/AMBuilder
Normal file
39
extensions/dhooks/AMBuilder
Normal file
@ -0,0 +1,39 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import os
|
||||
|
||||
for arch in SM.archs:
|
||||
binary = SM.ExtLibrary(builder, 'dhooks.ext', arch)
|
||||
binary.compiler.cxxincludes += [
|
||||
os.path.join(builder.currentSourcePath),
|
||||
os.path.join(SM.mms_root, 'core'),
|
||||
os.path.join(SM.mms_root, 'core', 'sourcehook'),
|
||||
os.path.join(builder.sourcePath, 'public'),
|
||||
os.path.join(builder.sourcePath, 'public', 'extensions'),
|
||||
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
|
||||
os.path.join(builder.sourcePath, 'public', 'jit'),
|
||||
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'vm'),
|
||||
os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl', 'include'),
|
||||
os.path.join(builder.sourcePath, 'public', 'amtl', 'amtl'),
|
||||
]
|
||||
binary.compiler.defines += ['META_NO_HL2SDK']
|
||||
binary.sources += [
|
||||
'extension.cpp',
|
||||
'listeners.cpp',
|
||||
'natives.cpp',
|
||||
'vhook.cpp',
|
||||
'util.cpp',
|
||||
os.path.join(builder.sourcePath, 'public', 'smsdk_ext.cpp'),
|
||||
]
|
||||
|
||||
if os.path.isfile(os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86', 'assembler-x86.cpp')):
|
||||
binary.sources += [os.path.join(builder.sourcePath, 'sourcepawn', 'vm', 'x86', 'assembler-x86.cpp'),]
|
||||
elif os.path.isfile(os.path.join(builder.sourcePath, 'public', 'jit', 'x86', 'assembler-x86.cpp')):
|
||||
binary.sources += [os.path.join(builder.sourcePath, 'public', 'jit', 'x86', 'assembler-x86.cpp'),]
|
||||
else:
|
||||
raise Exception('Could not find assembler-x86.cpp. Did you checkout SourceMod\'s submodules?')
|
||||
|
||||
SM.extensions += [builder.Add(binary)]
|
||||
141
extensions/dhooks/extension.cpp
Normal file
141
extensions/dhooks/extension.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#include "extension.h"
|
||||
#include "listeners.h"
|
||||
|
||||
DHooks g_DHooksIface; /**< Global singleton for extension's main interface */
|
||||
SMEXT_LINK(&g_DHooksIface);
|
||||
|
||||
IBinTools *g_pBinTools;
|
||||
ISDKHooks *g_pSDKHooks;
|
||||
ISDKTools *g_pSDKTools;
|
||||
DHooksEntityListener *g_pEntityListener = NULL;
|
||||
|
||||
HandleType_t g_HookSetupHandle = 0;
|
||||
HandleType_t g_HookParamsHandle = 0;
|
||||
HandleType_t g_HookReturnHandle = 0;
|
||||
|
||||
bool DHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
{
|
||||
HandleError err;
|
||||
g_HookSetupHandle = handlesys->CreateType("HookSetup", this, 0, NULL, NULL, myself->GetIdentity(), &err);
|
||||
if(g_HookSetupHandle == 0)
|
||||
{
|
||||
snprintf(error, maxlength, "Could not create hook setup handle type (err: %d)", err);
|
||||
return false;
|
||||
}
|
||||
g_HookParamsHandle = handlesys->CreateType("HookParams", this, 0, NULL, NULL, myself->GetIdentity(), &err);
|
||||
if(g_HookParamsHandle == 0)
|
||||
{
|
||||
snprintf(error, maxlength, "Could not create hook params handle type (err: %d)", err);
|
||||
return false;
|
||||
}
|
||||
g_HookReturnHandle = handlesys->CreateType("HookReturn", this, 0, NULL, NULL, myself->GetIdentity(), &err);
|
||||
if(g_HookReturnHandle == 0)
|
||||
{
|
||||
snprintf(error, maxlength, "Could not create hook return handle type (err: %d)", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
||||
sharesys->AddDependency(myself, "sdktools.ext", true, true);
|
||||
sharesys->AddDependency(myself, "sdkhooks.ext", true, true);
|
||||
|
||||
sharesys->RegisterLibrary(myself, "dhooks");
|
||||
plsys->AddPluginsListener(this);
|
||||
sharesys->AddNatives(myself, g_Natives);
|
||||
|
||||
g_pEntityListener = new DHooksEntityListener();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DHooks::OnHandleDestroy(HandleType_t type, void *object)
|
||||
{
|
||||
if(type == g_HookSetupHandle)
|
||||
{
|
||||
delete (HookSetup *)object;
|
||||
}
|
||||
else if(type == g_HookParamsHandle)
|
||||
{
|
||||
delete (HookParamsStruct *)object;
|
||||
}
|
||||
else if(type == g_HookReturnHandle)
|
||||
{
|
||||
delete (HookReturnStruct *)object;
|
||||
}
|
||||
}
|
||||
|
||||
void DHooks::SDK_OnAllLoaded()
|
||||
{
|
||||
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
|
||||
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
|
||||
SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks);
|
||||
|
||||
g_pSDKHooks->AddEntityListener(g_pEntityListener);
|
||||
}
|
||||
|
||||
void DHooks::SDK_OnUnload()
|
||||
{
|
||||
CleanupHooks();
|
||||
if(g_pEntityListener)
|
||||
{
|
||||
g_pEntityListener->CleanupListeners();
|
||||
g_pSDKHooks->RemoveEntityListener(g_pEntityListener);
|
||||
delete g_pEntityListener;
|
||||
}
|
||||
plsys->RemovePluginsListener(this);
|
||||
|
||||
handlesys->RemoveType(g_HookSetupHandle, myself->GetIdentity());
|
||||
handlesys->RemoveType(g_HookParamsHandle, myself->GetIdentity());
|
||||
handlesys->RemoveType(g_HookReturnHandle, myself->GetIdentity());
|
||||
}
|
||||
|
||||
bool DHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late)
|
||||
{
|
||||
if(!SetupHookManager(ismm))
|
||||
{
|
||||
snprintf(error, maxlength, "Failed to get IHookManagerAutoGen iface");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DHooks::OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
CleanupHooks(plugin->GetBaseContext());
|
||||
if(g_pEntityListener)
|
||||
{
|
||||
g_pEntityListener->CleanupListeners(plugin->GetBaseContext());
|
||||
}
|
||||
}
|
||||
// The next 3 functions handle cleanup if our interfaces are going to be unloaded
|
||||
bool DHooks::QueryRunning(char *error, size_t maxlength)
|
||||
{
|
||||
SM_CHECK_IFACE(SDKTOOLS, g_pSDKTools);
|
||||
SM_CHECK_IFACE(BINTOOLS, g_pBinTools);
|
||||
SM_CHECK_IFACE(SDKHOOKS, g_pSDKHooks);
|
||||
return true;
|
||||
}
|
||||
void DHooks::NotifyInterfaceDrop(SMInterface *pInterface)
|
||||
{
|
||||
if(strcmp(pInterface->GetInterfaceName(), SMINTERFACE_SDKHOOKS_NAME) == 0)
|
||||
{
|
||||
if(g_pEntityListener)
|
||||
{
|
||||
// If this fails, remove this line and just delete the ent listener instead
|
||||
g_pSDKHooks->RemoveEntityListener(g_pEntityListener);
|
||||
|
||||
g_pEntityListener->CleanupListeners();
|
||||
delete g_pEntityListener;
|
||||
g_pEntityListener = NULL;
|
||||
}
|
||||
g_pSDKHooks = NULL;
|
||||
}
|
||||
else if(strcmp(pInterface->GetInterfaceName(), SMINTERFACE_BINTOOLS_NAME) == 0)
|
||||
{
|
||||
g_pBinTools = NULL;
|
||||
}
|
||||
else if(strcmp(pInterface->GetInterfaceName(), SMINTERFACE_SDKTOOLS_NAME) == 0)
|
||||
{
|
||||
g_pSDKTools = NULL;
|
||||
}
|
||||
}
|
||||
132
extensions/dhooks/extension.h
Normal file
132
extensions/dhooks/extension.h
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Sample Extension
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
|
||||
/**
|
||||
* @file extension.h
|
||||
* @brief Sample extension code header.
|
||||
*/
|
||||
|
||||
#include "smsdk_ext.h"
|
||||
|
||||
#include <ISDKHooks.h>
|
||||
#include <IBinTools.h>
|
||||
#include <ISDKTools.h>
|
||||
#include "sdk-hacks.h"
|
||||
|
||||
/**
|
||||
* @brief Sample implementation of the SDK Extension.
|
||||
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
|
||||
*/
|
||||
|
||||
class DHooks : public SDKExtension, public ISMEntityListener, public IPluginsListener, public IHandleTypeDispatch
|
||||
{
|
||||
public:
|
||||
virtual void OnHandleDestroy(HandleType_t type, void *object);
|
||||
public: //IPluginsListener
|
||||
virtual void OnPluginUnloaded(IPlugin *plugin);
|
||||
public:
|
||||
/**
|
||||
* @brief This is called after the initial loading sequence has been processed.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param maxlength Size of error message buffer.
|
||||
* @param late Whether or not the module was loaded after map load.
|
||||
* @return True to succeed loading, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
*/
|
||||
virtual void SDK_OnUnload();
|
||||
|
||||
/**
|
||||
* @brief This is called once all known extensions have been loaded.
|
||||
* Note: It is is a good idea to add natives here, if any are provided.
|
||||
*/
|
||||
virtual void SDK_OnAllLoaded();
|
||||
|
||||
/**
|
||||
* @brief Called when the pause state is changed.
|
||||
*/
|
||||
//virtual void SDK_OnPauseChange(bool paused);
|
||||
|
||||
/**
|
||||
* @brief this is called when Core wants to know if your extension is working.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param maxlength Size of error message buffer.
|
||||
* @return True if working, false otherwise.
|
||||
*/
|
||||
virtual bool QueryRunning(char *error, size_t maxlength);
|
||||
//virtual bool QueryInterfaceDrop(SMInterface *pInterface);
|
||||
virtual void NotifyInterfaceDrop(SMInterface *pInterface);
|
||||
virtual void OnCoreMapEnd();
|
||||
public:
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
/**
|
||||
* @brief Called when Metamod is attached, before the extension version is called.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @param late Whether or not Metamod considers this a late load.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod is detaching, after the extension version is called.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod's pause state is changing.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param paused Pause state being set.
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
|
||||
#endif
|
||||
};
|
||||
extern SourceHook::IHookManagerAutoGen *g_pHookManager;
|
||||
extern sp_nativeinfo_t g_Natives[];
|
||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
118
extensions/dhooks/listeners.cpp
Normal file
118
extensions/dhooks/listeners.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include "listeners.h"
|
||||
#include "vhook.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
ke::Vector<EntityListener> g_EntityListeners;
|
||||
ke::Vector<DHooksManager *>g_pRemoveList;
|
||||
|
||||
void FrameCleanupHooks(void *data)
|
||||
{
|
||||
for (int i = g_pRemoveList.length() - 1; i >= 0; i--)
|
||||
{
|
||||
DHooksManager *manager = g_pRemoveList.at(i);
|
||||
delete manager;
|
||||
g_pRemoveList.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
void DHooks::OnCoreMapEnd()
|
||||
{
|
||||
for(int i = g_pHooks.length() -1; i >= 0; i--)
|
||||
{
|
||||
DHooksManager *manager = g_pHooks.at(i);
|
||||
if(manager->callback->hookType == HookType_GameRules)
|
||||
{
|
||||
delete manager;
|
||||
g_pHooks.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DHooksEntityListener::CleanupListeners(IPluginContext *pContext)
|
||||
{
|
||||
for(int i = g_EntityListeners.length() -1; i >= 0; i--)
|
||||
{
|
||||
if(pContext == NULL || pContext == g_EntityListeners.at(i).callback->GetParentRuntime()->GetDefaultContext())
|
||||
{
|
||||
g_EntityListeners.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DHooksEntityListener::OnEntityCreated(CBaseEntity *pEntity, const char *classname)
|
||||
{
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
|
||||
for(int i = g_EntityListeners.length() -1; i >= 0; i--)
|
||||
{
|
||||
EntityListener listerner = g_EntityListeners.at(i);
|
||||
if(listerner.type == ListenType_Created)
|
||||
{
|
||||
IPluginFunction *callback = listerner.callback;
|
||||
callback->PushCell(entity);
|
||||
callback->PushString(classname);
|
||||
callback->Execute(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DHooksEntityListener::OnEntityDestroyed(CBaseEntity *pEntity)
|
||||
{
|
||||
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
|
||||
for(int i = g_EntityListeners.length() -1; i >= 0; i--)
|
||||
{
|
||||
EntityListener listerner = g_EntityListeners.at(i);
|
||||
if(listerner.type == ListenType_Deleted)
|
||||
{
|
||||
IPluginFunction *callback = listerner.callback;
|
||||
callback->PushCell(gamehelpers->EntityToBCompatRef(pEntity));
|
||||
callback->Execute(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = g_pHooks.length() -1; i >= 0; i--)
|
||||
{
|
||||
DHooksManager *manager = g_pHooks.at(i);
|
||||
if(manager->callback->hookType == HookType_Entity && manager->callback->entity == entity)
|
||||
{
|
||||
if(g_pRemoveList.length() == 0)
|
||||
{
|
||||
smutils->AddFrameAction(&FrameCleanupHooks, NULL);
|
||||
}
|
||||
|
||||
g_pRemoveList.append(manager);
|
||||
g_pHooks.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool DHooksEntityListener::AddPluginEntityListener(ListenType type, IPluginFunction *callback)
|
||||
{
|
||||
for(int i = g_EntityListeners.length() -1; i >= 0; i--)
|
||||
{
|
||||
EntityListener listerner = g_EntityListeners.at(i);
|
||||
if(listerner.callback == callback && listerner.type == type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
EntityListener listener;
|
||||
listener.callback = callback;
|
||||
listener.type = type;
|
||||
g_EntityListeners.append(listener);
|
||||
return true;
|
||||
}
|
||||
bool DHooksEntityListener::RemovePluginEntityListener(ListenType type, IPluginFunction *callback)
|
||||
{
|
||||
for(int i = g_EntityListeners.length() -1; i >= 0; i--)
|
||||
{
|
||||
EntityListener listerner = g_EntityListeners.at(i);
|
||||
if(listerner.callback == callback && listerner.type == type)
|
||||
{
|
||||
g_EntityListeners.remove(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
31
extensions/dhooks/listeners.h
Normal file
31
extensions/dhooks/listeners.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _INCLUDE_LISTENERS_H_
|
||||
#define _INCLUDE_LISTENERS_H_
|
||||
|
||||
#include "extension.h"
|
||||
#include "vhook.h"
|
||||
|
||||
enum ListenType
|
||||
{
|
||||
ListenType_Created,
|
||||
ListenType_Deleted
|
||||
};
|
||||
|
||||
class DHooksEntityListener : public ISMEntityListener
|
||||
{
|
||||
public:
|
||||
virtual void OnEntityCreated(CBaseEntity *pEntity, const char *classname);
|
||||
virtual void OnEntityDestroyed(CBaseEntity *pEntity);
|
||||
void CleanupListeners(IPluginContext *func = NULL);
|
||||
bool AddPluginEntityListener(ListenType type, IPluginFunction *callback);
|
||||
bool RemovePluginEntityListener(ListenType type, IPluginFunction *callback);
|
||||
};
|
||||
|
||||
|
||||
struct EntityListener
|
||||
{
|
||||
ListenType type;
|
||||
IPluginFunction *callback;
|
||||
};
|
||||
|
||||
extern ke::Vector<DHooksManager *> g_pHooks;
|
||||
#endif
|
||||
1098
extensions/dhooks/natives.cpp
Normal file
1098
extensions/dhooks/natives.cpp
Normal file
File diff suppressed because it is too large
Load Diff
14
extensions/dhooks/natives.h
Normal file
14
extensions/dhooks/natives.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _INCLUDE_NATIVES_H_
|
||||
#define _INCLUDE_NATIVES_H_
|
||||
|
||||
#include "extension.h"
|
||||
#include "vhook.h"
|
||||
#include "listeners.h"
|
||||
|
||||
extern DHooksEntityListener *g_pEntityListener;
|
||||
extern ISDKTools *g_pSDKTools;
|
||||
extern HandleType_t g_HookSetupHandle;
|
||||
extern HandleType_t g_HookParamsHandle;
|
||||
extern HandleType_t g_HookReturnHandle;
|
||||
extern ke::Vector<DHooksManager *> g_pHooks;
|
||||
#endif
|
||||
75
extensions/dhooks/sdk-hacks.h
Normal file
75
extensions/dhooks/sdk-hacks.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef _INCLUDE_SDK_HACKS_H_
|
||||
#define _INCLUDE_SDK_HACKS_H_
|
||||
|
||||
class SDKVector
|
||||
{
|
||||
public:
|
||||
SDKVector(float x1, float y1, float z1)
|
||||
{
|
||||
this->x = x1;
|
||||
this->y = y1;
|
||||
this->z = z1;
|
||||
}
|
||||
SDKVector(void)
|
||||
{
|
||||
this->x = 0.0;
|
||||
this->y = 0.0;
|
||||
this->z = 0.0;
|
||||
}
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
struct string_t
|
||||
{
|
||||
public:
|
||||
bool operator!() const { return ( pszValue == NULL ); }
|
||||
bool operator==( const string_t &rhs ) const { return ( pszValue == rhs.pszValue ); }
|
||||
bool operator!=( const string_t &rhs ) const { return ( pszValue != rhs.pszValue ); }
|
||||
bool operator<( const string_t &rhs ) const { return ((void *)pszValue < (void *)rhs.pszValue ); }
|
||||
|
||||
const char *ToCStr() const { return ( pszValue ) ? pszValue : ""; }
|
||||
|
||||
protected:
|
||||
const char *pszValue;
|
||||
};
|
||||
|
||||
struct castable_string_t : public string_t // string_t is used in unions, hence, no constructor allowed
|
||||
{
|
||||
castable_string_t() { pszValue = NULL; }
|
||||
castable_string_t( const char *pszFrom ) { pszValue = (pszFrom && *pszFrom) ? pszFrom : 0; }
|
||||
};
|
||||
|
||||
#define NULL_STRING castable_string_t()
|
||||
#define STRING( string_t_obj ) (string_t_obj).ToCStr()
|
||||
#define MAKE_STRING( c_str ) castable_string_t( c_str )
|
||||
|
||||
#define FL_EDICT_FREE (1<<1)
|
||||
|
||||
struct edict_t
|
||||
{
|
||||
public:
|
||||
bool IsFree()
|
||||
{
|
||||
return (m_fStateFlags & FL_EDICT_FREE) != 0;
|
||||
}
|
||||
private:
|
||||
int m_fStateFlags;
|
||||
};
|
||||
|
||||
class CBaseHandle
|
||||
{
|
||||
/*public:
|
||||
bool IsValid() const {return m_Index != INVALID_EHANDLE_INDEX;}
|
||||
int GetEntryIndex() const
|
||||
{
|
||||
if ( !IsValid() )
|
||||
return NUM_ENT_ENTRIES-1;
|
||||
return m_Index & ENT_ENTRY_MASK;
|
||||
}*/
|
||||
private:
|
||||
unsigned long m_Index;
|
||||
};
|
||||
|
||||
#endif
|
||||
82
extensions/dhooks/smsdk_config.h
Normal file
82
extensions/dhooks/smsdk_config.h
Normal file
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod Sample Extension
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
|
||||
/**
|
||||
* @file smsdk_config.h
|
||||
* @brief Contains macros for configuring basic extension information.
|
||||
*/
|
||||
|
||||
/* Basic information exposed publicly */
|
||||
#define SMEXT_CONF_NAME "DHooks"
|
||||
#define SMEXT_CONF_DESCRIPTION "Dynamic Hooks"
|
||||
#define SMEXT_CONF_VERSION "2.2.0"
|
||||
#define SMEXT_CONF_AUTHOR "Dr!fter"
|
||||
#define SMEXT_CONF_URL "http://www.sourcemod.net/"
|
||||
#define SMEXT_CONF_LOGTAG "DHOOKS"
|
||||
#define SMEXT_CONF_LICENSE "GPL"
|
||||
#define SMEXT_CONF_DATESTRING __DATE__
|
||||
|
||||
/**
|
||||
* @brief Exposes plugin's main interface.
|
||||
*/
|
||||
#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name;
|
||||
|
||||
/**
|
||||
* @brief Sets whether or not this plugin required Metamod.
|
||||
* NOTE: Uncomment to enable, comment to disable.
|
||||
*/
|
||||
#define SMEXT_CONF_METAMOD
|
||||
|
||||
/** Enable interfaces you want to use here by uncommenting lines */
|
||||
//#define SMEXT_ENABLE_FORWARDSYS
|
||||
#define SMEXT_ENABLE_HANDLESYS
|
||||
#define SMEXT_ENABLE_PLAYERHELPERS
|
||||
//#define SMEXT_ENABLE_DBMANAGER
|
||||
//#define SMEXT_ENABLE_GAMECONF
|
||||
//#define SMEXT_ENABLE_MEMUTILS
|
||||
#define SMEXT_ENABLE_GAMEHELPERS
|
||||
//#define SMEXT_ENABLE_TIMERSYS
|
||||
//#define SMEXT_ENABLE_THREADER
|
||||
//#define SMEXT_ENABLE_LIBSYS
|
||||
//#define SMEXT_ENABLE_MENUS
|
||||
//#define SMEXT_ENABLE_ADTFACTORY
|
||||
#define SMEXT_ENABLE_PLUGINSYS
|
||||
//#define SMEXT_ENABLE_ADMINSYS
|
||||
//#define SMEXT_ENABLE_TEXTPARSERS
|
||||
//#define SMEXT_ENABLE_USERMSGS
|
||||
//#define SMEXT_ENABLE_TRANSLATOR
|
||||
//#define SMEXT_ENABLE_NINVOKE
|
||||
//#define SMEXT_ENABLE_ROOTCONSOLEMENU
|
||||
|
||||
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
48
extensions/dhooks/util.cpp
Normal file
48
extensions/dhooks/util.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "util.h"
|
||||
|
||||
void * GetObjectAddr(HookParamType type, unsigned int flags, void **params, size_t offset)
|
||||
{
|
||||
#ifdef WIN32
|
||||
if (type == HookParamType_Object)
|
||||
return (void *)((intptr_t)params + offset);
|
||||
#elif POSIX
|
||||
if (type == HookParamType_Object && !(flags & PASSFLAG_ODTOR)) //Objects are passed by rrefrence if they contain destructors.
|
||||
return (void *)((intptr_t)params + offset);
|
||||
#endif
|
||||
return *(void **)((intptr_t)params + offset);
|
||||
|
||||
}
|
||||
|
||||
size_t GetParamOffset(HookParamsStruct *paramStruct, unsigned int index)
|
||||
{
|
||||
size_t offset = 0;
|
||||
for (unsigned int i = 0; i < index; i++)
|
||||
{
|
||||
#ifndef WIN32
|
||||
if (paramStruct->dg->params.at(i).type == HookParamType_Object && (paramStruct->dg->params.at(i).flags & PASSFLAG_ODTOR)) //Passed by refrence
|
||||
{
|
||||
offset += sizeof(void *);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
offset += paramStruct->dg->params.at(i).size;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
size_t GetParamTypeSize(HookParamType type)
|
||||
{
|
||||
return sizeof(void *);
|
||||
}
|
||||
|
||||
size_t GetParamsSize(DHooksCallback *dg)//Get the full size, this is for creating the STACK.
|
||||
{
|
||||
size_t res = 0;
|
||||
|
||||
for (int i = dg->params.size() - 1; i >= 0; i--)
|
||||
{
|
||||
res += dg->params.at(i).size;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
10
extensions/dhooks/util.h
Normal file
10
extensions/dhooks/util.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _INCLUDE_UTIL_FUNCTIONS_H_
|
||||
#define _INCLUDE_UTIL_FUNCTIONS_H_
|
||||
|
||||
#include "vhook.h"
|
||||
|
||||
size_t GetParamOffset(HookParamsStruct *params, unsigned int index);
|
||||
void * GetObjectAddr(HookParamType type, unsigned int flags, void **params, size_t offset);
|
||||
size_t GetParamTypeSize(HookParamType type);
|
||||
size_t GetParamsSize(DHooksCallback *dg);
|
||||
#endif
|
||||
104
extensions/dhooks/version.rc
Normal file
104
extensions/dhooks/version.rc
Normal file
@ -0,0 +1,104 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
//#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
#include <sourcemod_version.h>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION SM_VERSION_FILE
|
||||
PRODUCTVERSION SM_VERSION_FILE
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "SourceMod DHooks Extension"
|
||||
VALUE "FileDescription", "SourceMod DHooks Extension"
|
||||
VALUE "FileVersion", SM_VERSION_STRING
|
||||
VALUE "InternalName", "SourceMod DHooks Extension"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2019, AlliedModders LLC"
|
||||
VALUE "OriginalFilename", BINARY_NAME
|
||||
VALUE "ProductName", "SourceMod DHooks Extension"
|
||||
VALUE "ProductVersion", SM_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
324
extensions/dhooks/vfunc_call.h
Normal file
324
extensions/dhooks/vfunc_call.h
Normal file
@ -0,0 +1,324 @@
|
||||
#ifndef _INCLUDE_VFUNC_CALL_H_
|
||||
#define _INCLUDE_VFUNC_CALL_H_
|
||||
|
||||
#include "vhook.h"
|
||||
#include "extension.h"
|
||||
#include "util.h"
|
||||
|
||||
#define PARAMINFO_SWITCH(passType) \
|
||||
paramInfo[i].flags = dg->params.at(i).flags; \
|
||||
paramInfo[i].size = dg->params.at(i).size; \
|
||||
paramInfo[i].type = passType;
|
||||
|
||||
#define VSTK_PARAM_SWITCH(paramType) \
|
||||
if(paramStruct->isChanged[i]) \
|
||||
{ \
|
||||
*(paramType *)vptr = *(paramType *)newAddr; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
*(paramType *)vptr = *(paramType *)orgAddr; \
|
||||
} \
|
||||
if(i + 1 != dg->params.size()) \
|
||||
{ \
|
||||
vptr += dg->params.at(i).size; \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define VSTK_PARAM_SWITCH_OBJECT() \
|
||||
memcpy(vptr, objAddr, dg->params.at(i).size); \
|
||||
if(i + 1 != dg->params.size()) \
|
||||
{ \
|
||||
vptr += dg->params.at(i).size; \
|
||||
} \
|
||||
break;
|
||||
|
||||
template <class T>
|
||||
T CallVFunction(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface)
|
||||
{
|
||||
SourceMod::PassInfo *paramInfo = NULL;
|
||||
SourceMod::PassInfo returnInfo;
|
||||
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
returnInfo.flags = dg->returnFlag;
|
||||
returnInfo.size = sizeof(T);
|
||||
if( dg->returnType != ReturnType_Vector)
|
||||
{
|
||||
returnInfo.type = PassType_Basic;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnInfo.type = PassType_Object;
|
||||
}
|
||||
}
|
||||
|
||||
ICallWrapper *pCall;
|
||||
|
||||
size_t size = GetParamsSize(dg);
|
||||
|
||||
unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size);
|
||||
unsigned char *vptr = vstk;
|
||||
|
||||
*(void **)vptr = iface;
|
||||
|
||||
if(paramStruct)
|
||||
{
|
||||
vptr += sizeof(void *);
|
||||
paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size());
|
||||
|
||||
for(int i = 0; i < (int)dg->params.size(); i++)
|
||||
{
|
||||
size_t offset = GetParamOffset(paramStruct, i);
|
||||
|
||||
void *orgAddr = (void **)((intptr_t)paramStruct->orgParams + offset);
|
||||
void *newAddr = (void **)((intptr_t)paramStruct->newParams + offset);
|
||||
|
||||
switch(dg->params.at(i).type)
|
||||
{
|
||||
case HookParamType_Int:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(int);
|
||||
case HookParamType_Bool:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(cell_t);
|
||||
case HookParamType_Float:
|
||||
PARAMINFO_SWITCH(PassType_Float);
|
||||
VSTK_PARAM_SWITCH(float);
|
||||
case HookParamType_String:
|
||||
PARAMINFO_SWITCH(PassType_Object);
|
||||
VSTK_PARAM_SWITCH(string_t);
|
||||
case HookParamType_StringPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(string_t *);
|
||||
case HookParamType_CharPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(char *);
|
||||
case HookParamType_VectorPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(SDKVector *);
|
||||
case HookParamType_CBaseEntity:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(CBaseEntity *);
|
||||
case HookParamType_Edict:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(edict_t *);
|
||||
case HookParamType_Object:
|
||||
{
|
||||
void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset);
|
||||
PARAMINFO_SWITCH(PassType_Object);
|
||||
VSTK_PARAM_SWITCH_OBJECT();
|
||||
}
|
||||
default:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(void *);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
T ret = 0;
|
||||
|
||||
if(dg->returnType == ReturnType_Void)
|
||||
{
|
||||
pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, NULL, paramInfo, dg->params.size());
|
||||
pCall->Execute(vstk, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.size());
|
||||
pCall->Execute(vstk, &ret);
|
||||
}
|
||||
|
||||
pCall->Destroy();
|
||||
free(vstk);
|
||||
|
||||
if(paramInfo != NULL)
|
||||
{
|
||||
free(paramInfo);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
template <>
|
||||
SDKVector CallVFunction<SDKVector>(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface)
|
||||
{
|
||||
SourceMod::PassInfo *paramInfo = NULL;
|
||||
SourceMod::PassInfo returnInfo;
|
||||
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
returnInfo.flags = dg->returnFlag;
|
||||
returnInfo.size = sizeof(SDKVector);
|
||||
returnInfo.type = PassType_Object;
|
||||
}
|
||||
|
||||
ICallWrapper *pCall;
|
||||
|
||||
size_t size = GetParamsSize(dg);
|
||||
|
||||
unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size);
|
||||
unsigned char *vptr = vstk;
|
||||
|
||||
*(void **)vptr = iface;
|
||||
|
||||
if(paramStruct)
|
||||
{
|
||||
vptr += sizeof(void *);
|
||||
paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size());
|
||||
for(int i = 0; i < (int)dg->params.size(); i++)
|
||||
{
|
||||
size_t offset = GetParamOffset(paramStruct, i);
|
||||
|
||||
void *orgAddr = *(void **)((intptr_t)paramStruct->orgParams + offset);
|
||||
void *newAddr = *(void **)((intptr_t)paramStruct->newParams + offset);
|
||||
|
||||
switch (dg->params.at(i).type)
|
||||
{
|
||||
case HookParamType_Int:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(int);
|
||||
case HookParamType_Bool:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(cell_t);
|
||||
case HookParamType_Float:
|
||||
PARAMINFO_SWITCH(PassType_Float);
|
||||
VSTK_PARAM_SWITCH(float);
|
||||
case HookParamType_String:
|
||||
PARAMINFO_SWITCH(PassType_Object);
|
||||
VSTK_PARAM_SWITCH(string_t);
|
||||
case HookParamType_StringPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(string_t *);
|
||||
case HookParamType_CharPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(char *);
|
||||
case HookParamType_VectorPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(SDKVector *);
|
||||
case HookParamType_CBaseEntity:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(CBaseEntity *);
|
||||
case HookParamType_Edict:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(edict_t *);
|
||||
case HookParamType_Object:
|
||||
{
|
||||
void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset);
|
||||
PARAMINFO_SWITCH(PassType_Object);
|
||||
VSTK_PARAM_SWITCH_OBJECT();
|
||||
}
|
||||
default:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(void *);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDKVector ret;
|
||||
|
||||
pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.size());
|
||||
pCall->Execute(vstk, &ret);
|
||||
|
||||
pCall->Destroy();
|
||||
free(vstk);
|
||||
|
||||
if(paramInfo != NULL)
|
||||
{
|
||||
free(paramInfo);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#ifndef WIN32
|
||||
template <>
|
||||
string_t CallVFunction<string_t>(DHooksCallback *dg, HookParamsStruct *paramStruct, void *iface)
|
||||
{
|
||||
SourceMod::PassInfo *paramInfo = NULL;
|
||||
SourceMod::PassInfo returnInfo;
|
||||
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
returnInfo.flags = dg->returnFlag;
|
||||
returnInfo.size = sizeof(string_t);
|
||||
returnInfo.type = PassType_Object;
|
||||
}
|
||||
|
||||
ICallWrapper *pCall;
|
||||
|
||||
size_t size = GetParamsSize(dg);
|
||||
|
||||
unsigned char *vstk = (unsigned char *)malloc(sizeof(void *) + size);
|
||||
unsigned char *vptr = vstk;
|
||||
|
||||
*(void **)vptr = iface;
|
||||
|
||||
if(paramStruct)
|
||||
{
|
||||
vptr += sizeof(void *);
|
||||
paramInfo = (SourceMod::PassInfo *)malloc(sizeof(SourceMod::PassInfo) * dg->params.size());
|
||||
for(int i = 0; i < dg->params.size(); i++)
|
||||
{
|
||||
size_t offset = GetParamOffset(paramStruct, i);
|
||||
|
||||
void *orgAddr = *(void **)((intptr_t)paramStruct->orgParams + offset);
|
||||
void *newAddr = *(void **)((intptr_t)paramStruct->newParams + offset);
|
||||
|
||||
switch (dg->params.at(i).type)
|
||||
{
|
||||
case HookParamType_Int:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(int);
|
||||
case HookParamType_Bool:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(cell_t);
|
||||
case HookParamType_Float:
|
||||
PARAMINFO_SWITCH(PassType_Float);
|
||||
VSTK_PARAM_SWITCH(float);
|
||||
case HookParamType_String:
|
||||
PARAMINFO_SWITCH(PassType_Object);
|
||||
VSTK_PARAM_SWITCH(string_t);
|
||||
case HookParamType_StringPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(string_t *);
|
||||
case HookParamType_CharPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(char *);
|
||||
case HookParamType_VectorPtr:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(SDKVector *);
|
||||
case HookParamType_CBaseEntity:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(CBaseEntity *);
|
||||
case HookParamType_Edict:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(edict_t *);
|
||||
case HookParamType_Object:
|
||||
{
|
||||
void *objAddr = GetObjectAddr(HookParamType_Object, paramStruct->dg->params.at(i).flags, paramStruct->orgParams, offset);
|
||||
PARAMINFO_SWITCH(PassType_Object);
|
||||
VSTK_PARAM_SWITCH_OBJECT();
|
||||
}
|
||||
default:
|
||||
PARAMINFO_SWITCH(PassType_Basic);
|
||||
VSTK_PARAM_SWITCH(void *);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_t ret;
|
||||
|
||||
pCall = g_pBinTools->CreateVCall(dg->offset, 0, 0, &returnInfo, paramInfo, dg->params.size());
|
||||
pCall->Execute(vstk, &ret);
|
||||
|
||||
pCall->Destroy();
|
||||
free(vstk);
|
||||
|
||||
if(paramInfo != NULL)
|
||||
{
|
||||
free(paramInfo);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
922
extensions/dhooks/vhook.cpp
Normal file
922
extensions/dhooks/vhook.cpp
Normal file
@ -0,0 +1,922 @@
|
||||
#include "vhook.h"
|
||||
#include "vfunc_call.h"
|
||||
#include "util.h"
|
||||
|
||||
SourceHook::IHookManagerAutoGen *g_pHookManager = NULL;
|
||||
|
||||
ke::Vector<DHooksManager *> g_pHooks;
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
#ifdef WIN32
|
||||
#define OBJECT_OFFSET sizeof(void *)
|
||||
#else
|
||||
#define OBJECT_OFFSET (sizeof(void *)*2)
|
||||
#endif
|
||||
|
||||
DHooksManager::DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, IPluginFunction *plugincb, bool post)
|
||||
{
|
||||
this->callback = MakeHandler(setup->returnType);
|
||||
this->hookid = 0;
|
||||
this->remove_callback = remove_callback;
|
||||
this->callback->offset = setup->offset;
|
||||
this->callback->plugin_callback = plugincb;
|
||||
this->callback->returnFlag = setup->returnFlag;
|
||||
this->callback->thisType = setup->thisType;
|
||||
this->callback->post = post;
|
||||
this->callback->hookType = setup->hookType;
|
||||
this->callback->params = setup->params;
|
||||
|
||||
this->addr = 0;
|
||||
|
||||
if(this->callback->hookType == HookType_Entity)
|
||||
{
|
||||
this->callback->entity = gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(this->callback->hookType == HookType_Raw)
|
||||
{
|
||||
this->addr = (intptr_t)iface;
|
||||
}
|
||||
this->callback->entity = -1;
|
||||
}
|
||||
|
||||
CProtoInfoBuilder protoInfo(ProtoInfo::CallConv_ThisCall);
|
||||
|
||||
for(int i = this->callback->params.size() -1; i >= 0; i--)
|
||||
{
|
||||
protoInfo.AddParam(this->callback->params.at(i).size, this->callback->params.at(i).pass_type, PASSFLAG_BYVAL, NULL, NULL, NULL, NULL);//This seems like we need to do something about it at some point...
|
||||
}
|
||||
|
||||
if(this->callback->returnType == ReturnType_Void)
|
||||
{
|
||||
protoInfo.SetReturnType(0, SourceHook::PassInfo::PassType_Unknown, 0, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
else if(this->callback->returnType == ReturnType_Float)
|
||||
{
|
||||
protoInfo.SetReturnType(sizeof(float), SourceHook::PassInfo::PassType_Float, setup->returnFlag, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
else if(this->callback->returnType == ReturnType_String)
|
||||
{
|
||||
protoInfo.SetReturnType(sizeof(string_t), SourceHook::PassInfo::PassType_Object, setup->returnFlag, NULL, NULL, NULL, NULL);//We have to be 4 really... or else RIP
|
||||
}
|
||||
else if(this->callback->returnType == ReturnType_Vector)
|
||||
{
|
||||
protoInfo.SetReturnType(sizeof(SDKVector), SourceHook::PassInfo::PassType_Object, setup->returnFlag, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
protoInfo.SetReturnType(sizeof(void *), SourceHook::PassInfo::PassType_Basic, setup->returnFlag, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
this->pManager = g_pHookManager->MakeHookMan(protoInfo, 0, this->callback->offset);
|
||||
|
||||
this->hookid = g_SHPtr->AddHook(g_PLID,ISourceHook::Hook_Normal, iface, 0, this->pManager, this->callback, this->callback->post);
|
||||
}
|
||||
|
||||
void CleanupHooks(IPluginContext *pContext)
|
||||
{
|
||||
for(int i = g_pHooks.length() -1; i >= 0; i--)
|
||||
{
|
||||
DHooksManager *manager = g_pHooks.at(i);
|
||||
|
||||
if(pContext == NULL || pContext == manager->callback->plugin_callback->GetParentRuntime()->GetDefaultContext())
|
||||
{
|
||||
delete manager;
|
||||
g_pHooks.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SetupHookManager(ISmmAPI *ismm)
|
||||
{
|
||||
g_pHookManager = static_cast<SourceHook::IHookManagerAutoGen *>(ismm->MetaFactory(MMIFACE_SH_HOOKMANAUTOGEN, NULL, NULL));
|
||||
|
||||
return g_pHookManager != NULL;
|
||||
}
|
||||
|
||||
SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case HookParamType_Float:
|
||||
return SourceHook::PassInfo::PassType_Float;
|
||||
case HookParamType_Object:
|
||||
return SourceHook::PassInfo::PassType_Object;
|
||||
}
|
||||
return SourceHook::PassInfo::PassType_Basic;
|
||||
}
|
||||
|
||||
size_t GetStackArgsSize(DHooksCallback *dg)
|
||||
{
|
||||
size_t res = GetParamsSize(dg);
|
||||
#ifdef WIN32
|
||||
if(dg->returnType == ReturnType_Vector)//Account for result vector ptr.
|
||||
#else
|
||||
if(dg->returnType == ReturnType_Vector || dg->returnType == ReturnType_String)
|
||||
#endif
|
||||
{
|
||||
res += OBJECT_OFFSET;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
HookParamsStruct::~HookParamsStruct()
|
||||
{
|
||||
if (this->orgParams != NULL)
|
||||
{
|
||||
free(this->orgParams);
|
||||
}
|
||||
if (this->isChanged != NULL)
|
||||
{
|
||||
free(this->isChanged);
|
||||
}
|
||||
if (this->newParams != NULL)
|
||||
{
|
||||
for (int i = dg->params.size() - 1; i >= 0; i--)
|
||||
{
|
||||
size_t offset = GetParamOffset(this, i);
|
||||
void *addr = (void **)((intptr_t)this->newParams + offset);
|
||||
|
||||
if (*(void **)addr == NULL)
|
||||
continue;
|
||||
|
||||
if (dg->params.at(i).type == HookParamType_VectorPtr)
|
||||
{
|
||||
delete *(SDKVector **)addr;
|
||||
}
|
||||
else if (dg->params.at(i).type == HookParamType_CharPtr)
|
||||
{
|
||||
delete *(char **)addr;
|
||||
}
|
||||
}
|
||||
free(this->newParams);
|
||||
}
|
||||
}
|
||||
|
||||
HookParamsStruct *GetParamStruct(DHooksCallback *dg, void **argStack, size_t argStackSize)
|
||||
{
|
||||
HookParamsStruct *params = new HookParamsStruct();
|
||||
params->dg = dg;
|
||||
#ifdef WIN32
|
||||
if(dg->returnType != ReturnType_Vector)
|
||||
#else
|
||||
if(dg->returnType != ReturnType_Vector && dg->returnType != ReturnType_String)
|
||||
#endif
|
||||
{
|
||||
params->orgParams = (void **)malloc(argStackSize);
|
||||
memcpy(params->orgParams, argStack, argStackSize);
|
||||
}
|
||||
else //Offset result ptr
|
||||
{
|
||||
params->orgParams = (void **)malloc(argStackSize-OBJECT_OFFSET);
|
||||
memcpy(params->orgParams, argStack+OBJECT_OFFSET, argStackSize-OBJECT_OFFSET);
|
||||
}
|
||||
size_t paramsSize = GetParamsSize(dg);
|
||||
|
||||
params->newParams = (void **)malloc(paramsSize);
|
||||
params->isChanged = (bool *)malloc(dg->params.size() * sizeof(bool));
|
||||
|
||||
for (unsigned int i = 0; i < dg->params.size(); i++)
|
||||
{
|
||||
*(void **)((intptr_t)params->newParams + GetParamOffset(params, i)) = NULL;
|
||||
params->isChanged[i] = false;
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
HookReturnStruct *GetReturnStruct(DHooksCallback *dg)
|
||||
{
|
||||
HookReturnStruct *res = new HookReturnStruct();
|
||||
res->isChanged = false;
|
||||
res->type = dg->returnType;
|
||||
res->orgResult = NULL;
|
||||
res->newResult = NULL;
|
||||
|
||||
if(g_SHPtr->GetOrigRet() && dg->post)
|
||||
{
|
||||
switch(dg->returnType)
|
||||
{
|
||||
case ReturnType_String:
|
||||
res->orgResult = malloc(sizeof(string_t));
|
||||
res->newResult = malloc(sizeof(string_t));
|
||||
*(string_t *)res->orgResult = META_RESULT_ORIG_RET(string_t);
|
||||
break;
|
||||
case ReturnType_Int:
|
||||
res->orgResult = malloc(sizeof(int));
|
||||
res->newResult = malloc(sizeof(int));
|
||||
*(int *)res->orgResult = META_RESULT_ORIG_RET(int);
|
||||
break;
|
||||
case ReturnType_Bool:
|
||||
res->orgResult = malloc(sizeof(bool));
|
||||
res->newResult = malloc(sizeof(bool));
|
||||
*(bool *)res->orgResult = META_RESULT_ORIG_RET(bool);
|
||||
break;
|
||||
case ReturnType_Float:
|
||||
res->orgResult = malloc(sizeof(float));
|
||||
res->newResult = malloc(sizeof(float));
|
||||
*(float *)res->orgResult = META_RESULT_ORIG_RET(float);
|
||||
break;
|
||||
case ReturnType_Vector:
|
||||
{
|
||||
res->orgResult = malloc(sizeof(SDKVector));
|
||||
res->newResult = malloc(sizeof(SDKVector));
|
||||
SDKVector vec = META_RESULT_ORIG_RET(SDKVector);
|
||||
*(SDKVector *)res->orgResult = vec;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res->orgResult = META_RESULT_ORIG_RET(void *);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(dg->returnType)
|
||||
{
|
||||
case ReturnType_String:
|
||||
res->orgResult = malloc(sizeof(string_t));
|
||||
res->newResult = malloc(sizeof(string_t));
|
||||
*(string_t *)res->orgResult = NULL_STRING;
|
||||
break;
|
||||
case ReturnType_Vector:
|
||||
res->orgResult = malloc(sizeof(SDKVector));
|
||||
res->newResult = malloc(sizeof(SDKVector));
|
||||
*(SDKVector *)res->orgResult = SDKVector();
|
||||
break;
|
||||
case ReturnType_Int:
|
||||
res->orgResult = malloc(sizeof(int));
|
||||
res->newResult = malloc(sizeof(int));
|
||||
*(int *)res->orgResult = 0;
|
||||
break;
|
||||
case ReturnType_Bool:
|
||||
res->orgResult = malloc(sizeof(bool));
|
||||
res->newResult = malloc(sizeof(bool));
|
||||
*(bool *)res->orgResult = false;
|
||||
break;
|
||||
case ReturnType_Float:
|
||||
res->orgResult = malloc(sizeof(float));
|
||||
res->newResult = malloc(sizeof(float));
|
||||
*(float *)res->orgResult = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
cell_t GetThisPtr(void *iface, ThisPointerType type)
|
||||
{
|
||||
if(type == ThisPointer_CBaseEntity)
|
||||
{
|
||||
return gamehelpers->EntityToBCompatRef((CBaseEntity *)iface);
|
||||
}
|
||||
|
||||
return (cell_t)iface;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void *Callback(DHooksCallback *dg, void **argStack, size_t *argsizep)
|
||||
#else
|
||||
void *Callback(DHooksCallback *dg, void **argStack)
|
||||
#endif
|
||||
{
|
||||
HookReturnStruct *returnStruct = NULL;
|
||||
HookParamsStruct *paramStruct = NULL;
|
||||
Handle_t rHndl;
|
||||
Handle_t pHndl;
|
||||
|
||||
#ifdef WIN32
|
||||
*argsizep = GetStackArgsSize(dg);
|
||||
#else
|
||||
size_t argsize = GetStackArgsSize(dg);
|
||||
#endif
|
||||
|
||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||
{
|
||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||
}
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
returnStruct = GetReturnStruct(dg);
|
||||
rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
if(!rHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return NULL;
|
||||
}
|
||||
dg->plugin_callback->PushCell(rHndl);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if(*argsizep > 0)
|
||||
{
|
||||
paramStruct = GetParamStruct(dg, argStack, *argsizep);
|
||||
#else
|
||||
if(argsize > 0)
|
||||
{
|
||||
paramStruct = GetParamStruct(dg, argStack, argsize);
|
||||
#endif
|
||||
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
if(!pHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
delete paramStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return NULL;
|
||||
}
|
||||
dg->plugin_callback->PushCell(pHndl);
|
||||
}
|
||||
cell_t result = (cell_t)MRES_Ignored;
|
||||
META_RES mres = MRES_IGNORED;
|
||||
|
||||
dg->plugin_callback->Execute(&result);
|
||||
|
||||
void *ret = g_SHPtr->GetOverrideRetPtr();
|
||||
switch((MRESReturn)result)
|
||||
{
|
||||
case MRES_Handled:
|
||||
case MRES_ChangedHandled:
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
ret = CallVFunction<void *>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_ChangedOverride:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
if(dg->returnType == ReturnType_String || dg->returnType == ReturnType_Int || dg->returnType == ReturnType_Bool)
|
||||
{
|
||||
ret = *(void **)returnStruct->newResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = returnStruct->newResult;
|
||||
}
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
CallVFunction<void *>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_Override:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_OVERRIDE);
|
||||
mres = MRES_OVERRIDE;
|
||||
if(dg->returnType == ReturnType_String || dg->returnType == ReturnType_Int || dg->returnType == ReturnType_Bool)
|
||||
{
|
||||
ret = *(void **)returnStruct->newResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = returnStruct->newResult;
|
||||
}
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MRES_Supercede:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
if(dg->returnType == ReturnType_String || dg->returnType == ReturnType_Int || dg->returnType == ReturnType_Bool)
|
||||
{
|
||||
ret = *(void **)returnStruct->newResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = returnStruct->newResult;
|
||||
}
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
break;
|
||||
}
|
||||
|
||||
HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if(returnStruct)
|
||||
{
|
||||
handlesys->FreeHandle(rHndl, &sec);
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
handlesys->FreeHandle(pHndl, &sec);
|
||||
}
|
||||
|
||||
if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#ifdef WIN32
|
||||
float Callback_float(DHooksCallback *dg, void **argStack, size_t *argsizep)
|
||||
#else
|
||||
float Callback_float(DHooksCallback *dg, void **argStack)
|
||||
#endif
|
||||
{
|
||||
HookReturnStruct *returnStruct = NULL;
|
||||
HookParamsStruct *paramStruct = NULL;
|
||||
Handle_t rHndl;
|
||||
Handle_t pHndl;
|
||||
|
||||
#ifdef WIN32
|
||||
*argsizep = GetStackArgsSize(dg);
|
||||
#else
|
||||
size_t argsize = GetStackArgsSize(dg);
|
||||
#endif
|
||||
|
||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||
{
|
||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||
}
|
||||
|
||||
returnStruct = GetReturnStruct(dg);
|
||||
rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
|
||||
if(!rHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return 0.0;
|
||||
}
|
||||
dg->plugin_callback->PushCell(rHndl);
|
||||
|
||||
#ifdef WIN32
|
||||
if(*argsizep > 0)
|
||||
{
|
||||
paramStruct = GetParamStruct(dg, argStack, *argsizep);
|
||||
#else
|
||||
if(argsize > 0)
|
||||
{
|
||||
paramStruct = GetParamStruct(dg, argStack, argsize);
|
||||
#endif
|
||||
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
if(!pHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
delete paramStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return 0.0;
|
||||
}
|
||||
dg->plugin_callback->PushCell(pHndl);
|
||||
}
|
||||
cell_t result = (cell_t)MRES_Ignored;
|
||||
META_RES mres = MRES_IGNORED;
|
||||
dg->plugin_callback->Execute(&result);
|
||||
|
||||
void *ret = g_SHPtr->GetOverrideRetPtr();
|
||||
switch((MRESReturn)result)
|
||||
{
|
||||
case MRES_Handled:
|
||||
case MRES_ChangedHandled:
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
*(float *)ret = CallVFunction<float>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_ChangedOverride:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
*(float *)ret = *(float *)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
CallVFunction<float>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_Override:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_OVERRIDE);
|
||||
mres = MRES_OVERRIDE;
|
||||
*(float *)ret = *(float *)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MRES_Supercede:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
*(float *)ret = *(float *)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
break;
|
||||
}
|
||||
|
||||
HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if(returnStruct)
|
||||
{
|
||||
handlesys->FreeHandle(rHndl, &sec);
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
handlesys->FreeHandle(pHndl, &sec);
|
||||
}
|
||||
|
||||
if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
return *(float *)ret;
|
||||
}
|
||||
#ifdef WIN32
|
||||
SDKVector *Callback_vector(DHooksCallback *dg, void **argStack, size_t *argsizep)
|
||||
#else
|
||||
SDKVector *Callback_vector(DHooksCallback *dg, void **argStack)
|
||||
#endif
|
||||
{
|
||||
SDKVector *vec_result = (SDKVector *)argStack[0]; // Save the result
|
||||
|
||||
HookReturnStruct *returnStruct = NULL;
|
||||
HookParamsStruct *paramStruct = NULL;
|
||||
Handle_t rHndl;
|
||||
Handle_t pHndl;
|
||||
|
||||
#ifdef WIN32
|
||||
*argsizep = GetStackArgsSize(dg);
|
||||
#else
|
||||
size_t argsize = GetStackArgsSize(dg);
|
||||
#endif
|
||||
|
||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||
{
|
||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||
}
|
||||
|
||||
returnStruct = GetReturnStruct(dg);
|
||||
rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
|
||||
if(!rHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return NULL;
|
||||
}
|
||||
dg->plugin_callback->PushCell(rHndl);
|
||||
|
||||
#ifdef WIN32
|
||||
if(*argsizep > 0)
|
||||
{
|
||||
paramStruct = GetParamStruct(dg, argStack, *argsizep);
|
||||
#else
|
||||
if(argsize > 0)
|
||||
{
|
||||
paramStruct = GetParamStruct(dg, argStack, argsize);
|
||||
#endif
|
||||
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
if(!pHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
delete paramStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return NULL;
|
||||
}
|
||||
dg->plugin_callback->PushCell(pHndl);
|
||||
}
|
||||
cell_t result = (cell_t)MRES_Ignored;
|
||||
META_RES mres = MRES_IGNORED;
|
||||
dg->plugin_callback->Execute(&result);
|
||||
|
||||
void *ret = g_SHPtr->GetOverrideRetPtr();
|
||||
ret = vec_result;
|
||||
switch((MRESReturn)result)
|
||||
{
|
||||
case MRES_Handled:
|
||||
case MRES_ChangedHandled:
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
*vec_result = CallVFunction<SDKVector>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_ChangedOverride:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
*vec_result = **(SDKVector **)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
CallVFunction<SDKVector>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_Override:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_OVERRIDE);
|
||||
mres = MRES_OVERRIDE;
|
||||
*vec_result = **(SDKVector **)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MRES_Supercede:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
*vec_result = **(SDKVector **)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
break;
|
||||
}
|
||||
|
||||
HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if(returnStruct)
|
||||
{
|
||||
handlesys->FreeHandle(rHndl, &sec);
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
handlesys->FreeHandle(pHndl, &sec);
|
||||
}
|
||||
|
||||
if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED)
|
||||
{
|
||||
vec_result->x = 0;
|
||||
vec_result->y = 0;
|
||||
vec_result->z = 0;
|
||||
return vec_result;
|
||||
}
|
||||
return vec_result;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
string_t *Callback_stringt(DHooksCallback *dg, void **argStack)
|
||||
{
|
||||
string_t *string_result = (string_t *)argStack[0]; // Save the result
|
||||
|
||||
HookReturnStruct *returnStruct = NULL;
|
||||
HookParamsStruct *paramStruct = NULL;
|
||||
Handle_t rHndl;
|
||||
Handle_t pHndl;
|
||||
|
||||
size_t argsize = GetStackArgsSize(dg);
|
||||
|
||||
if(dg->thisType == ThisPointer_CBaseEntity || dg->thisType == ThisPointer_Address)
|
||||
{
|
||||
dg->plugin_callback->PushCell(GetThisPtr(g_SHPtr->GetIfacePtr(), dg->thisType));
|
||||
}
|
||||
|
||||
returnStruct = GetReturnStruct(dg);
|
||||
rHndl = handlesys->CreateHandle(g_HookReturnHandle, returnStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
|
||||
if(!rHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return NULL;
|
||||
}
|
||||
dg->plugin_callback->PushCell(rHndl);
|
||||
|
||||
if(argsize > 0)
|
||||
{
|
||||
paramStruct = GetParamStruct(dg, argStack, argsize);
|
||||
pHndl = handlesys->CreateHandle(g_HookParamsHandle, paramStruct, dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity(), NULL);
|
||||
if(!pHndl)
|
||||
{
|
||||
dg->plugin_callback->Cancel();
|
||||
if(returnStruct)
|
||||
{
|
||||
delete returnStruct;
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
delete paramStruct;
|
||||
}
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
return NULL;
|
||||
}
|
||||
dg->plugin_callback->PushCell(pHndl);
|
||||
}
|
||||
cell_t result = (cell_t)MRES_Ignored;
|
||||
META_RES mres = MRES_IGNORED;
|
||||
dg->plugin_callback->Execute(&result);
|
||||
|
||||
void *ret = g_SHPtr->GetOverrideRetPtr();
|
||||
ret = string_result;
|
||||
switch((MRESReturn)result)
|
||||
{
|
||||
case MRES_Handled:
|
||||
case MRES_ChangedHandled:
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
*string_result = CallVFunction<string_t>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_ChangedOverride:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
*string_result = *(string_t *)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_SHPtr->DoRecall();
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
CallVFunction<SDKVector>(dg, paramStruct, g_SHPtr->GetIfacePtr());
|
||||
break;
|
||||
case MRES_Override:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_OVERRIDE);
|
||||
mres = MRES_OVERRIDE;
|
||||
*string_result = *(string_t *)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MRES_Supercede:
|
||||
if(dg->returnType != ReturnType_Void)
|
||||
{
|
||||
if(returnStruct->isChanged)
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_SUPERCEDE);
|
||||
mres = MRES_SUPERCEDE;
|
||||
*string_result = *(string_t *)returnStruct->newResult;
|
||||
}
|
||||
else //Throw an error if no override was set
|
||||
{
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->BlamePluginError(dg->plugin_callback, "Tried to override return value without return value being set");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_SHPtr->SetRes(MRES_IGNORED);
|
||||
mres = MRES_IGNORED;
|
||||
break;
|
||||
}
|
||||
|
||||
HandleSecurity sec(dg->plugin_callback->GetParentRuntime()->GetDefaultContext()->GetIdentity(), myself->GetIdentity());
|
||||
|
||||
if(returnStruct)
|
||||
{
|
||||
handlesys->FreeHandle(rHndl, &sec);
|
||||
}
|
||||
if(paramStruct)
|
||||
{
|
||||
handlesys->FreeHandle(pHndl, &sec);
|
||||
}
|
||||
|
||||
if(dg->returnType == ReturnType_Void || mres <= MRES_HANDLED)
|
||||
{
|
||||
*string_result = NULL_STRING;
|
||||
return string_result;
|
||||
}
|
||||
return string_result;
|
||||
}
|
||||
#endif
|
||||
345
extensions/dhooks/vhook.h
Normal file
345
extensions/dhooks/vhook.h
Normal file
@ -0,0 +1,345 @@
|
||||
#ifndef _INCLUDE_VHOOK_H_
|
||||
#define _INCLUDE_VHOOK_H_
|
||||
|
||||
#include "extension.h"
|
||||
|
||||
#include <sourcehook.h>
|
||||
#include <sh_vector.h>
|
||||
#include <macro-assembler.h>
|
||||
#include <assembler-x86.h>
|
||||
|
||||
enum MRESReturn
|
||||
{
|
||||
MRES_ChangedHandled = -2, // Use changed values and return MRES_Handled
|
||||
MRES_ChangedOverride, // Use changed values and return MRES_Override
|
||||
MRES_Ignored, // plugin didn't take any action
|
||||
MRES_Handled, // plugin did something, but real function should still be called
|
||||
MRES_Override, // call real function, but use my return value
|
||||
MRES_Supercede // skip real function; use my return value
|
||||
};
|
||||
|
||||
enum ObjectValueType
|
||||
{
|
||||
ObjectValueType_Int = 0,
|
||||
ObjectValueType_Bool,
|
||||
ObjectValueType_Ehandle,
|
||||
ObjectValueType_Float,
|
||||
ObjectValueType_CBaseEntityPtr,
|
||||
ObjectValueType_IntPtr,
|
||||
ObjectValueType_BoolPtr,
|
||||
ObjectValueType_EhandlePtr,
|
||||
ObjectValueType_FloatPtr,
|
||||
ObjectValueType_Vector,
|
||||
ObjectValueType_VectorPtr,
|
||||
ObjectValueType_CharPtr,
|
||||
ObjectValueType_String
|
||||
};
|
||||
|
||||
enum HookParamType
|
||||
{
|
||||
HookParamType_Unknown,
|
||||
HookParamType_Int,
|
||||
HookParamType_Bool,
|
||||
HookParamType_Float,
|
||||
HookParamType_String,
|
||||
HookParamType_StringPtr,
|
||||
HookParamType_CharPtr,
|
||||
HookParamType_VectorPtr,
|
||||
HookParamType_CBaseEntity,
|
||||
HookParamType_ObjectPtr,
|
||||
HookParamType_Edict,
|
||||
HookParamType_Object
|
||||
};
|
||||
|
||||
enum ReturnType
|
||||
{
|
||||
ReturnType_Unknown,
|
||||
ReturnType_Void,
|
||||
ReturnType_Int,
|
||||
ReturnType_Bool,
|
||||
ReturnType_Float,
|
||||
ReturnType_String,
|
||||
ReturnType_StringPtr,
|
||||
ReturnType_CharPtr,
|
||||
ReturnType_Vector,
|
||||
ReturnType_VectorPtr,
|
||||
ReturnType_CBaseEntity,
|
||||
ReturnType_Edict
|
||||
};
|
||||
|
||||
enum ThisPointerType
|
||||
{
|
||||
ThisPointer_Ignore,
|
||||
ThisPointer_CBaseEntity,
|
||||
ThisPointer_Address
|
||||
};
|
||||
|
||||
enum HookType
|
||||
{
|
||||
HookType_Entity,
|
||||
HookType_GameRules,
|
||||
HookType_Raw
|
||||
};
|
||||
|
||||
struct ParamInfo
|
||||
{
|
||||
HookParamType type;
|
||||
size_t size;
|
||||
unsigned int flags;
|
||||
SourceHook::PassInfo::PassType pass_type;
|
||||
};
|
||||
|
||||
class HookReturnStruct
|
||||
{
|
||||
public:
|
||||
~HookReturnStruct()
|
||||
{
|
||||
if(this->type == ReturnType_String || this->type == ReturnType_Int || this->type == ReturnType_Bool || this->type == ReturnType_Float || this->type == ReturnType_Vector)
|
||||
{
|
||||
free(this->newResult);
|
||||
free(this->orgResult);
|
||||
}
|
||||
else if(this->isChanged)
|
||||
{
|
||||
if(this->type == ReturnType_CharPtr)
|
||||
{
|
||||
delete [] (char *)this->newResult;
|
||||
}
|
||||
else if(this->type == ReturnType_VectorPtr)
|
||||
{
|
||||
delete (SDKVector *)this->newResult;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public:
|
||||
ReturnType type;
|
||||
bool isChanged;
|
||||
void *orgResult;
|
||||
void *newResult;
|
||||
};
|
||||
|
||||
class DHooksInfo
|
||||
{
|
||||
public:
|
||||
SourceHook::CVector<ParamInfo> params;
|
||||
int offset;
|
||||
unsigned int returnFlag;
|
||||
ReturnType returnType;
|
||||
bool post;
|
||||
IPluginFunction *plugin_callback;
|
||||
int entity;
|
||||
ThisPointerType thisType;
|
||||
HookType hookType;
|
||||
};
|
||||
|
||||
class DHooksCallback : public SourceHook::ISHDelegate, public DHooksInfo
|
||||
{
|
||||
public:
|
||||
virtual bool IsEqual(ISHDelegate *pOtherDeleg){return false;};
|
||||
virtual void DeleteThis()
|
||||
{
|
||||
*(void ***)this = this->oldvtable;
|
||||
g_pSM->GetScriptingEngine()->FreePageMemory(this->newvtable[2]);
|
||||
delete this->newvtable;
|
||||
delete this;
|
||||
};
|
||||
virtual void Call() {};
|
||||
public:
|
||||
void **newvtable;
|
||||
void **oldvtable;
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
void *Callback(DHooksCallback *dg, void **stack, size_t *argsizep);
|
||||
float Callback_float(DHooksCallback *dg, void **stack, size_t *argsizep);
|
||||
SDKVector *Callback_vector(DHooksCallback *dg, void **stack, size_t *argsizep);
|
||||
#else
|
||||
void *Callback(DHooksCallback *dg, void **stack);
|
||||
float Callback_float(DHooksCallback *dg, void **stack);
|
||||
SDKVector *Callback_vector(DHooksCallback *dg, void **stack);
|
||||
string_t *Callback_stringt(DHooksCallback *dg, void **stack);
|
||||
#endif
|
||||
|
||||
bool SetupHookManager(ISmmAPI *ismm);
|
||||
void CleanupHooks(IPluginContext *pContext = NULL);
|
||||
size_t GetParamTypeSize(HookParamType type);
|
||||
SourceHook::PassInfo::PassType GetParamTypePassType(HookParamType type);
|
||||
|
||||
#ifndef WIN32
|
||||
static void *GenerateThunk(ReturnType type)
|
||||
{
|
||||
sp::MacroAssemblerX86 masm;
|
||||
static const size_t kStackNeeded = (2) * 4; // 2 args max
|
||||
static const size_t kReserve = ke::Align(kStackNeeded+8, 16)-8;
|
||||
|
||||
masm.push(ebp);
|
||||
masm.movl(ebp, esp);
|
||||
masm.subl(esp, kReserve);
|
||||
if(type != ReturnType_String && type != ReturnType_Vector)
|
||||
{
|
||||
masm.lea(eax, Operand(ebp, 12)); // grab the incoming caller argument vector
|
||||
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
|
||||
masm.movl(eax, Operand(ebp, 8)); // grab the |this|
|
||||
masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/
|
||||
}
|
||||
else
|
||||
{
|
||||
masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector
|
||||
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
|
||||
masm.movl(eax, Operand(ebp, 12)); // grab the |this|
|
||||
masm.movl(Operand(esp, 0 * 4), eax); // set |this| as the 1st argument*/
|
||||
}
|
||||
if(type == ReturnType_Float)
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback_float));
|
||||
}
|
||||
else if(type == ReturnType_Vector)
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback_vector));
|
||||
}
|
||||
else if(type == ReturnType_String)
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback_stringt));
|
||||
}
|
||||
else
|
||||
{
|
||||
masm.call(ExternalAddress((void *)Callback));
|
||||
}
|
||||
masm.addl(esp, kReserve);
|
||||
masm.pop(ebp); // restore ebp
|
||||
masm.ret();
|
||||
|
||||
void *base = g_pSM->GetScriptingEngine()->AllocatePageMemory(masm.length());
|
||||
masm.emitToExecutableMemory(base);
|
||||
return base;
|
||||
}
|
||||
#else
|
||||
// HUGE THANKS TO BAILOPAN (dvander)!
|
||||
static void *GenerateThunk(ReturnType type)
|
||||
{
|
||||
sp::MacroAssembler masm;
|
||||
static const size_t kStackNeeded = (3 + 1) * 4; // 3 args max, 1 locals max
|
||||
static const size_t kReserve = ke::Align(kStackNeeded+8, 16)-8;
|
||||
|
||||
masm.push(ebp);
|
||||
masm.movl(ebp, esp);
|
||||
masm.subl(esp, kReserve);
|
||||
masm.lea(eax, Operand(esp, 3 * 4)); // ptr to 2nd var after argument space
|
||||
masm.movl(Operand(esp, 2 * 4), eax); // set the ptr as the third argument
|
||||
masm.lea(eax, Operand(ebp, 8)); // grab the incoming caller argument vector
|
||||
masm.movl(Operand(esp, 1 * 4), eax); // set that as the 2nd argument
|
||||
masm.movl(Operand(esp, 0 * 4), ecx); // set |this| as the 1st argument
|
||||
if(type == ReturnType_Float)
|
||||
{
|
||||
masm.call(ExternalAddress(Callback_float));
|
||||
}
|
||||
else if(type == ReturnType_Vector)
|
||||
{
|
||||
masm.call(ExternalAddress(Callback_vector));
|
||||
}
|
||||
else
|
||||
{
|
||||
masm.call(ExternalAddress(Callback));
|
||||
}
|
||||
masm.movl(ecx, Operand(esp, 3*4));
|
||||
masm.addl(esp, kReserve);
|
||||
masm.pop(ebp); // restore ebp
|
||||
masm.pop(edx); // grab return address in edx
|
||||
masm.addl(esp, ecx); // remove arguments
|
||||
masm.jmp(edx); // return to caller
|
||||
|
||||
void *base = g_pSM->GetScriptingEngine()->AllocatePageMemory(masm.length());
|
||||
masm.emitToExecutableMemory(base);
|
||||
return base;
|
||||
}
|
||||
#endif
|
||||
|
||||
static DHooksCallback *MakeHandler(ReturnType type)
|
||||
{
|
||||
DHooksCallback *dg = new DHooksCallback();
|
||||
dg->returnType = type;
|
||||
dg->oldvtable = *(void ***)dg;
|
||||
dg->newvtable = new void *[3];
|
||||
dg->newvtable[0] = dg->oldvtable[0];
|
||||
dg->newvtable[1] = dg->oldvtable[1];
|
||||
dg->newvtable[2] = GenerateThunk(type);
|
||||
*(void ***)dg = dg->newvtable;
|
||||
return dg;
|
||||
}
|
||||
|
||||
class HookParamsStruct
|
||||
{
|
||||
public:
|
||||
HookParamsStruct()
|
||||
{
|
||||
this->orgParams = NULL;
|
||||
this->newParams = NULL;
|
||||
this->dg = NULL;
|
||||
this->isChanged = NULL;
|
||||
}
|
||||
~HookParamsStruct();
|
||||
public:
|
||||
void **orgParams;
|
||||
void **newParams;
|
||||
bool *isChanged;
|
||||
DHooksCallback *dg;
|
||||
};
|
||||
|
||||
class HookSetup
|
||||
{
|
||||
public:
|
||||
HookSetup(ReturnType returnType, unsigned int returnFlag, HookType hookType, ThisPointerType thisType, int offset, IPluginFunction *callback)
|
||||
{
|
||||
this->returnType = returnType;
|
||||
this->returnFlag = returnFlag;
|
||||
this->hookType = hookType;
|
||||
this->thisType = thisType;
|
||||
this->offset = offset;
|
||||
this->callback = callback;
|
||||
};
|
||||
~HookSetup(){};
|
||||
public:
|
||||
unsigned int returnFlag;
|
||||
ReturnType returnType;
|
||||
HookType hookType;
|
||||
ThisPointerType thisType;
|
||||
SourceHook::CVector<ParamInfo> params;
|
||||
int offset;
|
||||
IPluginFunction *callback;
|
||||
};
|
||||
|
||||
class DHooksManager
|
||||
{
|
||||
public:
|
||||
DHooksManager(HookSetup *setup, void *iface, IPluginFunction *remove_callback, IPluginFunction *plugincb, bool post);
|
||||
~DHooksManager()
|
||||
{
|
||||
if(this->hookid)
|
||||
{
|
||||
g_SHPtr->RemoveHookByID(this->hookid);
|
||||
if(this->remove_callback)
|
||||
{
|
||||
this->remove_callback->PushCell(this->hookid);
|
||||
this->remove_callback->Execute(NULL);
|
||||
}
|
||||
if(this->pManager)
|
||||
{
|
||||
g_pHookManager->ReleaseHookMan(this->pManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
intptr_t addr;
|
||||
int hookid;
|
||||
DHooksCallback *callback;
|
||||
IPluginFunction *remove_callback;
|
||||
SourceHook::HookManagerPubFunc pManager;
|
||||
};
|
||||
|
||||
size_t GetStackArgsSize(DHooksCallback *dg);
|
||||
|
||||
extern IBinTools *g_pBinTools;
|
||||
extern HandleType_t g_HookParamsHandle;
|
||||
extern HandleType_t g_HookReturnHandle;
|
||||
#endif
|
||||
487
plugins/include/dhooks.inc
Normal file
487
plugins/include/dhooks.inc
Normal file
@ -0,0 +1,487 @@
|
||||
#if defined _dhooks_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _dhooks_included
|
||||
|
||||
enum ObjectValueType
|
||||
{
|
||||
ObjectValueType_Int = 0,
|
||||
ObjectValueType_Bool,
|
||||
ObjectValueType_Ehandle,
|
||||
ObjectValueType_Float,
|
||||
ObjectValueType_CBaseEntityPtr,
|
||||
ObjectValueType_IntPtr,
|
||||
ObjectValueType_BoolPtr,
|
||||
ObjectValueType_EhandlePtr,
|
||||
ObjectValueType_FloatPtr,
|
||||
ObjectValueType_Vector,
|
||||
ObjectValueType_VectorPtr,
|
||||
ObjectValueType_CharPtr,
|
||||
ObjectValueType_String
|
||||
};
|
||||
|
||||
enum ListenType
|
||||
{
|
||||
ListenType_Created,
|
||||
ListenType_Deleted
|
||||
};
|
||||
|
||||
enum ReturnType
|
||||
{
|
||||
ReturnType_Unknown,
|
||||
ReturnType_Void,
|
||||
ReturnType_Int,
|
||||
ReturnType_Bool,
|
||||
ReturnType_Float,
|
||||
ReturnType_String, //Note this is a string_t
|
||||
ReturnType_StringPtr, //Note this is a string_t *
|
||||
ReturnType_CharPtr,
|
||||
ReturnType_Vector,
|
||||
ReturnType_VectorPtr,
|
||||
ReturnType_CBaseEntity,
|
||||
ReturnType_Edict
|
||||
};
|
||||
|
||||
enum HookParamType
|
||||
{
|
||||
HookParamType_Unknown,
|
||||
HookParamType_Int,
|
||||
HookParamType_Bool,
|
||||
HookParamType_Float,
|
||||
HookParamType_String, //Note this is a string_t
|
||||
HookParamType_StringPtr, //Note this is a string_t *
|
||||
HookParamType_CharPtr,
|
||||
HookParamType_VectorPtr,
|
||||
HookParamType_CBaseEntity,
|
||||
HookParamType_ObjectPtr,
|
||||
HookParamType_Edict,
|
||||
HookParamType_Object
|
||||
};
|
||||
|
||||
enum ThisPointerType
|
||||
{
|
||||
ThisPointer_Ignore,
|
||||
ThisPointer_CBaseEntity,
|
||||
ThisPointer_Address
|
||||
};
|
||||
|
||||
enum HookType
|
||||
{
|
||||
HookType_Entity,
|
||||
HookType_GameRules,
|
||||
HookType_Raw
|
||||
};
|
||||
|
||||
enum MRESReturn
|
||||
{
|
||||
MRES_ChangedHandled = -2, // Use changed values and return MRES_Handled
|
||||
MRES_ChangedOverride, // Use changed values and return MRES_Override
|
||||
MRES_Ignored, // plugin didn't take any action
|
||||
MRES_Handled, // plugin did something, but real function should still be called
|
||||
MRES_Override, // call real function, but use my return value
|
||||
MRES_Supercede // skip real function; use my return value
|
||||
};
|
||||
|
||||
enum DHookPassFlag
|
||||
{
|
||||
DHookPass_ByVal = (1<<0), /**< Passing by value */
|
||||
DHookPass_ByRef = (1<<1), /**< Passing by reference */
|
||||
DHookPass_ODTOR = (1<<2), /**< Object has a destructor */
|
||||
DHookPass_OCTOR = (1<<3), /**< Object has a constructor */
|
||||
DHookPass_OASSIGNOP = (1<<4), /**< Object has an assignment operator */
|
||||
};
|
||||
|
||||
typeset ListenCB
|
||||
{
|
||||
//Deleted
|
||||
function void (int entity);
|
||||
|
||||
//Created
|
||||
function void (int entity, const char[] classname);
|
||||
};
|
||||
|
||||
typeset DHookRemovalCB
|
||||
{
|
||||
function void (int hookid);
|
||||
};
|
||||
typeset DHookCallback
|
||||
{
|
||||
//Function Example: void Ham::Test() with this pointer ignore
|
||||
function MRESReturn ();
|
||||
|
||||
//Function Example: void Ham::Test() with this pointer passed
|
||||
function MRESReturn (int pThis);
|
||||
|
||||
//Function Example: void Ham::Test(int cake) with this pointer ignore
|
||||
function MRESReturn (Handle hParams);
|
||||
|
||||
//Function Example: void Ham::Test(int cake) with this pointer passed
|
||||
function MRESReturn (int pThis, Handle hParams);
|
||||
|
||||
//Function Example: int Ham::Test() with this pointer ignore
|
||||
function MRESReturn (Handle hReturn);
|
||||
|
||||
//Function Example: int Ham::Test() with this pointer passed
|
||||
function MRESReturn (int pThis, Handle hReturn);
|
||||
|
||||
//Function Example: int Ham::Test(int cake) with this pointer ignore
|
||||
function MRESReturn (Handle hReturn, Handle hParams);
|
||||
|
||||
//Function Example: int Ham::Test(int cake) with this pointer passed
|
||||
function MRESReturn (int pThis, Handle hReturn, Handle hParams);
|
||||
|
||||
//Address NOW
|
||||
|
||||
//Function Example: void Ham::Test() with this pointer passed
|
||||
function MRESReturn (Address pThis);
|
||||
|
||||
//Function Example: void Ham::Test(int cake) with this pointer passed
|
||||
function MRESReturn (Address pThis, Handle hParams);
|
||||
|
||||
//Function Example: int Ham::Test() with this pointer passed
|
||||
function MRESReturn (Address pThis, Handle hReturn);
|
||||
|
||||
//Function Example: int Ham::Test(int cake) with this pointer passed
|
||||
function MRESReturn (Address pThis, Handle hReturn, Handle hParams);
|
||||
|
||||
};
|
||||
|
||||
/* Adds an entity listener hook
|
||||
*
|
||||
* @param type Type of listener to add
|
||||
* @param callback Callback to use
|
||||
*
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookAddEntityListener(ListenType type, ListenCB callback);
|
||||
|
||||
/* Removes an entity listener hook
|
||||
*
|
||||
* @param type Type of listener to remove
|
||||
* @param callback Callback this listener was using
|
||||
*
|
||||
* @return True if one was removed false otherwise.
|
||||
*/
|
||||
native bool DHookRemoveEntityListener(ListenType type, ListenCB callback);
|
||||
|
||||
/* Creates a hook
|
||||
*
|
||||
* @param offset vtable offset for function to hook
|
||||
* @param hooktype Type of hook
|
||||
* @param returntype Type type of return
|
||||
* @param thistype Type of this pointer or ignore (ignore can be used if not needed)
|
||||
* @param callback Optional callback function, if not set here must be set when hooking.
|
||||
*
|
||||
* @return Returns setup handle for the hook or INVALID_HANDLE.
|
||||
*/
|
||||
native Handle DHookCreate(int offset, HookType hooktype, ReturnType returntype, ThisPointerType thistype, DHookCallback callback=INVALID_FUNCTION);
|
||||
|
||||
/* Adds param to a hook setup
|
||||
*
|
||||
* @param setup Setup handle to add the param to.
|
||||
* @param type Param type
|
||||
* @param size Used for Objects (not Object ptr) to define the size of the object.
|
||||
* @param flag Used to change the pass type.
|
||||
*
|
||||
* @error Invalid setup handle or too many params added (request upping the max in thread)
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookAddParam(Handle setup, HookParamType type, int size=-1, DHookPassFlag flag=DHookPass_ByVal);
|
||||
|
||||
/* Hook entity
|
||||
*
|
||||
* @param setup Setup handle to use to add the hook.
|
||||
* @param post True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!)
|
||||
* @param entity Entity index to hook on.
|
||||
* @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback)
|
||||
* @param callback Optional callback function, if not set here must be set when creating the hook.
|
||||
*
|
||||
* @error Invalid setup handle, invalid address, invalid hook type or invalid callback.
|
||||
* @return -1 on fail a hookid on success
|
||||
*/
|
||||
native int DHookEntity(Handle setup, bool post, int entity, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION);
|
||||
|
||||
/* Hook gamerules
|
||||
*
|
||||
* @param setup Setup handle to use to add the hook.
|
||||
* @param post True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!)
|
||||
* @param removalcb Callback for when the hook is removed (Game rules hooks are auto-removed on map end and will call this callback)
|
||||
* @param callback Optional callback function, if not set here must be set when creating the hook.
|
||||
*
|
||||
* @error Invalid setup handle, invalid address, invalid hook type or invalid callback.
|
||||
* @return -1 on fail a hookid on success
|
||||
*/
|
||||
native int DHookGamerules(Handle setup, bool post, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION);
|
||||
|
||||
/* Hook a raw pointer
|
||||
*
|
||||
* @param setup Setup handle to use to add the hook.
|
||||
* @param post True to make the hook a post hook. (If you need to change the retunr value or need the return value use a post hook! If you need to change params and return use a pre and post hook!)
|
||||
* @param addr This pointer address.
|
||||
* @param removalcb Callback for when the hook is removed (Entity hooks are auto-removed on entity destroyed and will call this callback)
|
||||
* @param callback Optional callback function, if not set here must be set when creating the hook.
|
||||
*
|
||||
* @error Invalid setup handle, invalid address, invalid hook type or invalid callback.
|
||||
* @return -1 on fail a hookid on success
|
||||
*/
|
||||
native int DHookRaw(Handle setup, bool post, Address addr, DHookRemovalCB removalcb=INVALID_FUNCTION, DHookCallback callback=INVALID_FUNCTION);
|
||||
|
||||
/* Remove hook by hook id
|
||||
*
|
||||
* @param hookid Hook id to remove
|
||||
*
|
||||
* @return true on success false otherwise
|
||||
* @note This will not fire the removal callback!
|
||||
*/
|
||||
native bool DHookRemoveHookID(int hookid);
|
||||
|
||||
/* Get param value (Only use for: int, entity, bool or float param types)
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1. 0 Will return the number of params stored)
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type.
|
||||
* @return value if num greater than 0. If 0 returns paramcount.
|
||||
*/
|
||||
native any DHookGetParam(Handle hParams, int num);
|
||||
|
||||
/* Get vector param value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.)
|
||||
* @param vec Vector buffer to store result.
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookGetParamVector(Handle hParams, int num, float vec[3]);
|
||||
|
||||
/* Get string param value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to get. (Example if the function has 2 params and you need the value of the first param num would be 1.)
|
||||
* @param buffer String buffer to store result
|
||||
* @param size Buffer size
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookGetParamString(Handle hParams, int num, char[] buffer, int size);
|
||||
|
||||
/* Set param value (Only use for: int, entity, bool or float param types)
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @params num Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.)
|
||||
* @param value Value to set it as (only pass int, bool, float or entity index)
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetParam(Handle hParams, int num, any value);
|
||||
|
||||
/* Set vector param value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @params num Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.)
|
||||
* @param vec Value to set vector as.
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetParamVector(Handle hParams, int num, float vec[3]);
|
||||
|
||||
/* Set string param value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @params num Param number to set (Example if the function has 2 params and you need to set the value of the first param num would be 1.)
|
||||
* @param value Value to set string as.
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetParamString(Handle hParams, int num, char[] value);
|
||||
|
||||
/* Get return value (Only use for: int, entity, bool or float return types)
|
||||
*
|
||||
* @param hReturn Handle to return structure
|
||||
*
|
||||
* @error Invalid Handle, invalid type.
|
||||
* @return Returns default value if prehook returns actual value if post hook.
|
||||
*/
|
||||
native any DHookGetReturn(Handle hReturn);
|
||||
|
||||
/* Get return vector value
|
||||
*
|
||||
* @param hReturn Handle to return structure
|
||||
* @param vec Vector buffer to store result in. (In pre hooks will be default value (0.0,0.0,0.0))
|
||||
*
|
||||
* @error Invalid Handle, invalid type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookGetReturnVector(Handle hReturn, float vec[3]);
|
||||
|
||||
/* Get return string value
|
||||
*
|
||||
* @param hReturn Handle to return structure
|
||||
* @param buffer String buffer to store result in. (In pre hooks will be default value "")
|
||||
* @param size String buffer size
|
||||
*
|
||||
* @error Invalid Handle, invalid type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookGetReturnString(Handle hReturn, char[] buffer, int size);
|
||||
|
||||
/* Set return value (Only use for: int, entity, bool or float return types)
|
||||
*
|
||||
* @param hReturn Handle to return structure
|
||||
* @param value Value to set return as
|
||||
*
|
||||
* @error Invalid Handle, invalid type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetReturn(Handle hReturn, any value);
|
||||
|
||||
/* Set return vector value
|
||||
*
|
||||
* @param hReturn Handle to return structure
|
||||
* @param vec Value to set return vector as
|
||||
*
|
||||
* @error Invalid Handle, invalid type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetReturnVector(Handle hReturn, float vec[3]);
|
||||
|
||||
/* Set return string value
|
||||
*
|
||||
* @param hReturn Handle to return structure
|
||||
* @param value Value to set return string as
|
||||
*
|
||||
* @error Invalid Handle, invalid type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetReturnString(Handle hReturn, char[] value);
|
||||
|
||||
//WE SHOULD WRAP THESE AROUND STOCKS FOR NON PTR AS WE SUPPORT BOTH WITH THESE NATIVE'S
|
||||
|
||||
/* Gets an objects variable value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to get.
|
||||
* @param offset Offset within the object to the var to get.
|
||||
* @param type Type of var it is
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type.
|
||||
* @return Value of the objects var. If EHANDLE type or entity returns entity index.
|
||||
*/
|
||||
native any DHookGetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type);
|
||||
|
||||
/* Sets an objects variable value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to set.
|
||||
* @param offset Offset within the object to the var to set.
|
||||
* @param type Type of var it is
|
||||
* @param value The value to set the var to.
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetParamObjectPtrVar(Handle hParams, int num, int offset, ObjectValueType type, any value);
|
||||
|
||||
/* Gets an objects vector variable value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to get.
|
||||
* @param offset Offset within the object to the var to get.
|
||||
* @param type Type of var it is
|
||||
* @param buffer Buffer to store the result vector
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookGetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float buffer[3]);
|
||||
|
||||
/* Sets an objects vector variable value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to set.
|
||||
* @param offset Offset within the object to the var to set.
|
||||
* @param type Type of var it is
|
||||
* @param value The value to set the vector var to.
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookSetParamObjectPtrVarVector(Handle hParams, int num, int offset, ObjectValueType type, float value[3]);
|
||||
|
||||
/* Gets an objects string variable value
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to get.
|
||||
* @param offset Offset within the object to the var to get.
|
||||
* @param type Type of var it is
|
||||
* @param buffer Buffer to store the result vector
|
||||
* @param size Size of the buffer
|
||||
*
|
||||
* @error Invalid handle. Invalid param number. Invalid param type. Invalid Object type.
|
||||
* @noreturn
|
||||
*/
|
||||
native void DHookGetParamObjectPtrString(Handle hParams, int num, int offset, ObjectValueType type, char[] buffer, int size);
|
||||
|
||||
/* Checks if a pointer param is null
|
||||
*
|
||||
* @param hParams Handle to params structure
|
||||
* @param num Param number to check.
|
||||
*
|
||||
* @error Non pointer param
|
||||
* @return True if null false otherwise.
|
||||
*/
|
||||
native bool DHookIsNullParam(Handle hParams, int num);
|
||||
|
||||
public Extension __ext_dhooks =
|
||||
{
|
||||
name = "dhooks",
|
||||
file = "dhooks.ext",
|
||||
#if defined AUTOLOAD_EXTENSIONS
|
||||
autoload = 1,
|
||||
#else
|
||||
autoload = 0,
|
||||
#endif
|
||||
#if defined REQUIRE_EXTENSIONS
|
||||
required = 1,
|
||||
#else
|
||||
required = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_EXTENSIONS
|
||||
public __ext_dhooks_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("DHookAddEntityListener");
|
||||
MarkNativeAsOptional("DHookRemoveEntityListener");
|
||||
MarkNativeAsOptional("DHookCreate");
|
||||
MarkNativeAsOptional("DHookAddParam");
|
||||
MarkNativeAsOptional("DHookEntity");
|
||||
MarkNativeAsOptional("DHookGamerules");
|
||||
MarkNativeAsOptional("DHookRaw");
|
||||
MarkNativeAsOptional("DHookRemoveHookID");
|
||||
MarkNativeAsOptional("DHookGetParam");
|
||||
MarkNativeAsOptional("DHookGetParamVector");
|
||||
MarkNativeAsOptional("DHookGetParamString");
|
||||
MarkNativeAsOptional("DHookSetParam");
|
||||
MarkNativeAsOptional("DHookSetParamVector");
|
||||
MarkNativeAsOptional("DHookSetParamString");
|
||||
MarkNativeAsOptional("DHookGetReturn");
|
||||
MarkNativeAsOptional("DHookGetReturnVector");
|
||||
MarkNativeAsOptional("DHookGetReturnString");
|
||||
MarkNativeAsOptional("DHookSetReturn");
|
||||
MarkNativeAsOptional("DHookSetReturnVector");
|
||||
MarkNativeAsOptional("DHookSetReturnString");
|
||||
MarkNativeAsOptional("DHookGetParamObjectPtrVar");
|
||||
MarkNativeAsOptional("DHookSetParamObjectPtrVar");
|
||||
MarkNativeAsOptional("DHookGetParamObjectPtrVarVector");
|
||||
MarkNativeAsOptional("DHookSetParamObjectPtrVarVector");
|
||||
MarkNativeAsOptional("DHookIsNullParam");
|
||||
MarkNativeAsOptional("DHookGetParamObjectPtrString");
|
||||
}
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user