mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-06 16:06:37 -08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b09c2b62c8 | ||
|
|
31760518ed | ||
|
|
6a160bcc3d | ||
|
|
9c8e9db56e | ||
|
|
e2e0eab87d | ||
|
|
43292bb1d2 | ||
|
|
12c54cd4fc | ||
|
|
e155a70873 |
205
.github/workflows/cmake-single-platform.yml
vendored
205
.github/workflows/cmake-single-platform.yml
vendored
@@ -5,94 +5,193 @@ on:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
branches: [ "main" ]
|
||||
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest
|
||||
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Prepare env
|
||||
shell: bash
|
||||
run: echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup protobuf
|
||||
shell: bash
|
||||
run: sudo apt-get update && sudo apt install -y protobuf-compiler
|
||||
- name: Visual Studio environment
|
||||
shell: cmd
|
||||
run: |
|
||||
:: See https://github.com/microsoft/vswhere/wiki/Find-VC
|
||||
for /f "usebackq delims=*" %%i in (`vswhere -latest -property installationPath`) do (
|
||||
call "%%i"\Common7\Tools\vsdevcmd.bat -arch=x64 -host_arch=x64
|
||||
)
|
||||
|
||||
:: Loop over all environment variables and make them global.
|
||||
for /f "delims== tokens=1,2" %%a in ('set') do (
|
||||
echo>>"%GITHUB_ENV%" %%a=%%b
|
||||
)
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Generate build number
|
||||
id: buildnumber
|
||||
uses: onyxmueller/build-tag-number@v1
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
- run: |
|
||||
dotnet publish -c Release /p:Version=1.0.${{ env.BUILD_NUMBER }} managed/CounterStrikeSharp.API
|
||||
dotnet pack -c Release /p:Version=1.0.${{ env.BUILD_NUMBER }} managed/CounterStrikeSharp.API
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build build --config ${{env.BUILD_TYPE}}
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ..
|
||||
cmake --build . --config ${{env.BUILD_TYPE}} -- /m:16
|
||||
|
||||
- name: Clean build directory
|
||||
run: |
|
||||
mkdir -p build/addons/counterstrikesharp/bin/win64
|
||||
mv build/${{env.BUILD_TYPE}}/*.dll build/addons/counterstrikesharp/bin/win64
|
||||
mkdir build/output/
|
||||
mv build/addons build/output
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: counterstrikesharp-build-windows-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: build/output/
|
||||
|
||||
build_linux:
|
||||
runs-on: ubuntu-latest
|
||||
# Could not figure out how to run in a container only on some matrix paths, so I've split it out into its own build.
|
||||
container:
|
||||
image: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest
|
||||
steps:
|
||||
- name: Prepare env
|
||||
shell: bash
|
||||
run: echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ..
|
||||
cmake --build . --config ${{env.BUILD_TYPE}} -- -j16
|
||||
|
||||
- name: Clean build directory
|
||||
run: |
|
||||
mkdir build/output/
|
||||
mv build/addons build/output
|
||||
|
||||
- name: Add API to Artifacts
|
||||
run: |
|
||||
mkdir -p build/output/addons/counterstrikesharp/api
|
||||
cp -r managed/CounterStrikeSharp.API/bin/Release/net7.0/publish/* build/output/addons/counterstrikesharp/api
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: counterstrikesharp-build-linux-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: build/output/
|
||||
|
||||
build_managed:
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
buildnumber: ${{ steps.buildnumber.outputs.build_number }}
|
||||
steps:
|
||||
- name: Prepare env
|
||||
shell: bash
|
||||
run: echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
|
||||
- name: Fallback build number
|
||||
if: github.event_name == 'pull_request'
|
||||
shell: bash
|
||||
run: echo "BUILD_NUMBER=0" >> $GITHUB_ENV
|
||||
|
||||
# We don't need expensive submodules for the managed side.
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Generate build number
|
||||
if: github.event_name == 'push'
|
||||
id: buildnumber
|
||||
uses: onyxmueller/build-tag-number@v1
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
|
||||
- name: Build runtime v${{ env.BUILD_NUMBER }}
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
- run: |
|
||||
dotnet publish -c Release /p:Version=1.0.${{ env.BUILD_NUMBER }} managed/CounterStrikeSharp.API
|
||||
dotnet pack -c Release /p:Version=1.0.${{ env.BUILD_NUMBER }} managed/CounterStrikeSharp.API
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: counterstrikesharp-build-${{ env.BUILD_NUMBER }}-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: build/output/
|
||||
name: counterstrikesharp-build-api-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: managed/CounterStrikeSharp.API/bin/Release
|
||||
|
||||
- name: Zip CounterStrikeSharp Build
|
||||
run: (cd build/output && zip -qq -r ../../counterstrikesharp-build-${{ env.BUILD_NUMBER }}-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
publish:
|
||||
if: github.event_name == 'push'
|
||||
permissions:
|
||||
contents: write
|
||||
needs: [ "build_linux", "build_windows", "build_managed" ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Prepare env
|
||||
shell: bash
|
||||
run: echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: counterstrikesharp-build-windows-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: build/windows
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: counterstrikesharp-build-linux-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: build/linux
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: counterstrikesharp-build-api-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: build/api
|
||||
|
||||
# TODO: This stuff should really be in a matrix
|
||||
- name: Add API to Artifacts
|
||||
run: |
|
||||
mkdir -p build/linux/addons/counterstrikesharp/api
|
||||
mkdir -p build/windows/addons/counterstrikesharp/api
|
||||
cp -r build/api/net7.0/publish/* build/linux/addons/counterstrikesharp/api
|
||||
cp -r build/api/net7.0/publish/* build/windows/addons/counterstrikesharp/api
|
||||
|
||||
- name: Zip Builds
|
||||
run: |
|
||||
(cd build/linux && zip -qq -r ../../counterstrikesharp-build-${{ needs.build_managed.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
(cd build/windows && zip -qq -r ../../counterstrikesharp-build-${{ needs.build_managed.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
|
||||
- name: Add dotnet runtime
|
||||
run: |
|
||||
mkdir -p build/output/addons/counterstrikesharp/dotnet
|
||||
mkdir -p build/linux/addons/counterstrikesharp/dotnet
|
||||
curl -s -L https://download.visualstudio.microsoft.com/download/pr/dc2c0a53-85a8-4fda-a283-fa28adb5fbe2/8ccade5bc400a5bb40cd9240f003b45c/aspnetcore-runtime-7.0.11-linux-x64.tar.gz \
|
||||
| tar xvz -C build/output/addons/counterstrikesharp/dotnet
|
||||
mv build/output/addons/counterstrikesharp/dotnet/shared/Microsoft.NETCore.App/7.0.11/* build/output/addons/counterstrikesharp/dotnet/shared/Microsoft.NETCore.App/
|
||||
| tar xvz -C build/linux/addons/counterstrikesharp/dotnet
|
||||
mv build/linux/addons/counterstrikesharp/dotnet/shared/Microsoft.NETCore.App/7.0.11/* build/linux/addons/counterstrikesharp/dotnet/shared/Microsoft.NETCore.App/
|
||||
|
||||
mkdir -p build/windows/addons/counterstrikesharp/dotnet
|
||||
curl -s -L https://download.visualstudio.microsoft.com/download/pr/a99861c8-2e00-4587-aaef-60366ca77307/a44ceec2c5d34165ae881600f52edc43/aspnetcore-runtime-7.0.11-win-x64.zip -o dotnet.zip
|
||||
unzip -qq dotnet.zip -d build/windows/addons/counterstrikesharp/dotnet
|
||||
|
||||
- name: Zip CounterStrikeSharp Runtime Build
|
||||
run: (cd build/output && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ env.BUILD_NUMBER }}-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: counterstrikesharp-with-runtime-build-${{ env.BUILD_NUMBER }}-${{ env.GITHUB_SHA_SHORT }}
|
||||
path: build/output/
|
||||
- name: Zip Builds
|
||||
run: |
|
||||
(cd build/linux && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ needs.build_managed.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
(cd build/windows && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ needs.build_managed.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: v${{ env.BUILD_NUMBER }}
|
||||
tag_name: v${{ needs.build_managed.outputs.buildnumber }}
|
||||
files: |
|
||||
counterstrikesharp-build-${{ env.BUILD_NUMBER }}-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-with-runtime-build-${{ env.BUILD_NUMBER }}-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-build-${{ needs.build_managed.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-with-runtime-build-${{ needs.build_managed.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-build-${{ needs.build_managed.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-with-runtime-build-${{ needs.build_managed.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
|
||||
- name: Publish NuGet package
|
||||
run: |
|
||||
dotnet nuget push managed/CounterStrikeSharp.API/bin/Release/CounterStrikeSharp.API.1.0.${{ env.BUILD_NUMBER }}.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
dotnet nuget push managed/CounterStrikeSharp.API/bin/Release/CounterStrikeSharp.API.1.0.${{ env.BUILD_NUMBER }}.snupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
dotnet nuget push build/api/CounterStrikeSharp.API.1.0.${{ needs.build_managed.outputs.buildnumber }}.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
dotnet nuget push build/api/CounterStrikeSharp.API.1.0.${{ needs.build_managed.outputs.buildnumber }}.snupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
53
.github/workflows/pr-checks.yml
vendored
53
.github/workflows/pr-checks.yml
vendored
@@ -1,53 +0,0 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest
|
||||
permissions:
|
||||
pull-requests: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
csharp:
|
||||
- managed/**/*
|
||||
- src/scripting/natives/**/*
|
||||
cpp:
|
||||
- src/**/*
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
if: steps.changes.outputs.csharp == 'true'
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
- if: steps.changes.outputs.csharp == 'true'
|
||||
run: dotnet build -c Release managed/CounterStrikeSharp.API
|
||||
|
||||
- name: Setup protobuf
|
||||
shell: bash
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
run: sudo apt-get update && sudo apt install -y protobuf-compiler
|
||||
|
||||
- name: Configure CMake
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
if: steps.changes.outputs.cpp == 'true'
|
||||
run: cmake --build build --config ${{env.BUILD_TYPE}}
|
||||
64
.github/workflows/win32-test.yml
vendored
64
.github/workflows/win32-test.yml
vendored
@@ -1,64 +0,0 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
branches: [ "win32" ]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
steps:
|
||||
- name: Prepare env
|
||||
shell: bash
|
||||
run: echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
|
||||
- name: Visual Studio environment
|
||||
if: runner.os == 'Windows'
|
||||
shell: cmd
|
||||
run: |
|
||||
:: See https://github.com/microsoft/vswhere/wiki/Find-VC
|
||||
for /f "usebackq delims=*" %%i in (`vswhere -latest -property installationPath`) do (
|
||||
call "%%i"\Common7\Tools\vsdevcmd.bat -arch=x64 -host_arch=x64
|
||||
)
|
||||
|
||||
:: Loop over all environment variables and make them global.
|
||||
for /f "delims== tokens=1,2" %%a in ('set') do (
|
||||
echo>>"%GITHUB_ENV%" %%a=%%b
|
||||
)
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '7.0.x'
|
||||
|
||||
- name: Install Protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
|
||||
- name: Build Linux
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
cd ${{github.workspace}}
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ..
|
||||
cmake --build . --config ${{env.BUILD_TYPE}} -- -j16
|
||||
|
||||
- name: Build Windows
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
cd ${{github.workspace}}
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ..
|
||||
cmake --build . --config ${{env.BUILD_TYPE}} -- /m:16
|
||||
@@ -75,8 +75,6 @@ SET(SOURCE_FILES
|
||||
src/core/managers/entity_manager.h
|
||||
src/core/managers/chat_manager.cpp
|
||||
src/core/managers/chat_manager.h
|
||||
src/core/managers/client_command_manager.cpp
|
||||
src/core/managers/client_command_manager.h
|
||||
src/core/managers/server_manager.cpp
|
||||
src/core/managers/server_manager.h
|
||||
src/scripting/natives/natives_server.cpp
|
||||
|
||||
@@ -47,6 +47,13 @@
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x49\\x89\\xFF\\x41\\x56\\x41\\x55\\x41\\x54\\x4D\\x89\\xC4"
|
||||
}
|
||||
},
|
||||
"CBaseModelEntity_SetModel": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x2A\\x48\\x89\\x7C\\x24\\x2A\\x55\\x48\\x8B\\xEC\\x48\\x83\\xEC\\x50\\x48\\x8B\\xF9",
|
||||
"linux": "\\x55\\x48\\x89\\xF2\\x48\\x89\\xE5\\x41\\x54\\x49\\x89\\xFC\\x48\\x8D\\x7D\\xE0\\x48\\x83\\xEC\\x18\\x48\\x8D\\x05\\xE5\\xD1\\xBF\\x00"
|
||||
}
|
||||
},
|
||||
"CBasePlayerPawn_CommitSuicide": {
|
||||
"offsets": {
|
||||
"windows": 355,
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr AddCommand(string name, string description, bool serveronly, int flags, InputArgument callback){
|
||||
public static void AddCommand(string name, string description, bool serveronly, int flags, InputArgument callback){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
@@ -41,7 +41,6 @@ namespace CounterStrikeSharp.API.Core
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x807C6B9C);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (IntPtr)ScriptContext.GlobalScriptContext.GetResult(typeof(IntPtr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -209,14 +209,10 @@ namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
var wrappedHandler = new Func<int, IntPtr, HookResult>((i, ptr) =>
|
||||
{
|
||||
if (i == -1)
|
||||
{
|
||||
return HookResult.Continue;
|
||||
}
|
||||
var caller = (i != -1) ? new CCSPlayerController(NativeAPI.GetEntityFromIndex(i + 1)) : null;
|
||||
|
||||
var entity = new CCSPlayerController(NativeAPI.GetEntityFromIndex(i + 1));
|
||||
var command = new CommandInfo(ptr, entity);
|
||||
return handler.Invoke(entity.IsValid ? entity : null, command);
|
||||
var command = new CommandInfo(ptr, caller);
|
||||
return handler.Invoke(caller, command);
|
||||
});
|
||||
|
||||
var subscriber = new CallbackSubscriber(handler, wrappedHandler, () => { RemoveCommandListener(name, handler, mode); });
|
||||
|
||||
@@ -31,11 +31,11 @@ namespace CounterStrikeSharp.API.Core
|
||||
/// </summary>
|
||||
internal sealed partial class CoreConfigData
|
||||
{
|
||||
[JsonPropertyName("PublicChatTrigger")] public string PublicChatTrigger { get; internal set; } = "!";
|
||||
|
||||
[JsonPropertyName("SilentChatTrigger")] public string SilentChatTrigger { get; internal set; } = "/";
|
||||
[JsonPropertyName("PublicChatTrigger")] public string PublicChatTrigger { get; set; } = "!";
|
||||
|
||||
[JsonPropertyName("FollowCS2ServerGuidelines")] public bool FollowCS2ServerGuidelines { get; internal set; } = true;
|
||||
[JsonPropertyName("SilentChatTrigger")] public string SilentChatTrigger { get; set; } = "/";
|
||||
|
||||
[JsonPropertyName("FollowCS2ServerGuidelines")] public bool FollowCS2ServerGuidelines { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,12 +103,12 @@ namespace CounterStrikeSharp.API.Core
|
||||
try
|
||||
{
|
||||
var data = JsonSerializer.Deserialize<CoreConfigData>(File.ReadAllText(coreConfigPath), new JsonSerializerOptions() { ReadCommentHandling = JsonCommentHandling.Skip });
|
||||
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
_coreConfig = data;
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine($"Loaded core configuration");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of CounterStrikeSharp.
|
||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
public partial class CBaseModelEntity
|
||||
{
|
||||
public void SetModel(string model)
|
||||
{
|
||||
VirtualFunctions.SetModel(Handle, model);
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,7 @@ public static class VirtualFunctions
|
||||
|
||||
// void(*UTIL_Remove)(CEntityInstance*);
|
||||
public static Action<IntPtr> UTIL_Remove = VirtualFunction.CreateVoid<IntPtr>(GameData.GetSignature("UTIL_Remove"));
|
||||
|
||||
// void(*CBaseModelEntity_SetModel)(CBaseModelEntity*, const char*);
|
||||
public static Action<IntPtr, string> SetModel = VirtualFunction.CreateVoid<IntPtr, string>(GameData.GetSignature("CBaseModelEntity_SetModel"));
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "memory_module.h"
|
||||
#include "interfaces/cs2_interfaces.h"
|
||||
#include "core/managers/entity_manager.h"
|
||||
#include "core/managers/client_command_manager.h"
|
||||
#include "core/managers/server_manager.h"
|
||||
#include <public/game/server/iplayerinfo.h>
|
||||
#include <public/entity2/entitysystem.h>
|
||||
@@ -76,7 +75,6 @@ TimerSystem timerSystem;
|
||||
ConCommandManager conCommandManager;
|
||||
EntityManager entityManager;
|
||||
ChatManager chatManager;
|
||||
ClientCommandManager clientCommandManager;
|
||||
ServerManager serverManager;
|
||||
|
||||
void Initialize() {
|
||||
|
||||
@@ -48,7 +48,6 @@ class ChatCommands;
|
||||
class HookManager;
|
||||
class EntityManager;
|
||||
class ChatManager;
|
||||
class ClientCommandManager;
|
||||
class ServerManager;
|
||||
class CGameConfig;
|
||||
|
||||
@@ -92,7 +91,6 @@ extern EntityManager entityManager;
|
||||
extern TimerSystem timerSystem;
|
||||
extern ChatCommands chatCommands;
|
||||
extern ChatManager chatManager;
|
||||
extern ClientCommandManager clientCommandManager;
|
||||
extern ServerManager serverManager;
|
||||
|
||||
extern HookManager hookManager;
|
||||
|
||||
@@ -39,8 +39,7 @@ ChatManager::~ChatManager() {}
|
||||
void ChatManager::OnAllInitialized()
|
||||
{
|
||||
m_pHostSay = reinterpret_cast<HostSay>(
|
||||
modules::server->FindSignature(globals::gameConfig->GetSignature("Host_Say"))
|
||||
);
|
||||
modules::server->FindSignature(globals::gameConfig->GetSignature("Host_Say")));
|
||||
|
||||
if (m_pHostSay == nullptr) {
|
||||
CSSHARP_CORE_ERROR("Failed to find signature for \'Host_Say\'");
|
||||
@@ -60,30 +59,28 @@ void DetourHostSay(CBaseEntity* pController, CCommand& args, bool teamonly, int
|
||||
CCommand newArgs;
|
||||
newArgs.Tokenize(args.Arg(1));
|
||||
|
||||
if (pController) {
|
||||
auto pEvent = globals::gameEventManager->CreateEvent("player_chat", true);
|
||||
if (pEvent) {
|
||||
pEvent->SetBool("teamonly", teamonly);
|
||||
pEvent->SetInt("userid", pController->GetEntityIndex().Get() - 1);
|
||||
pEvent->SetString("text", args[1]);
|
||||
|
||||
globals::gameEventManager->FireEvent(pEvent, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (*args[1] == '/' || *args[1] == '!') {
|
||||
globals::chatManager.OnSayCommandPost(pController, newArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pHostSay(pController, args, teamonly, unk1, unk2);
|
||||
|
||||
if (pController) {
|
||||
auto pEvent = globals::gameEventManager->CreateEvent("player_chat", true);
|
||||
if (pEvent) {
|
||||
pEvent->SetBool("teamonly", teamonly);
|
||||
pEvent->SetInt("userid", pController->GetEntityIndex().Get());
|
||||
pEvent->SetString("text", args[1]);
|
||||
|
||||
globals::gameEventManager->FireEvent(pEvent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ChatManager::OnSayCommandPre(CBaseEntity* pController, CCommand& command) {
|
||||
return false;
|
||||
}
|
||||
bool ChatManager::OnSayCommandPre(CBaseEntity* pController, CCommand& command) { return false; }
|
||||
|
||||
bool ChatManager::OnSayCommandPost(CBaseEntity* pController, CCommand& command)
|
||||
void ChatManager::OnSayCommandPost(CBaseEntity* pController, CCommand& command)
|
||||
{
|
||||
const char* args = command.ArgS();
|
||||
auto commandStr = command.Arg(0);
|
||||
@@ -91,7 +88,7 @@ bool ChatManager::OnSayCommandPost(CBaseEntity* pController, CCommand& command)
|
||||
return InternalDispatch(pController, commandStr + 1, command);
|
||||
}
|
||||
|
||||
bool ChatManager::InternalDispatch(CBaseEntity* pPlayerController, const char* szTriggerPhase,
|
||||
void ChatManager::InternalDispatch(CBaseEntity* pPlayerController, const char* szTriggerPhase,
|
||||
CCommand& fullCommand)
|
||||
{
|
||||
auto ppArgV = new const char*[fullCommand.ArgC()];
|
||||
@@ -102,26 +99,28 @@ bool ChatManager::InternalDispatch(CBaseEntity* pPlayerController, const char* s
|
||||
|
||||
auto prefixedPhrase = std::string("css_") + szTriggerPhase;
|
||||
|
||||
auto command = globals::conCommandManager.FindCommand(prefixedPhrase.c_str());
|
||||
auto bValidWithPrefix = globals::conCommandManager.IsValidValveCommand(prefixedPhrase.c_str());
|
||||
|
||||
if (command) {
|
||||
if (bValidWithPrefix) {
|
||||
ppArgV[0] = prefixedPhrase.c_str();
|
||||
}
|
||||
|
||||
CCommand commandCopy(fullCommand.ArgC(), ppArgV);
|
||||
|
||||
if (pPlayerController == nullptr) {
|
||||
auto result = globals::conCommandManager.InternalDispatch(CPlayerSlot(-1), &commandCopy);
|
||||
globals::conCommandManager.ExecuteCommandCallbacks(
|
||||
commandCopy.Arg(0), CCommandContext(CommandTarget_t::CT_NO_TARGET, CPlayerSlot(-1)),
|
||||
commandCopy, HookMode::Pre);
|
||||
delete[] ppArgV;
|
||||
return result;
|
||||
return;
|
||||
}
|
||||
|
||||
auto index = pPlayerController->GetEntityIndex().Get();
|
||||
|
||||
auto slot = CPlayerSlot(index - 1);
|
||||
|
||||
auto result = globals::conCommandManager.InternalDispatch(slot, &commandCopy);
|
||||
globals::conCommandManager.ExecuteCommandCallbacks(
|
||||
commandCopy.Arg(0), CCommandContext(CommandTarget_t::CT_NO_TARGET, slot), commandCopy,
|
||||
HookMode::Pre);
|
||||
delete[] ppArgV;
|
||||
return result;
|
||||
}
|
||||
} // namespace counterstrikesharp
|
||||
@@ -53,10 +53,10 @@ class ChatManager : public GlobalClass
|
||||
void OnShutdown() override;
|
||||
|
||||
bool OnSayCommandPre(CBaseEntity* pController, CCommand& args);
|
||||
bool OnSayCommandPost(CBaseEntity* pController, CCommand& args);
|
||||
void OnSayCommandPost(CBaseEntity* pController, CCommand& args);
|
||||
|
||||
private:
|
||||
bool InternalDispatch(CBaseEntity* pPlayerController, const char* szTriggerPhrase,
|
||||
void InternalDispatch(CBaseEntity* pPlayerController, const char* szTriggerPhrase,
|
||||
CCommand& pFullCommand);
|
||||
|
||||
std::vector<ChatCommandInfo*> m_cmd_list;
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
#include "core/managers/client_command_manager.h"
|
||||
|
||||
#include <public/eiface.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "scripting/callback_manager.h"
|
||||
#include "core/log.h"
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
ClientCommandManager::ClientCommandManager() {}
|
||||
|
||||
ClientCommandManager::~ClientCommandManager() {}
|
||||
|
||||
void ClientCommandManager::OnAllInitialized()
|
||||
{
|
||||
m_global_cmd.callback_pre = globals::callbackManager.CreateCallback("OnClientCommandGlobalPre");
|
||||
m_global_cmd.callback_post =
|
||||
globals::callbackManager.CreateCallback("OnClientCommandGlobalPost");
|
||||
}
|
||||
|
||||
void ClientCommandManager::OnShutdown() {}
|
||||
|
||||
bool ClientCommandManager::DispatchClientCommand(CPlayerSlot slot, const char* cmd,
|
||||
const CCommand* args)
|
||||
{
|
||||
CSSHARP_CORE_TRACE("Dispatch client command {}", cmd);
|
||||
auto* p_info = m_cmd_lookup[cmd];
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (m_global_cmd.callback_pre->GetFunctionCount() > 0) {
|
||||
m_global_cmd.callback_pre->ScriptContext().Reset();
|
||||
m_global_cmd.callback_pre->ScriptContext().Push(slot.Get());
|
||||
m_global_cmd.callback_pre->ScriptContext().Push(args);
|
||||
|
||||
for (auto fnMethodToCall : m_global_cmd.callback_pre->GetFunctions()) {
|
||||
if (!fnMethodToCall)
|
||||
continue;
|
||||
fnMethodToCall(&m_global_cmd.callback_pre->ScriptContextStruct());
|
||||
|
||||
auto hookResult = m_global_cmd.callback_pre->ScriptContext().GetResult<HookResult>();
|
||||
CSSHARP_CORE_TRACE("Received hook result from command callback {}:{}", cmd, hookResult);
|
||||
|
||||
if (hookResult >= HookResult::Stop) {
|
||||
return true;
|
||||
} else if (hookResult >= HookResult::Handled) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_info && p_info->callback_pre) {
|
||||
p_info->callback_pre->ScriptContext().Reset();
|
||||
p_info->callback_pre->ScriptContext().Push(slot.Get());
|
||||
p_info->callback_pre->ScriptContext().Push(args);
|
||||
|
||||
for (auto fnMethodToCall : p_info->callback_pre->GetFunctions()) {
|
||||
if (!fnMethodToCall)
|
||||
continue;
|
||||
fnMethodToCall(&p_info->callback_pre->ScriptContextStruct());
|
||||
|
||||
auto hookResult = p_info->callback_pre->ScriptContext().GetResult<HookResult>();
|
||||
CSSHARP_CORE_TRACE("Received hook result from command callback {}:{}", cmd, hookResult);
|
||||
|
||||
if (hookResult >= HookResult::Stop) {
|
||||
return true;
|
||||
} else if (hookResult >= HookResult::Handled) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_global_cmd.callback_post->GetFunctionCount() > 0) {
|
||||
m_global_cmd.callback_post->ScriptContext().Reset();
|
||||
m_global_cmd.callback_post->ScriptContext().Push(slot.Get());
|
||||
m_global_cmd.callback_post->ScriptContext().Push(args);
|
||||
m_global_cmd.callback_post->Execute();
|
||||
}
|
||||
|
||||
if (result && p_info && p_info->callback_post) {
|
||||
p_info->callback_post->ScriptContext().Reset();
|
||||
p_info->callback_post->ScriptContext().Push(slot.Get());
|
||||
p_info->callback_post->ScriptContext().Push(args);
|
||||
p_info->callback_post->Execute();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
void ClientCommandManager::AddCommandListener(const char* cmd, CallbackT callback, bool bPost)
|
||||
{
|
||||
// Handle global command listeners that listen for every ClientCommand.
|
||||
if (cmd == nullptr) {
|
||||
if (bPost) {
|
||||
m_global_cmd.callback_post->AddListener(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
m_global_cmd.callback_pre->AddListener(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* p_info = m_cmd_lookup[std::string(cmd)];
|
||||
|
||||
if (!p_info) {
|
||||
p_info = new ClientCommandInfo();
|
||||
p_info->command = cmd;
|
||||
|
||||
p_info->callback_pre = globals::callbackManager.CreateCallback(cmd);
|
||||
p_info->callback_post = globals::callbackManager.CreateCallback(cmd);
|
||||
|
||||
m_cmd_list.push_back(p_info);
|
||||
m_cmd_lookup[cmd] = p_info;
|
||||
}
|
||||
|
||||
if (bPost) {
|
||||
p_info->callback_post->AddListener(callback);
|
||||
} else {
|
||||
p_info->callback_pre->AddListener(callback);
|
||||
}
|
||||
}
|
||||
void ClientCommandManager::RemoveCommandListener(const char* cmd, CallbackT callback, bool bPost)
|
||||
{
|
||||
if (cmd == nullptr) {
|
||||
if (bPost) {
|
||||
m_global_cmd.callback_post->RemoveListener(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
m_global_cmd.callback_pre->RemoveListener(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* p_info = m_cmd_lookup[std::string(cmd)];
|
||||
|
||||
if (!p_info) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bPost) {
|
||||
p_info->callback_post->RemoveListener(callback);
|
||||
} else {
|
||||
p_info->callback_pre->RemoveListener(callback);
|
||||
}
|
||||
}
|
||||
} // namespace counterstrikesharp
|
||||
@@ -1,45 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "core/globals.h"
|
||||
#include "core/global_listener.h"
|
||||
#include "scripting/script_engine.h"
|
||||
#include <string>
|
||||
#include "playerslot.h"
|
||||
|
||||
namespace counterstrikesharp {
|
||||
class ScriptCallback;
|
||||
|
||||
class ClientCommandInfo {
|
||||
friend class ClientCommandManager;
|
||||
|
||||
public:
|
||||
ClientCommandInfo() {}
|
||||
|
||||
private:
|
||||
std::string command;
|
||||
ScriptCallback* callback_pre;
|
||||
ScriptCallback* callback_post;
|
||||
};
|
||||
|
||||
class ClientCommandManager : public GlobalClass {
|
||||
|
||||
|
||||
public:
|
||||
ClientCommandManager();
|
||||
~ClientCommandManager();
|
||||
void OnAllInitialized() override;
|
||||
void OnShutdown() override;
|
||||
bool DispatchClientCommand(CPlayerSlot slot, const char* cmd, const CCommand* args);
|
||||
void AddCommandListener(const char* cmd, CallbackT callback, bool bPost);
|
||||
void RemoveCommandListener(const char* cmd, CallbackT callback, bool bPost);
|
||||
|
||||
private:
|
||||
std::vector<ClientCommandInfo*> m_cmd_list;
|
||||
std::map<std::string, ClientCommandInfo*> m_cmd_lookup;
|
||||
ClientCommandInfo m_global_cmd;
|
||||
};
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
@@ -157,307 +157,187 @@ CON_COMMAND(dump_schema, "dump schema symbols")
|
||||
output << std::setw(2) << j << std::endl;
|
||||
}
|
||||
|
||||
SH_DECL_HOOK2_void(ConCommandHandle, Dispatch, SH_NOATTRIB, false, const CCommandContext&,
|
||||
const CCommand&);
|
||||
SH_DECL_HOOK3_void(ICvar, DispatchConCommand, SH_NOATTRIB, 0, ConCommandHandle,
|
||||
const CCommandContext&, const CCommand&);
|
||||
|
||||
void ConCommandInfo::HookChange(CallbackT cb, bool post)
|
||||
ConCommandInfo::ConCommandInfo()
|
||||
{
|
||||
if (post) {
|
||||
this->callback_post->AddListener(cb);
|
||||
} else {
|
||||
this->callback_pre->AddListener(cb);
|
||||
}
|
||||
callback_pre = globals::callbackManager.CreateCallback("");
|
||||
callback_post = globals::callbackManager.CreateCallback("");
|
||||
}
|
||||
ConCommandInfo::~ConCommandInfo()
|
||||
{
|
||||
globals::callbackManager.ReleaseCallback(callback_pre);
|
||||
globals::callbackManager.ReleaseCallback(callback_post);
|
||||
}
|
||||
|
||||
void ConCommandInfo::UnhookChange(CallbackT cb, bool post)
|
||||
{
|
||||
if (post) {
|
||||
if (this->callback_post && this->callback_post->GetFunctionCount()) {
|
||||
callback_post->RemoveListener(cb);
|
||||
}
|
||||
} else {
|
||||
if (this->callback_pre && this->callback_pre->GetFunctionCount()) {
|
||||
callback_pre->RemoveListener(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConCommandManager::ConCommandManager() : last_command_client(-1) {}
|
||||
ConCommandManager::ConCommandManager() {}
|
||||
|
||||
ConCommandManager::~ConCommandManager() {}
|
||||
|
||||
void ConCommandManager::OnAllInitialized() {}
|
||||
void ConCommandManager::OnAllInitialized()
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, DispatchConCommand, globals::cvars, this,
|
||||
&ConCommandManager::Hook_DispatchConCommand, false);
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, DispatchConCommand, globals::cvars, this,
|
||||
&ConCommandManager::Hook_DispatchConCommand_Post, true);
|
||||
}
|
||||
|
||||
void ConCommandManager::OnShutdown() {}
|
||||
void ConCommandManager::OnShutdown()
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, DispatchConCommand, globals::cvars, this,
|
||||
&ConCommandManager::Hook_DispatchConCommand, false);
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, DispatchConCommand, globals::cvars, this,
|
||||
&ConCommandManager::Hook_DispatchConCommand_Post, true);
|
||||
}
|
||||
|
||||
void CommandCallback(const CCommandContext& context, const CCommand& command)
|
||||
{
|
||||
bool rval = globals::conCommandManager.InternalDispatch(context.GetPlayerSlot(), &command);
|
||||
|
||||
if (rval) {
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
// This is handled by the global hook
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
void CommandCallback_Post(const CCommandContext& context, const CCommand& command)
|
||||
void ConCommandManager::AddCommandListener(const char* name, CallbackT callback, HookMode mode)
|
||||
{
|
||||
bool rval = globals::conCommandManager.InternalDispatch_Post(context.GetPlayerSlot(), &command);
|
||||
auto strName = std::string(name);
|
||||
ConCommandInfo* pInfo = m_cmd_lookup[strName];
|
||||
|
||||
if (rval) {
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
if (!pInfo) {
|
||||
pInfo = new ConCommandInfo();
|
||||
m_cmd_lookup[strName] = pInfo;
|
||||
|
||||
ConCommandInfo* ConCommandManager::AddOrFindCommand(const char* name, const char* description,
|
||||
bool server_only, int flags)
|
||||
{
|
||||
ConCommandInfo* p_info = m_cmd_lookup[std::string(name)];
|
||||
|
||||
if (!p_info) {
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager] Could not find command in existing lookup {}",
|
||||
name);
|
||||
// auto found = std::find_if(m_cmd_list.begin(), m_cmd_list.end(),
|
||||
// [&](ConCommandInfo* info) {
|
||||
// return V_strcasecmp(info->command->GetName(), name) == 0;
|
||||
// });
|
||||
// if (found != m_cmd_list.end()) {
|
||||
// return *found;
|
||||
// }
|
||||
p_info = new ConCommandInfo();
|
||||
ConCommandHandle existingCommand = globals::cvars->FindCommand(name);
|
||||
ConCommandRefAbstract pointerConCommand;
|
||||
p_info->p_cmd = pointerConCommand;
|
||||
|
||||
if (!existingCommand.IsValid()) {
|
||||
if (!description) {
|
||||
description = "";
|
||||
}
|
||||
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager] Creating new command {}", name);
|
||||
|
||||
char* new_name = strdup(name);
|
||||
char* new_desc = strdup(description);
|
||||
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager] Creating new command {}, {}, {}, {}, {}",
|
||||
(void*)&pointerConCommand, new_name, (void*)CommandCallback,
|
||||
new_desc, flags);
|
||||
|
||||
auto conCommand =
|
||||
new ConCommand(&pointerConCommand, new_name, CommandCallback, new_desc, flags);
|
||||
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager] Creating callbacks for command {}", name);
|
||||
|
||||
p_info->command = conCommand;
|
||||
p_info->callback_pre = globals::callbackManager.CreateCallback(name);
|
||||
p_info->callback_post = globals::callbackManager.CreateCallback(name);
|
||||
p_info->server_only = server_only;
|
||||
|
||||
CSSHARP_CORE_TRACE(
|
||||
"[ConCommandManager] Adding hooks for command callback for command {}", name);
|
||||
|
||||
SH_ADD_HOOK(ConCommandHandle, Dispatch, &pointerConCommand.handle,
|
||||
SH_STATIC(CommandCallback), false);
|
||||
SH_ADD_HOOK(ConCommandHandle, Dispatch, &pointerConCommand.handle,
|
||||
SH_STATIC(CommandCallback_Post), true);
|
||||
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager] Adding command to internal lookup {}", name);
|
||||
|
||||
m_cmd_list.push_back(p_info);
|
||||
m_cmd_lookup[name] = p_info;
|
||||
} else {
|
||||
p_info->callback_pre = globals::callbackManager.CreateCallback(name);
|
||||
p_info->callback_post = globals::callbackManager.CreateCallback(name);
|
||||
p_info->server_only = server_only;
|
||||
ConCommandHandle hExistingCommand = globals::cvars->FindCommand(name);
|
||||
if (hExistingCommand.IsValid()) {
|
||||
pInfo->command = globals::cvars->GetCommand(hExistingCommand);
|
||||
}
|
||||
|
||||
return p_info;
|
||||
}
|
||||
|
||||
return p_info;
|
||||
}
|
||||
|
||||
ConCommandInfo* ConCommandManager::AddCommand(const char* name, const char* description,
|
||||
bool server_only, int flags, CallbackT callback)
|
||||
{
|
||||
ConCommandInfo* p_info = AddOrFindCommand(name, description, server_only, flags);
|
||||
if (!p_info || !p_info->callback_pre) {
|
||||
return nullptr;
|
||||
if (mode == HookMode::Pre) {
|
||||
pInfo->callback_pre->AddListener(callback);
|
||||
} else {
|
||||
pInfo->callback_post->AddListener(callback);
|
||||
}
|
||||
|
||||
p_info->callback_pre->AddListener(callback);
|
||||
|
||||
return p_info;
|
||||
}
|
||||
|
||||
bool ConCommandManager::RemoveCommand(const char* name, CallbackT callback)
|
||||
void ConCommandManager::RemoveCommandListener(const char* name, CallbackT callback, HookMode mode)
|
||||
{
|
||||
auto strName = std::string(strdup(name));
|
||||
ConCommandInfo* p_info = m_cmd_lookup[strName];
|
||||
if (!p_info)
|
||||
auto strName = std::string(name);
|
||||
ConCommandInfo* pInfo = m_cmd_lookup[strName];
|
||||
|
||||
if (!pInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == HookMode::Pre) {
|
||||
pInfo->callback_pre->RemoveListener(callback);
|
||||
} else {
|
||||
pInfo->callback_post->RemoveListener(callback);
|
||||
}
|
||||
}
|
||||
|
||||
bool ConCommandManager::AddValveCommand(const char* name, const char* description, bool server_only,
|
||||
int flags)
|
||||
{
|
||||
ConCommandHandle hExistingCommand = globals::cvars->FindCommand(name);
|
||||
if (hExistingCommand.IsValid())
|
||||
return false;
|
||||
|
||||
if (p_info->callback_pre && p_info->callback_pre->GetFunctionCount()) {
|
||||
p_info->callback_pre->RemoveListener(callback);
|
||||
ConCommandRefAbstract conCommandRefAbstract;
|
||||
auto conCommand =
|
||||
new ConCommand(&conCommandRefAbstract, strdup(name), CommandCallback, strdup(description), flags);
|
||||
|
||||
ConCommandInfo* pInfo = m_cmd_lookup[std::string(name)];
|
||||
|
||||
if (!pInfo) {
|
||||
pInfo = new ConCommandInfo();
|
||||
m_cmd_lookup[std::string(name)] = pInfo;
|
||||
}
|
||||
|
||||
if (p_info->callback_post && p_info->callback_post->GetFunctionCount()) {
|
||||
p_info->callback_post->RemoveListener(callback);
|
||||
}
|
||||
|
||||
if (!p_info->callback_pre || p_info->callback_pre->GetFunctionCount() == 0) {
|
||||
// It does not look like this actually removes the con command.
|
||||
// You can still find with `find` command.
|
||||
globals::cvars->UnregisterConCommand(p_info->p_cmd.handle);
|
||||
}
|
||||
pInfo->p_cmd = conCommandRefAbstract;
|
||||
pInfo->command = conCommand;
|
||||
pInfo->server_only = server_only;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ConCommandInfo* ConCommandManager::FindCommand(const char* name)
|
||||
bool ConCommandManager::RemoveValveCommand(const char* name)
|
||||
{
|
||||
ConCommandInfo* p_info = m_cmd_lookup[std::string(name)];
|
||||
auto hFoundCommand = globals::cvars->FindCommand(name);
|
||||
|
||||
if (p_info == nullptr) {
|
||||
auto found = std::find_if(m_cmd_list.begin(), m_cmd_list.end(), [&](ConCommandInfo* info) {
|
||||
return V_strcasecmp(info->command->GetName(), name) == 0;
|
||||
});
|
||||
if (found != m_cmd_list.end()) {
|
||||
return *found;
|
||||
}
|
||||
|
||||
ConCommandHandle p_cmd = globals::cvars->FindCommand(name);
|
||||
if (!p_cmd.IsValid())
|
||||
return nullptr;
|
||||
|
||||
p_info = new ConCommandInfo();
|
||||
p_info->command = globals::cvars->GetCommand(p_cmd);
|
||||
|
||||
p_info->p_cmd = *p_info->command->GetRef();
|
||||
p_info->callback_pre = globals::callbackManager.CreateCallback(name);
|
||||
p_info->callback_post = globals::callbackManager.CreateCallback(name);
|
||||
p_info->server_only = false;
|
||||
|
||||
m_cmd_list.push_back(p_info);
|
||||
m_cmd_lookup[name] = p_info;
|
||||
|
||||
return p_info;
|
||||
}
|
||||
|
||||
return p_info;
|
||||
}
|
||||
|
||||
int ConCommandManager::GetCommandClient() { return last_command_client; }
|
||||
|
||||
void ConCommandManager::SetCommandClient(int client) { last_command_client = client + 1; }
|
||||
|
||||
bool ConCommandManager::InternalDispatch(CPlayerSlot slot, const CCommand* args)
|
||||
{
|
||||
const char* cmd = args->Arg(0);
|
||||
|
||||
ConCommandInfo* p_info = m_cmd_lookup[cmd];
|
||||
if (p_info == nullptr) {
|
||||
if (slot.Get() == 0 && !globals::engine->IsDedicatedServer())
|
||||
return false;
|
||||
|
||||
for (ConCommandInfo* cmdInfo : m_cmd_list) {
|
||||
if ((cmdInfo != nullptr) && strcasecmp(cmdInfo->command->GetName(), cmd) == 0) {
|
||||
p_info = cmdInfo;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!p_info) {
|
||||
if (!hFoundCommand.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int realClient = slot.Get();
|
||||
globals::cvars->UnregisterConCommand(hFoundCommand);
|
||||
|
||||
bool result = false;
|
||||
if (p_info->callback_pre) {
|
||||
p_info->callback_pre->ScriptContext().Reset();
|
||||
p_info->callback_pre->ScriptContext().SetArgument(0, realClient);
|
||||
p_info->callback_pre->ScriptContext().SetArgument(1, args);
|
||||
p_info->callback_pre->Execute(false);
|
||||
|
||||
result = p_info->callback_pre->ScriptContext().GetResult<bool>();
|
||||
auto pInfo = m_cmd_lookup[std::string(name)];
|
||||
if (!pInfo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return result;
|
||||
pInfo->command = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConCommandManager::InternalDispatch_Post(CPlayerSlot slot, const CCommand* args)
|
||||
HookResult ConCommandManager::ExecuteCommandCallbacks(const char* name, const CCommandContext& ctx,
|
||||
const CCommand& args, HookMode mode)
|
||||
{
|
||||
const char* cmd = args->Arg(0);
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager::ExecuteCommandCallbacks][{}]: {}", mode == Pre ? "Pre" : "Post", name);
|
||||
ConCommandInfo* pInfo = m_cmd_lookup[std::string(name)];
|
||||
if (!pInfo) {
|
||||
return HookResult::Continue;
|
||||
}
|
||||
|
||||
ConCommandInfo* p_info = m_cmd_lookup[cmd];
|
||||
if (p_info == nullptr) {
|
||||
if (slot.Get() == 0 && !globals::engine->IsDedicatedServer())
|
||||
return false;
|
||||
auto pCallback = mode == HookMode::Pre ? pInfo->callback_pre : pInfo->callback_post;
|
||||
|
||||
for (ConCommandInfo* cmdInfo : m_cmd_list) {
|
||||
if ((cmdInfo != nullptr) && strcasecmp(cmdInfo->command->GetName(), cmd) == 0) {
|
||||
p_info = cmdInfo;
|
||||
continue;
|
||||
}
|
||||
pCallback->Reset();
|
||||
pCallback->ScriptContext().Push(ctx.GetPlayerSlot().Get());
|
||||
pCallback->ScriptContext().Push(&args);
|
||||
|
||||
for (auto fnMethodToCall : pCallback->GetFunctions()) {
|
||||
if (!fnMethodToCall)
|
||||
continue;
|
||||
fnMethodToCall(&pCallback->ScriptContextStruct());
|
||||
|
||||
auto result = pCallback->ScriptContext().GetResult<HookResult>();
|
||||
|
||||
if (result >= HookResult::Handled) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
int realClient = slot.Get();
|
||||
|
||||
bool result = false;
|
||||
if (p_info->callback_post) {
|
||||
p_info->callback_post->ScriptContext().Reset();
|
||||
p_info->callback_post->ScriptContext().SetArgument(0, realClient);
|
||||
p_info->callback_post->ScriptContext().SetArgument(1, args);
|
||||
p_info->callback_post->Execute(false);
|
||||
|
||||
result = p_info->callback_post->ScriptContext().GetResult<bool>();
|
||||
}
|
||||
|
||||
return result;
|
||||
return HookResult::Continue;
|
||||
}
|
||||
|
||||
bool ConCommandManager::DispatchClientCommand(CPlayerSlot slot, const char* cmd,
|
||||
const CCommand* args)
|
||||
void ConCommandManager::Hook_DispatchConCommand(ConCommandHandle cmd, const CCommandContext& ctx,
|
||||
const CCommand& args)
|
||||
{
|
||||
ConCommandInfo* p_info = m_cmd_lookup[cmd];
|
||||
if (p_info == nullptr) {
|
||||
auto found =
|
||||
std::find_if(m_cmd_list.begin(), m_cmd_list.end(), [&](const ConCommandInfo* info) {
|
||||
return V_strcasecmp(info->command->GetName(), cmd) == 0;
|
||||
});
|
||||
if (found == m_cmd_list.end()) {
|
||||
return false;
|
||||
}
|
||||
const char* name = args.Arg(0);
|
||||
|
||||
p_info = *found;
|
||||
CSSHARP_CORE_TRACE("[ConCommandManager::Hook_DispatchConCommand]: {}", name);
|
||||
|
||||
auto result = ExecuteCommandCallbacks(name, ctx, args, HookMode::Pre);
|
||||
if (result >= HookResult::Handled) {
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
if (p_info->server_only)
|
||||
return false;
|
||||
|
||||
bool result = false;
|
||||
if (p_info->callback_pre) {
|
||||
p_info->callback_pre->ScriptContext().Reset();
|
||||
p_info->callback_pre->ScriptContext().Push(slot.Get());
|
||||
p_info->callback_pre->ScriptContext().Push(args);
|
||||
p_info->callback_pre->Execute();
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
if (p_info->callback_post) {
|
||||
p_info->callback_post->ScriptContext().Reset();
|
||||
p_info->callback_post->ScriptContext().Push(slot.Get());
|
||||
p_info->callback_post->ScriptContext().Push(args);
|
||||
p_info->callback_post->Execute();
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
void ConCommandManager::Hook_DispatchConCommand_Post(ConCommandHandle cmd,
|
||||
const CCommandContext& ctx,
|
||||
const CCommand& args)
|
||||
{
|
||||
const char* name = args.Arg(0);
|
||||
|
||||
auto result = ExecuteCommandCallbacks(name, ctx, args, HookMode::Post);
|
||||
if (result >= HookResult::Handled) {
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
bool ConCommandManager::IsValidValveCommand(const char* name) {
|
||||
ConCommandHandle pCmd = globals::cvars->FindCommand(name);
|
||||
return pCmd.IsValid();
|
||||
}
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
@@ -40,6 +40,16 @@
|
||||
#include <string>
|
||||
#include "playerslot.h"
|
||||
|
||||
struct CaseInsensitiveComparator {
|
||||
bool operator()(const std::string& lhs, const std::string& rhs) const {
|
||||
return std::lexicographical_compare(
|
||||
lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
[](char a, char b) { return std::tolower(a) < std::tolower(b); }
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
namespace counterstrikesharp {
|
||||
class ScriptCallback;
|
||||
|
||||
@@ -47,7 +57,8 @@ class ConCommandInfo {
|
||||
friend class ConCommandManager;
|
||||
|
||||
public:
|
||||
ConCommandInfo() {}
|
||||
ConCommandInfo();
|
||||
~ConCommandInfo();
|
||||
|
||||
public:
|
||||
void HookChange(CallbackT callback, bool post);
|
||||
@@ -64,39 +75,26 @@ private:
|
||||
|
||||
class ConCommandManager : public GlobalClass {
|
||||
friend class ConCommandInfo;
|
||||
friend void CommandCallback(const CCommand& command);
|
||||
friend void CommandCallback_Post(const CCommand& command);
|
||||
|
||||
public:
|
||||
ConCommandManager();
|
||||
~ConCommandManager();
|
||||
void OnAllInitialized() override;
|
||||
void OnShutdown() override;
|
||||
ConCommandInfo* AddOrFindCommand(const char* name,
|
||||
const char* description,
|
||||
bool server_only,
|
||||
int flags);
|
||||
bool DispatchClientCommand(CPlayerSlot slot, const char* cmd, const CCommand* args);
|
||||
|
||||
bool InternalDispatch(CPlayerSlot slot, const CCommand* args);
|
||||
|
||||
int GetCommandClient();
|
||||
|
||||
bool InternalDispatch_Post(CPlayerSlot slot, const CCommand* args);
|
||||
|
||||
public:
|
||||
ConCommandInfo* AddCommand(
|
||||
const char* name, const char* description, bool server_only, int flags, CallbackT callback);
|
||||
bool RemoveCommand(const char* name, CallbackT callback);
|
||||
ConCommandInfo* FindCommand(const char* name);
|
||||
void AddCommandListener(const char* name, CallbackT callback, HookMode mode);
|
||||
void RemoveCommandListener(const char* name, CallbackT callback, HookMode mode);
|
||||
bool IsValidValveCommand(const char* name);
|
||||
bool AddValveCommand(const char* name, const char* description, bool server_only, int flags);
|
||||
bool RemoveValveCommand(const char* name);
|
||||
void Hook_DispatchConCommand(ConCommandHandle cmd, const CCommandContext& ctx, const CCommand& args);
|
||||
void Hook_DispatchConCommand_Post(ConCommandHandle cmd, const CCommandContext& ctx, const CCommand& args);
|
||||
HookResult ExecuteCommandCallbacks(const char* name, const CCommandContext& ctx,
|
||||
const CCommand& args, HookMode mode);
|
||||
|
||||
private:
|
||||
void SetCommandClient(int client);
|
||||
|
||||
private:
|
||||
int last_command_client;
|
||||
std::vector<ConCommandInfo*> m_cmd_list;
|
||||
std::map<std::string, ConCommandInfo*> m_cmd_lookup;
|
||||
std::map<std::string, ConCommandInfo*, CaseInsensitiveComparator> m_cmd_lookup;
|
||||
};
|
||||
|
||||
} // namespace counterstrikesharp
|
||||
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include "core/managers/player_manager.h"
|
||||
#include "core/managers/client_command_manager.h"
|
||||
#include "core/managers/con_command_manager.h"
|
||||
|
||||
#include <public/eiface.h>
|
||||
#include <public/inetchannelinfo.h>
|
||||
@@ -287,8 +287,10 @@ void PlayerManager::OnClientCommand(CPlayerSlot slot, const CCommand& args) cons
|
||||
|
||||
const char* cmd = args.Arg(0);
|
||||
|
||||
bool response = globals::clientCommandManager.DispatchClientCommand(slot, cmd, &args);
|
||||
if (response) {
|
||||
auto result = globals::conCommandManager.ExecuteCommandCallbacks(
|
||||
cmd, CCommandContext(CommandTarget_t::CT_NO_TARGET, slot), args, HookMode::Pre);
|
||||
|
||||
if (result >= HookResult::Handled) {
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include <eiface.h>
|
||||
|
||||
#include "core/managers/client_command_manager.h"
|
||||
#include "scripting/autonative.h"
|
||||
#include "scripting/callback_manager.h"
|
||||
#include "core/managers/con_command_manager.h"
|
||||
@@ -26,7 +25,7 @@
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
static ConCommandInfo* AddCommand(ScriptContext& script_context)
|
||||
static void AddCommand(ScriptContext& script_context)
|
||||
{
|
||||
auto name = script_context.GetArgument<const char*>(0);
|
||||
auto description = script_context.GetArgument<const char*>(1);
|
||||
@@ -37,7 +36,8 @@ static ConCommandInfo* AddCommand(ScriptContext& script_context)
|
||||
CSSHARP_CORE_TRACE("Adding command {}, {}, {}, {}, {}", name, description, server_only, flags,
|
||||
(void*)callback);
|
||||
|
||||
return globals::conCommandManager.AddCommand(name, description, server_only, flags, callback);
|
||||
globals::conCommandManager.AddValveCommand(name, description, server_only, flags);
|
||||
globals::conCommandManager.AddCommandListener(name, callback, HookMode::Pre);
|
||||
}
|
||||
|
||||
static void RemoveCommand(ScriptContext& script_context)
|
||||
@@ -45,7 +45,8 @@ static void RemoveCommand(ScriptContext& script_context)
|
||||
auto name = script_context.GetArgument<const char*>(0);
|
||||
auto callback = script_context.GetArgument<CallbackT>(1);
|
||||
|
||||
globals::conCommandManager.RemoveCommand(name, callback);
|
||||
globals::conCommandManager.RemoveCommandListener(name, callback, HookMode::Pre);
|
||||
globals::conCommandManager.RemoveValveCommand(name);
|
||||
}
|
||||
|
||||
static void AddCommandListener(ScriptContext& script_context)
|
||||
@@ -54,7 +55,7 @@ static void AddCommandListener(ScriptContext& script_context)
|
||||
auto callback = script_context.GetArgument<CallbackT>(1);
|
||||
auto post = script_context.GetArgument<bool>(2);
|
||||
|
||||
globals::clientCommandManager.AddCommandListener(name, callback, post);
|
||||
globals::conCommandManager.AddCommandListener(name, callback, post ? HookMode::Post : HookMode::Pre);
|
||||
}
|
||||
|
||||
static void RemoveCommandListener(ScriptContext& script_context)
|
||||
@@ -63,7 +64,7 @@ static void RemoveCommandListener(ScriptContext& script_context)
|
||||
auto callback = script_context.GetArgument<CallbackT>(1);
|
||||
auto post = script_context.GetArgument<bool>(2);
|
||||
|
||||
globals::clientCommandManager.RemoveCommandListener(name, callback, post);
|
||||
globals::conCommandManager.RemoveCommandListener(name, callback, post ? HookMode::Post : HookMode::Pre);
|
||||
}
|
||||
|
||||
static int CommandGetArgCount(ScriptContext& script_context)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ADD_COMMAND: name:string,description:string,serverOnly:bool,flags:int,callback:callback -> pointer
|
||||
ADD_COMMAND: name:string,description:string,serverOnly:bool,flags:int,callback:callback -> void
|
||||
REMOVE_COMMAND: name:string,callback:callback -> void
|
||||
ADD_COMMAND_LISTENER: cmd:string, callback:callback, post:bool -> void
|
||||
REMOVE_COMMAND_LISTENER: cmd:string, callback:callback, post:bool -> void
|
||||
|
||||
@@ -40,6 +40,11 @@ enum HookResult {
|
||||
Stop = 4,
|
||||
};
|
||||
|
||||
enum HookMode {
|
||||
Pre = 0,
|
||||
Post = 1,
|
||||
};
|
||||
|
||||
inline uint32_t hash_string(const char *string) {
|
||||
unsigned long result = 5381;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user