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"]
|
[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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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},
|
||||||
|
|||||||
@ -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]);
|
||||||
|
|||||||
@ -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))
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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]);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
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