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"] [submodule "hl2sdk-manifests"]
path = hl2sdk-manifests path = hl2sdk-manifests
url = https://github.com/alliedmodders/hl2sdk-manifests.git 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.target_archs = set()
self.enable_asan = getattr(builder.options, 'enable_asan', False) self.enable_asan = getattr(builder.options, 'enable_asan', False)
self.asan_libs = {} self.asan_libs = {}
self.libsafetyhook = {}
if builder.options.targets: if builder.options.targets:
target_archs = builder.options.targets.split(',') target_archs = builder.options.targets.split(',')
@ -522,13 +523,14 @@ class SMConfig(object):
def AddCDetour(self, binary): def AddCDetour(self, binary):
public_path = os.path.join(builder.sourcePath, 'public') public_path = os.path.join(builder.sourcePath, 'public')
binary.sources += [ binary.sources += [ os.path.join(public_path, 'CDetour', 'detours.cpp') ]
os.path.join(public_path, 'CDetour', 'detours.cpp'), binary.compiler.cxxincludes += [ os.path.join(public_path, 'safetyhook', 'include') ]
os.path.join(public_path, 'safetyhook', 'safetyhook.cpp'),
os.path.join(public_path, 'safetyhook', 'Zydis.c') for task in self.libsafetyhook:
] if task.target.arch == binary.compiler.target.arch:
binary.compiler.cxxincludes += [ os.path.join(public_path, 'safetyhook') ] binary.compiler.linkflags += [task.binary]
binary.compiler.includes += [ os.path.join(public_path, 'safetyhook') ] return
raise Exception('No suitable build of safetyhook was found.')
def HL2Library(self, context, compiler, name, sdk): def HL2Library(self, context, compiler, name, sdk):
binary = self.Library(context, compiler, name) binary = self.Library(context, compiler, name)
@ -578,6 +580,16 @@ if SM.use_auto_versioning():
{ 'SM': SM } { '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): class SPRoot(object):
def __init__(self): def __init__(self):
self.generated_headers = SM.generated_headers self.generated_headers = SM.generated_headers

View File

@ -413,6 +413,17 @@ ServerClass *CHalfLife2::FindServerClass(const char *classname)
return pInfo->sc; 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 *CHalfLife2::_FindServerClass(const char *classname)
{ {
DataTableInfo *pInfo = NULL; DataTableInfo *pInfo = NULL;

View File

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

View File

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

View File

@ -317,6 +317,10 @@ public:
} }
virtual bool LogPrint(const char *msg) virtual bool LogPrint(const char *msg)
{ {
if (!g_pLogHook) {
return false;
}
cell_t result = 0; cell_t result = 0;
g_pLogHook->PushString(msg); g_pLogHook->PushString(msg);
g_pLogHook->Execute(&result); g_pLogHook->Execute(&result);
@ -751,6 +755,39 @@ static cell_t sm_SetFilePermissions(IPluginContext *pContext, const cell_t *para
#endif #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) static cell_t sm_CreateDirectory(IPluginContext *pContext, const cell_t *params)
{ {
char *name; char *name;
@ -1224,6 +1261,7 @@ REGISTER_NATIVES(filesystem)
{"RemoveGameLogHook", sm_RemoveGameLogHook}, {"RemoveGameLogHook", sm_RemoveGameLogHook},
{"CreateDirectory", sm_CreateDirectory}, {"CreateDirectory", sm_CreateDirectory},
{"SetFilePermissions", sm_SetFilePermissions}, {"SetFilePermissions", sm_SetFilePermissions},
{"GetFilePermissions", sm_GetFilePermissions},
{"File.ReadLine", sm_ReadFileLine}, {"File.ReadLine", sm_ReadFileLine},
{"File.Read", sm_ReadFile}, {"File.Read", sm_ReadFile},

View File

@ -134,12 +134,10 @@ inline edict_t *BaseEntityToEdict(CBaseEntity *pEntity)
{ {
IServerUnknown *pUnk = (IServerUnknown *)pEntity; IServerUnknown *pUnk = (IServerUnknown *)pEntity;
IServerNetworkable *pNet = pUnk->GetNetworkable(); IServerNetworkable *pNet = pUnk->GetNetworkable();
if (pNet == nullptr)
if (!pNet)
{ {
return NULL; return nullptr;
} }
return pNet->GetEdict(); 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) static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
{ {
edict_t *pEdict = GetEdict(params[1]); IServerUnknown *pUnknown = (IServerUnknown *)g_HL2.ReferenceToEntity(params[1]);
if (!pUnknown)
if (!pEdict)
{ {
return 0; 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) 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]); return pContext->ThrowNativeError("Invalid entity (%d - %d)", g_HL2.ReferenceToIndex(params[1]), params[1]);
} }
IServerNetworkable *pNet = pUnk->GetNetworkable(); ServerClass *pClass = g_HL2.FindEntityServerClass(pEntity);
if (!pNet) if (!pClass)
{ {
return 0; return 0;
} }
ServerClass *pClass = pNet->GetServerClass();
pContext->StringToLocal(params[2], params[3], pClass->GetName()); pContext->StringToLocal(params[2], params[3], pClass->GetName());
return 1; return 1;
@ -1270,13 +1272,11 @@ static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
#define FIND_PROP_SEND(type, type_name) \ #define FIND_PROP_SEND(type, type_name) \
sm_sendprop_info_t info;\ sm_sendprop_info_t info;\
SendProp *pProp; \ SendProp *pProp; \
IServerUnknown *pUnk = (IServerUnknown *)pEntity; \ ServerClass *pServerClass = g_HL2.FindEntityServerClass(pEntity); \
IServerNetworkable *pNet = pUnk->GetNetworkable(); \ if (pServerClass == nullptr) { \
if (!pNet) \ pContext->ThrowNativeError("Failed to retrieve entity %d (%d) server class!", g_HL2.ReferenceToIndex(params[1]), params[1]); \
{ \
return pContext->ThrowNativeError("Edict %d (%d) is not networkable", 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); \ const char *class_name = g_HL2.GetEntityClassname(pEntity); \
return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \ 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; sm_sendprop_info_t info;
IServerUnknown *pUnk = (IServerUnknown *)pEntity; ServerClass *pServerClass = g_HL2.FindEntityServerClass(pEntity);
IServerNetworkable *pNet = pUnk->GetNetworkable(); if (pServerClass == nullptr)
if (!pNet)
{ {
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); const char *class_name = g_HL2.GetEntityClassname(pEntity);
return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", 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; edict_t *pOtherEdict = NULL;
if (pOther) if (pOther)
{ {
IServerNetworkable *pNetworkable = ((IServerUnknown *) pOther)->GetNetworkable(); pOtherEdict = BaseEntityToEdict(pOther);
if (!pNetworkable)
{
return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]);
}
pOtherEdict = pNetworkable->GetEdict();
if (!pOtherEdict || pOtherEdict->IsFree()) if (!pOtherEdict || pOtherEdict->IsFree())
{ {
return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]); 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 //Psychonic is awesome for this
sm_sendprop_info_t spi; sm_sendprop_info_t spi;
IServerUnknown *pUnk = (IServerUnknown *)pWeapon; ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pWeapon);
IServerNetworkable *pNet = pUnk->GetNetworkable(); 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]); return pContext->ThrowNativeError("Entity index %d is not a weapon", params[2]);
if (!gamehelpers->FindSendPropInfo("CBaseCombatWeapon", "m_hOwnerEntity", &spi)) if (!gamehelpers->FindSendPropInfo("CBaseCombatWeapon", "m_hOwnerEntity", &spi))

View File

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

View File

@ -230,10 +230,13 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params)
if (!pWeapon) if (!pWeapon)
return pContext->ThrowNativeError("Invalid entity index %d for weapon", params[2]); return pContext->ThrowNativeError("Invalid entity index %d for weapon", params[2]);
IServerUnknown *pUnk = (IServerUnknown *)pWeapon; ServerClass *pClass = gamehelpers->FindEntityServerClass(pWeapon);
IServerNetworkable *pNet = pUnk->GetNetworkable(); 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]); return pContext->ThrowNativeError("Entity index %d is not a weapon", params[2]);
sm_sendprop_info_t spi; sm_sendprop_info_t spi;

View File

@ -45,26 +45,27 @@ static CBaseEntity *FindEntityByNetClass(int start, const char *classname)
int maxEntities = gpGlobals->maxEntities; int maxEntities = gpGlobals->maxEntities;
for (int i = start; i < maxEntities; i++) for (int i = start; i < maxEntities; i++)
{ {
edict_t *current = gamehelpers->EdictOfIndex(i); CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (current == NULL || current->IsFree()) if (pEntity == nullptr)
{
continue; continue;
}
IServerNetworkable *network = current->GetNetworkable(); ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (network == NULL) if (pServerClass == nullptr)
{
continue; continue;
}
IHandleEntity *pHandleEnt = network->GetEntityHandle();
if (pHandleEnt == NULL)
continue;
ServerClass *sClass = network->GetServerClass();
const char *name = sClass->GetName();
const char *name = pServerClass->GetName();
if (!strcmp(name, classname)) if (!strcmp(name, classname))
return gamehelpers->ReferenceToEntity(gamehelpers->IndexOfEdict(current)); {
return pEntity;
}
} }
return NULL; return nullptr;
} }
static CBaseEntity* GetGameRulesProxyEnt() 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); hook.SetHookID(hookid);
netProcessVoiceData.push_back(new CVTableHook(hook)); netProcessVoiceData.push_back(new CVTableHook(hook));
} }
@ -584,7 +585,7 @@ bool CHookManager::SendFile(const char *filename, unsigned int transferID)
#if !defined CLIENTVOICE_HOOK_SUPPORT #if !defined CLIENTVOICE_HOOK_SUPPORT
bool CHookManager::ProcessVoiceData(CLC_VoiceData *msg) 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) if (pClient == NULL)
{ {
return true; return true;

View File

@ -50,19 +50,20 @@ void InitTeamNatives()
int edictCount = gpGlobals->maxEntities; int edictCount = gpGlobals->maxEntities;
for (int i=0; i<edictCount; i++) for (int i = 0; i < edictCount; i++)
{ {
edict_t *pEdict = PEntityOfEntIndex(i); CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (!pEdict || pEdict->IsFree()) if (pEntity == nullptr)
{ {
continue; continue;
} }
if (!pEdict->GetNetworkable())
ServerClass *pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{ {
continue; continue;
} }
ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
if (FindNestedDataTable(pClass->m_pTable, "DT_Team")) if (FindNestedDataTable(pClass->m_pTable, "DT_Team"))
{ {
SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum"); SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
@ -70,15 +71,14 @@ void InitTeamNatives()
if (pTeamNumProp != NULL) if (pTeamNumProp != NULL)
{ {
int offset = pTeamNumProp->GetOffset(); int offset = pTeamNumProp->GetOffset();
CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity(); int TeamIndex = *(int *)((unsigned char *)pEntity + offset);
int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
if (TeamIndex >= (int)g_Teams.size()) if (TeamIndex >= (int)g_Teams.size())
{ {
g_Teams.resize(TeamIndex+1); g_Teams.resize(TeamIndex+1);
} }
g_Teams[TeamIndex].ClassName = pClass->GetName(); 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()) if (index >= 1 && index <= playerhelpers->GetMaxClients())
{ {
IGamePlayer *player = playerhelpers->GetGamePlayer(index); IGamePlayer *player = playerhelpers->GetGamePlayer(index);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected()) if(!player->IsConnected()) {
{
pContext->ThrowNativeError("Client %d is not connected", param); pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail; return Data_Fail;
} else if (!player->IsInGame()) { }
if(!(data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param); pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail; return Data_Fail;
} }
pEntity = gamehelpers->ReferenceToEntity(param); pEntity = gamehelpers->ReferenceToEntity(param);
} else if (param == -1) { } else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL) if (data->decflags & VDECODE_FLAG_ALLOWNULL)
@ -469,15 +471,17 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
if (index >= 1 && index <= playerhelpers->GetMaxClients()) if (index >= 1 && index <= playerhelpers->GetMaxClients())
{ {
IGamePlayer *player = playerhelpers->GetGamePlayer(index); IGamePlayer *player = playerhelpers->GetGamePlayer(index);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected()) if(!player->IsConnected()) {
{
pContext->ThrowNativeError("Client %d is not connected", param); pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail; return Data_Fail;
} else if (!player->IsInGame()) { }
if(!(data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param); pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail; return Data_Fail;
} }
pEntity = gamehelpers->ReferenceToEntity(param); pEntity = gamehelpers->ReferenceToEntity(param);
} else if (param == -1) { } else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL) if (data->decflags & VDECODE_FLAG_ALLOWNULL)
@ -521,15 +525,17 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
if (param >= 1 && param <= playerhelpers->GetMaxClients()) if (param >= 1 && param <= playerhelpers->GetMaxClients())
{ {
IGamePlayer *player = playerhelpers->GetGamePlayer(param); IGamePlayer *player = playerhelpers->GetGamePlayer(param);
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
&& !player->IsConnected()) if(!player->IsConnected()) {
{
pContext->ThrowNativeError("Client %d is not connected", param); pContext->ThrowNativeError("Client %d is not connected", param);
return Data_Fail; return Data_Fail;
} else if (!player->IsInGame()) { }
if(!(data->decflags & VDECODE_FLAG_ALLOWNOTINGAME) && !player->IsInGame()) {
pContext->ThrowNativeError("Client %d is not in game", param); pContext->ThrowNativeError("Client %d is not in game", param);
return Data_Fail; return Data_Fail;
} }
pEdict = player->GetEdict(); pEdict = player->GetEdict();
} else if (param == -1) { } else if (param == -1) {
if (data->decflags & VDECODE_FLAG_ALLOWNULL) if (data->decflags & VDECODE_FLAG_ALLOWNULL)

View File

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

View File

@ -753,8 +753,8 @@ CEntityFactoryDictionary *GetEntityFactoryDictionary()
int32_t funcOffset = *(int32_t *)((intptr_t)addr + offset); int32_t funcOffset = *(int32_t *)((intptr_t)addr + offset);
// Get real address of function // Get real address of function
// Address of signature + offset of relative offset + sizeof(int32_t) offset + relative offset // Address of signature + offset of relative offset + pointer size + relative offset
addr = (void *)((intptr_t)addr + offset + sizeof(intptr_t) + funcOffset); addr = (void *)((intptr_t)addr + offset + sizeof(void *) + funcOffset);
} }
pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retData, NULL, 0); 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; CBaseEntity* pEntity;
ENTINDEX_TO_CBASEENTITY(params[1], 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")) if (!FindNestedDataTable(pClass->m_pTable, "DT_BaseAnimating"))
{ {
return pContext->ThrowNativeError("Entity %d (%d) is not a CBaseAnimating", gamehelpers->ReferenceToIndex(params[1]), params[1]); 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; CBaseEntity* pEntity;
ENTINDEX_TO_CBASEENTITY(params[1], 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")) if (!FindNestedDataTable(pClass->m_pTable, "DT_BaseAnimating"))
{ {
return pContext->ThrowNativeError("Entity %d (%d) is not a CBaseAnimating", gamehelpers->ReferenceToIndex(params[1]), params[1]); 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) for (size_t i = playerhelpers->GetMaxClients() + 1; i < MAX_EDICTS; ++i)
{ {
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i); CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == NULL) if (pEntity == nullptr)
{
continue; continue;
}
IServerUnknown *pUnknown = (IServerUnknown *)pEntity; ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable(); if (pServerClass == nullptr)
if (!pNetworkable) {
continue; continue;
}
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE)) if (!UTIL_ContainsDataTable(pServerClass->m_pTable, TF_WEAPON_DATATABLE))
{
continue; continue;
}
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false); 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); 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) void CritManager::OnEntityCreated(CBaseEntity *pEntity, const char *classname)
{ {
if (!m_enabled) if (!m_enabled)
{
return; return;
}
IServerUnknown *pUnknown = (IServerUnknown *)pEntity; ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable(); if (pServerClass == nullptr)
if (!pNetworkable) {
return; return;
}
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE)) if (!UTIL_ContainsDataTable(pServerClass->m_pTable, TF_WEAPON_DATATABLE))
{
return; return;
}
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false); 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); 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); CBaseEntity *pWeapon = META_IFACEPTR(CBaseEntity);
// If there's an invalid ent or invalid networkable here, we've got issues elsewhere. // If there's an invalid ent or invalid server class here, we've got issues elsewhere.
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pWeapon);
IServerNetworkable *pNetWeapon = ((IServerUnknown *)pWeapon)->GetNetworkable(); if (pServerClass == nullptr)
ServerClass *pServerClass = pNetWeapon->GetServerClass();
if (!pServerClass)
{ {
g_pSM->LogError(myself, "Invalid server class on weapon."); g_pSM->LogError(myself, "Invalid server class on weapon.");
RETURN_META_VALUE(MRES_IGNORED, false); 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++) for (int i = ((start != -1) ? start : 0); i < gpGlobals->maxEntities; i++)
{ {
current = engine->PEntityOfEntIndex(i); CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (current == NULL || current->IsFree()) if (pEntity == nullptr)
{ {
continue; continue;
} }
IServerNetworkable *network = current->GetNetworkable(); ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
if (network == NULL)
{ {
continue; continue;
} }
ServerClass *sClass = network->GetServerClass(); const char *name = pServerClass->GetName();
const char *name = sClass->GetName();
if (strcmp(name, classname) == 0) if (strcmp(name, classname) == 0)
{ {
return i; 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); 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. * Returns a file timestamp as a unix timestamp.
* *

View File

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

View File

@ -40,7 +40,7 @@
*/ */
#define SMINTERFACE_GAMEHELPERS_NAME "IGameHelpers" #define SMINTERFACE_GAMEHELPERS_NAME "IGameHelpers"
#define SMINTERFACE_GAMEHELPERS_VERSION 11 #define SMINTERFACE_GAMEHELPERS_VERSION 12
class CBaseEntity; class CBaseEntity;
class CBaseHandle; class CBaseHandle;
@ -351,6 +351,13 @@ namespace SourceMod
* @return 64-bit server Steam id. * @return 64-bit server Steam id.
*/ */
virtual uint64_t GetServerSteamId64() const =0; 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