mirror of
https://github.com/alliedmodders/sourcemod.git
synced 2025-12-06 18:08:36 +00:00
Merge branch 'master' into sdktools64
This commit is contained in:
commit
f874bf43a2
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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},
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
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
Loading…
Reference in New Issue
Block a user