Merge branch 'master' into sdktools64

This commit is contained in:
bottiger1 2024-07-01 16:59:04 -07:00 committed by GitHub
commit f874bf43a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 253 additions and 71554 deletions

3
.gitmodules vendored
View File

@ -9,3 +9,6 @@
[submodule "hl2sdk-manifests"]
path = hl2sdk-manifests
url = https://github.com/alliedmodders/hl2sdk-manifests.git
[submodule "public/safetyhook"]
path = public/safetyhook
url = https://github.com/alliedmodders/safetyhook

View File

@ -55,6 +55,7 @@ class SMConfig(object):
self.target_archs = set()
self.enable_asan = getattr(builder.options, 'enable_asan', False)
self.asan_libs = {}
self.libsafetyhook = {}
if builder.options.targets:
target_archs = builder.options.targets.split(',')
@ -522,13 +523,14 @@ class SMConfig(object):
def AddCDetour(self, binary):
public_path = os.path.join(builder.sourcePath, 'public')
binary.sources += [
os.path.join(public_path, 'CDetour', 'detours.cpp'),
os.path.join(public_path, 'safetyhook', 'safetyhook.cpp'),
os.path.join(public_path, 'safetyhook', 'Zydis.c')
]
binary.compiler.cxxincludes += [ os.path.join(public_path, 'safetyhook') ]
binary.compiler.includes += [ os.path.join(public_path, 'safetyhook') ]
binary.sources += [ os.path.join(public_path, 'CDetour', 'detours.cpp') ]
binary.compiler.cxxincludes += [ os.path.join(public_path, 'safetyhook', 'include') ]
for task in self.libsafetyhook:
if task.target.arch == binary.compiler.target.arch:
binary.compiler.linkflags += [task.binary]
return
raise Exception('No suitable build of safetyhook was found.')
def HL2Library(self, context, compiler, name, sdk):
binary = self.Library(context, compiler, name)
@ -578,6 +580,16 @@ if SM.use_auto_versioning():
{ 'SM': SM }
)
class SafetyHookShim(object):
def __init__(self):
self.all_targets = {}
self.libsafetyhook = {}
SafetyHook = SafetyHookShim()
SafetyHook.all_targets = SM.all_targets
builder.Build('public/safetyhook/AMBuilder', {'SafetyHook': SafetyHook })
SM.libsafetyhook = SafetyHook.libsafetyhook
class SPRoot(object):
def __init__(self):
self.generated_headers = SM.generated_headers

View File

@ -413,6 +413,17 @@ ServerClass *CHalfLife2::FindServerClass(const char *classname)
return pInfo->sc;
}
ServerClass *CHalfLife2::FindEntityServerClass(CBaseEntity *pEntity)
{
IServerNetworkable* pNetwork = ((IServerUnknown *)pEntity)->GetNetworkable();
if (pNetwork == nullptr)
{
return nullptr;
}
return pNetwork->GetServerClass();
}
DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
{
DataTableInfo *pInfo = NULL;

View File

@ -221,6 +221,7 @@ public: //IGameHelpers
bool FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info);
datamap_t *GetDataMap(CBaseEntity *pEntity);
ServerClass *FindServerClass(const char *classname);
ServerClass *FindEntityServerClass(CBaseEntity *pEntity);
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable);
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);

View File

@ -342,6 +342,7 @@ SMCError TextParsers::ParseStream_SMC(void *stream,
SMCResult res;
SMCStates states;
char c;
bool end_of_last_buffer_was_backslash = false;
StringInfo strings[3];
StringInfo emptystring;
@ -383,6 +384,10 @@ SMCError TextParsers::ParseStream_SMC(void *stream,
if (reparse_point)
{
read += (parse_point - reparse_point);
if(read > 0)
{
end_of_last_buffer_was_backslash = reparse_point[-1] == '\\';
}
parse_point = reparse_point;
reparse_point = NULL;
}
@ -454,7 +459,7 @@ SMCError TextParsers::ParseStream_SMC(void *stream,
if (in_quote)
{
/* If i was 0, we could have reparsed, so make sure there's no buffer underrun */
if ((&parse_point[i] != in_buf) && c == '"' && parse_point[i-1] != '\\')
if ( (&parse_point[i] != in_buf) && c == '"' && !((i == 0 && end_of_last_buffer_was_backslash) || (i > 0 && parse_point[i-1] == '\\')) )
{
/* If we reached a quote in an ignore phase,
* we're staging a string and we must rotate it out.
@ -726,6 +731,7 @@ SMCError TextParsers::ParseStream_SMC(void *stream,
if (parse_point)
{
parse_point = &parse_point[read];
end_of_last_buffer_was_backslash = parse_point[-1] == '\\';
parse_point -= bytes;
}
}

View File

@ -317,6 +317,10 @@ public:
}
virtual bool LogPrint(const char *msg)
{
if (!g_pLogHook) {
return false;
}
cell_t result = 0;
g_pLogHook->PushString(msg);
g_pLogHook->Execute(&result);
@ -751,6 +755,39 @@ static cell_t sm_SetFilePermissions(IPluginContext *pContext, const cell_t *para
#endif
}
static cell_t sm_GetFilePermissions(IPluginContext *pContext, const cell_t *params)
{
char *name;
char realpath[PLATFORM_MAX_PATH];
pContext->LocalToString(params[1], &name);
g_pSM->BuildPath(Path_Game, realpath, sizeof(realpath), "%s", name);
cell_t *mask;
pContext->LocalToPhysAddr(params[2], &mask);
#if defined PLATFORM_WINDOWS
struct _stat buffer;
cell_t valid = _stat(realpath, &buffer) == 0;
if ((buffer.st_mode & _S_IREAD) != 0) {
*mask |= (FPERM_U_READ|FPERM_G_READ|FPERM_O_READ)|(FPERM_U_EXEC|FPERM_G_EXEC|FPERM_O_EXEC);
}
if ((buffer.st_mode & _S_IWRITE) != 0) {
*mask |= (FPERM_U_WRITE|FPERM_G_WRITE|FPERM_O_WRITE);
}
return valid;
#else
struct stat buffer;
cell_t valid = stat(realpath, &buffer) == 0;
*mask = buffer.st_mode;
return valid;
#endif
}
static cell_t sm_CreateDirectory(IPluginContext *pContext, const cell_t *params)
{
char *name;
@ -1224,6 +1261,7 @@ REGISTER_NATIVES(filesystem)
{"RemoveGameLogHook", sm_RemoveGameLogHook},
{"CreateDirectory", sm_CreateDirectory},
{"SetFilePermissions", sm_SetFilePermissions},
{"GetFilePermissions", sm_GetFilePermissions},
{"File.ReadLine", sm_ReadFileLine},
{"File.Read", sm_ReadFile},

View File

@ -134,12 +134,10 @@ inline edict_t *BaseEntityToEdict(CBaseEntity *pEntity)
{
IServerUnknown *pUnk = (IServerUnknown *)pEntity;
IServerNetworkable *pNet = pUnk->GetNetworkable();
if (!pNet)
if (pNet == nullptr)
{
return NULL;
return nullptr;
}
return pNet->GetEdict();
}
@ -363,14 +361,20 @@ static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
{
edict_t *pEdict = GetEdict(params[1]);
if (!pEdict)
IServerUnknown *pUnknown = (IServerUnknown *)g_HL2.ReferenceToEntity(params[1]);
if (!pUnknown)
{
return 0;
}
return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
IServerNetworkable *pNet = pUnknown->GetNetworkable();
if (!pNet)
{
return 0;
}
edict_t* edict = pNet->GetEdict();
return (edict && !edict->IsFree()) ? 1 : 0;
}
static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
@ -436,14 +440,12 @@ static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
return pContext->ThrowNativeError("Invalid entity (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
}
IServerNetworkable *pNet = pUnk->GetNetworkable();
if (!pNet)
ServerClass *pClass = g_HL2.FindEntityServerClass(pEntity);
if (!pClass)
{
return 0;
}
ServerClass *pClass = pNet->GetServerClass();
pContext->StringToLocal(params[2], params[3], pClass->GetName());
return 1;
@ -1270,13 +1272,11 @@ static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
#define FIND_PROP_SEND(type, type_name) \
sm_sendprop_info_t info;\
SendProp *pProp; \
IServerUnknown *pUnk = (IServerUnknown *)pEntity; \
IServerNetworkable *pNet = pUnk->GetNetworkable(); \
if (!pNet) \
{ \
return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]); \
ServerClass *pServerClass = g_HL2.FindEntityServerClass(pEntity); \
if (pServerClass == nullptr) { \
pContext->ThrowNativeError("Failed to retrieve entity %d (%d) server class!", g_HL2.ReferenceToIndex(params[1]), params[1]); \
} \
if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info)) \
if (!g_HL2.FindSendPropInfo(pServerClass->GetName(), prop, &info)) \
{ \
const char *class_name = g_HL2.GetEntityClassname(pEntity); \
return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
@ -1434,13 +1434,13 @@ static cell_t GetEntPropArraySize(IPluginContext *pContext, const cell_t *params
{
sm_sendprop_info_t info;
IServerUnknown *pUnk = (IServerUnknown *)pEntity;
IServerNetworkable *pNet = pUnk->GetNetworkable();
if (!pNet)
ServerClass *pServerClass = g_HL2.FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]);
return pContext->ThrowNativeError("Failed to retrieve entity %d (%d) server class!", g_HL2.ReferenceToIndex(params[1]), params[1]);
}
if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info))
if (!g_HL2.FindSendPropInfo(pServerClass->GetName(), prop, &info))
{
const char *class_name = g_HL2.GetEntityClassname(pEntity);
return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)",
@ -2079,13 +2079,7 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params)
edict_t *pOtherEdict = NULL;
if (pOther)
{
IServerNetworkable *pNetworkable = ((IServerUnknown *) pOther)->GetNetworkable();
if (!pNetworkable)
{
return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]);
}
pOtherEdict = pNetworkable->GetEdict();
pOtherEdict = BaseEntityToEdict(pOther);
if (!pOtherEdict || pOtherEdict->IsFree())
{
return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]);

View File

@ -254,10 +254,13 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
//Psychonic is awesome for this
sm_sendprop_info_t spi;
IServerUnknown *pUnk = (IServerUnknown *)pWeapon;
IServerNetworkable *pNet = pUnk->GetNetworkable();
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pWeapon);
if (pServerClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d server class!", params[2]);
}
if (!UTIL_FindDataTable(pNet->GetServerClass()->m_pTable, "DT_WeaponCSBase", &spi, 0))
if (!UTIL_FindDataTable(pServerClass->m_pTable, "DT_WeaponCSBase", &spi, 0))
return pContext->ThrowNativeError("Entity index %d is not a weapon", params[2]);
if (!gamehelpers->FindSendPropInfo("CBaseCombatWeapon", "m_hOwnerEntity", &spi))

View File

@ -614,13 +614,18 @@ HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callbac
if (!!strcmp(g_HookTypes[type].dtReq, ""))
{
IServerUnknown *pUnk = (IServerUnknown *)pEnt;
IServerNetworkable *pNet = pUnk->GetNetworkable();
if (pNet && !UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, g_HookTypes[type].dtReq))
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEnt);
if (pServerClass == nullptr)
{
return HookRet_BadEntForHookType;
}
if (!UTIL_ContainsDataTable(pServerClass->m_pTable, g_HookTypes[type].dtReq))
{
return HookRet_BadEntForHookType;
}
}
size_t entry;
CVTableHook vhook(pEnt);
std::vector<CVTableList *> &vtablehooklist = g_HookList[type];

View File

@ -230,10 +230,13 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params)
if (!pWeapon)
return pContext->ThrowNativeError("Invalid entity index %d for weapon", params[2]);
IServerUnknown *pUnk = (IServerUnknown *)pWeapon;
IServerNetworkable *pNet = pUnk->GetNetworkable();
ServerClass *pClass = gamehelpers->FindEntityServerClass(pWeapon);
if (pClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d server class!", params[2]);
}
if (!UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, "DT_BaseCombatWeapon"))
if (!UTIL_ContainsDataTable(pClass->m_pTable, "DT_BaseCombatWeapon"))
return pContext->ThrowNativeError("Entity index %d is not a weapon", params[2]);
sm_sendprop_info_t spi;

View File

@ -45,26 +45,27 @@ static CBaseEntity *FindEntityByNetClass(int start, const char *classname)
int maxEntities = gpGlobals->maxEntities;
for (int i = start; i < maxEntities; i++)
{
edict_t *current = gamehelpers->EdictOfIndex(i);
if (current == NULL || current->IsFree())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
IServerNetworkable *network = current->GetNetworkable();
if (network == NULL)
continue;
IHandleEntity *pHandleEnt = network->GetEntityHandle();
if (pHandleEnt == NULL)
continue;
ServerClass *sClass = network->GetServerClass();
const char *name = sClass->GetName();
if (!strcmp(name, classname))
return gamehelpers->ReferenceToEntity(gamehelpers->IndexOfEdict(current));
}
return NULL;
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
continue;
}
const char *name = pServerClass->GetName();
if (!strcmp(name, classname))
{
return pEntity;
}
}
return nullptr;
}
static CBaseEntity* GetGameRulesProxyEnt()

View File

@ -234,7 +234,8 @@ void CHookManager::OnClientConnected(int client)
}
}
int hookid = SH_ADD_VPHOOK(IClientMessageHandler, ProcessVoiceData, (IClientMessageHandler *)((intptr_t)(pClient) + sizeof(intptr_t)), SH_MEMBER(this, &CHookManager::ProcessVoiceData), true);
int hookid = SH_ADD_VPHOOK(IClientMessageHandler, ProcessVoiceData, (IClientMessageHandler *)((intptr_t)(pClient) + sizeof(void *)), SH_MEMBER(this, &CHookManager::ProcessVoiceData), true);
hook.SetHookID(hookid);
netProcessVoiceData.push_back(new CVTableHook(hook));
}
@ -584,7 +585,7 @@ bool CHookManager::SendFile(const char *filename, unsigned int transferID)
#if !defined CLIENTVOICE_HOOK_SUPPORT
bool CHookManager::ProcessVoiceData(CLC_VoiceData *msg)
{
IClient *pClient = (IClient *)((intptr_t)(META_IFACEPTR(IClient)) - sizeof(intptr_t));
IClient *pClient = (IClient *)((intptr_t)(META_IFACEPTR(IClient)) - sizeof(void *));
if (pClient == NULL)
{
return true;

View File

@ -50,19 +50,20 @@ void InitTeamNatives()
int edictCount = gpGlobals->maxEntities;
for (int i=0; i<edictCount; i++)
for (int i = 0; i < edictCount; i++)
{
edict_t *pEdict = PEntityOfEntIndex(i);
if (!pEdict || pEdict->IsFree())
{
continue;
}
if (!pEdict->GetNetworkable())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
}
ServerClass *pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
continue;
}
ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
if (FindNestedDataTable(pClass->m_pTable, "DT_Team"))
{
SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
@ -70,15 +71,14 @@ void InitTeamNatives()
if (pTeamNumProp != NULL)
{
int offset = pTeamNumProp->GetOffset();
CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
int TeamIndex = *(int *)((unsigned char *)pEntity + offset);
if (TeamIndex >= (int)g_Teams.size())
{
g_Teams.resize(TeamIndex+1);
}
g_Teams[TeamIndex].ClassName = pClass->GetName();
g_Teams[TeamIndex].pEnt = pEnt;
g_Teams[TeamIndex].pEnt = pEntity;
}
}
}

View File

@ -424,15 +424,17 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
if (index >= 1 && index <= playerhelpers->GetMaxClients())
{
IGamePlayer *player = playerhelpers->GetGamePlayer(index);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected())
{
if(!player->IsConnected()) {
pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail;
} else if (!player->IsInGame()) {
}
if(!(data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail;
}
pEntity = gamehelpers->ReferenceToEntity(param);
} else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
@ -469,15 +471,17 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
if (index >= 1 && index <= playerhelpers->GetMaxClients())
{
IGamePlayer *player = playerhelpers->GetGamePlayer(index);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected())
{
if(!player->IsConnected()) {
pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail;
} else if (!player->IsInGame()) {
}
if(!(data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail;
}
pEntity = gamehelpers->ReferenceToEntity(param);
} else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
@ -521,15 +525,17 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
if (param >= 1 && param <= playerhelpers->GetMaxClients())
{
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected())
{
if(!player->IsConnected()) {
pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail;
} else if (!player->IsInGame()) {
}
if(!(data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail;
}
pEdict = player->GetEdict();
} else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL)

View File

@ -321,28 +321,23 @@ void GetResourceEntity()
{
int edictCount = gpGlobals->maxEntities;
for (int i=0; i<edictCount; i++)
for (int i = 0; i < edictCount; i++)
{
edict_t *pEdict = PEntityOfEntIndex(i);
if (!pEdict || pEdict->IsFree())
{
continue;
}
if (!pEdict->GetNetworkable())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
}
IHandleEntity *pHandleEnt = pEdict->GetNetworkable()->GetEntityHandle();
if (!pHandleEnt)
ServerClass *pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
continue;
}
ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
if (FindNestedDataTable(pClass->m_pTable, "DT_PlayerResource"))
{
g_ResourceEntity = pHandleEnt->GetRefEHandle();
g_ResourceEntity = ((IHandleEntity *)pEntity)->GetRefEHandle();
break;
}
}

View File

@ -753,8 +753,8 @@ CEntityFactoryDictionary *GetEntityFactoryDictionary()
int32_t funcOffset = *(int32_t *)((intptr_t)addr + offset);
// Get real address of function
// Address of signature + offset of relative offset + sizeof(int32_t) offset + relative offset
addr = (void *)((intptr_t)addr + offset + sizeof(intptr_t) + funcOffset);
// Address of signature + offset of relative offset + pointer size + relative offset
addr = (void *)((intptr_t)addr + offset + sizeof(void *) + funcOffset);
}
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retData, NULL, 0);

View File

@ -1689,7 +1689,12 @@ static cell_t LookupEntityAttachment(IPluginContext* pContext, const cell_t* par
CBaseEntity* pEntity;
ENTINDEX_TO_CBASEENTITY(params[1], pEntity);
ServerClass* pClass = ((IServerUnknown*)pEntity)->GetNetworkable()->GetServerClass();
ServerClass* pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d (%d) server class!", gamehelpers->ReferenceToIndex(params[1]), params[1]);
}
if (!FindNestedDataTable(pClass->m_pTable, "DT_BaseAnimating"))
{
return pContext->ThrowNativeError("Entity %d (%d) is not a CBaseAnimating", gamehelpers->ReferenceToIndex(params[1]), params[1]);
@ -1735,7 +1740,12 @@ static cell_t GetEntityAttachment(IPluginContext* pContext, const cell_t* params
CBaseEntity* pEntity;
ENTINDEX_TO_CBASEENTITY(params[1], pEntity);
ServerClass* pClass = ((IServerUnknown*)pEntity)->GetNetworkable()->GetServerClass();
ServerClass* pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d (%d) server class!", gamehelpers->ReferenceToIndex(params[1]), params[1]);
}
if (!FindNestedDataTable(pClass->m_pTable, "DT_BaseAnimating"))
{
return pContext->ThrowNativeError("Entity %d (%d) is not a CBaseAnimating", gamehelpers->ReferenceToIndex(params[1]), params[1]);

View File

@ -76,16 +76,21 @@ bool CritManager::TryEnable()
for (size_t i = playerhelpers->GetMaxClients() + 1; i < MAX_EDICTS; ++i)
{
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == NULL)
if (pEntity == nullptr)
{
continue;
}
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable();
if (!pNetworkable)
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
continue;
}
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE))
if (!UTIL_ContainsDataTable(pServerClass->m_pTable, TF_WEAPON_DATATABLE))
{
continue;
}
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false);
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false);
@ -116,15 +121,20 @@ void CritManager::Disable()
void CritManager::OnEntityCreated(CBaseEntity *pEntity, const char *classname)
{
if (!m_enabled)
{
return;
}
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable();
if (!pNetworkable)
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
return;
}
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE))
if (!UTIL_ContainsDataTable(pServerClass->m_pTable, TF_WEAPON_DATATABLE))
{
return;
}
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false);
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false);
@ -164,11 +174,9 @@ bool CritManager::Hook_CalcIsAttackCriticalHelpers(bool noCrits)
{
CBaseEntity *pWeapon = META_IFACEPTR(CBaseEntity);
// If there's an invalid ent or invalid networkable here, we've got issues elsewhere.
IServerNetworkable *pNetWeapon = ((IServerUnknown *)pWeapon)->GetNetworkable();
ServerClass *pServerClass = pNetWeapon->GetServerClass();
if (!pServerClass)
// If there's an invalid ent or invalid server class here, we've got issues elsewhere.
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pWeapon);
if (pServerClass == nullptr)
{
g_pSM->LogError(myself, "Invalid server class on weapon.");
RETURN_META_VALUE(MRES_IGNORED, false);

View File

@ -435,23 +435,19 @@ int FindEntityByNetClass(int start, const char *classname)
for (int i = ((start != -1) ? start : 0); i < gpGlobals->maxEntities; i++)
{
current = engine->PEntityOfEntIndex(i);
if (current == NULL || current->IsFree())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
}
IServerNetworkable *network = current->GetNetworkable();
if (network == NULL)
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
continue;
}
ServerClass *sClass = network->GetServerClass();
const char *name = sClass->GetName();
const char *name = pServerClass->GetName();
if (strcmp(name, classname) == 0)
{
return i;

View File

@ -601,6 +601,15 @@ native bool CreateDirectory(const char[] path, int mode=FPERM_O_READ|FPERM_O_EXE
*/
native bool SetFilePermissions(const char[] path, int mode);
/**
* Retrieves a file or directories permissions.
*
* @param path Path to the file.
* @param mode Variable to store the permissions in.
* @return True on success, false otherwise.
*/
native bool GetFilePermissions(const char[] path, int &mode);
/**
* Returns a file timestamp as a unix timestamp.
*

View File

@ -32,7 +32,7 @@
#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
#define _INCLUDE_SOURCEMOD_DETOURS_H_
#include "../safetyhook/safetyhook.hpp"
#include "safetyhook.hpp"
#include <smsdk_ext.h>
#define DETOUR_MEMBER_CALL(name) (this->*name##_Actual)

View File

@ -40,7 +40,7 @@
*/
#define SMINTERFACE_GAMEHELPERS_NAME "IGameHelpers"
#define SMINTERFACE_GAMEHELPERS_VERSION 11
#define SMINTERFACE_GAMEHELPERS_VERSION 12
class CBaseEntity;
class CBaseHandle;
@ -351,6 +351,13 @@ namespace SourceMod
* @return 64-bit server Steam id.
*/
virtual uint64_t GetServerSteamId64() const =0;
/**
* @brief Finds a given entity's server class.
*
* @return ServerClass pointer on success, nullptr on failure.
*/
virtual ServerClass *FindEntityServerClass(CBaseEntity *pEntity) = 0;
};
}

1
public/safetyhook Submodule

@ -0,0 +1 @@
Subproject commit 4c933195789e9a0551a49c929dc3a2dd1e8fb97f

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff