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)"; - - + + +