Add basic ReHLDS and ReGameDLL support (#417)

* Add ReHLDS API files and its dependencies

Note: This has been stolen from ReAPI AMXX module and modified/adjusted to match AMXX existing includes and to provide as less dependencies as possible as well

* Add the necessary files to get ReHLDS interface

* Split SV_DropClient into pre/post code

* Init ReHLDS API and add SV_DropClient hook

* Add Cvar_DirectSet hook and adjust code with helpers

Note: we don't need to split code here. This is pretty much the naive and straight way, but fairly enough for our case. If it happens we got a lot more hooks, we may consider to use some class to manage better the things.

* Move platform and interface stuff in their own files in public directory

* Make sure to init cvar stuff after ReHLDS

* Add ReGameDLL API files and its dependencies in cstrike module

* Init ReHLDS in cstrike module and adjust code

Note: About cs_uset_set_model(). ReHLDS API doesn't offer a way to know directly the precached models, so instead of looping through all the ressources, the models list is saved one time at map change into a hashmap.

* Init ReGameDLL and adjust code

* Fix linux compilation

* Init ReGameDLL in fakemeta module and adjust code

* Rename /reapi directory to /resdk to avoid confusion

* Retrieve gamerules pointer through InstallGameRules in fakemeta module

* Retrieve gamerules pointer through InstallGameRules in cstrike module

Note: actually gamerules is not used if regamedll is enabled, but it could be used in future natives.

* Fix a typo when ReGameDLL is not enabled

* Fix missing interface check for ReHLDS.

I'm pretty sure I was checking at the very first since I worked first on vanilla version of engine, looks like change has been lost.
This commit is contained in:
Vincent Herbet
2017-03-09 19:59:38 +01:00
committed by GitHub
parent 1c3e8de57a
commit 115916d753
48 changed files with 5298 additions and 379 deletions

View File

@ -19,6 +19,8 @@ binary.sources = [
'../../../public/memtools/MemoryUtils.cpp',
'../../../public/memtools/CDetour/detours.cpp',
'../../../public/memtools/CDetour/asm/asm.c',
'../../../public/resdk/mod_rehlds_api.cpp',
'../../../public/resdk/mod_regamedll_api.cpp',
]
if builder.target_platform == 'windows':

View File

@ -326,7 +326,7 @@ enum CsWeaponClassType
/**
* Weapon infos.
*/
typedef struct
struct WeaponInfoStruct
{
int id;
int cost;
@ -336,8 +336,8 @@ typedef struct
int maxRounds;
int ammoType;
char *entityName;
}
WeaponInfoStruct;
const char *ammoName;
};
/**
* Weapon infos for use with cs_get_weapon_info().

View File

@ -15,6 +15,8 @@
#include "CstrikeUtils.h"
#include "CstrikeHacks.h"
#include "CstrikeItemsInfos.h"
#include <resdk/mod_rehlds_api.h>
#include <resdk/mod_regamedll_api.h>
int ForwardInternalCommand = -1;
int ForwardOnBuy = -1;
@ -64,10 +66,20 @@ server_t *Server;
// Mod global variable
void **GameRules;
void *GameRulesRH;
bool HasReHlds;
bool HasReGameDll;
bool HasRestricteditem_Enabled;
bool InternalCommand_Enabled;
bool GiveDefaultItems_Enabled;
void InitializeHacks()
{
HasReHlds = RehldsApi_Init();
HasReGameDll = RegamedllApi_Init();
CtrlDetours_ClientCommand(true);
CtrlDetours_BuyCommands(true);
CtrlDetours_Natives(true);
@ -88,7 +100,11 @@ void ShutdownHacks()
const char *CMD_ARGV(int i)
{
if (*UseBotArgs)
if (HasReGameDll)
{
return ReGameFuncs->Cmd_Argv(i);
}
else if (*UseBotArgs)
{
if (i < 4)
{
@ -101,9 +117,10 @@ const char *CMD_ARGV(int i)
return g_engfuncs.pfnCmd_Argv(i);
}
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
void (*C_ClientCommand_Actual)(edict_t *) = nullptr;
void ClientCommand_Custom(edict_t *pEdict, const char *command, const char *arg1, IReGameHook_InternalCommand *chain = nullptr)
{
auto command = CMD_ARGV(0);
auto client = TypeConversion.edict_to_id(pEdict);
CurrentItemId = CSI_NONE;
@ -117,7 +134,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
// Handling buy via menu.
if (!strcmp(command, "menuselect"))
{
auto slot = atoi(CMD_ARGV(1));
auto slot = atoi(arg1);
if (slot > 0 && slot < 9)
{
@ -172,7 +189,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
}
}
if (HasInternalCommandForward && *UseBotArgs && MF_ExecuteForward(ForwardInternalCommand, client, *BotArgs) > 0)
if (HasInternalCommandForward && (HasReGameDll || *UseBotArgs) && MF_ExecuteForward(ForwardInternalCommand, client, CMD_ARGV(0)) > 0)
{
return;
}
@ -185,11 +202,21 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
TriggeredFromCommand = CurrentItemId != CSI_NONE;
DETOUR_STATIC_CALL(C_ClientCommand)(pEdict);
chain ? chain->callNext(pEdict, command, arg1) : C_ClientCommand_Actual(pEdict);
TriggeredFromCommand = BlockMoneyUpdate = BlockAmmosUpdate = false;
}
void C_ClientCommand(edict_t* pEdict) // void ClientCommand(edict_t *pEntity)
{
ClientCommand_Custom(pEdict, CMD_ARGV(0), CMD_ARGV(1));
}
void InternalCommand_RH(IReGameHook_InternalCommand* chain, edict_t *pEdict, const char *command, const char *arg1)
{
ClientCommand_Custom(pEdict, CMD_ARGV(0), CMD_ARGV(1), chain);
}
edict_s* OnCreateNamedEntity(int classname)
{
if (NoKnivesMode)
@ -219,6 +246,18 @@ DETOUR_DECL_MEMBER0(GiveDefaultItems, void) // void CBasePlayer::GiveDefaultIte
g_pengfuncsTable->pfnCreateNamedEntity = nullptr;
}
void GiveDefaultItems_RH(IReGameHook_CBasePlayer_GiveDefaultItems *chain, class CBasePlayer *pPlayer)
{
if (NoKnivesMode)
{
g_pengfuncsTable->pfnCreateNamedEntity = OnCreateNamedEntity;
}
chain->callNext(pPlayer);
g_pengfuncsTable->pfnCreateNamedEntity = nullptr;
}
DETOUR_DECL_MEMBER1(CanPlayerBuy, bool, bool, display) // bool CBasePlayer::CanPlayerBuy(bool display)
{
auto canBuy = DETOUR_MEMBER_CALL(CanPlayerBuy)(display);
@ -340,6 +379,35 @@ DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void C
DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
}
bool CBasePlayer_HasRestrictItem_RH(IReGameHook_CBasePlayer_HasRestrictItem *chain, class CBasePlayer *pPlayer, ItemID item, ItemRestType type)
{
if (type == ITEM_TYPE_BUYING && CurrentItemId != CSI_NONE)
{
auto player = TypeConversion.cbase_to_id(pPlayer);
if (MF_IsPlayerAlive(player) && MF_ExecuteForward(ForwardOnBuy, player, CurrentItemId) > 0)
{
return true;
}
}
return chain->callNext(pPlayer, item, type);
}
bool BuyGunAmmo_RH(IReGameHook_BuyGunAmmo *chain, class CBasePlayer *pPlayer, class CBasePlayerItem *pWeapon, bool blinkMoney)
{
if (CurrentItemId == CSI_PRIAMMO || CurrentItemId == CSI_SECAMMO)
{
auto player = TypeConversion.cbase_to_id(pPlayer);
if (MF_IsPlayerAlive(player) && MF_ExecuteForward(ForwardOnBuy, player, CurrentItemId) > 0)
{
return false;
}
}
return chain->callNext(pPlayer, pWeapon, blinkMoney);
}
void ToggleDetour(CDetour *detour, bool enable)
{
@ -363,137 +431,190 @@ void CtrlDetours_ClientCommand(bool set)
{
if (set)
{
auto base = reinterpret_cast<void *>(MDLL_ClientCommand);
if (HasReGameDll)
{
if (!InternalCommand_Enabled)
{
ReGameHookchains->InternalCommand()->registerHook(InternalCommand_RH);
InternalCommand_Enabled = true;
}
}
else
{
auto base = reinterpret_cast<void *>(MDLL_ClientCommand);
#if defined(KE_WINDOWS)
TypeDescription type;
TypeDescription type;
if (MainConfig->GetOffset("UseBotArgs", &type))
{
UseBotArgs = get_pdata<decltype(UseBotArgs)>(base, type.fieldOffset);
}
if (MainConfig->GetOffset("UseBotArgs", &type))
{
UseBotArgs = get_pdata<decltype(UseBotArgs)>(base, type.fieldOffset);
}
if (MainConfig->GetOffset("BotArgs", &type))
{
BotArgs = get_pdata<decltype(BotArgs)>(base, type.fieldOffset);
}
if (MainConfig->GetOffset("BotArgs", &type))
{
BotArgs = get_pdata<decltype(BotArgs)>(base, type.fieldOffset);
}
#else
void *address = nullptr;
void *address = nullptr;
if (MainConfig->GetMemSig("UseBotArgs", &address))
{
UseBotArgs = reinterpret_cast<decltype(UseBotArgs)>(address);
}
if (MainConfig->GetMemSig("UseBotArgs", &address))
{
UseBotArgs = reinterpret_cast<decltype(UseBotArgs)>(address);
}
if (MainConfig->GetMemSig("BotArgs", &address))
{
BotArgs = reinterpret_cast<decltype(BotArgs)>(address);
}
if (MainConfig->GetMemSig("BotArgs", &address))
{
BotArgs = reinterpret_cast<decltype(BotArgs)>(address);
}
#endif
ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, base);
ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, base);
if (!ClientCommandDetour)
{
MF_Log("ClientCommand is not available - forwards CS_InternalCommand and CS_OnBuy[Attempt] have been disabled");
CtrlDetours_ClientCommand(false);
}
else if (!UseBotArgs || !BotArgs)
{
MF_Log("UseBotArgs or BotArgs is not available - forward CS_InternalCommand has been disabled");
}
if (!ClientCommandDetour)
{
MF_Log("ClientCommand is not available - forwards CS_InternalCommand and CS_OnBuy[Attempt] have been disabled");
ToggleHook_ClientCommands(false);
}
else if (!UseBotArgs || !BotArgs)
{
MF_Log("UseBotArgs or BotArgs is not available - forward CS_InternalCommand has been disabled");
}
}
}
else
{
DestroyDetour(ClientCommandDetour);
if (HasReGameDll)
{
ReGameHookchains->InternalCommand()->unregisterHook(InternalCommand_RH);
InternalCommand_Enabled = false;
}
else
{
DestroyDetour(ClientCommandDetour);
}
}
}
void ToggleDetour_ClientCommands(bool enable)
void ToggleHook_ClientCommands(bool enable)
{
ToggleDetour(ClientCommandDetour, enable);
if (HasReGameDll)
{
CtrlDetours_ClientCommand(enable);
}
else
{
ToggleDetour(ClientCommandDetour, enable);
}
}
void CtrlDetours_BuyCommands(bool set)
{
if (set)
{
void *address = nullptr;
if (MainConfig->GetMemSig("BuyGunAmmo", &address))
if (HasReGameDll)
{
BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, address);
}
if (MainConfig->GetMemSig("GiveNamedItem", &address))
{
GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, address);
}
if (MainConfig->GetMemSig("AddAccount", &address))
{
AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, address);
}
if (MainConfig->GetMemSig("CanPlayerBuy", &address))
{
CanPlayerBuyDetour = DETOUR_CREATE_MEMBER_FIXED(CanPlayerBuy, address);
}
if (MainConfig->GetMemSig("CanBuyThis", &address))
{
CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, address);
}
if (!BuyGunAmmoDetour || !GiveNamedItemDetour || !AddAccountDetour || !CanPlayerBuyDetour || !CanBuyThisDetour)
{
if (!BuyGunAmmoDetour)
if (!HasRestricteditem_Enabled)
{
MF_Log("BuyGunAmmo is not available");
ReGameHookchains->CBasePlayer_HasRestrictItem()->registerHook(CBasePlayer_HasRestrictItem_RH);
ReGameHookchains->BuyGunAmmo()->registerHook(BuyGunAmmo_RH);
HasRestricteditem_Enabled = true;
}
}
else
{
void *address = nullptr;
if (MainConfig->GetMemSig("BuyGunAmmo", &address))
{
BuyGunAmmoDetour = DETOUR_CREATE_STATIC_FIXED(BuyGunAmmo, address);
}
if (!GiveNamedItemDetour)
if (MainConfig->GetMemSig("GiveNamedItem", &address))
{
MF_Log("GiveNamedItem is not available");
GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, address);
}
if (!AddAccountDetour)
if (MainConfig->GetMemSig("AddAccount", &address))
{
MF_Log("AddAccount is not available");
AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, address);
}
if (!CanPlayerBuyDetour)
if (MainConfig->GetMemSig("CanPlayerBuy", &address))
{
MF_Log("CanPlayerBuy is not available");
CanPlayerBuyDetour = DETOUR_CREATE_MEMBER_FIXED(CanPlayerBuy, address);
}
if (!CanBuyThisDetour)
if (MainConfig->GetMemSig("CanBuyThis", &address))
{
MF_Log("CanBuyThis is not available");
CanBuyThisDetour = DETOUR_CREATE_STATIC_FIXED(CanBuyThis, address);
}
MF_Log("Some functions are not available - forwards CS_OnBuy[Attempt] have been disabled");
ToggleDetour_BuyCommands(false);
if (!BuyGunAmmoDetour || !GiveNamedItemDetour || !AddAccountDetour || !CanPlayerBuyDetour || !CanBuyThisDetour)
{
if (!BuyGunAmmoDetour)
{
MF_Log("BuyGunAmmo is not available");
}
if (!GiveNamedItemDetour)
{
MF_Log("GiveNamedItem is not available");
}
if (!AddAccountDetour)
{
MF_Log("AddAccount is not available");
}
if (!CanPlayerBuyDetour)
{
MF_Log("CanPlayerBuy is not available");
}
if (!CanBuyThisDetour)
{
MF_Log("CanBuyThis is not available");
}
MF_Log("Some functions are not available - forwards CS_OnBuy[Attempt] have been disabled");
ToggleHook_BuyCommands(false);
}
}
}
else
{
DestroyDetour(BuyGunAmmoDetour);
DestroyDetour(GiveNamedItemDetour);
DestroyDetour(AddAccountDetour);
DestroyDetour(CanPlayerBuyDetour);
DestroyDetour(CanBuyThisDetour);
if (HasReGameDll)
{
ReGameHookchains->CBasePlayer_HasRestrictItem()->unregisterHook(CBasePlayer_HasRestrictItem_RH);
ReGameHookchains->BuyGunAmmo()->unregisterHook(BuyGunAmmo_RH);
HasRestricteditem_Enabled = false;
}
else
{
DestroyDetour(BuyGunAmmoDetour);
DestroyDetour(GiveNamedItemDetour);
DestroyDetour(AddAccountDetour);
DestroyDetour(CanPlayerBuyDetour);
DestroyDetour(CanBuyThisDetour);
}
}
}
void ToggleDetour_BuyCommands(bool enable)
void ToggleHook_BuyCommands(bool enable)
{
ToggleDetour(BuyGunAmmoDetour, enable);
ToggleDetour(GiveNamedItemDetour, enable);
ToggleDetour(AddAccountDetour, enable);
ToggleDetour(CanPlayerBuyDetour, enable);
ToggleDetour(CanBuyThisDetour, enable);
if (HasReGameDll)
{
CtrlDetours_BuyCommands(enable);
}
else
{
ToggleDetour(BuyGunAmmoDetour, enable);
ToggleDetour(GiveNamedItemDetour, enable);
ToggleDetour(AddAccountDetour, enable);
ToggleDetour(CanPlayerBuyDetour, enable);
ToggleDetour(CanBuyThisDetour, enable);
}
}
@ -501,54 +622,94 @@ void CtrlDetours_Natives(bool set)
{
if (set)
{
void *address = nullptr;
if (MainConfig->GetMemSig("GiveDefaultItems", &address))
if (HasReGameDll)
{
GiveDefaultItemsDetour = DETOUR_CREATE_MEMBER_FIXED(GiveDefaultItems, address);
if (!GiveDefaultItems_Enabled)
{
ReGameHookchains->CBasePlayer_GiveDefaultItems()->registerHook(GiveDefaultItems_RH);
GiveDefaultItems_Enabled = true;
}
}
if (!GiveDefaultItemsDetour)
else
{
MF_Log("GiveDefaultItems is not available - native cs_set_no_knives has been disabled");
void *address = nullptr;
if (MainConfig->GetMemSig("GiveDefaultItems", &address))
{
GiveDefaultItemsDetour = DETOUR_CREATE_MEMBER_FIXED(GiveDefaultItems, address);
}
if (!GiveDefaultItemsDetour)
{
MF_Log("GiveDefaultItems is not available - native cs_set_no_knives has been disabled");
}
}
}
else
{
DestroyDetour(GiveDefaultItemsDetour);
if (HasReGameDll)
{
ReGameHookchains->CBasePlayer_GiveDefaultItems()->unregisterHook(GiveDefaultItems_RH);
GiveDefaultItems_Enabled = false;
}
else
{
DestroyDetour(GiveDefaultItemsDetour);
}
}
}
void ToggleHook_GiveDefaultItems(bool enable)
{
if (HasReGameDll)
{
CtrlDetours_Natives(enable);
}
else
{
ToggleDetour(GiveDefaultItemsDetour, enable);
}
}
void InitFuncsAddresses()
{
void *address = nullptr;
if (MainConfig->GetMemSig("CreateNamedEntity", &address)) // cs_create_entity()
if (HasReGameDll)
{
CS_CreateNamedEntity = reinterpret_cast<CreateNamedEntityFunc>(address);
RemoveEntityHashValue = ReGameFuncs->RemoveEntityHashValue;
CS_CreateNamedEntity = ReGameFuncs->CREATE_NAMED_ENTITY2;
CS_UTIL_FindEntityByString = ReGameFuncs->UTIL_FindEntityByString;
AddEntityHashValue = ReGameFuncs->AddEntityHashValue;
}
if (MainConfig->GetMemSig("FindEntityByString", &address)) // cs_find_ent_by_class()
else
{
CS_UTIL_FindEntityByString = reinterpret_cast<UTIL_FindEntityByStringFunc>(address);
}
void *address = nullptr;
if (MainConfig->GetMemSig("GetWeaponInfo", &address)) // cs_get_weapon_info()
{
GetWeaponInfo = reinterpret_cast<GetWeaponInfoFunc>(address);
}
if (MainConfig->GetMemSig("CreateNamedEntity", &address)) // cs_create_entity()
{
CS_CreateNamedEntity = reinterpret_cast<CreateNamedEntityFunc>(address);
}
if (MainConfig->GetMemSig("AddEntityHashValue", &address)) // cs_set_ent_class()
{
AddEntityHashValue = reinterpret_cast<AddEntityHashValueFunc>(address);
}
if (MainConfig->GetMemSig("FindEntityByString", &address)) // cs_find_ent_by_class()
{
CS_UTIL_FindEntityByString = reinterpret_cast<UTIL_FindEntityByStringFunc>(address);
}
if (MainConfig->GetMemSig("RemoveEntityHashValue", &address)) // cs_set_ent_class()
{
RemoveEntityHashValue = reinterpret_cast<RemoveEntityHashValueFunc>(address);
}
if (MainConfig->GetMemSig("GetWeaponInfo", &address)) // cs_get_weapon_info()
{
GetWeaponInfo = reinterpret_cast<GetWeaponInfoFunc>(address);
}
if (MainConfig->GetMemSig("AddEntityHashValue", &address)) // cs_set_ent_class()
{
AddEntityHashValue = reinterpret_cast<AddEntityHashValueFunc>(address);
}
if (MainConfig->GetMemSig("RemoveEntityHashValue", &address)) // cs_set_ent_class()
{
RemoveEntityHashValue = reinterpret_cast<RemoveEntityHashValueFunc>(address);
}
}
if (!CS_CreateNamedEntity)
{
@ -560,7 +721,12 @@ void InitFuncsAddresses()
MF_Log("UTIL_FindEntByString is not available - native cs_find_ent_by_class() has been disabled");
}
if (!GetWeaponInfo)
if (!AddEntityHashValue || !AddEntityHashValue)
{
MF_Log("AddEntityHashValue or AddEntityHashValue is not available - native cs_set_ent_class() has been disabled");
}
if (!HasReGameDll && !GetWeaponInfo)
{
MF_Log("GetWeaponInfo is not available - native cs_get_weapon_info() and forward CS_OnBuy have been disabled");
CtrlDetours_BuyCommands(false);
@ -584,66 +750,86 @@ void InitClassMembers()
!MoneyDesc.fieldOffset)
{
MF_Log("Invalid or missing entity gamedata files - forwards CS_OnBuy[Attempt] have been disabled");
CtrlDetours_BuyCommands(false);
ToggleHook_BuyCommands(false);
}
}
CGameRules* InstallGameRules(IReGameHook_InstallGameRules *chain)
{
GameRulesRH = chain->callNext();
return static_cast<CGameRules*>(GameRulesRH);
}
void InitGlobalVars()
{
void *address = nullptr;
if (!HasReHlds)
{
#if defined(KE_WINDOWS)
TypeDescription typeDesc;
TypeDescription typeDesc;
if (CommonConfig->GetOffset("svs", &typeDesc))
{
uintptr_t base = *reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(g_engfuncs.pfnGetCurrentPlayer) + typeDesc.fieldOffset);
ServerStatic = reinterpret_cast<decltype(ServerStatic)>(base - 4);
}
if (CommonConfig->GetAddress("sv", &address))
{
Server = *reinterpret_cast<decltype(Server)*>(address);
}
if (CommonConfig->GetAddress("g_pGameRules", &address))
{
GameRules = *reinterpret_cast<decltype(GameRules)*>(address);
}
if (CommonConfig->GetOffset("svs", &typeDesc))
{
uintptr_t base = *reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(g_engfuncs.pfnGetCurrentPlayer) + typeDesc.fieldOffset);
ServerStatic = reinterpret_cast<decltype(ServerStatic)>(base - 4);
}
if (CommonConfig->GetAddress("sv", &address))
{
Server = *reinterpret_cast<decltype(Server)*>(address);
}
#else
if (CommonConfig->GetMemSig("svs", &address))
{
ServerStatic = reinterpret_cast<decltype(ServerStatic)>(address);
}
if (CommonConfig->GetMemSig("svs", &address))
{
ServerStatic = reinterpret_cast<decltype(ServerStatic)>(address);
}
if (CommonConfig->GetMemSig("sv", &address))
{
Server = reinterpret_cast<decltype(Server)>(address);
}
if (CommonConfig->GetMemSig("g_pGameRules", &address))
{
GameRules = reinterpret_cast<decltype(GameRules)>(address);
}
if (CommonConfig->GetMemSig("sv", &address))
{
Server = reinterpret_cast<decltype(Server)>(address);
}
#endif
if (!ServerStatic)
{
MF_Log("svs global variable is not available");
}
if (!Server)
if (HasReGameDll)
{
MF_Log("sv global variable is not available");
ReGameHookchains->InstallGameRules()->registerHook(InstallGameRules);
}
else
{
#if defined(KE_WINDOWS)
if (CommonConfig->GetAddress("g_pGameRules", &address))
{
GameRules = *reinterpret_cast<decltype(GameRules)*>(address);
}
#else
if (CommonConfig->GetMemSig("g_pGameRules", &address))
{
GameRules = reinterpret_cast<decltype(GameRules)>(address);
}
#endif
}
if (!GameRules)
if (!HasReHlds)
{
MF_Log("g_pGameRules is not available - Forward CS_OnBuy has been disabled");
CtrlDetours_BuyCommands(false);
if (!ServerStatic)
{
MF_Log("svs global variable is not available");
}
if (!Server)
{
MF_Log("sv global variable is not available");
}
}
if (!HasReGameDll)
{
if (!GameRules)
{
MF_Log("g_pGameRules is not available - Forward CS_OnBuy has been disabled");
CtrlDetours_BuyCommands(false);
}
}
}

View File

@ -19,6 +19,7 @@
#include <CDetour/detours.h>
#include <engine_strucs.h>
#include "CstrikeDatas.h"
#include <resdk/cstrike/regamedll_api.h>
void InitializeHacks();
void InitFuncsAddresses();
@ -30,8 +31,9 @@ void CtrlDetours_ClientCommand(bool set);
void CtrlDetours_BuyCommands(bool set);
void CtrlDetours_Natives(bool set);
void ToggleDetour_ClientCommands(bool enable);
void ToggleDetour_BuyCommands(bool enable);
void ToggleHook_ClientCommands(bool enable);
void ToggleHook_BuyCommands(bool enable);
void ToggleHook_GiveDefaultItems(bool enable);
extern AMX_NATIVE_INFO CstrikeNatives[];
@ -60,10 +62,10 @@ enum class HashType
};
typedef edict_t* (*CreateNamedEntityFunc)(string_t iszClassname);
typedef void* (*UTIL_FindEntityByStringFunc)(void* pStartEntity, const char *szKeyword, const char *szValue);
typedef class CBaseEntity* (*UTIL_FindEntityByStringFunc)(class CBaseEntity *pStartEntity, const char *szKeyword, const char *szValue);
typedef WeaponInfoStruct* (*GetWeaponInfoFunc)(int id);
typedef void (*AddEntityHashValueFunc)(struct entvars_s *pev, const char *value, HashType fieldType);
typedef void (*RemoveEntityHashValueFunc)(struct entvars_s *pev, const char *value, HashType fieldType);
typedef void (*AddEntityHashValueFunc)(entvars_s *pev, const char *value, hash_types_e fieldType);
typedef void (*RemoveEntityHashValueFunc)(entvars_t *pev, const char *value, hash_types_e fieldType);
extern CreateNamedEntityFunc CS_CreateNamedEntity;
extern UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString;
@ -79,8 +81,12 @@ extern bool NoKnivesMode;
extern server_static_t *ServerStatic;
extern server_t *Server;
extern void **GameRules;
extern void *GameRulesRH;
extern int *UseBotArgs;
extern const char **BotArgs;
extern bool HasReHlds;
extern bool HasReGameDll;
#endif // CSTRIKE_HACKS_H

View File

@ -17,6 +17,7 @@
#include "CstrikeItemsInfos.h"
#include "CstrikeUserMessages.h"
#include <IGameConfigs.h>
#include <resdk/mod_rehlds_api.h>
IGameConfig *MainConfig;
IGameConfig *CommonConfig;
@ -24,6 +25,8 @@ IGameConfigManager *ConfigManager;
HLTypeConversion TypeConversion;
extern StringHashMap<int> ModelsList;
int AmxxCheckGame(const char *game)
{
if (strcasecmp(game, "cstrike") == 0 ||
@ -34,6 +37,30 @@ int AmxxCheckGame(const char *game)
return AMXX_GAME_BAD;
}
void SV_ActivateServer_RH(IRehldsHook_SV_ActivateServer *chain, int runPhysics)
{
chain->callNext(runPhysics);
auto numResources = RehldsData->GetResourcesNum();
if (!numResources)
{
return;
}
ModelsList.clear();
for (auto i = 0; i < numResources; ++i) // Saves all the precached models into a list.
{
auto resource = RehldsData->GetResource(i);
if (resource->type == t_model)
{
ModelsList.insert(resource->szFileName, i);
}
}
}
void OnAmxxAttach()
{
MF_AddNatives(CstrikeNatives);
@ -58,6 +85,11 @@ void OnAmxxAttach()
}
InitializeHacks();
if (HasReHlds)
{
RehldsHookchains->SV_ActivateServer()->registerHook(SV_ActivateServer_RH);
}
}
void OnPluginsLoaded()
@ -74,23 +106,30 @@ void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
// Used to catch WeaponList message at map change.
EnableMessageHooks();
if (!ClientCommandDetour) // All CS_* forwards requires ClientCommand. Unlikely to fail.
if (!HasReGameDll && !ClientCommandDetour) // All CS_* forwards requires ClientCommand. Unlikely to fail.
{
ToggleDetour_ClientCommands(false);
ToggleDetour_BuyCommands(false);
ToggleHook_ClientCommands(false);
ToggleHook_BuyCommands(false);
RETURN_META(MRES_IGNORED);
}
auto haveBotDetours = UseBotArgs && BotArgs;
auto haveBuyDetours = BuyGunAmmoDetour && GiveNamedItemDetour && AddAccountDetour && CanPlayerBuyDetour && CanBuyThisDetour;
auto haveBotHooks = true;
auto haveBuyHooks = true;
HasInternalCommandForward = haveBotDetours && UTIL_CheckForPublic("CS_InternalCommand");
HasOnBuyAttemptForward = haveBuyDetours && UTIL_CheckForPublic("CS_OnBuyAttempt");
HasOnBuyForward = haveBuyDetours && UTIL_CheckForPublic("CS_OnBuy");
if (!HasReGameDll)
{
haveBotHooks = UseBotArgs && BotArgs;
haveBuyHooks = BuyGunAmmoDetour && GiveNamedItemDetour && AddAccountDetour && CanPlayerBuyDetour && CanBuyThisDetour;
}
ToggleDetour_ClientCommands(HasInternalCommandForward || HasOnBuyAttemptForward || HasOnBuyForward);
ToggleDetour_BuyCommands(HasOnBuyForward);
HasInternalCommandForward = haveBotHooks && UTIL_CheckForPublic("CS_InternalCommand");
HasOnBuyAttemptForward = haveBuyHooks && UTIL_CheckForPublic("CS_OnBuyAttempt");
HasOnBuyForward = haveBuyHooks && UTIL_CheckForPublic("CS_OnBuy");
ToggleHook_ClientCommands(HasInternalCommandForward || HasOnBuyAttemptForward || HasOnBuyForward);
ToggleHook_BuyCommands(HasOnBuyForward);
ToggleHook_GiveDefaultItems(false);
RETURN_META(MRES_IGNORED);
}
@ -104,13 +143,15 @@ void OnServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
void OnServerDeactivate()
{
if (!ClientCommandDetour)
if (!HasReGameDll && !ClientCommandDetour)
{
RETURN_META(MRES_IGNORED);
}
ToggleDetour_ClientCommands(false);
ToggleDetour_BuyCommands(false);
GameRulesRH = nullptr;
ToggleHook_ClientCommands(false);
ToggleHook_BuyCommands(false);
RETURN_META(MRES_IGNORED);
}

View File

@ -19,8 +19,10 @@
#include "CstrikeItemsInfos.h"
#include <CDetour/detours.h>
#include <amtl/am-string.h>
#include <resdk/mod_regamedll_api.h>
bool NoKnivesMode = false;
StringHashMap<int> ModelsList;
// native cs_set_user_money(index, money, flash = 1);
static cell AMX_NATIVE_CALL cs_set_user_money(AMX *amx, cell *params)
@ -865,18 +867,17 @@ static cell AMX_NATIVE_CALL cs_set_user_model(AMX *amx, cell *params)
char modelpath[260];
ke::SafeSprintf(modelpath, sizeof(modelpath), "models/player/%s/%s.mdl", newModel, newModel);
for (size_t i = 0; i < HL_MODEL_MAX; ++i)
{
if (Server->model_precache[i] && !strcmp(Server->model_precache[i], modelpath))
{
if (pPlayer->v.modelindex != i)
{
SET_MODEL(pPlayer, STRING(ALLOC_STRING(modelpath)));
}
auto modelIndex = 0;
set_pdata<int>(pPlayer, m_modelIndexPlayer, i);
return 1;
if (ModelsList.retrieve(modelpath, &modelIndex))
{
if (pPlayer->v.modelindex != modelIndex)
{
SET_MODEL(pPlayer, STRING(ALLOC_STRING(modelpath)));
}
set_pdata<int>(pPlayer, m_modelIndexPlayer, modelIndex);
return 1;
}
MF_Log("Model must be precached using cs_set_user_model with update_index parameter set");
@ -1044,7 +1045,7 @@ static cell AMX_NATIVE_CALL cs_get_no_knives(AMX *amx, cell *params)
// native cs_set_no_knives(noknives = 0);
static cell AMX_NATIVE_CALL cs_set_no_knives(AMX *amx, cell *params)
{
if (!GiveDefaultItemsDetour)
if (!HasReGameDll && !GiveDefaultItemsDetour)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_set_no_knives() is disabled. Check your amxx logs.");
return 0;
@ -1052,14 +1053,7 @@ static cell AMX_NATIVE_CALL cs_set_no_knives(AMX *amx, cell *params)
NoKnivesMode = params[1] != 0;
if (NoKnivesMode)
{
GiveDefaultItemsDetour->EnableDetour();
}
else
{
GiveDefaultItemsDetour->DisableDetour();
}
ToggleHook_GiveDefaultItems(NoKnivesMode);
return 1;
}
@ -1698,7 +1692,7 @@ static cell AMX_NATIVE_CALL cs_find_ent_by_class(AMX* amx, cell* params)
}
int len;
void* pEntity = TypeConversion.id_to_cbase(params[1]);
auto pEntity = (CBaseEntity*)TypeConversion.id_to_cbase(params[1]);
const char* value = MF_GetAmxString(amx, params[2], 0, &len);
int index = TypeConversion.cbase_to_id(CS_UTIL_FindEntityByString(pEntity, "classname", value));
@ -1724,7 +1718,7 @@ static cell AMX_NATIVE_CALL cs_find_ent_by_owner(AMX* amx, cell* params)
CHECK_ENTITY_SIMPLE(owner);
int length;
void* pEntity = TypeConversion.id_to_cbase(params[1]);
auto pEntity = (CBaseEntity*)TypeConversion.id_to_cbase(params[1]);
const char* value = MF_GetAmxString(amx, params[2], 0, &length);
edict_t *pOwner = TypeConversion.id_to_edict(owner);
@ -1763,14 +1757,14 @@ static cell AMX_NATIVE_CALL cs_set_ent_class(AMX* amx, cell* params)
if (pev->classname)
{
RemoveEntityHashValue(pev, STRING(pev->classname), HashType::Classname);
RemoveEntityHashValue(pev, STRING(pev->classname), CLASSNAME);
}
int length;
auto new_classname = MF_GetAmxString(amx, params[2], 0, &length);
pev->classname = ALLOC_STRING(new_classname);
AddEntityHashValue(pev, STRING(pev->classname), HashType::Classname);
AddEntityHashValue(pev, STRING(pev->classname), CLASSNAME);
return 1;
}
@ -1882,7 +1876,7 @@ static cell AMX_NATIVE_CALL cs_get_translated_item_alias(AMX* amx, cell* params)
// native cs_get_weapon_info(weapon_id, CsWeaponInfo:type);
static cell AMX_NATIVE_CALL cs_get_weapon_info(AMX* amx, cell* params)
{
if (GetWeaponInfo <= 0)
if (!HasReGameDll && GetWeaponInfo <= 0)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_get_weapon_info() is disabled. Check your amxx logs.");
return 0;
@ -1891,9 +1885,9 @@ static cell AMX_NATIVE_CALL cs_get_weapon_info(AMX* amx, cell* params)
int weapon_id = params[1];
int info_type = params[2];
WeaponInfoStruct *info;
WeaponInfoStruct *info;
if (weapon_id <= CSW_NONE || weapon_id > CSW_LAST_WEAPON || !(info = GetWeaponInfo(weapon_id)))
if (weapon_id <= CSW_NONE || weapon_id > CSW_LAST_WEAPON || !(info = HasReGameDll ? ReGameApi->GetWeaponInfo(weapon_id) : GetWeaponInfo(weapon_id)))
{
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid weapon id: %d", weapon_id);
return 0;
@ -1925,6 +1919,7 @@ static cell AMX_NATIVE_CALL cs_get_weapon_info(AMX* amx, cell* params)
{
return info->ammoType;
}
// TODO: Ammo name (custom)
}
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid info type: %d", info_type);

View File

@ -18,6 +18,7 @@
#include "CstrikeUtils.h"
#include "CstrikeHacks.h"
#include <amtl/am-vector.h>
#include <resdk/mod_rehlds_api.h>
extern ke::Vector<int> ModelsUpdateQueue;
@ -119,6 +120,11 @@ class CPlayer
g_pengfuncsTable->pfnSetClientKeyValue = SetClientKeyValue;
}
if (HasReHlds)
{
return;
}
if (!ServerStatic)
{
MF_Log("Postponing of model update disabled, check your gamedata files");

View File

@ -144,6 +144,8 @@
<ClCompile Include="..\..\..\..\public\memtools\CDetour\asm\asm.c" />
<ClCompile Include="..\..\..\..\public\memtools\CDetour\detours.cpp" />
<ClCompile Include="..\..\..\..\public\memtools\MemoryUtils.cpp" />
<ClCompile Include="..\..\..\..\public\resdk\mod_regamedll_api.cpp" />
<ClCompile Include="..\..\..\..\public\resdk\mod_rehlds_api.cpp" />
<ClCompile Include="..\CstrikeMain.cpp" />
<ClCompile Include="..\CstrikeHacks.cpp" />
<ClCompile Include="..\CstrikeNatives.cpp" />
@ -158,6 +160,14 @@
<ClInclude Include="..\..\..\..\public\memtools\CDetour\detourhelpers.h" />
<ClInclude Include="..\..\..\..\public\memtools\CDetour\detours.h" />
<ClInclude Include="..\..\..\..\public\memtools\MemoryUtils.h" />
<ClInclude Include="..\..\..\..\public\resdk\common\hookchains.h" />
<ClInclude Include="..\..\..\..\public\resdk\cstrike\regamedll_api.h" />
<ClInclude Include="..\..\..\..\public\resdk\cstrike\regamedll_const.h" />
<ClInclude Include="..\..\..\..\public\resdk\cstrike\regamedll_interfaces.h" />
<ClInclude Include="..\..\..\..\public\resdk\engine\rehlds_api.h" />
<ClInclude Include="..\..\..\..\public\resdk\engine\rehlds_interfaces.h" />
<ClInclude Include="..\..\..\..\public\resdk\mod_regamedll_api.h" />
<ClInclude Include="..\..\..\..\public\resdk\mod_rehlds_api.h" />
<ClInclude Include="..\CstrikeItemsInfos.h" />
<ClInclude Include="..\CstrikeDatas.h" />
<ClInclude Include="..\CstrikeHacks.h" />

View File

@ -27,6 +27,18 @@
<Filter Include="Memtools\CDetour\asm">
<UniqueIdentifier>{4f3c4a13-065a-49b1-83a1-f646a3ec3678}</UniqueIdentifier>
</Filter>
<Filter Include="ReSDK">
<UniqueIdentifier>{7f37b35a-6ac7-4269-81a1-60dab5abbee4}</UniqueIdentifier>
</Filter>
<Filter Include="ReSDK\engine">
<UniqueIdentifier>{bcfa2fd6-45a9-4671-a48e-f9ae4fdd3a9a}</UniqueIdentifier>
</Filter>
<Filter Include="ReSDK\common">
<UniqueIdentifier>{d192d10f-9ccb-4357-a360-875a563b016a}</UniqueIdentifier>
</Filter>
<Filter Include="ReSDK\cstrike">
<UniqueIdentifier>{ba0b72ba-25d8-48c3-af84-c1d4d7436636}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\CstrikeHacks.cpp">
@ -62,6 +74,12 @@
<ClCompile Include="..\CstrikeItemsInfos.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\public\resdk\mod_regamedll_api.cpp">
<Filter>ReSDK</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\public\resdk\mod_rehlds_api.cpp">
<Filter>ReSDK</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\CstrikePlayer.h">
@ -100,6 +118,30 @@
<ClInclude Include="..\CstrikeItemsInfos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\common\hookchains.h">
<Filter>ReSDK\common</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\cstrike\regamedll_api.h">
<Filter>ReSDK\cstrike</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\cstrike\regamedll_const.h">
<Filter>ReSDK\cstrike</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\cstrike\regamedll_interfaces.h">
<Filter>ReSDK\cstrike</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\engine\rehlds_api.h">
<Filter>ReSDK\engine</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\engine\rehlds_interfaces.h">
<Filter>ReSDK\engine</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\mod_regamedll_api.h">
<Filter>ReSDK</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\public\resdk\mod_rehlds_api.h">
<Filter>ReSDK</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\..\plugins\include\cstrike.inc">