mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-08 17:07:20 -08:00
78 lines
2.7 KiB
C#
78 lines
2.7 KiB
C#
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using CounterStrikeSharp.API.Modules.Memory;
|
|
using CounterStrikeSharp.API.Modules.Utils;
|
|
|
|
namespace CounterStrikeSharp.API.Modules.Entities;
|
|
|
|
public static class EntitySystem
|
|
{
|
|
private static Lazy<IntPtr> ConcreteEntityListPointer = new(NativeAPI.GetConcreteEntityListPointer);
|
|
|
|
private const int MaxEntities = 32768;
|
|
private const int MaxEntitiesPerChunk = 512;
|
|
private const int MaxChunks = MaxEntities / MaxEntitiesPerChunk;
|
|
private const int SizeOfEntityIdentity = 0x78;
|
|
private const int HandleOffset = 0x10;
|
|
private const uint InvalidEHandleIndex = 0xFFFFFFFF;
|
|
|
|
static unsafe Span<IntPtr> IdentityChunks => new((void*)ConcreteEntityListPointer.Value, MaxChunks);
|
|
public static IntPtr FirstActiveEntity => Marshal.ReadIntPtr(ConcreteEntityListPointer.Value, MaxEntitiesPerChunk);
|
|
|
|
public static IntPtr? GetEntityByHandle(uint raw)
|
|
{
|
|
return GetEntityByHandle(new CHandle<CEntityInstance>(raw));
|
|
}
|
|
|
|
public static IntPtr? GetEntityByHandle<T>(CHandle<T> handle) where T : NativeEntity
|
|
{
|
|
if (!handle.IsValid)
|
|
return null;
|
|
|
|
IntPtr pChunkToUse = IdentityChunks[(int)(handle.Index / MaxEntitiesPerChunk)];
|
|
if (pChunkToUse == IntPtr.Zero)
|
|
return null;
|
|
|
|
IntPtr pIdentityPtr = IntPtr.Add(pChunkToUse, SizeOfEntityIdentity * (int)(handle.Index % MaxEntitiesPerChunk));
|
|
|
|
if (pIdentityPtr == IntPtr.Zero)
|
|
return null;
|
|
|
|
var foundHandle = new CEntityHandle(pIdentityPtr + HandleOffset);
|
|
|
|
if (foundHandle.Raw != handle.Raw)
|
|
return null;
|
|
|
|
return Marshal.ReadIntPtr(pIdentityPtr);
|
|
}
|
|
|
|
public static IntPtr? GetEntityByIndex(uint index)
|
|
{
|
|
if ((int)index <= -1 || index >= MaxEntities - 1) return null;
|
|
|
|
IntPtr pChunkToUse = IdentityChunks[(int)(index / MaxEntitiesPerChunk)];
|
|
if (pChunkToUse == IntPtr.Zero)
|
|
return null;
|
|
|
|
IntPtr pIdentityPtr = IntPtr.Add(pChunkToUse, SizeOfEntityIdentity * (int)(index % MaxEntitiesPerChunk));
|
|
|
|
if (pIdentityPtr == IntPtr.Zero)
|
|
return null;
|
|
|
|
var foundHandle = new CEntityHandle(pIdentityPtr + HandleOffset);
|
|
|
|
if (foundHandle.Index != index)
|
|
return null;
|
|
|
|
return Marshal.ReadIntPtr(pIdentityPtr);
|
|
}
|
|
|
|
public static uint GetRawHandleFromEntityPointer(IntPtr pointer)
|
|
{
|
|
if (pointer == IntPtr.Zero)
|
|
return InvalidEHandleIndex;
|
|
|
|
return Schema.GetPointer<CEntityIdentity?>(pointer, "CEntityInstance", "m_pEntity")?.EntityHandle.Raw ??
|
|
InvalidEHandleIndex;
|
|
}
|
|
} |