diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index a781721..b73cd3d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -100,34 +100,50 @@ jobs:
release:
name: Release
if: startsWith(github.ref, 'refs/tags/')
- needs: [build-linux, build-windows]
+ needs: [ build-linux, build-windows ]
runs-on: ubuntu-latest
permissions:
contents: write
+
steps:
- - name: Download Linux artifact
- uses: actions/download-artifact@v4
- with:
- name: RayTrace-linux
- path: ./build/linux
+ - name: Download Linux artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: RayTrace-linux
+ path: ./artifacts/linux
- - name: Download Windows artifact
- uses: actions/download-artifact@v4
- with:
- name: RayTrace-windows
- path: ./build/windows
+ - name: Download Windows artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: RayTrace-windows
+ path: ./artifacts/windows
- - name: Archive packages
- run: |
- version="${GITHUB_REF#refs/tags/}"
- tar -czf RayTrace-${version}-linux.tar.gz -C build/linux .
- tar -czf RayTrace-${version}-windows.tar.gz -C build/windows .
+ - name: Prepare release packages
+ run: |
+ version="${GITHUB_REF#refs/tags/}"
+
+ mkdir release
+
+ # Linux MM plugin
+ tar -czf release/RayTrace-MM-${version}-linux.tar.gz \
+ -C artifacts/linux .
+
+ # Windows MM plugin
+ tar -czf release/RayTrace-MM-${version}-windows.tar.gz \
+ -C artifacts/windows .
+
+ # CS# package (platform independent)
+ mkdir cs
+ cp -r artifacts/linux/addons/counterstrikesharp cs/
+
+ tar -czf release/RayTrace-CSSharp-${version}.tar.gz \
+ -C cs .
- - name: Upload release archive
- uses: svenstaro/upload-release-action@v2
- with:
- repo_token: ${{ secrets.GITHUB_TOKEN }}
- file: RayTrace-*.tar.gz
- tag: ${{ github.ref }}
- file_glob: true
- release_name: "${{ github.ref_name }} - Download"
+ - name: Upload release archives
+ uses: svenstaro/upload-release-action@v2
+ with:
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
+ file: release/*.tar.gz
+ tag: ${{ github.ref }}
+ file_glob: true
+ release_name: "${{ github.ref_name }}"
\ No newline at end of file
diff --git a/README.md b/README.md
index 955de5d..089182c 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,20 @@
# Ray-Trace
-**Shared ray tracing interface for Metamod:Source & CounterStrikeSharp plugins**
+**Shared ray tracing interface for Metamod:Source & CounterStrikeSharp
+plugins**
------------------------------------------------------------------------
## Overview
-`Ray-Trace` is a lightweight **Metamod interface module** for
+`Ray-Trace` is a lightweight **Metamod interface module** for\
**Counter-Strike 2** servers.
It exposes a shared interface: `CRayTraceInterface001` which can be
consumed from:
-- Native **Metamod C++ plugins**
-- Managed **CounterStrikeSharp C# plugins**
+- Native **Metamod C++ plugins**
+- Managed **CounterStrikeSharp C# plugins**
The interface is implemented as a **C++ virtual class** and is accessed
from C# by calling its **vtable functions directly** using a native
@@ -26,21 +27,21 @@ worlds without duplicating engine detours.
## Features
-- Metamod meta interface (`CRayTraceInterface001`)
-- Works in **C++ and C#**
-- Physics / hitbox / world trace presets
-- Custom collision masks
-- Optional debug beam rendering
-- Zero configuration
-- Ultra low overhead
-- ABI-safe (no STL types in interface)
-- Virtual destructor for safe lifetime management
+- Metamod meta interface (`CRayTraceInterface001`)
+- Works in **C++ and C#**
+- Physics / hitbox / world trace presets
+- Custom collision masks
+- Optional debug beam rendering
+- Zero configuration
+- Ultra low overhead
+- ABI-safe (no STL types in interface)
+- Virtual destructor for safe lifetime management
------------------------------------------------------------------------
## Exposed Interface (C++)
-```cpp
+``` cpp
class CRayTraceInterface
{
public:
@@ -80,20 +81,20 @@ public:
TraceResult* pOutResult
) = 0;
};
-````
+```
**Return value:**
-* `true` → trace hit something, `TraceResult` is valid
-* `false` → no hit
+- `true` → trace hit something, `TraceResult` is valid\
+- `false` → no hit
----
+------------------------------------------------------------------------
## Getting the interface
### C++ (Metamod plugin)
-```cpp
+``` cpp
CRayTraceInterface* g_pRayTrace = nullptr;
bool g_bRayTraceLoaded = false;
@@ -118,26 +119,35 @@ bool LoadRayTrace()
### C# (CounterStrikeSharp plugin)
-For managed plugins, use the provided official wrapper:
+There are **two ways** to use the managed side:
-```
-public/Example.cs
-```
+1. `public/Example.cs` (reference implementation, for learning / custom
+ binding)
+2. **Official release packages (recommended)**
-This file contains:
+The recommended way is to use the prebuilt release components:
-* Correct vtable bindings for Linux & Windows
-* Native-compatible struct layouts (`TraceOptions`, `TraceResult`)
-* High-level safe API for tracing
-* No need to manually bind delegates
+- Install **RayTraceImpl** as a CS# plugin:
----
+ addons/counterstrikesharp/plugins/RayTraceImpl/RayTraceImpl.dll
+
+- Install **RayTraceApi** as a shared assembly:
+
+ addons/counterstrikesharp/shared/RayTraceApi/RayTraceApi.dll
+
+Then reference `RayTraceApi.dll` in your own plugin project and call the
+API normally.
+
+`public/Example.cs` demonstrates manual binding and struct layout, but
+in production you should rely on the release bridge + shared API.
+
+------------------------------------------------------------------------
## Calling methods from C++ (Metamod)
### TraceShape example
-```cpp
+``` cpp
Vector vecOrigin{};
QAngle angView{};
TraceOptions traceOpts{};
@@ -167,32 +177,46 @@ if (g_pRayTrace && g_bRayTraceLoaded)
}
```
----
+------------------------------------------------------------------------
## Calling methods from C# (CounterStrikeSharp plugin)
-The official managed API is implemented in:
+After installing RayTraceImpl + RayTraceApi from releases:
-```
-public/Example.cs
+1. Add reference in your plugin `.csproj`:
+
+``` xml
+
+
+ libs/RayTraceApi.dll
+
+
```
-### Example usage
+2. Use the API:
-```csharp
-using RayTrace;
+``` csharp
+using RayTraceAPI;
using CounterStrikeSharp.API.Modules.Utils;
+internal static PluginCapability RayTraceInterface { get; } = new("raytrace:craytraceinterface");
+
public void DoTrace(CCSPlayerController player)
{
- Vector origin = player.PlayerPawn.Value!.AbsOrigin;
- QAngle angles = player.PlayerPawn.Value!.EyeAngles;
+ var rayTrace = RayTraceInterface.Get();
+ if (rayTrace == null)
+ return;
- TraceOptions options = new(
- InteractionLayers.MASK_SHOT_PHYSICS
- );
+ var playerPawn = player.PlayerPawn.Value;
+ if (playerPawn == null)
+ return;
- if (CRayTrace.TraceShape(origin, angles, null, options, out TraceResult result))
+ Vector origin = playerPawn.AbsOrigin!;
+ QAngle angles = playerPawn.EyeAngles!;
+
+ TraceOptions options = new();
+
+ if (rayTrace.TraceShape(origin, angles, null, options, out TraceResult result))
{
Console.WriteLine($"Hit fraction: {result.Fraction}");
Console.WriteLine($"EndPos: {result.EndPos}");
@@ -200,7 +224,14 @@ public void DoTrace(CCSPlayerController player)
}
```
----
+The bridge handles:
+
+- Interface lookup via MetaFactory
+- Correct vtable offsets (Linux / Windows)
+- Delegate binding
+- Native struct layout alignment
+
+------------------------------------------------------------------------
## VTable offsets (ABI note)
@@ -211,28 +242,29 @@ Due to C++ ABI differences:
| Linux (Itanium ABI) | 2 | 3 | 4 |
| Windows (MSVC ABI) | 1 | 2 | 3 |
-`public/Example.cs` applies correct offsets by default.
+`public/Example.cs` shows how offsets are applied manually.\
+Release builds handle this automatically inside RayTraceImpl.
----
+------------------------------------------------------------------------
## Notes about ABI & Destructor
-* `CRayTraceInterface` has a virtual destructor.
-* The object is owned by the Ray-Trace Metamod module.
-* Plugins must never call `delete` on the interface pointer.
-* C# must only clear its handle on unload.
-* All parameters are passed as native pointers (`nint`).
+- `CRayTraceInterface` has a virtual destructor.
+- The object is owned by the Ray-Trace Metamod module.
+- Plugins must never call `delete` on the interface pointer.
+- C# must only clear its handle on unload.
+- All parameters are passed as native pointers (`nint`).
----
+------------------------------------------------------------------------
## License
-GPLv3
-[https://www.gnu.org/licenses/gpl-3.0.en.html](https://www.gnu.org/licenses/gpl-3.0.en.html)
+GPLv3\
+https://www.gnu.org/licenses/gpl-3.0.en.html
----
+------------------------------------------------------------------------
## Author
-**Michal "Slynx" Přikryl**
-[https://slynxdev.cz](https://slynxdev.cz)
+**Michal "Slynx" Přikryl**\
+https://slynxdev.cz
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 152fee3..69e726a 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -16,7 +16,11 @@ RUN apt update && apt install -y \
pkg-config \
libcurl4-openssl-dev \
libmaxminddb-dev \
- curl
+ curl \
+ && curl -sSL https://packages.microsoft.com/config/debian/11/packages-microsoft-prod.deb -o packages-microsoft-prod.deb \
+ && dpkg -i packages-microsoft-prod.deb \
+ && rm packages-microsoft-prod.deb \
+ && apt update && apt install -y dotnet-sdk-8.0
RUN git config --system --add safe.directory '*'
diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh
index bdc7cef..d0f3b28 100644
--- a/docker/docker-entrypoint.sh
+++ b/docker/docker-entrypoint.sh
@@ -20,13 +20,13 @@ rm -rf "$SDK_DIR"
mkdir -p "$SDK_DIR"
echo "=== Downloading HL2SDK-CS2 ==="
-git clone --depth=1 -b cs2 https://github.com/alliedmodders/hl2sdk "$HL2SDK_DIR"
+git clone --recursive --branch SlynxCZ/cs2 --single-branch https://github.com/FUNPLAY-pro-CS2/hl2sdk.git "$HL2SDK_DIR"
echo "=== Downloading Metamod-Source ==="
-git clone --depth=1 https://github.com/alliedmodders/metamod-source "$MMSOURCE_DIR"
+git clone --recursive --branch master --single-branch https://github.com/alliedmodders/metamod-source.git "$MMSOURCE_DIR"
echo "=== Downloading Protobufs ==="
-git clone --depth=1 https://github.com/SteamDatabase/Protobufs "$CSGO_PROTO_DIR"
+git clone --recursive https://github.com/SteamDatabase/Protobufs "$CSGO_PROTO_DIR"
### --- Export env vars for CMake ------------------------------------------
export HL2SDKCS2="$HL2SDK_DIR"
@@ -50,4 +50,22 @@ cmake .. \
-DCMAKE_CXX_COMPILER=g++
echo "=== Building with GCC | Release | All ==="
-cmake --build . --config Release -j"$(nproc)"
\ No newline at end of file
+cmake --build . --config Release -j"$(nproc)"
+cd ../
+
+mkdir -p build/addons/counterstrikesharp/plugins
+mkdir -p build/addons/counterstrikesharp/shared/RayTraceApi
+
+dotnet publish managed/RayTrace/RayTraceImpl/RayTraceImpl.csproj \
+ -c Release \
+ -o build/addons/counterstrikesharp/plugins/RayTraceImpl \
+ --no-self-contained \
+ /p:PublishSingleFile=false \
+ /p:CopyLocalLockFileAssemblies=false
+
+dotnet publish managed/RayTrace/RayTraceApi/RayTraceApi.csproj \
+ -c Release \
+ -o build/addons/counterstrikesharp/shared/RayTraceApi \
+ --no-self-contained \
+ /p:PublishSingleFile=false \
+ /p:CopyLocalLockFileAssemblies=false
diff --git a/managed/RayTrace/RayTraceApi.cs b/managed/RayTrace/RayTraceApi/RayTraceApi.cs
similarity index 100%
rename from managed/RayTrace/RayTraceApi.cs
rename to managed/RayTrace/RayTraceApi/RayTraceApi.cs
diff --git a/managed/RayTrace/RayTraceApi.csproj b/managed/RayTrace/RayTraceApi/RayTraceApi.csproj
similarity index 83%
rename from managed/RayTrace/RayTraceApi.csproj
rename to managed/RayTrace/RayTraceApi/RayTraceApi.csproj
index dacee6c..1c6a788 100644
--- a/managed/RayTrace/RayTraceApi.csproj
+++ b/managed/RayTrace/RayTraceApi/RayTraceApi.csproj
@@ -5,6 +5,7 @@
enable
enable
true
+ false
diff --git a/managed/RayTrace/RayTraceImpl.sln b/managed/RayTrace/RayTraceImpl.sln
index b5b4c6c..68b34fa 100644
--- a/managed/RayTrace/RayTraceImpl.sln
+++ b/managed/RayTrace/RayTraceImpl.sln
@@ -1,8 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RayTraceImpl", "RayTraceImpl.csproj", "{0D0FD0C6-A1A6-47A7-8370-29CCE2CD4598}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RayTraceImpl", "RayTraceImpl/RayTraceImpl.csproj", "{0D0FD0C6-A1A6-47A7-8370-29CCE2CD4598}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RayTraceApi", "RayTraceApi.csproj", "{13E6E993-1E09-4B9A-9888-98481E1C3178}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RayTraceApi", "RayTraceApi/RayTraceApi.csproj", "{13E6E993-1E09-4B9A-9888-98481E1C3178}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/managed/RayTrace/RayTraceImpl.cs b/managed/RayTrace/RayTraceImpl/RayTraceImpl.cs
similarity index 99%
rename from managed/RayTrace/RayTraceImpl.cs
rename to managed/RayTrace/RayTraceImpl/RayTraceImpl.cs
index be25a9e..59f003a 100644
--- a/managed/RayTrace/RayTraceImpl.cs
+++ b/managed/RayTrace/RayTraceImpl/RayTraceImpl.cs
@@ -18,7 +18,7 @@ using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Utils;
using RayTraceAPI;
-namespace RayTrace;
+namespace RayTraceImpl;
// ReSharper disable once InconsistentNaming
// ReSharper disable once UnusedType.Global
diff --git a/managed/RayTrace/RayTraceImpl.csproj b/managed/RayTrace/RayTraceImpl/RayTraceImpl.csproj
similarity index 53%
rename from managed/RayTrace/RayTraceImpl.csproj
rename to managed/RayTrace/RayTraceImpl/RayTraceImpl.csproj
index 1360a19..8e22ac7 100644
--- a/managed/RayTrace/RayTraceImpl.csproj
+++ b/managed/RayTrace/RayTraceImpl/RayTraceImpl.csproj
@@ -5,25 +5,15 @@
enable
enable
true
+ false
-
-
- ..\0Harmony.dll
-
-
-
-
-
-
- $(DefineConstants);
- SEMVER="$(SEMVER)";
- GITHUB_SHA_SHORT="$(GITHUB_SHA_SHORT)";
-
-
+
+
+