update readme

This commit is contained in:
SlynxCZ 2026-01-30 10:31:43 +04:00
parent 923edbbba0
commit 8e0e61acd1

211
README.md
View file

@ -1,44 +1,48 @@
# Ray-Trace # Ray-Trace
**Shared ray tracing interface for Metamod:Source & CounterStrikeSharp plugins** **Shared ray tracing interface for Metamod:Source & CounterStrikeSharp
plugins**
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Overview ## Overview
`Ray-Trace` is a lightweight **Metamod interface module** for `Ray-Trace` is a lightweight **Metamod interface module** for\
**Counter-Strike 2** servers. **Counter-Strike 2** servers.
It exposes a shared interface: `CRayTraceInterface001` which can be consumed from: It exposes a shared interface: `CRayTraceInterface001` which can be
consumed from:
- Native **Metamod C++ plugins** - Native **Metamod C++ plugins**
- Managed **CounterStrikeSharp C# plugins** - Managed **CounterStrikeSharp C# plugins**
The interface is implemented as a **C++ virtual class** and is accessed The interface is implemented as a **C++ virtual class** and is accessed
from C# by calling its **vtable functions directly** using a native handle. from C# by calling its **vtable functions directly** using a native
handle.
The goal is to provide a **single tracing backend** usable from both worlds The goal is to provide a **single tracing backend** usable from both
worlds\
without duplicating engine detours. without duplicating engine detours.
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Features ## Features
- Metamod meta interface (`CRayTraceInterface001`) - Metamod meta interface (`CRayTraceInterface001`)
- Works in **C++ and C#** - Works in **C++ and C#**
- Physics / hitbox / world trace presets - Physics / hitbox / world trace presets
- Custom collision masks - Custom collision masks
- Optional debug beam rendering - Optional debug beam rendering
- Zero configuration - Zero configuration
- Ultra low overhead - Ultra low overhead
- ABI-safe (no STL types in interface) - ABI-safe (no STL types in interface)
- Virtual destructor for safe lifetime management - Virtual destructor for safe lifetime management
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Exposed Interface (C++) ## Exposed Interface (C++)
```cpp ``` cpp
class CRayTraceInterface class CRayTraceInterface
{ {
public: public:
@ -69,16 +73,17 @@ public:
) = 0; ) = 0;
}; };
``` ```
**Return value:**
- true → trace hit something, TraceResult is valid **Return value:** - true → trace hit something, TraceResult is valid\
- false → no hit - false → no hit
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Getting the interface ## Getting the interface
**C++ (Metamod plugin)** **C++ (Metamod plugin)**
```cpp ``` cpp
CRayTraceInterface* g_pRayTrace = nullptr; CRayTraceInterface* g_pRayTrace = nullptr;
bool g_bRayTraceLoaded = false; bool g_bRayTraceLoaded = false;
@ -102,7 +107,8 @@ bool LoadRayTrace()
``` ```
**C# (CounterStrikeSharp plugin)** **C# (CounterStrikeSharp plugin)**
```csharp
``` csharp
private nint g_pRayTraceHandle = nint.Zero; private nint g_pRayTraceHandle = nint.Zero;
private bool g_bRayTraceLoaded = false; private bool g_bRayTraceLoaded = false;
@ -119,13 +125,17 @@ public override void Load(bool hotReload)
g_bRayTraceLoaded = true; g_bRayTraceLoaded = true;
} }
``` ```
The returned handle is a pointer to the native CRayTraceInterface object.
The returned handle is a pointer to the native CRayTraceInterface
object.
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Calling methods from C++ (Metamod) ## Calling methods from C++ (Metamod)
**TraceShape example** **TraceShape example**
```cpp
``` cpp
Vector vecOrigin{}; Vector vecOrigin{};
QAngle angView{}; QAngle angView{};
TraceOptions traceOpts{}; TraceOptions traceOpts{};
@ -156,7 +166,8 @@ if (g_pRayTrace && g_bRayTraceLoaded)
``` ```
**TraceEndShape example** **TraceEndShape example**
```cpp
``` cpp
TraceResult traceResult{}; TraceResult traceResult{};
bool bHit = g_pRayTrace->TraceEndShape( bool bHit = g_pRayTrace->TraceEndShape(
@ -169,7 +180,8 @@ bool bHit = g_pRayTrace->TraceEndShape(
``` ```
**TraceShapeEx (low-level)** **TraceShapeEx (low-level)**
```cpp
``` cpp
Ray_t ray{}; Ray_t ray{};
CTraceFilter filter( CTraceFilter filter(
static_cast<uint64_t>(MASK_SHOT_FULL), static_cast<uint64_t>(MASK_SHOT_FULL),
@ -191,7 +203,8 @@ bool bHit = g_pRayTrace->TraceShapeEx(
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Calling methods from C# (CounterStrikeSharp plugin) ## Calling methods from C# (CounterStrikeSharp plugin)
```csharp
``` csharp
private delegate bool TraceShapeFn( private delegate bool TraceShapeFn(
nint pThis, nint pThis,
nint pOrigin, nint pOrigin,
@ -235,26 +248,94 @@ public bool TraceShape(
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Memory allocation from C# (Important)
When calling `TraceShape` or `TraceEndShape` from C#, the plugin **must
allocate native memory** for the following structures:
- `TraceOptions`
- `TraceResult`
These parameters are native pointers in C++ (`TraceOptions*` and
`TraceResult*`) and must remain valid for the duration of the call.
The recommended and safest approach is using **stackalloc** (or unsafe
stack variables) to provide native memory on the stack.
Failing to allocate valid memory for these parameters will result in
crashes or undefined behavior.
### Example (C# stackalloc)
``` csharp
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct TraceOptions
{
public ulong InteractsWith;
public ulong InteractsExclude;
public int DrawBeam;
}
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct TraceResult
{
public Vector EndPos;
public nint HitEntity;
public float Fraction;
public int AllSolid;
public Vector Normal;
}
unsafe
{
Vector origin = player.Position;
QAngle angles = player.ViewAngles;
TraceOptions* opts = stackalloc TraceOptions[1];
opts->InteractsWith = (ulong)MASK_SHOT_FULL;
opts->InteractsExclude = 0;
opts->DrawBeam = 0;
TraceResult* result = stackalloc TraceResult[1];
bool hit = _traceShape!(
g_pRayTraceHandle,
(nint)&origin,
(nint)&angles,
nint.Zero,
(nint)opts,
(nint)result
);
if (hit)
{
Console.WriteLine($"Hit at: {result->EndPos}");
}
}
```
------------------------------------------------------------------------
## Low-level usage from C# (Ray_t & CTraceFilter) ## Low-level usage from C# (Ray_t & CTraceFilter)
When using the low-level method `TraceShapeEx` from a C# plugin, the plugin When using the low-level method `TraceShapeEx` from a C# plugin, the
must provide its own native-compatible implementations of the following plugin must provide its own native-compatible implementations of the
engine structures: following engine structures:
- `Ray_t` - `Ray_t`
- `CTraceFilter` - `CTraceFilter`
These structures are not exposed directly by the Ray-Trace interface and These structures are not exposed directly by the Ray-Trace interface and
must be recreated in managed code with correct memory layout. must be recreated in managed code with correct memory layout.
### Ray_t (C#) ### Ray_t (C#)
The C# plugin must define a struct that matches the native `Ray_t` layout The C# plugin must define a struct that matches the native `Ray_t`
used by the engine. layout used by the engine.
Example (simplified): Example (simplified):
```csharp ``` csharp
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Ray_t public struct Ray_t
{ {
@ -264,19 +345,21 @@ public struct Ray_t
public byte m_IsSwept; public byte m_IsSwept;
} }
``` ```
(Exact layout depends on the engine version and must match native memory.)
**CTraceFilter (C#)** (Exact layout depends on the engine version and must match native
memory.)
**CTraceFilter (C#)**\
For `CTraceFilter`, the plugin must: For `CTraceFilter`, the plugin must:
- Define a managed struct matching the native layout.
- Resolve the CTraceFilter vtable pointer using a signature scan.
- Assign the resolved vtable to the struct before calling TraceShapeEx.
This is required because CTraceFilter is a polymorphic C++ class and its - Define a managed struct matching the native layout.
virtual table is not directly exposed to managed code. - Resolve the CTraceFilter vtable pointer using a signature scan.
- Assign the resolved vtable to the struct before calling
TraceShapeEx.
Example concept: Example concept:
```csharp
``` csharp
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct CTraceFilter public unsafe struct CTraceFilter
{ {
@ -285,31 +368,33 @@ public unsafe struct CTraceFilter
public T ...; public T ...;
} }
``` ```
The vtable pointer must be resolved at runtime using a signature scan
against the game binary.
**Important notes** **Important notes** - This setup is only required when using the
- This setup is only required when using the low-level API: low-level API: - TraceShapeEx(...) - High-level functions (TraceShape,
- TraceShapeEx(...) TraceEndShape) do not require custom Ray_t or CTraceFilter handling from
- High-level functions (TraceShape, TraceEndShape) do not require custom Ray_t or CTraceFilter handling from C#. C#. - Incorrect structure layout or invalid vtable resolution will
- Incorrect structure layout or invalid vtable resolution will result in crashes or undefined behavior. result in crashes or undefined behavior. - This is considered an
- This is considered an advanced use case intended for engine-level plugins. advanced use case intended for engine-level plugins.
------------------------------------------------------------------------ ------------------------------------------------------------------------
## Notes about ABI & Destructor ## Notes about ABI & Destructor
- CRayTraceInterface has a virtual destructor.
- The object is owned by the Ray-Trace Metamod module. - CRayTraceInterface has a virtual destructor.
- Plugins must never call delete on the interface pointer. - The object is owned by the Ray-Trace Metamod module.
- C# must only clear its handle on unload. - Plugins must never call delete on the interface pointer.
- All parameters are passed as native pointers (nint). - C# must only clear its handle on unload.
- All parameters are passed as native pointers (nint).
# Build # Build
## Requirements ## Requirements
- HL2SDK-CS2
- Metamod:Source - HL2SDK-CS2
- CMake - Metamod:Source
```bash - CMake
``` bash
git clone https://github.com/FUNPLAY-pro-CS2/Ray-Trace.git git clone https://github.com/FUNPLAY-pro-CS2/Ray-Trace.git
cd Ray-Trace cd Ray-Trace
git submodule update --init --recursive git submodule update --init --recursive
@ -319,9 +404,11 @@ docker compose -f docker/docker-compose.yml up
------------------------------------------------------------------------ ------------------------------------------------------------------------
## License ## License
GPLv3
GPLv3\
https://www.gnu.org/licenses/gpl-3.0.en.html https://www.gnu.org/licenses/gpl-3.0.en.html
## Author ## Author
**Michal "Slynx" Přikryl**
https://slynxdev.cz **Michal "Slynx" Přikryl**\
https://slynxdev.cz