268 lines
7.3 KiB
C++
268 lines
7.3 KiB
C++
/* AMX Mod X
|
|
*
|
|
* by the AMX Mod X Development Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* 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, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* In addition, as a special exception, the author gives permission to
|
|
* link the code of this program with the Half-Life Game Engine ("HL
|
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
* respects for all of the code used other than the HL Engine and MODs
|
|
* from Valve. If you modify this file, you may extend this exception
|
|
* to your version of the file, but you are not obligated to do so. If
|
|
* you do not wish to do so, delete this exception statement from your
|
|
* version.
|
|
*
|
|
* Description: AMX Mod X Module Interface hooks
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
|
|
#include "sdk/amxxmodule.h"
|
|
|
|
#include "hamsandwich.h"
|
|
|
|
#include "CVector.h"
|
|
#include "CString.h"
|
|
|
|
#include "FileParser.h"
|
|
|
|
#include "NEW_Util.h"
|
|
|
|
#include "VTableManager.h"
|
|
#include "VTableEntries.h"
|
|
|
|
CVector<String *> SuffixNames; /**< List of names being searched for in the config file. */
|
|
CVector<void (*)(const char *, const char *)> SuffixFunctions; /**< Callback functions for when we find a hunted keyvalue. */
|
|
CVector<void (*)(void)> ConfigDoneCallbacks; /**< Callbacks when our config file is done being parsed. */
|
|
|
|
edict_t *NEW_FirstEdict=NULL; /**< Used for the NEW_Utils INDEXENT/ENTINDEX replacements. */
|
|
bool NEW_Initialized=false; /**< Whether NEW_Utils has been initialized yet. */
|
|
|
|
void FP_SetupOffsets(const char *name, FP_ptrFeedback feedback);
|
|
|
|
|
|
unsigned int HAM_pev=0; /**< Offset of pev from the this pointer. */
|
|
unsigned int HAM_pevset=0; /**< Whether or not the pev offset has been set. */
|
|
unsigned int HAM_classbase=0; /**< Offset of the vtable from the this pointer. */
|
|
unsigned int HAM_classbaseset=0; /**< Whether or not the classbase offset has been set. */
|
|
|
|
char ModKey[256]; /**< Temporary buffer for holding the <modname>_<os> prefix. */
|
|
|
|
/**
|
|
* Adds a callback to the config parser for this config suffix.
|
|
*
|
|
* @param suffix The suffix to add, eg "takedamage" would be called for "cs_linux_takedamage"
|
|
* @param callback The function to call when this key is found.
|
|
* @noreturn
|
|
*/
|
|
void RegisterKeySuffix(const char *suffix, void (*callback)(const char *,const char *))
|
|
{
|
|
String *Suffix=new String(suffix);
|
|
|
|
|
|
SuffixNames.push_back(Suffix);
|
|
|
|
SuffixFunctions.push_back(callback);
|
|
};
|
|
|
|
/**
|
|
* Adds this entry to the configdone callback.
|
|
*
|
|
* @param callback Function to call when the config file is done being parsed.
|
|
* @noreturn
|
|
*/
|
|
void RegisterConfigCallback(void (*callback)(void))
|
|
{
|
|
ConfigDoneCallbacks.push_back(callback);
|
|
};
|
|
/**
|
|
* Starts each vtable entry. This needs to be edited for every additional hook.
|
|
*
|
|
* @noreturn
|
|
*/
|
|
void HAM_CallInitialization(void)
|
|
{
|
|
#define VTINIT(TableName) VTable##TableName::Initialize(&HAM_pev,&HAM_pevset,&HAM_classbase,&HAM_classbaseset)
|
|
|
|
VTINIT(TakeDamage);
|
|
VTINIT(Use);
|
|
VTINIT(Killed);
|
|
VTINIT(Blocked);
|
|
VTINIT(Respawn);
|
|
VTINIT(Restart);
|
|
VTINIT(AddPoints);
|
|
VTINIT(AddPointsToTeam);
|
|
VTINIT(AddPlayerItem);
|
|
VTINIT(RemovePlayerItem);
|
|
VTINIT(BloodColor);
|
|
VTINIT(Classify);
|
|
VTINIT(GetToggleState);
|
|
VTINIT(IsAlive);
|
|
VTINIT(IsBSPModel);
|
|
VTINIT(IsInWorld);
|
|
VTINIT(IsMoving);
|
|
VTINIT(IsNetClient);
|
|
VTINIT(IsPlayer);
|
|
VTINIT(IsSneaking);
|
|
VTINIT(ObjectCaps);
|
|
VTINIT(Think);
|
|
VTINIT(Touch);
|
|
|
|
|
|
#undef VTINIT
|
|
}
|
|
|
|
/**
|
|
* Tells all the table entries that the config file is done being parsed. Register their natives now.
|
|
*
|
|
* @noreturn
|
|
*/
|
|
void HAM_CallConfigDone(void)
|
|
{
|
|
int i=0; /**< Iterator. */
|
|
int end=ConfigDoneCallbacks.size(); /**< How many to parse. */
|
|
|
|
while (i<end)
|
|
{
|
|
ConfigDoneCallbacks[i]();
|
|
++i;
|
|
}
|
|
|
|
// done with this, free up the vector
|
|
ConfigDoneCallbacks.clear();
|
|
};
|
|
|
|
/**
|
|
* Simple wrapper to uniform string to number conversion. I don't just use -1 on strtol base because I don't want octal conversion.
|
|
*
|
|
* @param input The input string.
|
|
* @return The input string converted to an unsigned integer.
|
|
*/
|
|
int HAM_StrToNum(const char *input)
|
|
{
|
|
char *end; /**< Temporary pointer, needed for strtoul(). */
|
|
|
|
// if begins with 0x or 0X it's to be interpretted as hex
|
|
if (*input=='0' &&
|
|
(*(input+1)=='x' || *(input+1)=='X'))
|
|
{
|
|
return strtoul(input,&end,16);
|
|
}
|
|
|
|
// otherwise it's to be interpretted as base 10
|
|
return strtoul(input,&end,10);
|
|
}
|
|
/**
|
|
* This is called every time a key with the <mod>_<os>_ prefix is found.
|
|
*
|
|
* @param key The full key (eg: cs_windows_takedamage)
|
|
* @param data The corresponding data.
|
|
* @return true when key is used, false otherwise
|
|
*/
|
|
bool HAM_GetKey(const char *key, const char *data)
|
|
{
|
|
char TempKey[512]; /**< Temporary buffer. */
|
|
int i=0; /**< Iterator. */
|
|
int end=SuffixNames.size(); /**< How many suffixes to check. */
|
|
bool found=false; /**< Whether this key has been used or not. */
|
|
|
|
while (i<end)
|
|
{
|
|
snprintf(TempKey,sizeof(TempKey)-1,"%s_%s",ModKey,SuffixNames[i]->c_str());
|
|
if (strcmp(TempKey,key)==0)
|
|
{
|
|
SuffixFunctions[i](SuffixNames[i]->c_str(),data);
|
|
found=true;
|
|
}
|
|
++i;
|
|
}
|
|
return found;
|
|
}
|
|
/**
|
|
* Simple function to set the "pev" field that is used by all forwards.
|
|
*
|
|
* @param key The key suffix being forwarded.
|
|
* @param data The data corresponding to the key.
|
|
* @noreturn
|
|
*/
|
|
void HAM_SetPev(const char *key, const char *data)
|
|
{
|
|
HAM_pev=HAM_StrToNum(data);
|
|
HAM_pevset=1;
|
|
}
|
|
/**
|
|
* Simple function to set the "classbase" field that is used by all natives when built with GCC.
|
|
*
|
|
* @param key The key suffix being forwarded.
|
|
* @param data The data corresponding to the key.
|
|
* @noreturn
|
|
*/
|
|
#if defined __linux__
|
|
void HAM_SetClassBase(const char *key, const char *data)
|
|
{
|
|
HAM_classbase=HAM_StrToNum(data);
|
|
HAM_classbaseset=1;
|
|
}
|
|
#endif
|
|
|
|
void OnAmxxAttach()
|
|
{
|
|
HAM_CallInitialization();
|
|
#ifdef __linux__
|
|
snprintf(ModKey,sizeof(ModKey)-1,"%s_linux",MF_GetModname());
|
|
#else
|
|
snprintf(ModKey,sizeof(ModKey)-1,"%s_windows",MF_GetModname());
|
|
#endif
|
|
|
|
RegisterKeySuffix("pev",HAM_SetPev);
|
|
|
|
// this is only needed for Linux
|
|
#if defined __linux__
|
|
RegisterKeySuffix("classbase",HAM_SetClassBase);
|
|
#else // Emulate it being set on Windows, since it's not needed
|
|
HAM_classbase=0;
|
|
HAM_classbaseset=1;
|
|
#endif
|
|
|
|
RegisterRegisterNatives();
|
|
|
|
FP_SetupOffsets(ModKey,HAM_GetKey);
|
|
|
|
HAM_CallConfigDone();
|
|
|
|
/* TODO: Cbase natives
|
|
if (HAM_Set & HAM_GOT_PEV)
|
|
{
|
|
HAM_RegisterCbaseFast();
|
|
}
|
|
HAM_RegisterCbaseSafe();
|
|
|
|
VTH_Natives();
|
|
*/
|
|
}
|
|
|
|
void OnPluginsLoaded()
|
|
{
|
|
NEW_Initialize(INDEXENT(0));
|
|
|
|
};
|
|
void OnPluginsUnloaded()
|
|
{
|
|
VTMan.Cleanup();
|
|
};
|