mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-06 08:03:12 -08:00
Compare commits
138 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cf124bfb6 | ||
|
|
1f904a52a7 | ||
|
|
32c99b2e49 | ||
|
|
5c9d38b2b0 | ||
|
|
b54f5c3dee | ||
|
|
761380dff6 | ||
|
|
71ae253e5e | ||
|
|
c2f212df51 | ||
|
|
ad7f7bd365 | ||
|
|
a0fcb7817e | ||
|
|
cdb7a6ed17 | ||
|
|
38e29531c3 | ||
|
|
5f95969980 | ||
|
|
42dd270b78 | ||
|
|
b807c3eda8 | ||
|
|
3ede4c366c | ||
|
|
49cc91e373 | ||
|
|
8a795de9fa | ||
|
|
e36d2e07e4 | ||
|
|
cdd2a8275e | ||
|
|
2b31f519eb | ||
|
|
2c7f896189 | ||
|
|
5a354a25e3 | ||
|
|
74ce0d295a | ||
|
|
9c8f25f721 | ||
|
|
4b1a2c427e | ||
|
|
8f59fd5b97 | ||
|
|
cbeac50e4a | ||
|
|
eba7d9c313 | ||
|
|
23828153eb | ||
|
|
0e3698b370 | ||
|
|
bb38b1cb1a | ||
|
|
10f472ec85 | ||
|
|
28ce183cdc | ||
|
|
dddf24d0f3 | ||
|
|
fce68cb160 | ||
|
|
a82faeb5c8 | ||
|
|
ce3ff449b9 | ||
|
|
aa40d81a86 | ||
|
|
5644921873 | ||
|
|
3860ca1662 | ||
|
|
b79fd19c85 | ||
|
|
b7ea025b03 | ||
|
|
5ac173df51 | ||
|
|
c82a58f5ab | ||
|
|
1806919559 | ||
|
|
f8451c2818 | ||
|
|
a87bd25b48 | ||
|
|
9c5468e5ba | ||
|
|
f826be664f | ||
|
|
7f5103d9ee | ||
|
|
877b7c5a4a | ||
|
|
24363d6352 | ||
|
|
2eaf7c2d8c | ||
|
|
8b486ecf7e | ||
|
|
54cc93e0f8 | ||
|
|
a695eec4fa | ||
|
|
e207be2fbf | ||
|
|
eea64519a6 | ||
|
|
13ec19e412 | ||
|
|
3240a5e582 | ||
|
|
cafc4e237f | ||
|
|
02d5191e74 | ||
|
|
aec696abc0 | ||
|
|
c01aeec14b | ||
|
|
41e7bee85a | ||
|
|
9834271956 | ||
|
|
fb5967d102 | ||
|
|
928bc3f74d | ||
|
|
6a7d7dba4f | ||
|
|
11e5e9972d | ||
|
|
9a221b4ebb | ||
|
|
e270bdfd44 | ||
|
|
f591fe58d0 | ||
|
|
052cb4e14e | ||
|
|
bc3bec4aa8 | ||
|
|
20bab7f4a8 | ||
|
|
c7eac71109 | ||
|
|
e3d2370e2e | ||
|
|
142242744c | ||
|
|
0eebffd860 | ||
|
|
25ca5dbe0c | ||
|
|
7cae4be96d | ||
|
|
83bc1a95fb | ||
|
|
71c694b52e | ||
|
|
a452d79ba3 | ||
|
|
dfc9859806 | ||
|
|
f99f58402a | ||
|
|
6317559bd2 | ||
|
|
ad6e1ca2e2 | ||
|
|
2564ef9f39 | ||
|
|
83a341d3cf | ||
|
|
534fc42444 | ||
|
|
41355d05fa | ||
|
|
d9da15be83 | ||
|
|
75e2f6e8aa | ||
|
|
37b34e1d41 | ||
|
|
5ce04649fd | ||
|
|
7b7202fe8a | ||
|
|
cadb817ed2 | ||
|
|
211516cce5 | ||
|
|
ab211a42e6 | ||
|
|
696ecadee4 | ||
|
|
e4d598dba8 | ||
|
|
5c67d88844 | ||
|
|
9d8b6beae6 | ||
|
|
39604b7ad7 | ||
|
|
1b1f1d04dd | ||
|
|
dbc348c1bf | ||
|
|
d295589c44 | ||
|
|
16767fd494 | ||
|
|
36a97bfffd | ||
|
|
178f7472c6 | ||
|
|
cba5144bbf | ||
|
|
0de951cb6f | ||
|
|
c3d44a87bc | ||
|
|
bd3c0c76e3 | ||
|
|
656c0e3a84 | ||
|
|
40c842149c | ||
|
|
64d1c0a9f4 | ||
|
|
a6de51c444 | ||
|
|
2535ac0575 | ||
|
|
bc61323315 | ||
|
|
241817b7f2 | ||
|
|
fbcdce34fc | ||
|
|
daf0d25f36 | ||
|
|
12485be29f | ||
|
|
983d91491d | ||
|
|
71507b1e25 | ||
|
|
cfe14b35fe | ||
|
|
5a6cdf0da3 | ||
|
|
a5399dd5fe | ||
|
|
ab996c34e9 | ||
|
|
6e2e25b96e | ||
|
|
1142c9f063 | ||
|
|
72178c9598 | ||
|
|
7617bd1556 | ||
|
|
501d51a668 |
@@ -1,21 +1,72 @@
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
# Spacing
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 100
|
||||
UseTab: Never
|
||||
ColumnLimit: 140
|
||||
|
||||
# Line Endings
|
||||
LineEnding: LF
|
||||
InsertNewlineAtEOF: true
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
|
||||
AlignAfterOpenBracket: Align
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
SortIncludes: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
IndentCaseLabels: false
|
||||
IndentCaseLabels: true
|
||||
|
||||
# Line Breaks
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterStruct: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterUnion: true
|
||||
AfterNamespace: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
|
||||
PointerAlignment: Left
|
||||
SortIncludes: CaseSensitive
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
# External headers in <> with extension or /
|
||||
- Regex: '<[-\w\/-_]+[\.\/][-\w\/-_]+>'
|
||||
Priority: 2
|
||||
# Standard headers in <>
|
||||
- Regex: '<[-\w\/-_]+>'
|
||||
Priority: 3
|
||||
# Local headers in ""
|
||||
- Regex: '"[-\w\/-_]*"'
|
||||
Priority: 4
|
||||
|
||||
ReflowComments: true
|
||||
CompactNamespaces: false
|
||||
Cpp11BracedListStyle: false
|
||||
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
|
||||
AlignEscapedNewlines: Left
|
||||
AlignTrailingComments: Never
|
||||
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: OnlyFirstIf
|
||||
AllowShortLambdasOnASingleLine: Empty
|
||||
BinPackArguments: true
|
||||
BinPackParameters: false
|
||||
|
||||
LambdaBodyIndentation: OuterScope
|
||||
|
||||
11
.devcontainer/linux/devcontainer.json
Normal file
11
.devcontainer/linux/devcontainer.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "SteamRT Sniper SDK",
|
||||
"image": "registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
14
.editorconfig
Normal file
14
.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
max_line_length = 140
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.json,*.yaml,*.yml}]
|
||||
indent_size = 2
|
||||
13
.github/dependabot.yaml
vendored
Normal file
13
.github/dependabot.yaml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Update the submodule in libraries/hl2sdk-cs2 every day
|
||||
- package-ecosystem: "gitsubmodule"
|
||||
directory: "/"
|
||||
allow:
|
||||
- dependency-name: "libraries/hl2sdk-cs2"
|
||||
- dependency-name: "libraries/metamod-source"
|
||||
- dependency-name: "libraries/Protobufs"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
commit-message:
|
||||
prefix: "chore(deps)"
|
||||
21
.github/workflows/actionlint.yaml
vendored
Normal file
21
.github/workflows/actionlint.yaml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: actionlint
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
paths:
|
||||
- ".github/actions/**"
|
||||
- ".github/workflows/**"
|
||||
|
||||
jobs:
|
||||
actionlint:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: actionlint
|
||||
uses: reviewdog/action-actionlint@v1
|
||||
with:
|
||||
reporter: github-pr-review
|
||||
fail_on_error: true
|
||||
99
.github/workflows/cmake-single-platform.yml
vendored
99
.github/workflows/cmake-single-platform.yml
vendored
@@ -3,22 +3,46 @@ name: Build & Publish
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docfx/**'
|
||||
branches: [ "main", "dev" ]
|
||||
- "docfx/**"
|
||||
branches: ["main", "dev"]
|
||||
pull_request:
|
||||
branches: [ "main", "dev" ]
|
||||
branches: ["main", "dev"]
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
buildnumber: ${{ steps.buildnumber.outputs.build_number }}
|
||||
steps:
|
||||
- name: Generate build number
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
id: buildnumber
|
||||
uses: onyxmueller/build-tag-number@v1
|
||||
with:
|
||||
token: ${{secrets.github_token}}
|
||||
|
||||
build_windows:
|
||||
needs: setup
|
||||
runs-on: windows-latest
|
||||
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' || github.ref != 'refs/heads/main' }}
|
||||
shell: bash
|
||||
run: echo "BUILD_NUMBER=0" >> $GITHUB_ENV
|
||||
|
||||
- name: Main build number
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
run: echo "BUILD_NUMBER=${{ needs.setup.outputs.buildnumber }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Visual Studio environment
|
||||
shell: cmd
|
||||
run: |
|
||||
@@ -34,7 +58,7 @@ jobs:
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
submodules: "recursive"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -56,6 +80,7 @@ jobs:
|
||||
path: build/output/
|
||||
|
||||
build_linux:
|
||||
needs: setup
|
||||
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:
|
||||
@@ -65,9 +90,18 @@ jobs:
|
||||
shell: bash
|
||||
run: echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
||||
|
||||
- name: Fallback build number
|
||||
if: ${{ github.event_name == 'pull_request' || github.ref != 'refs/heads/main' }}
|
||||
shell: bash
|
||||
run: echo "BUILD_NUMBER=0" >> $GITHUB_ENV
|
||||
|
||||
- name: Main build number
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
run: echo "BUILD_NUMBER=${{ needs.setup.outputs.buildnumber }}" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
submodules: "recursive"
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -87,11 +121,10 @@ jobs:
|
||||
path: build/output/
|
||||
|
||||
build_managed:
|
||||
needs: setup
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
buildnumber: ${{ steps.buildnumber.outputs.build_number }}
|
||||
steps:
|
||||
- name: Prepare env
|
||||
shell: bash
|
||||
@@ -102,20 +135,17 @@ jobs:
|
||||
shell: bash
|
||||
run: echo "BUILD_NUMBER=0" >> $GITHUB_ENV
|
||||
|
||||
- name: Main build number
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
run: echo "BUILD_NUMBER=${{ needs.setup.outputs.buildnumber }}" >> $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' && github.ref == 'refs/heads/main' }}
|
||||
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'
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Install dependencies
|
||||
run: dotnet restore managed/CounterStrikeSharp.sln
|
||||
@@ -133,7 +163,7 @@ jobs:
|
||||
- name: Publish artifacts
|
||||
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
|
||||
dotnet pack -c Release /p:Version=1.0.${{ env.BUILD_NUMBER }} managed/CounterStrikeSharp.API
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -144,7 +174,7 @@ jobs:
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
permissions:
|
||||
contents: write
|
||||
needs: [ "build_linux", "build_windows", "build_managed" ]
|
||||
needs: ["setup", "build_linux", "build_windows", "build_managed"]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Prepare env
|
||||
@@ -171,49 +201,48 @@ jobs:
|
||||
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
|
||||
cp -r build/api/net8.0/publish/* build/linux/addons/counterstrikesharp/api
|
||||
cp -r build/api/net8.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 *)
|
||||
(cd build/linux && zip -qq -r ../../counterstrikesharp-build-${{ needs.setup.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
(cd build/windows && zip -qq -r ../../counterstrikesharp-build-${{ needs.setup.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
|
||||
- name: Add dotnet runtime
|
||||
run: |
|
||||
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 \
|
||||
curl -s -L https://download.visualstudio.microsoft.com/download/pr/c1371dc2-eed2-47be-9af3-ae060dbe3c7d/bd509e0a87629764ed47608466d183e6/aspnetcore-runtime-8.0.3-linux-x64.tar.gz \
|
||||
| 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
|
||||
curl -s -L https://download.visualstudio.microsoft.com/download/pr/086d1dd6-57a5-437a-a1ef-549cf702fb48/dd4a8fe6c53a1016a414d6f2925c1323/aspnetcore-runtime-8.0.3-win-x64.zip -o dotnet.zip
|
||||
unzip -qq dotnet.zip -d build/windows/addons/counterstrikesharp/dotnet
|
||||
|
||||
- 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 *)
|
||||
(cd build/linux && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ needs.setup.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
(cd build/windows && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ needs.setup.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||
|
||||
- name: Release
|
||||
id: release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: v${{ needs.build_managed.outputs.buildnumber }}
|
||||
tag_name: v${{ needs.setup.outputs.buildnumber }}
|
||||
files: |
|
||||
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
|
||||
counterstrikesharp-build-${{ needs.setup.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-with-runtime-build-${{ needs.setup.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-build-${{ needs.setup.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
counterstrikesharp-with-runtime-build-${{ needs.setup.outputs.buildnumber }}-linux-${{ env.GITHUB_SHA_SHORT }}.zip
|
||||
|
||||
- name: Publish NuGet package
|
||||
run: |
|
||||
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
|
||||
dotnet nuget push build/api/CounterStrikeSharp.API.1.0.${{ needs.setup.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.setup.outputs.buildnumber }}.snupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
|
||||
- name: Send Notification to Discord
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
uses: Ilshidur/action-discord@0.3.2
|
||||
with:
|
||||
args: "A new release of CS# has been tagged (v${{ needs.build_managed.outputs.buildnumber }}) at ${{ steps.release.outputs.url }}"
|
||||
args: "A new release of CS# has been tagged (v${{ needs.setup.outputs.buildnumber }}) at ${{ steps.release.outputs.url }}"
|
||||
|
||||
20
.github/workflows/issues-triage-removal.yml
vendored
Normal file
20
.github/workflows/issues-triage-removal.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Label new issues
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- milestoned
|
||||
|
||||
jobs:
|
||||
label_issues:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Remove label
|
||||
run: gh issue edit "$NUMBER" --remove-label "$LABELS"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
LABELS: untriaged
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,9 +1,9 @@
|
||||
.ccls-cache/
|
||||
.cmake/
|
||||
cmake-build-debug*/
|
||||
cmake-build-*/
|
||||
.kdev4/
|
||||
.vscode/
|
||||
generated/
|
||||
!**/protobuf/generated/
|
||||
|
||||
# configure_file auto generated.
|
||||
configs/addons/metamod/counterstrikesharp.vdf
|
||||
@@ -12,6 +12,7 @@ libraries/mono/
|
||||
|
||||
CMakeSettings.json
|
||||
|
||||
build-*/
|
||||
build/
|
||||
build_test/
|
||||
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -14,12 +14,12 @@
|
||||
[submodule "libraries/dyncall"]
|
||||
path = libraries/dyncall
|
||||
url = https://github.com/LWJGL-CI/dyncall
|
||||
[submodule "libraries/GameTracking-CS2"]
|
||||
path = libraries/GameTracking-CS2
|
||||
url = https://github.com/SteamDatabase/GameTracking-CS2
|
||||
[submodule "libraries/DynoHook"]
|
||||
path = libraries/DynoHook
|
||||
url = https://github.com/qubka/DynoHook
|
||||
[submodule "libraries/asmjit"]
|
||||
path = libraries/asmjit
|
||||
url = https://github.com/asmjit/asmjit
|
||||
[submodule "libraries/Protobufs"]
|
||||
path = libraries/Protobufs
|
||||
url = https://github.com/SteamDatabase/Protobufs
|
||||
|
||||
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"editor.defaultFormatter": null,
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
@@ -5,6 +5,8 @@ project(counterstrikesharp C CXX ASM)
|
||||
|
||||
include("makefiles/shared.cmake")
|
||||
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
add_subdirectory(libraries/spdlog)
|
||||
add_subdirectory(libraries/dyncall)
|
||||
add_subdirectory(libraries/funchook)
|
||||
@@ -13,7 +15,10 @@ add_subdirectory(libraries/DynoHook)
|
||||
set_property(TARGET dynohook PROPERTY DYNO_ARCH_X86 64)
|
||||
set_property(TARGET funchook-static PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
SET(SOURCE_FILES
|
||||
include("makefiles/protobuf.cmake")
|
||||
|
||||
set(SOURCE_FILES
|
||||
libraries/hl2sdk-cs2/public/tier0/memoverride.cpp
|
||||
src/mm_plugin.cpp
|
||||
src/mm_plugin.h
|
||||
libraries/hl2sdk-cs2/tier1/convar.cpp
|
||||
@@ -49,10 +54,10 @@ SET(SOURCE_FILES
|
||||
src/core/managers/event_manager.cpp
|
||||
src/core/timer_system.h
|
||||
src/core/timer_system.cpp
|
||||
src/core/tick_scheduler.h
|
||||
src/core/tick_scheduler.cpp
|
||||
src/scripting/autonative.h
|
||||
src/scripting/natives/natives_engine.cpp
|
||||
src/core/engine_trace.h
|
||||
src/core/engine_trace.cpp
|
||||
src/scripting/natives/natives_callbacks.cpp
|
||||
src/core/managers/player_manager.h
|
||||
src/core/managers/player_manager.cpp
|
||||
@@ -68,7 +73,6 @@ SET(SOURCE_FILES
|
||||
src/core/memory_module.h
|
||||
src/core/memory_module.cpp
|
||||
src/core/cs2_sdk/interfaces/cgameresourceserviceserver.h
|
||||
src/core/cs2_sdk/interfaces/cschemasystem.h
|
||||
src/core/cs2_sdk/interfaces/cs2_interfaces.h
|
||||
src/core/cs2_sdk/interfaces/cs2_interfaces.cpp
|
||||
src/core/cs2_sdk/schema.h
|
||||
@@ -86,72 +90,48 @@ SET(SOURCE_FILES
|
||||
src/core/managers/server_manager.cpp
|
||||
src/core/managers/server_manager.h
|
||||
src/scripting/natives/natives_server.cpp
|
||||
src/scripting/natives/natives_usermessages.cpp
|
||||
libraries/nlohmann/json.hpp
|
||||
src/core/managers/voice_manager.cpp
|
||||
src/core/managers/voice_manager.h
|
||||
src/core/managers/usermessage_manager.cpp
|
||||
src/core/managers/usermessage_manager.h
|
||||
src/scripting/natives/natives_dynamichooks.cpp
|
||||
src/core/game_system.h
|
||||
src/core/game_system.cpp
|
||||
src/core/UserMessage.h
|
||||
src/core/UserMessage.cpp
|
||||
src/core/recipientfilters.h
|
||||
)
|
||||
|
||||
|
||||
if (LINUX)
|
||||
# memoverride.cpp is not usable on CMake Windows, cuz CMake default link libraries (seems) always link ucrt.lib
|
||||
set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
libraries/hl2sdk-cs2/public/tier0/memoverride.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(PROTO_DIRS -I${CMAKE_CURRENT_SOURCE_DIR}/libraries/GameTracking-CS2/Protobufs)
|
||||
file(GLOB PROTOS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/GameTracking-CS2/Protobufs/*.proto")
|
||||
|
||||
## Generate protobuf source & headers
|
||||
if (LINUX)
|
||||
set(PROTOC_EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/libraries/hl2sdk-cs2/devtools/bin/linux/protoc)
|
||||
elseif(WIN32)
|
||||
set(PROTOC_EXECUTABLE ${CMAKE_CURRENT_SOURCE_DIR}/libraries/hl2sdk-cs2/devtools/bin/protoc.exe)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT protobuf_output_stamp
|
||||
COMMAND ${PROTOC_EXECUTABLE} --proto_path=thirdparty/protobuf-3.21.8/src --proto_path=common --cpp_out=common common/network_connection.proto
|
||||
COMMENT "Generating protobuf file"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libraries/hl2sdk-cs2
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
SET(SOURCE_FILES ${SOURCE_FILES} protobuf_output_stamp)
|
||||
|
||||
# Sources
|
||||
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${NATIVES_SOURCES} ${CONVERSIONS_SOURCES} ${CONVERSIONS_HEADERS})
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/core/cs2_sdk
|
||||
${PROJECT_NAME}
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/core/cs2_sdk
|
||||
)
|
||||
|
||||
if (LINUX)
|
||||
if(LINUX)
|
||||
include("makefiles/linux.base.cmake")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
PREFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/addons/counterstrikesharp/bin/linuxsteamrt64"
|
||||
PREFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/addons/counterstrikesharp/bin/linuxsteamrt64"
|
||||
)
|
||||
elseif(WIN32)
|
||||
include("makefiles/windows.base.cmake")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
PREFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/addons/counterstrikesharp/bin/win64"
|
||||
PREFIX ""
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/addons/counterstrikesharp/bin/win64"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# Libraries
|
||||
target_link_libraries(${PROJECT_NAME} ${COUNTER_STRIKE_SHARP_LINK_LIBRARIES})
|
||||
target_link_libraries(${PROJECT_NAME} ${COUNTER_STRIKE_SHARP_LINK_LIBRARIES} Protobufs)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${PROJECT_NAME} PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/configs ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
TARGET ${PROJECT_NAME} PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${CMAKE_SOURCE_DIR}/configs ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
103
CONTRIBUTING.md
Normal file
103
CONTRIBUTING.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Contributing to CounterStrikeSharp
|
||||
|
||||
We'd love for you to contribute to CS# to make it better than it is today!
|
||||
|
||||
Here are the guidelines we'd like you to follow:
|
||||
|
||||
- [Question or Problem?](#question)
|
||||
- [Issues and Bugs](#issue)
|
||||
- [Submission Guidelines](#submit)
|
||||
- [Coding Format](#format)
|
||||
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
If you have questions about how to contribute to CounterStrikeSharp, please join our [Discord][discord] server.
|
||||
|
||||
## <a name="issue"></a> Found an Issue?
|
||||
|
||||
If you find a bug in the source code or a mistake in the documentation, you can help us by
|
||||
submitting an issue to our [GitHub Repository][github]. Even better you can submit a Pull Request
|
||||
with a fix.
|
||||
|
||||
**Please see the [Submission Guidelines](#submit) below.**
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
### Submitting an Issue
|
||||
Before you submit your issue please search the archive, maybe your question was already answered.
|
||||
|
||||
If your issue appears to be a bug and hasn't been reported, open a new issue. Help us to maximize
|
||||
the effort we can spend fixing issues and adding new features, by not reporting duplicate issues.
|
||||
Providing the following information will increase the chances of your issue being dealt with
|
||||
quickly:
|
||||
|
||||
* **Overview of the Issue** - if an error is being thrown a stack trace helps
|
||||
* **Operating System** - is this a problem with a specific OS (Windows or Linux)?
|
||||
* **Reproduce the Error** - provide details, if possible, on how to reproduce the error
|
||||
* **Related Issues** - has a similar issue been reported before?
|
||||
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be causing the problem (line of code or commit)
|
||||
|
||||
### Submitting a Pull Request
|
||||
Before you submit your pull request consider the following guidelines:
|
||||
|
||||
* Search [GitHub](https://github.com/roflmuffin/CounterStrikeSharp/pulls) for an open or closed Pull Request
|
||||
that relates to your submission. You don't want to duplicate effort.
|
||||
* If adding a feature or enhancement, we recommend you first [start a discussion for
|
||||
it](https://github.com/roflmuffin/CounterStrikeSharp/discussions) before submitting a Pull Request.
|
||||
* [Fork](https://help.github.com/articles/fork-a-repo/) this repo.
|
||||
* [Clone](https://help.github.com/articles/cloning-a-repository/) your copy.
|
||||
```shell
|
||||
git clone https://github.com/YOUR_USERNAME/CounterStrikeSharp.git
|
||||
cd CounterStrikeSharp/
|
||||
```
|
||||
* After cloning, set a new remote [upstream](https://help.github.com/articles/configuring-a-remote-for-a-fork/) (this helps to keep your fork up to date)
|
||||
|
||||
```shell
|
||||
git remote add upstream https://github.com/roflmuffin/CounterStrikeSharp.git
|
||||
```
|
||||
|
||||
* Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
* Create your patch and run appropriate tests.
|
||||
* Commit your changes using a descriptive commit message that uses the imperative, present tense: "change" not "changed" nor "changes".
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
* Push your branch to GitHub:
|
||||
|
||||
```shell
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
In GitHub, send a pull request to `CounterStrikeSharp:master`.
|
||||
If we suggest changes, then:
|
||||
|
||||
* Make the required updates.
|
||||
* Re-run CounterStrikeSharp to ensure everything is still working & tests are passing.
|
||||
* Commit your changes to your branch (e.g. `my-fix-branch`).
|
||||
* Push the changes to your GitHub repository (this will update your Pull Request).
|
||||
|
||||
If the PR gets too outdated we may ask you to rebase and force push to update the PR:
|
||||
|
||||
```shell
|
||||
git fetch upstream
|
||||
git rebase upstream/master
|
||||
git push origin my-fix-branch -f
|
||||
```
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
#### After your pull request is merged
|
||||
|
||||
After your pull request is merged, you can safely delete your branch and pull the changes
|
||||
from the main (upstream) repository.
|
||||
|
||||
[github]: https://github.com/roflmuffin/CounterStrikeSharp
|
||||
[discord]: https://discord.gg/eAZU3guKWU
|
||||
30
README.md
30
README.md
@@ -1,15 +1,19 @@
|
||||
# CounterStrikeSharp
|
||||
<div align=right>Table of Contents ↗️</div>
|
||||
|
||||
CounterStrikeSharp is a server side modding framework for Counter-Strike: Global Offensive. This project attempts to implement a .NET Core scripting layer on top of a Metamod Source Plugin, allowing developers to create plugins that interact with the game server in a modern language (C#) to facilitate the creation of maintainable and testable code.
|
||||
<h1 align=center><code>CounterStrikeSharp</code></h1>
|
||||
|
||||
<div align=center>
|
||||
<a href=https://github.com/roflmuffin/CounterStrikeSharp/releases><img src=https://img.shields.io/github/v/release/roflmuffin/CounterStrikeSharp?style=flat-square&label=latest></a>
|
||||
<a href=https://github.com/roflmuffin/CounterStrikeSharp/releases><img src=https://img.shields.io/github/release-date/roflmuffin/CounterStrikeSharp?style=flat-square&label=last%20release></a>
|
||||
<a href=https://github.com/roflmuffin/CounterStrikeSharp/releases><img src=https://img.shields.io/github/downloads/roflmuffin/CounterStrikeSharp/total.svg?style=flat-square alt=downloads></a>
|
||||
<a href=https://discord.gg/eAZU3guKWU><img src=https://img.shields.io/discord/1160907911501991946?logo=discord&cacheSeconds=3500&style=flat-square alt="chat on discord"></a>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
CounterStrikeSharp is a server side modding framework for Counter-Strike 2. This project implements a .NET 8 scripting layer on top of a Metamod Source Plugin, allowing developers to create plugins that interact with the game server in a modern language (C#) to facilitate the creation of maintainable and testable code.
|
||||
|
||||
[Come and join our Discord](https://discord.gg/eAZU3guKWU)
|
||||
|
||||
## History
|
||||
|
||||
This project is an ongoing migration of a previous project (titled [VSP.NET](https://github.com/roflmuffin/vspdotnet)) whereby a scripting layer was added to a Valve Server Plugin for CSGO.
|
||||
|
||||
Due to the architectural changes of CS2, the plugin is being rebuilt on the ground up, to support Linux 64-bit, something which was previously impossible.
|
||||
|
||||
## Install
|
||||
|
||||
Download the latest build from [here](https://github.com/roflmuffin/CounterStrikeSharp/releases). (Download the with runtime version if this is your first time installing).
|
||||
@@ -18,14 +22,12 @@ Detailed installation instructions can be found in the [docs](https://docs.cssha
|
||||
|
||||
## What works?
|
||||
|
||||
_(Note, these were features in the previous VSP.NET project, but have not been implemented yet in this project)_
|
||||
|
||||
These features are the core of the platform and work pretty well/have a low risk of causing issues.
|
||||
|
||||
- [x] Console Commands, Server Commands (e.g. css_mycommand)
|
||||
- [x] Chat Commands with `!` and `/` prefixes (e.g. !mycommand)
|
||||
- [ ] **(In Progress)** Console Variables
|
||||
- [x] Game Event Handlers & Custom Events (e.g. player_death)
|
||||
- [x] Fake Console Variables (commands which mimic ConVar behaviour as these have not been fully reverse engineered)
|
||||
- [x] Game Event Handlers & Firing of Events (e.g. player_death)
|
||||
- [x] Basic event value get/set (string, bool, int32, float)
|
||||
- [x] Complex event values get/set (ehandle, pawn, player controller)
|
||||
- [x] Game Tick Based Timers (e.g. repeating map timers)
|
||||
@@ -34,7 +36,7 @@ These features are the core of the platform and work pretty well/have a low risk
|
||||
- [x] Client Listeners (e.g. connect, disconnect, put in server)
|
||||
- [x] OnMapStart
|
||||
- [x] OnTick
|
||||
- [x] Server Information (current map, game time, tick rate, model precaching)
|
||||
- [x] Server Information (current map, game time)
|
||||
- [x] Schema System Access (access player values like current weapon, money, location etc.)
|
||||
|
||||
## Links
|
||||
@@ -81,7 +83,7 @@ public class HelloWorldPlugin : BasePlugin
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[ConsoleCommand("issue_warning", "Issue warning to player")]
|
||||
[ConsoleCommand("css_issue_warning", "Issue warning to player")]
|
||||
public void OnCommand(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
Logger.LogWarning("Player shouldn't be doing that");
|
||||
|
||||
@@ -3,5 +3,8 @@
|
||||
"SilentChatTrigger": [ "/" ],
|
||||
"FollowCS2ServerGuidelines": true,
|
||||
"PluginHotReloadEnabled": true,
|
||||
"ServerLanguage": "en"
|
||||
"PluginAutoLoadEnabled": true,
|
||||
"ServerLanguage": "en",
|
||||
"UnlockConCommands": true,
|
||||
"UnlockConVars": true
|
||||
}
|
||||
@@ -2,190 +2,230 @@
|
||||
"UTIL_ClientPrintAll": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x08\\x48\\x89\\x6C\\x24\\x10\\x48\\x89\\x74\\x24\\x18\\x57\\x48\\x81\\xEC\\x70\\x01\\x2A\\x2A\\x8B\\xE9",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x49\\x89\\xD7\\x41\\x56\\x49\\x89\\xF6\\x41\\x55\\x41\\x89\\xFD"
|
||||
"windows": "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 81 EC 70 01 ? ? 8B E9",
|
||||
"linux": "55 48 89 E5 41 57 49 89 D7 41 56 49 89 F6 41 55 41 89 FD"
|
||||
}
|
||||
},
|
||||
"ClientPrint": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x85\\xC9\\x0F\\x84\\x2A\\x2A\\x2A\\x2A\\x48\\x8B\\xC4\\x48\\x89\\x58\\x18",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x49\\x89\\xCF\\x41\\x56\\x49\\x89\\xD6\\x41\\x55\\x41\\x89\\xF5\\x41\\x54\\x4C\\x8D\\xA5\\xA0\\xFE\\xFF\\xFF"
|
||||
"windows": "48 85 C9 0F 84 ? ? ? ? 48 89 5C 24 ? 55",
|
||||
"linux": "55 48 89 E5 41 57 49 89 CF 41 56 49 89 D6 41 55 41 89 F5 41 54 4C 8D A5 A0 FE FF FF"
|
||||
}
|
||||
},
|
||||
"CCSPlayerController_SwitchTeam": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x40\\x56\\x57\\x48\\x81\\xEC\\x2A\\x2A\\x2A\\x2A\\x48\\x8B\\xF9\\x8B\\xF2\\x8B\\xCA",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x55\\x49\\x89\\xFD\\x89\\xF7"
|
||||
"windows": "40 56 57 48 81 EC ? ? ? ? 48 8B F9 8B F2 8B CA",
|
||||
"linux": "55 48 89 E5 41 55 49 89 FD 89 F7"
|
||||
}
|
||||
},
|
||||
"CCSPlayerController_ChangeTeam": {
|
||||
"offsets": {
|
||||
"windows": 93,
|
||||
"linux": 92
|
||||
"windows": 100,
|
||||
"linux": 99
|
||||
}
|
||||
},
|
||||
"CCSPlayerController_Respawn": {
|
||||
"offsets": {
|
||||
"windows": 245,
|
||||
"linux": 247
|
||||
"windows": 257,
|
||||
"linux": 259
|
||||
}
|
||||
},
|
||||
"CBasePlayerController_SetPawn": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x44\\x88\\x4C\\x24\\x20\\x55\\x57\\x41\\x54\\x41\\x56\\x41\\x57\\x48\\x8D\\x6C\\x24\\x2A\\x48\\x81\\xEC\\x2A",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x49\\x89\\xFC\\x53\\x48\\x89\\xF3\\x48\\x81\\xEC\\xC8\\x00\\x00\\x00"
|
||||
"windows": "48 89 74 24 ? 55 41 54 41 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 4C 8B F9",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 49 89 FD 41 54 45 89 C4"
|
||||
}
|
||||
},
|
||||
"CCSPlayerPawnBase_PostThink": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x8B\\xC4\\x48\\x89\\x48\\x08\\x55\\x53\\x56\\x57\\x41\\x56\\x48\\x8D\\xA8\\xD8\\xFE\\xFF\\xFF",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x53\\x48\\x89\\xFB\\x48\\x81\\xEC\\x2A\\x2A\\x2A\\x2A\\xE8\\x2A\\x2A\\x2A\\x2A\\x48\\x89\\xDF"
|
||||
"windows": "48 ? ? 55 53 56 57 41 ? 48 ? ? ? 48 ? ? ? ? ? ? 4C 89 68",
|
||||
"linux": "55 48 89 E5 41 56 41 55 41 54 53 48 89 FB 48 83 EC 40 E8"
|
||||
}
|
||||
},
|
||||
"CGameEventManager_Init": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "40 53 48 83 EC 20 48 8B 01 48 8B D9 FF 50 10",
|
||||
"linux": "55 48 89 E5 41 54 49 89 FC 48 83 EC 08 48 8B 07 FF 50 18"
|
||||
}
|
||||
},
|
||||
"GiveNamedItem": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x18\\x48\\x89\\x74\\x24\\x20\\x55\\x57\\x41\\x54\\x41\\x56\\x41\\x57\\x48\\x8D\\x6C\\x24\\xD9",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x49\\x89\\xCE\\x41\\x55\\x49\\x89\\xF5\\x41\\x54\\x49\\x89\\xD4"
|
||||
"windows": "48 89 5C 24 ? 48 89 74 24 ? 55 57 41 ? 41 ? 41 ? 48 ? ? ? ? 48 ? ? ? ? ? ? 4D ? ? 48",
|
||||
"linux": "55 48 89 E5 41 57 41 56 49 89 D6 41 55 49 89 CD 41 54 49 89 F4 53 48 89 FB 48 8D 3D"
|
||||
}
|
||||
},
|
||||
"UTIL_Remove": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x85\\xC9\\x74\\x2A\\x48\\x8B\\xD1\\x48\\x8B\\x0D\\x2A\\x2A\\x2A\\x2A",
|
||||
"linux": "\\x48\\x89\\xFE\\x48\\x85\\xFF\\x74\\x2A\\x48\\x8D\\x05\\x2A\\x2A\\x2A\\x2A\\x48"
|
||||
"windows": "48 85 C9 74 ? 48 8B D1 48 8B 0D ? ? ? ?",
|
||||
"linux": "48 89 FE 48 85 FF 74 ? 48 8D 05 ? ? ? ? 48"
|
||||
}
|
||||
},
|
||||
"Host_Say": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x44\\x89\\x4C\\x24\\x20\\x44\\x88\\x44\\x24\\x18",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x49\\x89\\xFF\\x41\\x56\\x41\\x55\\x41\\x54\\x4D\\x89\\xC4"
|
||||
"windows": "44 89 4C 24 20 44 88 44 24 18",
|
||||
"linux": "55 48 89 E5 41 57 41 56 49 89 F6 41 55 4D 89 C5"
|
||||
}
|
||||
},
|
||||
"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\\x4C\\x8B\\xC2",
|
||||
"linux": "\\x55\\x48\\x89\\xF2\\x48\\x89\\xE5\\x41\\x54\\x49\\x89\\xFC\\x48\\x8D\\x7D\\xE0\\x48\\x83\\xEC\\x2A\\x48\\x8D\\x05\\x2A\\x2A\\x2A\\x2A\\x48\\x8B\\x30\\x48\\x8B\\x06"
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 ? 48 89 7C 24 ? 55 48 8B EC 48 83 EC 50 48 8B F9 4C 8B C2",
|
||||
"linux": "55 48 89 F2 48 89 E5 41 54 49 89 FC 48 8D 7D E0 48 83 EC ? 48 8D 05 ? ? ? ? 48 8B 30 48 8B 06"
|
||||
}
|
||||
},
|
||||
"CCSPlayer_WeaponServices_CanUse": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x48\\x89\\x6C\\x24\\x18\\x56\\x57\\x41\\x56\\x48\\x83\\xEC\\x30\\x80\\xB9\\xA0\\x00\\x00\\x00\\x00",
|
||||
"linux": "\\x48\\x85\\xF6\\x0F\\x84\\x2A\\x2A\\x2A\\x2A\\x55\\x31\\xC9\\x48\\x89\\xE5\\x41\\x55\\x49\\x89\\xFD"
|
||||
"windows": "48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 56 48 83 EC ? 48 8B 01 48 8B FA",
|
||||
"linux": "55 48 8D 15 ? ? ? ? 48 89 E5 41 55 49 89 FD 41 54 49 89 F4"
|
||||
}
|
||||
},
|
||||
"CCSPlayer_ItemServices_CanAcquire": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 8B C4 44 89 40 ? 48 89 50 ? 48 89 48",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 49 89 CD 41 54 53 48 83 EC"
|
||||
}
|
||||
},
|
||||
"GetCSWeaponDataFromKey": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8B FA 8B F1 48 85 D2 0F 84",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 89 FE 41 55 41 54 45"
|
||||
}
|
||||
},
|
||||
"CCSPlayer_ItemServices_GiveNamedItem": {
|
||||
"offsets": {
|
||||
"windows": 19,
|
||||
"linux": 20
|
||||
}
|
||||
},
|
||||
"CCSPlayer_ItemServices_DropActivePlayerWeapon": {
|
||||
"offsets": {
|
||||
"windows": 18,
|
||||
"linux": 19
|
||||
"windows": 20,
|
||||
"linux": 21
|
||||
}
|
||||
},
|
||||
"CCSPlayer_ItemServices_RemoveWeapons": {
|
||||
"offsets": {
|
||||
"windows": 19,
|
||||
"linux": 20
|
||||
}
|
||||
"offsets": {
|
||||
"windows": 21,
|
||||
"linux": 22
|
||||
}
|
||||
},
|
||||
"CGameSceneNode_GetSkeletonInstance": {
|
||||
"offsets": {
|
||||
"windows": 8,
|
||||
"linux": 8
|
||||
"windows": 8,
|
||||
"linux": 8
|
||||
}
|
||||
},
|
||||
"CCSGameRules_TerminateRound": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x8B\\xC4\\x4C\\x89\\x48\\x20\\x55\\x57",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x49\\x89\\xFC\\x53\\x48\\x81\\xEC\\xE8\\x01\\x00\\x00\\x48\\x8D\\x05\\x2A\\x2A\\x2A\\x2A"
|
||||
}
|
||||
"library": "server",
|
||||
"windows": "48 8B C4 4C 89 48 ? 48 89 48 ? 55 41 55",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 49 89 FC 53 48 81 EC 88 00 00 00 48 8D 05 ? ? ? ?"
|
||||
}
|
||||
},
|
||||
"CCSGameRules_FindPickerEntity": {
|
||||
"offsets": {
|
||||
"windows": 27,
|
||||
"linux": 28
|
||||
}
|
||||
},
|
||||
"UTIL_CreateEntityByName": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x83\\xEC\\x48\\xC6\\x44\\x24\\x30\\x00",
|
||||
"linux": "\\x48\\x8D\\x05\\x2A\\x2A\\x2A\\x2A\\x55\\x48\\x89\\xFA"
|
||||
}
|
||||
"library": "server",
|
||||
"windows": "48 83 EC 48 C6 44 24 30 00",
|
||||
"linux": "48 8D 05 ? ? ? ? 55 48 89 FA"
|
||||
}
|
||||
},
|
||||
"CBaseEntity_DispatchSpawn": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x57\\x48\\x83\\xEC\\x30\\x48\\x8B\\xDA\\x48\\x8B\\xF9\\x48\\x85\\xC9",
|
||||
"linux": "\\x48\\x85\\xFF\\x74\\x2A\\x55\\x48\\x89\\xE5\\x41\\x56"
|
||||
}
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 10 57 48 83 EC 30 48 8B DA 48 8B F9 48 85 C9",
|
||||
"linux": "48 85 FF 74 ? 55 48 89 E5 41 56"
|
||||
}
|
||||
},
|
||||
"CEntityInstance_AcceptInput": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x48\\x89\\x74\\x24\\x18\\x57\\x48\\x83\\xEC\\x40\\x49\\x8B\\xF0",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x49\\x89\\xFF\\x41\\x56\\x48\\x8D\\x7D\\xC0"
|
||||
"windows": "48 89 5C 24 10 48 89 74 24 18 57 48 83 EC 40 49 8B F0",
|
||||
"linux": "55 48 89 E5 41 57 49 89 FF 41 56 48 8D 7D C0"
|
||||
}
|
||||
},
|
||||
"CEntitySystem_AddEntityIOEvent": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 ? 48 89 74 24 ? 57 48 ? ? ? 49 ? ? 48 ? ? 48 ? ? 74",
|
||||
"linux": "55 41 BA FF FF FF FF"
|
||||
}
|
||||
},
|
||||
"LegacyGameEventListener": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x8B\\x15\\x2A\\x2A\\x2A\\x2A\\x48\\x85\\xD2\\x74\\x2A\\x85\\xC9\\x74",
|
||||
"linux": "\\x48\\x8B\\x05\\x2A\\x2A\\x2A\\x2A\\x48\\x85\\xC0\\x74\\x2A\\x83\\xFF\\x3F\\x76\\x2A\\x31\\xC0"
|
||||
"windows": "48 8B 15 ? ? ? ? 48 85 D2 74 ? 85 C9 74",
|
||||
"linux": "48 8B 05 ? ? ? ? 48 85 C0 74 ? 85 FF"
|
||||
}
|
||||
},
|
||||
"CBasePlayerPawn_CommitSuicide": {
|
||||
"offsets": {
|
||||
"windows": 360,
|
||||
"linux": 360
|
||||
"windows": 380,
|
||||
"linux": 380
|
||||
}
|
||||
},
|
||||
"CBasePlayerPawn_RemovePlayerItem": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"linux": "\\x55\\x48\\x89\\x2A\\x41\\x2A\\x49\\x89\\x2A\\x41\\x2A\\x49\\x89\\x2A\\xE8\\x2A\\x2A\\x2A\\x2A\\x49\\x39",
|
||||
"windows": "\\x48\\x85\\xD2\\x0F\\x84\\x2A\\x2A\\x2A\\x2A\\x48\\x89\\x5C\\x24\\x08\\x57\\x48\\x83\\xEC\\x30\\x48\\x8B\\xDA"
|
||||
"windows": "48 ? ? 0F 84 ? ? ? ? 48 89 5C 24 ? 57 48 ? ? ? 48 ? ? 48 ? ? E8",
|
||||
"linux": "55 48 89 ? 41 ? 49 89 ? 41 ? 49 89 ? E8 ? ? ? ? 49 39"
|
||||
}
|
||||
},
|
||||
"CBaseEntity_Teleport": {
|
||||
"offsets": {
|
||||
"windows": 149,
|
||||
"linux": 148
|
||||
"windows": 157,
|
||||
"linux": 156
|
||||
}
|
||||
},
|
||||
"CBaseEntity_TakeDamageOld": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x40\\x56\\x57\\x48\\x83\\xEC\\x58\\x48\\x8B\\x41\\x10",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x49\\x89\\xFC\\x53\\x48\\x83\\xEC\\x38\\x4C\\x8D\\x2D\\x2A\\x2A\\x2A\\x2A\\x49\\x8B\\x7D\\x00\\x48\\x85\\xFF\\x0F\\x84\\x2A\\x2A\\x2A\\x2A"
|
||||
"windows": "48 89 74 24 ? 57 48 81 EC 80 00 00 00 48 8B 41",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 49 89 FC 53 48 83 EC 58 4C 8D 3D"
|
||||
}
|
||||
},
|
||||
"CBaseTrigger_StartTouch": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x41\\x56\\x41\\x57\\x48\\x83\\xEC\\x58\\x48\\x8B\\x01",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x56\\x49\\x89\\xF6\\x41\\x55\\x49\\x89\\xFD\\x41\\x54\\x53\\xBB"
|
||||
"windows": "40 57 41 57 48 83 EC 28 48 8B 01",
|
||||
"linux": "55 48 89 E5 41 56 49 89 F6 41 55 49 89 FD 41 54 53 BB"
|
||||
}
|
||||
},
|
||||
"CBaseTrigger_EndTouch": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x40\\x53\\x57\\x41\\x55\\x48\\x83\\xEC\\x40",
|
||||
"linux": "\\x55\\xBA\\xFF\\xFF\\xFF\\xFF\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x49\\x89\\xF5\\x41"
|
||||
"windows": "40 53 41 55 48 83 EC 28",
|
||||
"linux": "55 BA FF FF FF FF 48 89 E5 41 57 41 56 41 55 49 89 F5 41"
|
||||
}
|
||||
},
|
||||
"StateChanged": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x40\\x55\\x53\\x56\\x41\\x55\\x41\\x57\\x48\\x8D\\x6C\\x24\\xB0",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x53\\x89\\xD3"
|
||||
"windows": "40 55 53 56 41 56 41 57 48 8D 6C 24 ? 48 81 EC 70 01 00 00",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 53 89 D3"
|
||||
}
|
||||
},
|
||||
"NetworkStateChanged": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x4C\\x8B\\xC9\\x48\\x8B\\x09\\x48\\x85\\xC9\\x74\\x2A\\x48\\x8B\\x41\\x10",
|
||||
"linux": "\\x4C\\x8B\\x07\\x4D\\x85\\xC0\\x74\\x2A\\x49\\x8B\\x40\\x10"
|
||||
"windows": "4C 8B C9 48 8B 09 48 85 C9 74 ? 48 8B 41 10",
|
||||
"linux": "4C 8B 07 4D 85 C0 74 ? 49 8B 40 10"
|
||||
}
|
||||
},
|
||||
"GameEntitySystem": {
|
||||
@@ -203,8 +243,27 @@
|
||||
"CEntityIOOutput_FireOutputInternal": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x4C\\x89\\x4C\\x24\\x20\\x53\\x55\\x57\\x41\\x54\\x41\\x56\\x48\\x81\\xEC",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x49\\x89\\xD4\\x53\\x48\\x89\\xF3\\x48\\x83\\xEC\\x58"
|
||||
"windows": "4C 89 4C 24 20 53 55 57 41 54 41 56 48 81 EC",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 41 54 49 89 D4 53 48 89 F3 48 83 EC 58"
|
||||
}
|
||||
},
|
||||
"IGameSystem_InitAllSystems_pFirst": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 8B 3D ? ? ? ? 48 85 FF 0F 84 ? ? ? ? BE",
|
||||
"linux": "4C 8B 35 ? ? ? ? 4D 85 F6 75 ? E9"
|
||||
}
|
||||
},
|
||||
"CEntityResourceManifest_AddResource": {
|
||||
"offsets": {
|
||||
"windows": 2,
|
||||
"linux": 0
|
||||
}
|
||||
},
|
||||
"CheckTransmitPlayerSlot": {
|
||||
"offsets": {
|
||||
"windows": 584,
|
||||
"linux": 584
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,320 +0,0 @@
|
||||
ActionType_t
|
||||
AimMatrixBlendMode
|
||||
AmmoFlags_t
|
||||
AmmoPosition_t
|
||||
AnimationProcessingType_t
|
||||
AnimationSnapshotType_t
|
||||
AnimationType_t
|
||||
AnimLoopMode_t
|
||||
AnimNodeNetworkMode
|
||||
AnimParamButton_t
|
||||
AnimParamNetworkSetting
|
||||
AnimParamType_t
|
||||
AnimPoseControl
|
||||
AnimScriptType
|
||||
AnimValueSource
|
||||
AnimVectorSource
|
||||
attributeprovidertypes_t
|
||||
BaseExplosionTypes_t
|
||||
BBoxVolumeType_t
|
||||
BeamClipStyle_t
|
||||
BeamType_t
|
||||
BeginDeathLifeStateTransition_t
|
||||
BinaryNodeChildOption
|
||||
BinaryNodeTiming
|
||||
Blend2DMode
|
||||
BlendKeyType
|
||||
BloomBlendMode_t
|
||||
BlurFilterType_t
|
||||
BoneMaskBlendSpace
|
||||
BoneTransformSpace_t
|
||||
BrushSolidities_e
|
||||
C4LightEffect_t
|
||||
CAnimationGraphVisualizerPrimitiveType
|
||||
CanPlaySequence_t
|
||||
ChatIgnoreType_t
|
||||
ChickenActivity
|
||||
ChoiceBlendMethod
|
||||
ChoiceChangeMethod
|
||||
ChoiceMethod
|
||||
Class_T
|
||||
CLogicBranchList__LogicBranchListenerLastState_t
|
||||
ClosestPointTestType_t
|
||||
CNmBoneMask__WeightInfo_t
|
||||
CommandEntitySpecType_t
|
||||
CommandExecMode_t
|
||||
CompMatPropertyMutatorConditionType_t
|
||||
CompMatPropertyMutatorType_t
|
||||
CompositeMaterialInputContainerSourceType_t
|
||||
CompositeMaterialInputLooseVariableType_t
|
||||
CompositeMaterialInputTextureType_t
|
||||
CompositeMaterialMatchFilterType_t
|
||||
CompositeMaterialVarSystemVar_t
|
||||
CRR_Response__ResponseEnum_t
|
||||
CSPlayerBlockingUseAction_t
|
||||
CSPlayerState
|
||||
CSWeaponCategory
|
||||
CSWeaponMode
|
||||
CSWeaponSilencerType
|
||||
CSWeaponState_t
|
||||
CSWeaponType
|
||||
DamageTypes_t
|
||||
DampingSpeedFunction
|
||||
DebugOverlayBits_t
|
||||
Detail2Combo_t
|
||||
DetailCombo_t
|
||||
DisableShadows_t
|
||||
Disposition_t
|
||||
doorCheck_e
|
||||
DoorState_t
|
||||
EDemoBoneSelectionMode
|
||||
EInButtonState
|
||||
EKillTypes_t
|
||||
ELayoutNodeType
|
||||
EntFinderMethod_t
|
||||
EntityDisolveType_t
|
||||
EntityDormancyType_t
|
||||
EntityIOTargetType_t
|
||||
EntitySubclassScope_t
|
||||
EOverrideBlockLOS_t
|
||||
EStyleNodeType
|
||||
Explosions
|
||||
FacingMode
|
||||
FieldNetworkOption
|
||||
fieldtype_t
|
||||
filter_t
|
||||
FixAngleSet_t
|
||||
FlexOpCode_t
|
||||
FootFallTagFoot_t
|
||||
FootLockSubVisualization
|
||||
FootPinningTimingSource
|
||||
FootstepLandedFootSoundType_t
|
||||
ForcedCrouchState_t
|
||||
FuncDoorSpawnPos_t
|
||||
FuseVariableAccess_t
|
||||
FuseVariableType_t
|
||||
GameAnimEventIndex_t
|
||||
gear_slot_t
|
||||
GrenadeType_t
|
||||
HierarchyType_t
|
||||
HitboxLerpType_t
|
||||
HitGroup_t
|
||||
HorizJustification_e
|
||||
Hull_t
|
||||
IChoreoServices__ChoreoState_t
|
||||
IChoreoServices__ScriptState_t
|
||||
IKChannelMode
|
||||
IkEndEffectorType
|
||||
IKSolverType
|
||||
IKTargetCoordinateSystem
|
||||
IKTargetSource
|
||||
IkTargetType
|
||||
InheritableBoolType_t
|
||||
InputBitMask_t
|
||||
InputLayoutVariation_t
|
||||
ItemFlagTypes_t
|
||||
JiggleBoneSimSpace
|
||||
JointAxis_t
|
||||
JointMotion_t
|
||||
JumpCorrectionMethod
|
||||
LatchDirtyPermission_t
|
||||
LayoutPositionType_e
|
||||
LessonPanelLayoutFileTypes_t
|
||||
LifeState_t
|
||||
loadout_slot_t
|
||||
MaterialProxyType_t
|
||||
Materials
|
||||
MatterialAttributeTagType_t
|
||||
MedalRank_t
|
||||
MeshDrawPrimitiveFlags_t
|
||||
MissingParentInheritBehavior_t
|
||||
ModelBoneFlexComponent_t
|
||||
ModelConfigAttachmentType_t
|
||||
ModelSkeletonData_t__BoneFlags_t
|
||||
ModifyDamageReturn_t
|
||||
MoodType_t
|
||||
MorphBundleType_t
|
||||
MorphFlexControllerRemapType_t
|
||||
MoveCollide_t
|
||||
MoveLinearAuthoredPos_t
|
||||
MovementGait_t
|
||||
MoveMountingAmount_t
|
||||
MoveType_t
|
||||
NavAttributeEnum
|
||||
NavDirType
|
||||
navproperties_t
|
||||
NmFootPhase_t
|
||||
NmFootPhaseCondition_t
|
||||
NmFrameSnapEventMode_t
|
||||
NmTransitionRule_t
|
||||
NmTransitionRuleCondition_t
|
||||
NPCFollowFormation_t
|
||||
NPCLookType_t
|
||||
ObjectTypeFlags_t
|
||||
ObserverInterpState_t
|
||||
ObserverMode_t
|
||||
OnFrame
|
||||
ParticleAlphaReferenceType_t
|
||||
ParticleAttachment_t
|
||||
ParticleAttrBoxFlags_t
|
||||
ParticleCollisionMode_t
|
||||
ParticleColorBlendMode_t
|
||||
ParticleColorBlendType_t
|
||||
ParticleControlPointAxis_t
|
||||
ParticleDepthFeatheringMode_t
|
||||
ParticleDetailLevel_t
|
||||
ParticleDirectionNoiseType_t
|
||||
ParticleEndcapMode_t
|
||||
ParticleFalloffFunction_t
|
||||
ParticleFloatBiasType_t
|
||||
ParticleFloatInputMode_t
|
||||
ParticleFloatMapType_t
|
||||
ParticleFloatRandomMode_t
|
||||
ParticleFloatType_t
|
||||
ParticleFogType_t
|
||||
ParticleHitboxBiasType_t
|
||||
ParticleHitboxDataSelection_t
|
||||
ParticleImpulseType_t
|
||||
ParticleLightBehaviorChoiceList_t
|
||||
ParticleLightFogLightingMode_t
|
||||
ParticleLightingQuality_t
|
||||
ParticleLightnintBranchBehavior_t
|
||||
ParticleLightTypeChoiceList_t
|
||||
ParticleLightUnitChoiceList_t
|
||||
ParticleModelType_t
|
||||
ParticleOmni2LightTypeChoiceList_t
|
||||
ParticleOrientationChoiceList_t
|
||||
ParticleOrientationSetMode_t
|
||||
ParticleOutputBlendMode_t
|
||||
ParticleParentSetMode_t
|
||||
ParticlePinDistance_t
|
||||
ParticlePostProcessPriorityGroup_t
|
||||
ParticleRotationLockType_t
|
||||
ParticleSelection_t
|
||||
ParticleSequenceCropOverride_t
|
||||
ParticleSetMethod_t
|
||||
ParticleSortingChoiceList_t
|
||||
ParticleTextureLayerBlendType_t
|
||||
ParticleTopology_t
|
||||
ParticleTraceMissBehavior_t
|
||||
ParticleTraceSet_t
|
||||
ParticleTransformType_t
|
||||
ParticleVecType_t
|
||||
ParticleVRHandChoiceList_t
|
||||
PerformanceMode_t
|
||||
PermModelInfo_t__FlagEnum
|
||||
PetGroundType_t
|
||||
PFNoiseModifier_t
|
||||
PFNoiseTurbulence_t
|
||||
PFNoiseType_t
|
||||
PFuncVisualizationType_t
|
||||
PlayerAnimEvent_t
|
||||
PlayerConnectedState
|
||||
PointTemplateClientOnlyEntityBehavior_t
|
||||
PointTemplateOwnerSpawnGroupType_t
|
||||
PointWorldTextJustifyHorizontal_t
|
||||
PointWorldTextJustifyVertical_t
|
||||
PointWorldTextReorientMode_t
|
||||
PoseType_t
|
||||
PreviewCharacterMode
|
||||
PreviewEOMCelebration
|
||||
PreviewWeaponState
|
||||
PropDoorRotatingOpenDirection_e
|
||||
PropDoorRotatingSpawnPos_t
|
||||
PulseCursorCancelPriority_t
|
||||
PulseCursorExecResult_t
|
||||
PulseInstructionCode_t
|
||||
PulseMethodCallMode_t
|
||||
PulseTestEnumColor_t
|
||||
PulseTestEnumShape_t
|
||||
PulseValueType_t
|
||||
QuestProgress__Reason
|
||||
RagdollPoseControl
|
||||
RenderBufferFlags_t
|
||||
RenderFx_t
|
||||
RenderMode_t
|
||||
RenderMultisampleType_t
|
||||
RenderPrimitiveType_t
|
||||
RenderSlotType_t
|
||||
ResetCycleOption
|
||||
RumbleEffect_t
|
||||
ScalarExpressionType_t
|
||||
SceneOnPlayerDeath_t
|
||||
ScriptedConflictResponse_t
|
||||
ScriptedMoveTo_t
|
||||
ScriptedMoveType_t
|
||||
ScriptedOnDeath_t
|
||||
SelectorTagBehavior_t
|
||||
SeqCmd_t
|
||||
SeqPoseSetting_t
|
||||
SequenceFinishNotifyState_t
|
||||
ShadowType_t
|
||||
ShakeCommand_t
|
||||
ShardSolid_t
|
||||
ShatterDamageCause
|
||||
ShatterGlassStressType
|
||||
ShatterPanelMode
|
||||
SimpleConstraintSoundProfile__SimpleConstraintsSoundProfileKeypoints_t
|
||||
SnapshotIndexType_t
|
||||
SolidType_t
|
||||
SolveIKChainAnimNodeDebugSetting
|
||||
SosActionSortType_t
|
||||
SosActionStopType_t
|
||||
SosEditItemType_t
|
||||
SosGroupType_t
|
||||
SoundEventStartType_t
|
||||
SoundFlags_t
|
||||
soundlevel_t
|
||||
SpawnDebugOverrideState_t
|
||||
SpawnDebugRestrictionOverrideState_t
|
||||
SpawnPointCoopEnemy__BotDefaultBehavior_t
|
||||
SpriteCardPerParticleScale_t
|
||||
SpriteCardShaderType_t
|
||||
SpriteCardTextureChannel_t
|
||||
SpriteCardTextureType_t
|
||||
StanceOverrideMode
|
||||
StanceType_t
|
||||
StandardLightingAttenuationStyle_t
|
||||
StateActionBehavior
|
||||
StepPhase
|
||||
SubclassVDataChangeType_t
|
||||
SurroundingBoundsType_t
|
||||
TakeDamageFlags_t
|
||||
TextureRepetitionMode_t
|
||||
ThreeState_t
|
||||
TimelineCompression_t
|
||||
TOGGLE_STATE
|
||||
Touch_t
|
||||
TrackOrientationType_t
|
||||
TRAIN_CODE
|
||||
TrainOrientationType_t
|
||||
TrainVelocityType_t
|
||||
ValueRemapperHapticsType_t
|
||||
ValueRemapperInputType_t
|
||||
ValueRemapperMomentumType_t
|
||||
ValueRemapperOutputType_t
|
||||
ValueRemapperRatchetType_t
|
||||
VectorExpressionType_t
|
||||
VectorFloatExpressionType_t
|
||||
VelocityMetricMode
|
||||
VertJustification_e
|
||||
ViewFadeMode_t
|
||||
VMixChannelOperation_t
|
||||
VMixFilterSlope_t
|
||||
VMixFilterType_t
|
||||
VMixLFOShape_t
|
||||
VMixPannerType_t
|
||||
VMixProcessorType_t
|
||||
VMixSubgraphSwitchInterpolationType_t
|
||||
vote_create_failed_t
|
||||
VPhysXAggregateData_t__VPhysXFlagEnum_t
|
||||
VPhysXBodyPart_t__VPhysXFlagEnum_t
|
||||
VPhysXConstraintParams_t__EnumFlags0_t
|
||||
VPhysXJoint_t__Flags_t
|
||||
WaterLevel_t
|
||||
WeaponAttackType_t
|
||||
WeaponSound_t
|
||||
WeaponSwitchReason_t
|
||||
WorldTextPanelHorizontalAlign_t
|
||||
WorldTextPanelOrientation_t
|
||||
WorldTextPanelVerticalAlign_t
|
||||
1
configs/addons/counterstrikesharp/shared/README.md
Normal file
1
configs/addons/counterstrikesharp/shared/README.md
Normal file
@@ -0,0 +1 @@
|
||||
This folder should contain any shared APIs, in the same DLL structure as the plugins folder (MySharedApi/MySharedApi.dll)
|
||||
67
docfx/docs/features/shared-plugin-api.md
Normal file
67
docfx/docs/features/shared-plugin-api.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Shared Plugin API (Capabilities)
|
||||
description: How to add inter-plugin communication to CounterStrikeSharp plugins.
|
||||
---
|
||||
|
||||
# Shared Plugin API
|
||||
|
||||
How to expose and use shared plugin APIs between multiple plugins.
|
||||
|
||||
## Creating a Contract Library
|
||||
|
||||
Inter-plugin communication requires a contract/shared library that simply exposes the shape of the API, using simple interfaces. e.g.
|
||||
|
||||
```csharp
|
||||
public interface IBalanceHandler
|
||||
{
|
||||
decimal Balance { get; }
|
||||
|
||||
// These are just here to show that you can have methods on your shared types.
|
||||
// You could also add a Setter to the Balance property.
|
||||
public decimal Add(decimal amount);
|
||||
public decimal Subtract(decimal amount);
|
||||
}
|
||||
```
|
||||
|
||||
This library ideally should not contain any business logic, and simply define the schema for callers.
|
||||
|
||||
This library should be placed in the `shared` subfolder, in the same folder layout as the plugins folder. So if a contract DLL is named `MySharedApi.dll` its file path should be: `shared/MySharedApi/MySharedApi.dll`.
|
||||
|
||||
## Creating a Capability
|
||||
|
||||
A capability can be declared with a simple static variable in your plugin class. A `PlayerCapability` is a player specific capability, and a `PluginCapability` is generic functionality that a plugin can expose.
|
||||
|
||||
```csharp
|
||||
public static PlayerCapability<IBalanceHandler> BalanceCapability { get; } = new("myplugin:balance");
|
||||
|
||||
public static PluginCapability<IBalanceService> BalanceServiceCapability { get; } = new("myplugin:balance_service");
|
||||
```
|
||||
|
||||
For every plugin that wishes to use this new "Balance API", they must ensure they create a capability using the shared API interface (`IBalanceHandler`), as well as use the same name (`myplugin:balance`).
|
||||
|
||||
## Registering a Capability
|
||||
|
||||
If you are the plugin that is expected to provide the basis of the API (i.e. you are providing a currency/balance plugin which does nothing except store users balances), then you will need to provide the implementation that other callers will use. This is done through the use of static members on the `Capabilities` class:
|
||||
|
||||
```csharp
|
||||
// Player capabilities are given the calling player context
|
||||
Capabilities.RegisterPlayerCapability(BalanceCapability, player => new BalanceHandler(player));
|
||||
|
||||
// Plugin capabilities can simply return an instance of the interface
|
||||
Capabilities.RegisterPluginCapability(BalanceServiceCapability, () => new BalanceService());
|
||||
```
|
||||
|
||||
### Using Capabilities
|
||||
|
||||
To utilise a capability, simply call the `.Get()` method provided on the static capability you declared earlier, i.e.
|
||||
|
||||
```csharp
|
||||
var balance = BalanceCapability.Get(player);
|
||||
var balanceService = BalanceServiceCapability.Get();
|
||||
|
||||
if (balance == null) return;
|
||||
|
||||
balance.Add(500);
|
||||
```
|
||||
|
||||
This value _MUST_ be checked for null, as if there are no plugins providing implementations for a given capability, this method will return null, and you must handle this flow in your plugin.
|
||||
@@ -9,3 +9,6 @@
|
||||
|
||||
- name: Global Listeners
|
||||
href: global-listeners.md
|
||||
|
||||
- name: Shared Plugin API
|
||||
href: shared-plugin-api.md
|
||||
|
||||
@@ -9,7 +9,7 @@ How to write your first plugin for CounterStrikeSharp
|
||||
|
||||
## Creating a New Project
|
||||
|
||||
First, ensure you have the relevant .NET 7.0 SDK for your platform installed on your machine. You can find the links to the latest downloads on the <a href="https://dotnet.microsoft.com/en-us/download/dotnet/7.0" target="_blank"> official Microsoft download page</a>.
|
||||
First, ensure you have the relevant .NET 8.0 SDK for your platform installed on your machine. You can find the links to the latest downloads on the <a href="https://dotnet.microsoft.com/en-us/download/dotnet/8.0" target="_blank"> official Microsoft download page</a>.
|
||||
|
||||
### Creating a Class Library
|
||||
|
||||
@@ -25,7 +25,7 @@ Use your IDE (Visual Studio/Rider) to add a reference to the `CounterStrikeSharp
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
@@ -65,7 +65,7 @@ public class HelloWorldPlugin : BasePlugin
|
||||
}
|
||||
```
|
||||
|
||||
Now build your project using your ide or the `dotnet build` command. You should now have a built binary file in your `bin/Debug/net7.0` subdirectory in the project.
|
||||
Now build your project using your ide or the `dotnet build` command. You should now have a built binary file in your `bin/Debug/net8.0` subdirectory in the project.
|
||||
|
||||
### Installing your Plugin
|
||||
|
||||
|
||||
@@ -28,11 +28,22 @@ receive a ban.
|
||||
> [!NOTE]
|
||||
> Disable this option at your own risk.
|
||||
|
||||
|
||||
## PluginHotReloadEnabled
|
||||
|
||||
When enabled, plugins are automatically reloaded when their .dll file is updated.
|
||||
|
||||
## PluginAutoLoadEnabled
|
||||
|
||||
When enabled, plugins are automatically loaded from the plugins directory on server start.
|
||||
|
||||
## ServerLanguage
|
||||
|
||||
Configures the default language to use for server commands & messages. The format for the culture name based on RFC 4646 is `languagecode2-country`/`regioncode2`, where `languagecode2` is the two-letter language code and `country/regioncode2` is the two-letter subculture code. Examples include `ja-JP` for Japanese (Japan) and `en-US` for English (United States). Defaults to "en".
|
||||
Configures the default language to use for server commands & messages. The format for the culture name based on RFC 4646 is `languagecode2-country`/`regioncode2`, where `languagecode2` is the two-letter language code and `country/regioncode2` is the two-letter subculture code. Examples include `ja-JP` for Japanese (Japan) and `en-US` for English (United States). Defaults to "en".
|
||||
|
||||
## UnlockConCommands
|
||||
|
||||
When enabled, will remove the `FCVAR_HIDDEN`,`FCVAR_DEVELOPMENTONLY`, `FCVAR_MISSING0`, `FCVAR_MISSING1`, `FCVAR_MISSING2`, `FCVAR_MISSING3` flags from all console commands.
|
||||
|
||||
## UnlockConVars
|
||||
|
||||
When enabled, will remove the `FCVAR_HIDDEN`,`FCVAR_DEVELOPMENTONLY`, `FCVAR_MISSING0`, `FCVAR_MISSING1`, `FCVAR_MISSING2`, `FCVAR_MISSING3` flags from all console variables.
|
||||
|
||||
5
docfx/examples/WithFakeConvars.md
Normal file
5
docfx/examples/WithFakeConvars.md
Normal file
@@ -0,0 +1,5 @@
|
||||
[!INCLUDE [WithFakeConvars](../../examples/WithFakeConvars/README.md)]
|
||||
|
||||
<a href="https://github.com/roflmuffin/CounterStrikeSharp/tree/main/examples/WithFakeConvars" class="btn btn-secondary">View project on Github <i class="bi bi-github"></i></a>
|
||||
|
||||
[!code-csharp[](../../examples/WithFakeConvars/WithFakeConvarsPlugin.cs)]
|
||||
11
docfx/examples/WithSharedTypes.md
Normal file
11
docfx/examples/WithSharedTypes.md
Normal file
@@ -0,0 +1,11 @@
|
||||
[!INCLUDE [WithSharedTypes](../../examples/WithSharedTypes/README.md)]
|
||||
|
||||
<a href="https://github.com/roflmuffin/CounterStrikeSharp/tree/main/examples/WithSharedTypes" class="btn btn-secondary">View project on Github <i class="bi bi-github"></i></a>
|
||||
|
||||
[!code-csharp[](../../examples/WithSharedTypes/WithSharedTypesPlugin.cs)]
|
||||
|
||||
[!INCLUDE [WithSharedTypesConsumer](../../examples/WithSharedTypesConsumer/README.md)]
|
||||
|
||||
<a href="https://github.com/roflmuffin/CounterStrikeSharp/tree/main/examples/WithSharedTypesConsumer" class="btn btn-secondary">View project on Github <i class="bi bi-github"></i></a>
|
||||
|
||||
[!code-csharp[](../../examples/WithSharedTypesConsumer/WithSharedTypesConsumerPlugin.cs)]
|
||||
5
docfx/examples/WithUserMessages.md
Normal file
5
docfx/examples/WithUserMessages.md
Normal file
@@ -0,0 +1,5 @@
|
||||
[!INCLUDE [WithUserMessages](../../examples/WithUserMessages/README.md)]
|
||||
|
||||
<a href="https://github.com/roflmuffin/CounterStrikeSharp/tree/main/examples/WithUserMessages" class="btn btn-secondary">View project on Github <i class="bi bi-github"></i></a>
|
||||
|
||||
[!code-csharp[](../../examples/WithUserMessages/WithUserMessagesPlugin.cs)]
|
||||
@@ -3,6 +3,8 @@ items:
|
||||
href: HelloWorld.md
|
||||
- name: Commands
|
||||
href: WithCommands.md
|
||||
- name: Fake ConVars
|
||||
href: WithFakeConvars.md
|
||||
- name: Config
|
||||
href: WithConfig.md
|
||||
- name: Dependency Injection
|
||||
@@ -13,8 +15,12 @@ items:
|
||||
href: WithGameEventHandlers.md
|
||||
- name: Database (Dapper)
|
||||
href: WithDatabase.md
|
||||
- name: Shared Plugin Types
|
||||
href: WithSharedTypes.md
|
||||
- name: Translations
|
||||
href: WithTranslations.md
|
||||
- name: User Messages
|
||||
href: WithUserMessages.md
|
||||
- name: Voice Overrides
|
||||
href: WithVoiceOverrides.md
|
||||
- name: Warcraft Plugin
|
||||
|
||||
37
eng/formatting/download-tools.ps1
Normal file
37
eng/formatting/download-tools.ps1
Normal file
@@ -0,0 +1,37 @@
|
||||
# Tool taken from dotnet/runtime
|
||||
# https://github.com/dotnet/runtime/blob/a8158c170b694f8c1dbae114c63c346b38244901/eng/formatting/download-tools.ps1
|
||||
|
||||
function DownloadClangTool {
|
||||
param (
|
||||
[string]
|
||||
$toolName,
|
||||
[string]
|
||||
$downloadOutputPath
|
||||
)
|
||||
|
||||
$clangVersion = "17.0.6"
|
||||
$clangToolsRootUrl = "https://clrjit2.blob.core.windows.net/clang-tools"
|
||||
$clangPlatform = "windows-x64"
|
||||
|
||||
$toolUrl = "$clangToolsRootUrl/$clangVersion/$clangPlatform/$toolName.exe"
|
||||
$targetPath = "$downloadOutputPath\$toolName.exe"
|
||||
|
||||
if (-not $(ls $downloadOutputPath | Where-Object { $_.Name -eq "$toolName.exe" })) {
|
||||
Write-Output "Downloading '$toolUrl' to '$targetPath'"
|
||||
# Pass -PassThru as otherwise Invoke-WebRequest leaves a corrupted file if the download fails. With -PassThru the download is buffered first.
|
||||
# -UseBasicParsing is necessary for older PowerShells when Internet Explorer might not be installed/configured
|
||||
$null = Invoke-WebRequest -Uri "$toolUrl" -OutFile $(Join-Path $downloadOutputPath -ChildPath "$toolName.exe") -PassThru -UseBasicParsing
|
||||
}
|
||||
else {
|
||||
Write-Output "Found '$targetPath'"
|
||||
}
|
||||
}
|
||||
|
||||
$downloadPathFolder = Split-Path $PSScriptRoot -Parent | Split-Path -Parent | Join-Path -ChildPath "artifacts" | Join-Path -ChildPath "tools"
|
||||
|
||||
mkdir $downloadPathFolder -ErrorAction SilentlyContinue
|
||||
|
||||
DownloadClangTool "clang-format" "$downloadPathFolder"
|
||||
|
||||
# Add to path to enable scripts to skip additional downloading steps since the tools will already be on the path.
|
||||
$env:PATH = "$downloadPathFolder;$env:PATH"
|
||||
60
eng/formatting/download-tools.sh
Normal file
60
eng/formatting/download-tools.sh
Normal file
@@ -0,0 +1,60 @@
|
||||
# Tool taken from dotnet/runtime
|
||||
# https://github.com/dotnet/runtime/blob/a8158c170b694f8c1dbae114c63c346b38244901/eng/formatting/download-tools.sh
|
||||
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -ue
|
||||
|
||||
source="${BASH_SOURCE[0]}"
|
||||
|
||||
# resolve $source until the file is no longer a symlink
|
||||
while [[ -h "$source" ]]; do
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
source="$(readlink "$source")"
|
||||
# if $source was a relative symlink, we need to resolve it relative to the path where the
|
||||
# symlink file was located
|
||||
[[ $source != /* ]] && source="$scriptroot/$source"
|
||||
done
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
|
||||
function DownloadClangTool {
|
||||
|
||||
clangVersion="17.0.6"
|
||||
clangToolsRootUrl="https://clrjit2.blob.core.windows.net/clang-tools"
|
||||
|
||||
clangPlatform="$(dotnet --info | grep 'RID:')"
|
||||
clangPlatform="${clangPlatform##*RID:* }"
|
||||
echo "dotnet RID: ${clangPlatform}"
|
||||
|
||||
# override common RIDs with compatible version so we don't need to upload binaries for each RID
|
||||
case $clangPlatform in
|
||||
ubuntu.*-x64)
|
||||
clangPlatform=linux-x64
|
||||
;;
|
||||
esac
|
||||
|
||||
toolUrl="${clangToolsRootUrl}/${clangVersion}/${clangPlatform}/$1"
|
||||
toolOutput=$2/$1
|
||||
|
||||
echo "Downloading $1 from ${toolUrl} to ${toolOutput}"
|
||||
|
||||
if [[ ! -x "$toolOutput" ]]; then
|
||||
curl --silent --retry 5 --fail -o "${toolOutput}" "$toolUrl"
|
||||
chmod 751 $toolOutput
|
||||
fi
|
||||
|
||||
if [[ ! -x "$toolOutput" ]]; then
|
||||
echo "Failed to download $1"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
engFolder="$(cd -P "$( dirname "$scriptroot" )" && pwd )"
|
||||
downloadPathFolder="$(cd -P "$( dirname "$engFolder" )" && pwd )/artifacts/tools"
|
||||
|
||||
mkdir -p "$downloadPathFolder"
|
||||
|
||||
DownloadClangTool "clang-format" "$downloadPathFolder"
|
||||
|
||||
export PATH=$downloadPathFolder:$PATH
|
||||
29
eng/formatting/format.sh
Normal file
29
eng/formatting/format.sh
Normal file
@@ -0,0 +1,29 @@
|
||||
# Tool taken from dotnet/runtime
|
||||
# https://github.com/dotnet/runtime/blob/a8158c170b694f8c1dbae114c63c346b38244901/eng/formatting/format.sh
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
LC_ALL=C
|
||||
# Select files to format
|
||||
NATIVE_FILES=$(git diff --cached --name-only --diff-filter=ACM "*.h" "*.hpp" "*.c" "*.cpp" "*.inl" | sed 's| |\\ |g')
|
||||
MANAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM "*.cs" "*.vb" | sed 's| |\\ |g')
|
||||
|
||||
exec 1>&2
|
||||
|
||||
if [ -n "$NATIVE_FILES" ]; then
|
||||
# Format all selected files
|
||||
echo "$NATIVE_FILES" | cat | xargs | sed -e 's/ /,/g' | xargs "./artifacts/tools/clang-format" -style=file -i
|
||||
|
||||
# Add back the modified files to staging
|
||||
echo "$NATIVE_FILES" | xargs git add
|
||||
fi
|
||||
|
||||
if [ -n "$MANAGED_FILES" ]; then
|
||||
# Format all selected files
|
||||
echo "$MANAGED_FILES" | cat | xargs | sed -e 's/ /,/g' | dotnet format whitespace --include - --folder
|
||||
|
||||
# Add back the modified files to staging
|
||||
echo "$MANAGED_FILES" | xargs git add
|
||||
fi
|
||||
|
||||
exit 0
|
||||
71
eng/install/install.ps1
Normal file
71
eng/install/install.ps1
Normal file
@@ -0,0 +1,71 @@
|
||||
# Install script that downloads Metamod:Source and Counter-Strike Sharp (with runtime)
|
||||
|
||||
$MM_DOWNLOAD_URL = "https://mms.alliedmods.net/mmsdrop/2.0/mmsource-2.0.0-git1286-windows.zip"
|
||||
$TARGET_DIR = "./game/csgo"
|
||||
$GAMEINFO_FILE = Join-Path $TARGET_DIR "gameinfo.gi"
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# Verification
|
||||
if (-not (Test-Path $GAMEINFO_FILE)) {
|
||||
Write-Error "Error: $GAMEINFO_FILE does not exist in the specified directory."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# GitHub API for Counter-Strike Sharp Releases
|
||||
$RELEASE_INFO = (Invoke-WebRequest -Uri "https://api.github.com/repos/roflmuffin/CounterStrikeSharp/releases/latest").Content | ConvertFrom-Json
|
||||
|
||||
# Filtering download URLs
|
||||
$CSSHARP_DOWNLOAD_URL = $RELEASE_INFO.assets |
|
||||
Where-Object { $_.browser_download_url -like '*windows*.zip*' -and $_.browser_download_url -notlike '*with-runtime*' } |
|
||||
Select-Object -First 1 -ExpandProperty browser_download_url
|
||||
|
||||
$CSSHARP_RUNTIME_DOWNLOAD_URL = $RELEASE_INFO.assets |
|
||||
Where-Object { $_.browser_download_url -like '*windows*.zip*' -and $_.browser_download_url -like '*with-runtime*' } |
|
||||
Select-Object -First 1 -ExpandProperty browser_download_url
|
||||
|
||||
### METAMOD:SOURCE ###
|
||||
Write-Output "Downloading Metamod:Source..."
|
||||
|
||||
Invoke-WebRequest -Uri $MM_DOWNLOAD_URL -OutFile metamod.zip
|
||||
Write-Output "Extracting Metamod:Source to $TARGET_DIR..."
|
||||
Expand-Archive -Force -Path metamod.zip -DestinationPath $TARGET_DIR
|
||||
Remove-Item metamod.zip
|
||||
|
||||
### GAMEINFO.GI UPDATE ###
|
||||
$NEW_ENTRY = " Game csgo/addons/metamod"
|
||||
$FILE_CONTENT = Get-Content $GAMEINFO_FILE
|
||||
|
||||
Write-Output "Updating $GAMEINFO_FILE..."
|
||||
if ($FILE_CONTENT -contains $NEW_ENTRY) {
|
||||
Write-Output "The entry '$NEW_ENTRY' already exists in $GAMEINFO_FILE. No changes were made."
|
||||
} else {
|
||||
$Pattern = "Game_LowViolence"
|
||||
$Modified = $false
|
||||
$NewContent = @()
|
||||
|
||||
foreach ($line in $FILE_CONTENT) {
|
||||
if ($line -match $Pattern -and -not $Modified) {
|
||||
$NewContent += $line
|
||||
$NewContent += $NEW_ENTRY
|
||||
$Modified = $true
|
||||
} else {
|
||||
$NewContent += $line
|
||||
}
|
||||
}
|
||||
|
||||
$NewContent | Set-Content $GAMEINFO_FILE
|
||||
Write-Host "The file $GAMEINFO_FILE has been modified successfully. '$NEW_ENTRY' has been added."
|
||||
}
|
||||
|
||||
### COUNTER-STRIKE SHARP ###
|
||||
Write-Output "Downloading Counter-Strike Sharp (with runtime)..."
|
||||
|
||||
# Determine if runtime needs to be downloaded
|
||||
if (-not (Test-Path "./game/csgo/addons/CounterStrikeSharp/dotnet/dotnet.exe")) {
|
||||
$CSSHARP_DOWNLOAD_URL = $CSSHARP_RUNTIME_DOWNLOAD_URL
|
||||
}
|
||||
|
||||
Invoke-WebRequest -Uri $CSSHARP_DOWNLOAD_URL -OutFile cssharp.zip
|
||||
Write-Output "Extracting Counter-Strike Sharp to $TARGET_DIR..."
|
||||
Expand-Archive -Force -Path cssharp.zip -DestinationPath $TARGET_DIR
|
||||
Remove-Item cssharp.zip
|
||||
72
eng/install/install.sh
Executable file
72
eng/install/install.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Install script that downloads Metamod:Source and Counter-Strike Sharp (with runtime)
|
||||
|
||||
MM_DOWNLOAD_URL="https://mms.alliedmods.net/mmsdrop/2.0/mmsource-2.0.0-git1286-linux.tar.gz"
|
||||
TARGET_DIR="./game/csgo"
|
||||
GAMEINFO_FILE="${TARGET_DIR}/gameinfo.gi"
|
||||
|
||||
if [ ! -f "${GAMEINFO_FILE}" ]; then
|
||||
printf "Error: %s does not exist in the specified directory.\n" "$GAMEINFO_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RELEASE_INFO=$(curl -s https://api.github.com/repos/roflmuffin/CounterStrikeSharp/releases/latest)
|
||||
|
||||
# Filter and store download URLs
|
||||
CSSHARP_DOWNLOAD_URL=$(echo "$RELEASE_INFO" | grep -o "browser_download_url.*linux.*\.zip" | cut -d '"' -f 3 | grep -v "with-runtime")
|
||||
CSSHARP_RUNTIME_DOWNLOAD_URL=$(echo "$RELEASE_INFO" | grep -o "browser_download_url.*linux.*\.zip" | cut -d '"' -f 3 | grep "with-runtime")
|
||||
|
||||
### METAMOD:SOURCE ###
|
||||
printf "Downloading Metamod:Source...\n"
|
||||
|
||||
curl -s -L -o metamod.tar.gz "$MM_DOWNLOAD_URL"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
printf "Extracting Metamod:Source to %s...\n" "$TARGET_DIR"
|
||||
tar -xzf metamod.tar.gz -C "$TARGET_DIR"
|
||||
|
||||
rm metamod.tar.gz
|
||||
else
|
||||
echo "Download failed. Please check the URL and your connection."
|
||||
fi
|
||||
|
||||
### GAMEINFO.GI UPDATE ###
|
||||
NEW_ENTRY=" Game csgo/addons/metamod"
|
||||
|
||||
printf "Updating %s...\n" "$GAMEINFO_FILE"
|
||||
if grep -Fxq "$NEW_ENTRY" "$GAMEINFO_FILE"; then
|
||||
echo "The entry '$(echo $NEW_ENTRY | xargs)' already exists in ${GAMEINFO_FILE}. No changes were made."
|
||||
else
|
||||
awk -v new_entry="$NEW_ENTRY" '
|
||||
BEGIN { found=0; }
|
||||
// {
|
||||
if (found) {
|
||||
print new_entry;
|
||||
found=0;
|
||||
}
|
||||
print;
|
||||
}
|
||||
/Game_LowViolence/ { found=1; }
|
||||
' "$GAMEINFO_FILE" > "$GAMEINFO_FILE.tmp" && mv "$GAMEINFO_FILE.tmp" "$GAMEINFO_FILE"
|
||||
|
||||
printf "The file %s has been modified successfully. '%s' has been added.\n" "$GAMEINFO_FILE" "$(echo $NEW_ENTRY | xargs)"
|
||||
fi
|
||||
|
||||
printf "Downloading Counter-Strike Sharp (with runtime)...\n"
|
||||
|
||||
# If ./game/csgo/addons/CounterStrikeSharp/dotnet/dotnet does not exist, use the runtime download url
|
||||
if [ ! -f "./game/csgo/addons/CounterStrikeSharp/dotnet/dotnet" ]; then
|
||||
CSSHARP_DOWNLOAD_URL="$CSSHARP_RUNTIME_DOWNLOAD_URL"
|
||||
fi
|
||||
|
||||
curl -s -L -o cssharp.zip "$CSSHARP_DOWNLOAD_URL"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
printf "Extracting Counter-Strike Sharp to %s...\n" "$TARGET_DIR"
|
||||
unzip -q -o cssharp.zip -d "$TARGET_DIR"
|
||||
|
||||
rm cssharp.zip
|
||||
else
|
||||
echo "Download failed. Please check the URL and your connection."
|
||||
fi
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace MySharedTypes.Contracts;
|
||||
|
||||
public interface IBalanceHandler
|
||||
{
|
||||
decimal Balance { get; }
|
||||
|
||||
// These are just here to show that you can have methods on your shared types.
|
||||
// You could also add a Setter to the Balance property.
|
||||
public decimal Add(decimal amount);
|
||||
public decimal Subtract(decimal amount);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace MySharedTypes.Contracts;
|
||||
|
||||
public interface IBalanceService
|
||||
{
|
||||
public void ClearAllBalances();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
|
||||
2
examples/WithCheckTransmit/README.md
Normal file
2
examples/WithCheckTransmit/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# With CheckTransmit
|
||||
This example shows how to work with the `CheckTransmit` listener.
|
||||
13
examples/WithCheckTransmit/WithCheckTransmit.csproj
Normal file
13
examples/WithCheckTransmit/WithCheckTransmit.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\managed\CounterStrikeSharp.API\CounterStrikeSharp.API.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
115
examples/WithCheckTransmit/WithCheckTransmitPlugin.cs
Normal file
115
examples/WithCheckTransmit/WithCheckTransmitPlugin.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
|
||||
namespace WithCheckTransmit;
|
||||
|
||||
[MinimumApiVersion(276)]
|
||||
public class WithCheckTransmitPlugin : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "Example: With CheckTransmit";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
public override string ModuleAuthor => "CounterStrikeSharp & Contributors";
|
||||
public override string ModuleDescription => "A simple plugin that uses the CheckTransmit listener!";
|
||||
|
||||
private Dictionary<int, bool> ShouldSeeDoors = new Dictionary<int, bool>();
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
// This command is related to the following example.
|
||||
AddCommand("nodoors", "Toggle door transmit", (player, info) =>
|
||||
{
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (ShouldSeeDoors.ContainsKey(player.Slot))
|
||||
{
|
||||
ShouldSeeDoors[player.Slot] = !ShouldSeeDoors[player.Slot];
|
||||
} else
|
||||
{
|
||||
ShouldSeeDoors.Add(player.Slot, false);
|
||||
}
|
||||
|
||||
info.ReplyToCommand($"You should {(ShouldSeeDoors[player.Slot] ? "see" : "not see")} doors");
|
||||
});
|
||||
|
||||
// In this example, we will hide every door for players that have enabled the option with the command 'nodoors'
|
||||
RegisterListener<Listeners.CheckTransmit>((CCheckTransmitInfoList infoList) =>
|
||||
{
|
||||
// Get the list of the currently available doors (prop_door_rotating)
|
||||
IEnumerable<CPropDoorRotating> doors = Utilities.FindAllEntitiesByDesignerName<CPropDoorRotating>("prop_door_rotating");
|
||||
|
||||
// Do nothing if there is none.
|
||||
if (!doors.Any())
|
||||
return;
|
||||
|
||||
// Go through every received info
|
||||
foreach ((CCheckTransmitInfo info, CCSPlayerController? player) in infoList)
|
||||
{
|
||||
// If no player is found, we can continue
|
||||
if (player == null)
|
||||
continue;
|
||||
|
||||
// Otherwise, lets do the work:
|
||||
|
||||
// Check if we should clear or not:
|
||||
|
||||
// If we have no data saved for this player, then we should not continue
|
||||
if (!ShouldSeeDoors.ContainsKey(player.Slot))
|
||||
continue;
|
||||
|
||||
// If this value is true, then this player should see doors
|
||||
if (ShouldSeeDoors[player.Slot])
|
||||
continue;
|
||||
|
||||
// Otherwise, lets remove the door entity indexes from the info list so they won't be transmitted
|
||||
foreach (CPropDoorRotating door in doors)
|
||||
{
|
||||
info.TransmitEntities.Remove(door);
|
||||
}
|
||||
|
||||
// NOTE: this is a barebone example, saving data and doing sanity checks is up to you.
|
||||
}
|
||||
});
|
||||
|
||||
// In this example, we will hide other players in the same team as the player.
|
||||
// NOTE: 'Hiding' players requires extra work to do, killing non-transmitted players results in crash.
|
||||
RegisterListener<Listeners.CheckTransmit>((CCheckTransmitInfoList infoList) =>
|
||||
{
|
||||
// Get the list of the current players, we only work with this value later on
|
||||
List<CCSPlayerController> players = Utilities.GetPlayers();
|
||||
|
||||
// Go through every received info
|
||||
foreach ((CCheckTransmitInfo info, CCSPlayerController? player) in infoList)
|
||||
{
|
||||
// If no player is found, we can continue
|
||||
if (player == null)
|
||||
continue;
|
||||
|
||||
// Otherwise, lets do the work:
|
||||
|
||||
// as an example, lets hide everyone for this player who is in the same team.
|
||||
IEnumerable<CCSPlayerController> targetPlayers = players.Where(p =>
|
||||
// is the player and its pawn valid
|
||||
p.IsValid && p.Pawn.IsValid &&
|
||||
|
||||
// we shouldn't hide ourselves
|
||||
p.Slot != player.Slot &&
|
||||
|
||||
// is the player is in the same team
|
||||
p.Team == player.Team &&
|
||||
|
||||
// is alive
|
||||
p.PlayerPawn.Value?.LifeState == (byte)LifeState_t.LIFE_ALIVE
|
||||
);
|
||||
|
||||
foreach (CCSPlayerController targetPlayer in targetPlayers)
|
||||
{
|
||||
// Calling 'Remove' will clear the entity index of the target player pawn from the transmission list
|
||||
// so it won't be transmitted for the 'player'.
|
||||
info.TransmitEntities.Remove(targetPlayer.Pawn);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
9
examples/WithFakeConvars/ConVars.cs
Normal file
9
examples/WithFakeConvars/ConVars.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
|
||||
namespace WithFakeConvars;
|
||||
|
||||
public static class ConVars
|
||||
{
|
||||
// This convar is registered from the plugin instance but can be used anywhere.
|
||||
public static FakeConVar<int> ExampleStaticCvar = new("example_static", "An example static cvar");
|
||||
}
|
||||
21
examples/WithFakeConvars/EvenNumberValidator.cs
Normal file
21
examples/WithFakeConvars/EvenNumberValidator.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using CounterStrikeSharp.API.Modules.Cvars.Validators;
|
||||
|
||||
namespace WithFakeConvars;
|
||||
|
||||
// This is an example of a custom validator that checks if a number is even.
|
||||
public class EvenNumberValidator : IValidator<int>
|
||||
{
|
||||
public bool Validate(int value, out string? errorMessage)
|
||||
{
|
||||
if (value % 2 == 0)
|
||||
{
|
||||
errorMessage = null;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorMessage = "Value must be an even number";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
examples/WithFakeConvars/README.md
Normal file
2
examples/WithFakeConvars/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# With Fake Convars
|
||||
This is an example that shows how to register "fake" convars, which are actually console commands that track their internal state.
|
||||
12
examples/WithFakeConvars/WithFakeConvars.csproj
Normal file
12
examples/WithFakeConvars/WithFakeConvars.csproj
Normal file
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\managed\CounterStrikeSharp.API\CounterStrikeSharp.API.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
58
examples/WithFakeConvars/WithFakeConvarsPlugin.cs
Normal file
58
examples/WithFakeConvars/WithFakeConvarsPlugin.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
using CounterStrikeSharp.API.Modules.Cvars.Validators;
|
||||
|
||||
namespace WithFakeConvars;
|
||||
|
||||
[MinimumApiVersion(175)]
|
||||
public class WithFakeConvarsPlugin : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "Example: With Fake Convars";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
public override string ModuleAuthor => "CounterStrikeSharp & Contributors";
|
||||
public override string ModuleDescription => "A simple plugin that registers some console variables";
|
||||
|
||||
// FakeConVar is a class that can be used to create custom console variables.
|
||||
// You can specify a name, description, default value, and custom validators.
|
||||
public FakeConVar<bool> BoolCvar = new("example_bool", "An example boolean cvar", true);
|
||||
|
||||
// Range validator is an inbuilt validator that can be used to ensure that a value is within a certain range.
|
||||
public FakeConVar<int> ExampleIntCvar = new("example_int", "An example integer cvar", 10, flags: ConVarFlags.FCVAR_NONE, new RangeValidator<int>(0, 100));
|
||||
|
||||
public FakeConVar<float> ExampleFloatCvar = new("example_float", "An example float cvar", 10, flags: ConVarFlags.FCVAR_NONE, new RangeValidator<float>(5, 20));
|
||||
public FakeConVar<string> ExampleStringCvar = new("example_string", "An example string cvar", "default");
|
||||
|
||||
// Replicated, Cheat & Protected flags are supported.
|
||||
public FakeConVar<float> ExamplePublicCvar = new("example_public_float", "An example public float cvar", 5,
|
||||
ConVarFlags.FCVAR_REPLICATED);
|
||||
|
||||
// Can only be changed if sv_cheats is enabled.
|
||||
public FakeConVar<float> ExampleCheatCvar = new("example_cheat_float", "An example cheat float cvar", 5,
|
||||
ConVarFlags.FCVAR_CHEAT);
|
||||
|
||||
// Protected cvars do not output their value when queried.
|
||||
public FakeConVar<float> ExampleProtectedCvar = new("example_protected_float", "An example cheat float cvar", 5,
|
||||
ConVarFlags.FCVAR_PROTECTED);
|
||||
|
||||
// You can create your own custom validators by implementing the IValidator interface.
|
||||
public FakeConVar<int> ExampleEvenNumberCvar = new("example_even_number", "An example even number cvar", 0, flags: ConVarFlags.FCVAR_NONE, new EvenNumberValidator());
|
||||
|
||||
public FakeConVar<int> RequiresRestartCvar = new("example_requires_restart", "A cvar that requires a restart when changed");
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
// You can subscribe to the ValueChanged event to execute code when the value of a cvar changes.
|
||||
// In this example, we restart the game when the value of RequiresRestartCvar is greater than 5.
|
||||
RequiresRestartCvar.ValueChanged += (sender, value) =>
|
||||
{
|
||||
if (value > 5)
|
||||
{
|
||||
Server.ExecuteCommand("mp_restartgame 1");
|
||||
}
|
||||
};
|
||||
|
||||
RegisterFakeConVars(typeof(ConVars));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
33
examples/WithSharedTypes/BalanceHandler.cs
Normal file
33
examples/WithSharedTypes/BalanceHandler.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using MySharedTypes.Contracts;
|
||||
|
||||
namespace WithSharedTypes;
|
||||
|
||||
public class BalanceHandler : IBalanceHandler
|
||||
{
|
||||
private readonly CCSPlayerController _player;
|
||||
|
||||
// This could be a database, a file, or a dictionary like this.
|
||||
internal static readonly Dictionary<CCSPlayerController, decimal> Balances = new();
|
||||
|
||||
public BalanceHandler(CCSPlayerController player)
|
||||
{
|
||||
_player = player;
|
||||
}
|
||||
|
||||
public decimal Balance
|
||||
{
|
||||
get => Balances.TryGetValue(_player, out var balance) ? balance : 0;
|
||||
set => Balances[_player] = value;
|
||||
}
|
||||
|
||||
public decimal Add(decimal amount)
|
||||
{
|
||||
return Balance += amount;
|
||||
}
|
||||
|
||||
public decimal Subtract(decimal amount)
|
||||
{
|
||||
return Balance -= amount;
|
||||
}
|
||||
}
|
||||
11
examples/WithSharedTypes/BalanceService.cs
Normal file
11
examples/WithSharedTypes/BalanceService.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using MySharedTypes.Contracts;
|
||||
|
||||
namespace WithSharedTypes;
|
||||
|
||||
public class BalanceService : IBalanceService
|
||||
{
|
||||
public void ClearAllBalances()
|
||||
{
|
||||
BalanceHandler.Balances.Clear();
|
||||
}
|
||||
}
|
||||
5
examples/WithSharedTypes/README.md
Normal file
5
examples/WithSharedTypes/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# With Shared Types (Capabilities)
|
||||
|
||||
An example plugin that exposes a balance contract library, to use as a shared library between multiple plugins.
|
||||
|
||||
This allows one plugin to expose a capability for a player or plugin, and other plugins to use the exposed API.
|
||||
13
examples/WithSharedTypes/WithSharedTypes.csproj
Normal file
13
examples/WithSharedTypes/WithSharedTypes.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\managed\CounterStrikeSharp.API\CounterStrikeSharp.API.csproj" />
|
||||
<ProjectReference Include="..\MySharedTypes.Contracts\MySharedTypes.Contracts\MySharedTypes.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
57
examples/WithSharedTypes/WithSharedTypesPlugin.cs
Normal file
57
examples/WithSharedTypes/WithSharedTypesPlugin.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Core.Capabilities;
|
||||
using MySharedTypes.Contracts;
|
||||
|
||||
namespace WithSharedTypes;
|
||||
|
||||
[MinimumApiVersion(184)]
|
||||
public class WithSharedTypesPlugin : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "Example: Shared Types";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
public override string ModuleAuthor => "CounterStrikeSharp & Contributors";
|
||||
public override string ModuleDescription => "A simple plugin that shares types between multiple plugins";
|
||||
|
||||
// Declares a player capability, that stores some sort of functionality for a player.
|
||||
// In this case, it's a balance handler, which is used to store a player's balance.
|
||||
// Note that we use the same name for the capability as the one in the other plugin.
|
||||
// IBalanceHandler is defined in MySharedTypes.Contracts, which is a shared library and placed in the `shared/` subfolder.
|
||||
public static PlayerCapability<IBalanceHandler> BalanceCapability { get; } = new("myplugin:balance");
|
||||
|
||||
// Declares a player capability of a primitive type, in this case, a decimal.
|
||||
public static PlayerCapability<Decimal> BalanceCapabilityDecimal { get; } = new("myplugin:balance_decimal");
|
||||
|
||||
// Plugin capabilities are similar to player capabilities, but they are not tied to a player, and are just generic APIs
|
||||
// that are exposed by a plugin. In this case, we expose a balance service, which is used to clear all balances.
|
||||
public static PluginCapability<IBalanceService> BalanceServiceCapability { get; } = new("myplugin:balance_service");
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
// Register the capability implementations here. Note that plugins don't need to register an implementation if it is already implemented in another plugin.
|
||||
Capabilities.RegisterPlayerCapability(BalanceCapability, player => new BalanceHandler(player));
|
||||
Capabilities.RegisterPluginCapability(BalanceServiceCapability, () => new BalanceService());
|
||||
Capabilities.RegisterPlayerCapability(BalanceCapabilityDecimal, (player) => new BalanceHandler(player).Balance);
|
||||
|
||||
AddCommand("css_balance", "Gets your current balance", (player, info) =>
|
||||
{
|
||||
if (player == null) return;
|
||||
player.PrintToChat($"Your balance is {BalanceCapability.Get(player)?.Balance}");
|
||||
});
|
||||
|
||||
AddCommand("css_give", "Gives you money", (player, info) =>
|
||||
{
|
||||
if (player == null) return;
|
||||
|
||||
var balance = BalanceCapability.Get(player);
|
||||
if (balance == null) return;
|
||||
|
||||
balance.Add(100);
|
||||
player.PrintToChat($"Your balance is now {balance.Balance}");
|
||||
});
|
||||
}
|
||||
|
||||
public override void Unload(bool hotReload)
|
||||
{
|
||||
}
|
||||
}
|
||||
2
examples/WithSharedTypesConsumer/README.md
Normal file
2
examples/WithSharedTypesConsumer/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# With Shared Types (Consumer Plugin)
|
||||
Uses the decimal balance shared library.
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\managed\CounterStrikeSharp.API\CounterStrikeSharp.API.csproj" />
|
||||
<ProjectReference Include="..\MySharedTypes.Contracts\MySharedTypes.Contracts\MySharedTypes.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,56 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Core.Capabilities;
|
||||
using CounterStrikeSharp.API.Core.Plugin;
|
||||
using MySharedTypes.Contracts;
|
||||
|
||||
namespace WithSharedTypesConsumer;
|
||||
|
||||
[MinimumApiVersion(184)]
|
||||
public class WithSharedTypesConsumerPlugin : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "Example: Shared Types (Consumer)";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
public override string ModuleAuthor => "CounterStrikeSharp & Contributors";
|
||||
public override string ModuleDescription => "A simple plugin that utilises the balance api from another plugin";
|
||||
|
||||
public static PlayerCapability<IBalanceHandler> BalanceCapability { get; } = new("myplugin:balance");
|
||||
public static PlayerCapability<Decimal> BalanceCapabilityDecimal { get; } = new("myplugin:balance_decimal");
|
||||
|
||||
public static PluginCapability<IBalanceService> BalanceServiceCapability { get; } = new("myplugin:balance_service");
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
AddCommand("css_subtract", "Subtracts 50 from your balance", (player, info) =>
|
||||
{
|
||||
if (player == null) return;
|
||||
var balance = BalanceCapability.Get(player);
|
||||
if (balance == null) return;
|
||||
balance.Subtract(50);
|
||||
player.PrintToChat($"Your balance is now {balance.Balance}");
|
||||
});
|
||||
|
||||
AddCommand("css_clearbalances", "Clears all balances", (player, info) =>
|
||||
{
|
||||
if (player == null) return;
|
||||
var service = BalanceServiceCapability.Get();
|
||||
if (service == null) return;
|
||||
|
||||
service.ClearAllBalances();
|
||||
|
||||
var balance = BalanceCapability.Get(player);
|
||||
if (balance == null) return;
|
||||
player.PrintToChat($"Your balance is now {balance.Balance}");
|
||||
});
|
||||
|
||||
AddCommand("css_decimalbalance", "Gets your current balance", (player, info) =>
|
||||
{
|
||||
if (player == null) return;
|
||||
player.PrintToChat($"Your balance is {BalanceCapabilityDecimal.Get(player)}");
|
||||
});
|
||||
}
|
||||
|
||||
public override void Unload(bool hotReload)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Globalization;
|
||||
using System.Globalization;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
@@ -22,18 +22,29 @@ public class WithTranslationsPlugin : BasePlugin
|
||||
// A global `Localizer` is provided on the plugin instance.
|
||||
// You can also use dependency injection to inject `IStringLocalizer` in your own services.
|
||||
Logger.LogInformation("This message is in the server language: {Message}", Localizer["test.translation"]);
|
||||
|
||||
|
||||
// IStringLocalizer can accept standard string format arguments.
|
||||
// "This number has 2 decimal places {0:n2}" -> "This number has 2 decimal places 123.55"
|
||||
Logger.LogInformation(Localizer["test.format", 123.551]);
|
||||
|
||||
|
||||
// This message has colour codes
|
||||
Server.PrintToChatAll(Localizer["test.colors"]);
|
||||
|
||||
// This message has colour codes and formatted values
|
||||
Server.PrintToChatAll(Localizer["test.colors.withformat", 123.551]);
|
||||
|
||||
// This prints the message to all players in their respective language
|
||||
PrintToAllPlayersLocalized("test.format", 123.456);
|
||||
}
|
||||
|
||||
|
||||
void PrintToAllPlayersLocalized(string key, params object[] args)
|
||||
{
|
||||
foreach (var player in Utilities.GetPlayers().Where(x => x.IsValid))
|
||||
{
|
||||
player.PrintToChat(Localizer.ForPlayer(player, key, args));
|
||||
}
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_replylanguage", "Test Translations")]
|
||||
public void OnCommandReplyLanguage(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
|
||||
2
examples/WithUserMessages/README.md
Normal file
2
examples/WithUserMessages/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# With User Messages
|
||||
This is example shows how you can hook, interrupt and send User Messages.
|
||||
12
examples/WithUserMessages/WithUserMessages.csproj
Normal file
12
examples/WithUserMessages/WithUserMessages.csproj
Normal file
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\managed\CounterStrikeSharp.API\CounterStrikeSharp.API.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
84
examples/WithUserMessages/WithUserMessagesPlugin.cs
Normal file
84
examples/WithUserMessages/WithUserMessagesPlugin.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.UserMessages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace WithUserMessages;
|
||||
|
||||
[MinimumApiVersion(80)]
|
||||
public class WithUserMessagesPlugin : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "Example: With User Messages";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
public override string ModuleAuthor => "CounterStrikeSharp & Contributors";
|
||||
public override string ModuleDescription => "A simple plugin that hooks and sends User Messages";
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
// Hooks can be added using the user message ID. In this case it's the ID for `CMsgTEFireBullets`.
|
||||
HookUserMessage(452, um =>
|
||||
{
|
||||
// Sets all weapon sounds to the sound of a silenced usp.
|
||||
um.SetUInt("weapon_id", 0);
|
||||
um.SetInt("sound_type", 9);
|
||||
um.SetUInt("item_def_index", 61);
|
||||
|
||||
return HookResult.Continue;
|
||||
}, HookMode.Pre);
|
||||
|
||||
HookUserMessage(118, um =>
|
||||
{
|
||||
var author = um.ReadString("param1");
|
||||
var message = um.ReadString("param2");
|
||||
Logger.LogInformation("Chat message from {Author}: {Message}", author, message);
|
||||
|
||||
for (var i = 0; i < um.Recipients.Count; i++)
|
||||
{
|
||||
Logger.LogInformation("Recipient {Index}: {Name}", i, um.Recipients[i].PlayerName);
|
||||
}
|
||||
|
||||
if (message.Contains("stop"))
|
||||
{
|
||||
return HookResult.Stop;
|
||||
}
|
||||
|
||||
if (message.Contains("skip"))
|
||||
{
|
||||
um.Recipients.Clear();
|
||||
}
|
||||
|
||||
return HookResult.Continue;
|
||||
});
|
||||
}
|
||||
|
||||
[ConsoleCommand("css_shake")]
|
||||
public void OnCommandShake(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
if (player == null) return;
|
||||
|
||||
// UserMessage.FromPartialName is a helper method that creates a UserMessage object from a partial network name.
|
||||
// In this case, it will resolve to `CUserMessageShake`.
|
||||
var message = UserMessage.FromPartialName("Shake");
|
||||
|
||||
message.SetFloat("duration", 2);
|
||||
message.SetFloat("amplitude", 5);
|
||||
message.SetFloat("frequency", 10f);
|
||||
message.SetInt("command", 0);
|
||||
|
||||
if (command.GetArg(1) == "all")
|
||||
{
|
||||
message.Recipients.AddAllPlayers();
|
||||
}
|
||||
else
|
||||
{
|
||||
message.Recipients.Add(player);
|
||||
}
|
||||
|
||||
message.Send();
|
||||
|
||||
// You can also use an overload of `Send` to send the message to a specific player without manually creating a recipient filter.
|
||||
// message.Send(player);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
|
||||
Submodule libraries/GameTracking-CS2 deleted from 3556d2a923
1
libraries/Protobufs
Submodule
1
libraries/Protobufs
Submodule
Submodule libraries/Protobufs added at 76e070dc65
Submodule libraries/hl2sdk-cs2 updated: 43bfe744a1...fc4b98f1a7
Submodule libraries/metamod-source updated: e857fbe90c...607301adc3
3747
libraries/moodycamel/concurrentqueue.h
Normal file
3747
libraries/moodycamel/concurrentqueue.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,4 @@
|
||||
#set(_ITERATOR_DEBUG_LEVEL 2)
|
||||
add_definitions(-D_LINUX -DPOSIX -DLINUX -DGNUC -DCOMPILER_GCC -DPLATFORM_64BITS)
|
||||
|
||||
add_definitions(-D_LINUX -DPOSIX -DLINUX -DGNUC -DCOMPILER_GCC -DPLATFORM_64BITS -D_FILE_OFFSET_BITS=64 -D_GLIBCXX_USE_CXX11_ABI=0)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Dstrnicmp=strncasecmp -D_snprintf=snprintf")
|
||||
@@ -16,16 +14,19 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -Wno-reorder")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse -msse -fno-strict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics -v -fvisibility=default")
|
||||
|
||||
SET(
|
||||
COUNTER_STRIKE_SHARP_LINK_LIBRARIES
|
||||
${SOURCESDK_LIB}/linux64/libtier0.so
|
||||
${SOURCESDK_LIB}/linux64/tier1.a
|
||||
${SOURCESDK_LIB}/linux64/interfaces.a
|
||||
${SOURCESDK_LIB}/linux64/mathlib.a
|
||||
spdlog
|
||||
dynload_s
|
||||
dyncall_s
|
||||
distorm
|
||||
funchook-static
|
||||
dynohook
|
||||
)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs=libprotobuf.a")
|
||||
|
||||
set(
|
||||
COUNTER_STRIKE_SHARP_LINK_LIBRARIES
|
||||
${SOURCESDK_LIB}/linux64/libtier0.so
|
||||
${SOURCESDK_LIB}/linux64/tier1.a
|
||||
${SOURCESDK_LIB}/linux64/interfaces.a
|
||||
${SOURCESDK_LIB}/linux64/mathlib.a
|
||||
spdlog
|
||||
dynload_s
|
||||
dyncall_s
|
||||
distorm
|
||||
funchook-static
|
||||
dynohook
|
||||
)
|
||||
|
||||
59
makefiles/protobuf.cmake
Normal file
59
makefiles/protobuf.cmake
Normal file
@@ -0,0 +1,59 @@
|
||||
# Credit for this protobuf generation cmake file goes to Poggicek.
|
||||
# Based on their work at https://github.com/Poggicek/StickerInspect
|
||||
|
||||
set(PROTO_TARGETS
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/network_connection.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/networkbasetypes.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/cs_gameevents.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/engine_gcmessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/gcsdk_gcmessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/cstrike15_gcmessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/cstrike15_usermessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/netmessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/steammessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/usermessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/gameevents.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/clientmessages.proto
|
||||
${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo/te.proto
|
||||
)
|
||||
|
||||
if(UNIX)
|
||||
set(PROTOC_EXECUTABLE ${PROJECT_SOURCE_DIR}/libraries/hl2sdk-cs2/devtools/bin/linux/protoc)
|
||||
elseif(WIN32)
|
||||
set(PROTOC_EXECUTABLE ${PROJECT_SOURCE_DIR}/libraries/hl2sdk-cs2/devtools/bin/protoc.exe)
|
||||
endif()
|
||||
|
||||
foreach(PROTO_TARGET ${PROTO_TARGETS})
|
||||
get_filename_component(PROTO_FILENAME ${PROTO_TARGET} NAME_WLE)
|
||||
list(APPEND PROTO_OUTPUT ${PROTO_FILENAME}.pb.cc ${PROTO_FILENAME}.pb.h)
|
||||
list(APPEND PROTO_INPUT ${PROTO_FILENAME}.proto)
|
||||
get_filename_component(PROTO_PATH ${PROTO_TARGET} DIRECTORY)
|
||||
list(APPEND PROTO_PATHS "--proto_path=${PROTO_PATH}")
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES PROTO_PATHS)
|
||||
list(TRANSFORM PROTO_OUTPUT PREPEND ${CMAKE_CURRENT_BINARY_DIR}/protobufcompiler/)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/protobufcompiler)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PROTO_OUTPUT}
|
||||
COMMAND "${PROTOC_EXECUTABLE}" -I ${PROJECT_SOURCE_DIR}/libraries/hl2sdk-cs2/thirdparty/protobuf-3.21.8/src --proto_path=${PROJECT_SOURCE_DIR}/libraries/Protobufs/csgo ${PROTO_PATHS} --cpp_out=${CMAKE_CURRENT_BINARY_DIR}/protobufcompiler ${PROTO_INPUT}
|
||||
COMMENT "Generating protobuf file"
|
||||
)
|
||||
|
||||
add_library(Protobufs STATIC
|
||||
${PROTO_OUTPUT}
|
||||
)
|
||||
|
||||
target_include_directories(Protobufs
|
||||
PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/protobufcompiler
|
||||
PUBLIC ${PROJECT_SOURCE_DIR}/libraries/hl2sdk-cs2/thirdparty/protobuf-3.21.8/src
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(Protobufs PUBLIC ${PROJECT_SOURCE_DIR}/libraries/hl2sdk-cs2/lib/public/win64/2015/libprotobuf.lib)
|
||||
elseif(UNIX)
|
||||
target_link_libraries(Protobufs PUBLIC ${PROJECT_SOURCE_DIR}/libraries/hl2sdk-cs2/lib/linux64/release/libprotobuf.a)
|
||||
endif()
|
||||
set_target_properties(Protobufs PROPERTIES LINKER_LANGUAGE CXX)
|
||||
set_target_properties(Protobufs PROPERTIES FOLDER SDK)
|
||||
@@ -1,8 +1,8 @@
|
||||
if (UNIX AND NOT APPLE)
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(LINUX TRUE)
|
||||
endif()
|
||||
|
||||
if (WIN32 AND NOT MSVC)
|
||||
if(WIN32 AND NOT MSVC)
|
||||
message(FATAL "MSVC restricted.")
|
||||
endif()
|
||||
|
||||
@@ -11,23 +11,39 @@ set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING
|
||||
FORCE
|
||||
)
|
||||
|
||||
# TODO: Use C++20 instead.
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
if (LINUX)
|
||||
if(LINUX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
endif()
|
||||
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
|
||||
set(LIBRARIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libraries)
|
||||
set(SOURCESDK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libraries/hl2sdk-cs2)
|
||||
set(METAMOD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libraries/metamod-source)
|
||||
|
||||
set(SOURCESDK ${SOURCESDK_DIR}/${BRANCH})
|
||||
set(SOURCESDK_LIB ${SOURCESDK}/lib)
|
||||
|
||||
add_definitions(-DMETA_IS_SOURCE2)
|
||||
add_definitions(-DMETA_IS_SOURCE2 -D_ITERATOR_DEBUG_LEVEL=0)
|
||||
|
||||
if(DEFINED ENV{GITHUB_SHA_SHORT})
|
||||
add_definitions(-DGITHUB_SHA="$ENV{GITHUB_SHA_SHORT}")
|
||||
else()
|
||||
add_definitions(-DGITHUB_SHA="Local")
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{BUILD_NUMBER})
|
||||
add_definitions(-DBUILD_NUMBER="$ENV{BUILD_NUMBER}")
|
||||
else()
|
||||
add_definitions(-DBUILD_NUMBER="0")
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${SOURCESDK}
|
||||
@@ -43,6 +59,7 @@ include_directories(
|
||||
${SOURCESDK}/public/entity2
|
||||
${SOURCESDK}/public/game/server
|
||||
${SOURCESDK}/public/entity2
|
||||
${SOURCESDK}/public/schemasystem
|
||||
${METAMOD_DIR}/core
|
||||
${METAMOD_DIR}/core/sourcehook
|
||||
libraries/dyncall/dynload
|
||||
@@ -51,7 +68,10 @@ include_directories(
|
||||
libraries/tl
|
||||
libraries/funchook/include
|
||||
libraries/DynoHook/src
|
||||
libraries/moodycamel
|
||||
libraries
|
||||
)
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/metamod/configure_metamod.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/metamod/configure_metamod.cmake)
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ add_definitions(
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4819 /wd4828 /wd5033 /permissive- /utf-8 /wd4005 /MP")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /OPT:REF /OPT:ICF")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:libcmt")
|
||||
|
||||
set(COUNTER_STRIKE_SHARP_LINK_LIBRARIES
|
||||
${SOURCESDK_LIB}/public/win64/tier0.lib
|
||||
@@ -18,4 +19,4 @@ set(COUNTER_STRIKE_SHARP_LINK_LIBRARIES
|
||||
distorm
|
||||
funchook-static
|
||||
dynohook
|
||||
)
|
||||
)
|
||||
|
||||
@@ -102,9 +102,18 @@ public class AdminTests
|
||||
[Fact]
|
||||
public void ShouldAddCommandPermissionOverridesAtRuntime()
|
||||
{
|
||||
Assert.False(AdminManager.CommandIsOverriden("runtime_command"));
|
||||
AdminManager.AddPermissionOverride("runtime_command", "@runtime/override");
|
||||
Assert.True(AdminManager.CommandIsOverriden("runtime_command"));
|
||||
Assert.Equal("@runtime/override", AdminManager.GetPermissionOverrides("runtime_command").Single());
|
||||
Assert.False(AdminManager.CommandIsOverriden("runtime_command_a"));
|
||||
AdminManager.AddPermissionOverride("runtime_command_a", "@runtime/override");
|
||||
Assert.True(AdminManager.CommandIsOverriden("runtime_command_a"));
|
||||
Assert.Equal("@runtime/override", AdminManager.GetPermissionOverrides("runtime_command_a").Single());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldAddCommandPermissionOverridesWithEmpty()
|
||||
{
|
||||
Assert.False(AdminManager.CommandIsOverriden("runtime_command_b"));
|
||||
AdminManager.AddPermissionOverride("runtime_command_b");
|
||||
Assert.True(AdminManager.CommandIsOverriden("runtime_command_b"));
|
||||
Assert.False(AdminManager.GetPermissionOverrides("runtime_command_b").Any());
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
|
||||
@@ -13,4 +13,14 @@ public class Api
|
||||
{
|
||||
return Assembly.GetAssembly(typeof(BasePlugin))!.GetName().Version!.Build;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the assembly version of CounterStrikeSharp running on the server as a string including git commit hash
|
||||
/// </summary>
|
||||
/// <example>1.0.0+9d8b6be</example>
|
||||
public static string GetVersionString()
|
||||
{
|
||||
return Assembly.GetAssembly(typeof(BasePlugin))!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()!
|
||||
.InformationalVersion;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
BIN
managed/CounterStrikeSharp.API/ApiCompat/v202.dll
Normal file
BIN
managed/CounterStrikeSharp.API/ApiCompat/v202.dll
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,7 @@ namespace CounterStrikeSharp.API
|
||||
[Flags]
|
||||
public enum ConVarFlags : Int64
|
||||
{
|
||||
FCVAR_NONE = 0,
|
||||
FCVAR_LINKED_CONCOMMAND = (1 << 0),
|
||||
|
||||
FCVAR_DEVELOPMENTONLY =
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
|
||||
using System;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.UserMessages;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
@@ -124,6 +127,17 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static CommandCallingContext CommandGetCallingContext(IntPtr command){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(command);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x886D0EB6);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (CommandCallingContext)ScriptContext.GlobalScriptContext.GetResult(typeof(CommandCallingContext));
|
||||
}
|
||||
}
|
||||
|
||||
public static void IssueClientCommand(int slot, string command){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -303,16 +317,6 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetGameFrameTime(){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x97E331CA);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (float)ScriptContext.GlobalScriptContext.GetResult(typeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
public static double GetEngineTime(){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -333,6 +337,16 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetGameFrameTime(){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x97E331CA);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (float)ScriptContext.GlobalScriptContext.GetResult(typeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
public static void IssueServerCommand(string command){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -490,20 +504,31 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static void QueueTaskForNextFrame(IntPtr callback){
|
||||
public static void QueueTaskForNextFrame(InputArgument callback){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(callback);
|
||||
ScriptContext.GlobalScriptContext.Push((InputArgument)callback);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x9FE394D8);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void QueueTaskForNextWorldUpdate(IntPtr callback){
|
||||
public static void QueueTaskForFrame(int tick, InputArgument callback){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(callback);
|
||||
ScriptContext.GlobalScriptContext.Push(tick);
|
||||
ScriptContext.GlobalScriptContext.Push((InputArgument)callback);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x2F92C340);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void QueueTaskForNextWorldUpdate(InputArgument callback){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push((InputArgument)callback);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xAD51A0C9);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
@@ -545,6 +570,17 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisconnectClient(int slot, int reason){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(slot);
|
||||
ScriptContext.GlobalScriptContext.Push(reason);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x799EE9C3);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr GetEntityFromIndex(int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -701,6 +737,37 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static void AcceptInput(IntPtr pthis, string inputname, IntPtr activator, IntPtr caller, string value, int outputid){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(pthis);
|
||||
ScriptContext.GlobalScriptContext.Push(inputname);
|
||||
ScriptContext.GlobalScriptContext.Push(activator);
|
||||
ScriptContext.GlobalScriptContext.Push(caller);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.Push(outputid);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x259E084C);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddEntityIoEvent(IntPtr ptarget, string inputname, IntPtr activator, IntPtr caller, string value, float delay, int outputid){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(ptarget);
|
||||
ScriptContext.GlobalScriptContext.Push(inputname);
|
||||
ScriptContext.GlobalScriptContext.Push(activator);
|
||||
ScriptContext.GlobalScriptContext.Push(caller);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.Push(delay);
|
||||
ScriptContext.GlobalScriptContext.Push(outputid);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x4CFDE98A);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void HookEvent(string name, InputArgument callback, bool ispost){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -737,6 +804,16 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static void FreeEvent(IntPtr gameevent){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(gameevent);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x7E8B60C2);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void FireEvent(IntPtr gameevent, bool dontbroadcast){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -1073,6 +1150,16 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveAllNetworkVectorElements(IntPtr vec){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(vec);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x67206C08);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static short GetSchemaOffset(string classname, string propname){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
@@ -1179,6 +1266,375 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static void HookUsermessage(int messageid, InputArgument callback, HookMode mode){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(messageid);
|
||||
ScriptContext.GlobalScriptContext.Push((InputArgument)callback);
|
||||
ScriptContext.GlobalScriptContext.Push(mode);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x76C63A83);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnhookUsermessage(int messageid, InputArgument callback, HookMode mode){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(messageid);
|
||||
ScriptContext.GlobalScriptContext.Push((InputArgument)callback);
|
||||
ScriptContext.GlobalScriptContext.Push(mode);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x63B0AC38);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool PbHasfield(UserMessage message, string name){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xC971FB70);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (bool)ScriptContext.GlobalScriptContext.GetResult(typeof(bool));
|
||||
}
|
||||
}
|
||||
|
||||
public static int PbReadint(UserMessage message, string name, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x5FA8BDC9);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (int)ScriptContext.GlobalScriptContext.GetResult(typeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
public static long PbReadint64(UserMessage message, string name, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xECCF528B);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (long)ScriptContext.GlobalScriptContext.GetResult(typeof(long));
|
||||
}
|
||||
}
|
||||
|
||||
public static float PbReadfloat(UserMessage message, string name, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xED208CEA);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (float)ScriptContext.GlobalScriptContext.GetResult(typeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
public static bool PbReadbool(UserMessage message, string name, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x54C0D7F4);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (bool)ScriptContext.GlobalScriptContext.GetResult(typeof(bool));
|
||||
}
|
||||
}
|
||||
|
||||
public static string PbReadstring(UserMessage message, string name, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x66CACEEF);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (string)ScriptContext.GlobalScriptContext.GetResult(typeof(string));
|
||||
}
|
||||
}
|
||||
|
||||
public static int PbGetrepeatedfieldcount(UserMessage message, string name){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xDE4E1549);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (int)ScriptContext.GlobalScriptContext.GetResult(typeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbSetint(UserMessage message, string name, int value, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x99BBC059);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbSetint64(UserMessage message, string name, long value, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xF7AD351B);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbSetfloat(UserMessage message, string name, float value, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xF7FDEB7A);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbSetbool(UserMessage message, string name, bool value, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xD1342864);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbSetstring(UserMessage message, string name, string value, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x15C78B7F);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbAddint(UserMessage message, string name, int value){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x66CD6A1A);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbAddint64(UserMessage message, string name, object value){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x4FD05AD8);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbAddfloat(UserMessage message, string name, float value){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x5117B239);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbAddbool(UserMessage message, string name, bool value){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x40827C47);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbAddstring(UserMessage message, string name, string value){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(value);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x8DFD739C);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void PbRemoverepeatedfieldvalue(UserMessage message, string name, int index){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.Push(index);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x1721FCB1);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static string PbGetdebugstring(UserMessage message){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x913FB7BA);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (string)ScriptContext.GlobalScriptContext.GetResult(typeof(string));
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong UsermessageGetrecipients(UserMessage message){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x70CDDEBE);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (ulong)ScriptContext.GlobalScriptContext.GetResult(typeof(ulong));
|
||||
}
|
||||
}
|
||||
|
||||
public static void UsermessageSetrecipients(UserMessage message, ulong recipients){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.Push(recipients);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xB4ED43AA);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static int UsermessageFindmessageidbyname(string name){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x22CD6C9F);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (int)ScriptContext.GlobalScriptContext.GetResult(typeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr UsermessageCreate(string name){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(name);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xE8E83344);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (IntPtr)ScriptContext.GlobalScriptContext.GetResult(typeof(IntPtr));
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr UsermessageCreatebyid(int id){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(id);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xBC758632);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (IntPtr)ScriptContext.GlobalScriptContext.GetResult(typeof(IntPtr));
|
||||
}
|
||||
}
|
||||
|
||||
public static void UsermessageSend(UserMessage message){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x24EB6B3C);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static void UsermessageDelete(UserMessage message){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xE10465D9);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
}
|
||||
}
|
||||
|
||||
public static int UsermessageGetid(UserMessage message){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xC17BA71B);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (int)ScriptContext.GlobalScriptContext.GetResult(typeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
public static string UsermessageGetname(UserMessage message){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xEFE0FD1);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (string)ScriptContext.GlobalScriptContext.GetResult(typeof(string));
|
||||
}
|
||||
}
|
||||
|
||||
public static string UsermessageGettype(UserMessage message){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.Push(message);
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0xEF4842E);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (string)ScriptContext.GlobalScriptContext.GetResult(typeof(string));
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr VectorNew(){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
|
||||
@@ -106,13 +106,13 @@ namespace CounterStrikeSharp.API.Core
|
||||
[RequiresPermissions("@css/generic")]
|
||||
private void OnCSSCommand(CCSPlayerController? caller, CommandInfo info)
|
||||
{
|
||||
var currentVersion = Api.GetVersion();
|
||||
var versionString = $"v{Api.GetVersion()} ({Api.GetVersionString()})";
|
||||
|
||||
info.ReplyToCommand(
|
||||
" CounterStrikeSharp was created and is maintained by Michael \"roflmuffin\" Wilson.\n" +
|
||||
" Counter-Strike Sharp uses code borrowed from SourceMod, Source.Python, FiveM, Saul Rennison, source2gen and CS2Fixes.\n" +
|
||||
" See ACKNOWLEDGEMENTS.md for more information.\n" +
|
||||
" Current API Version: " + currentVersion, true);
|
||||
" Current API Version: " + versionString);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -124,25 +124,24 @@ namespace CounterStrikeSharp.API.Core
|
||||
case "list":
|
||||
{
|
||||
info.ReplyToCommand(
|
||||
$" List of all plugins currently loaded by CounterStrikeSharp: {_pluginManager.GetLoadedPlugins().Count()} plugins loaded.",
|
||||
true);
|
||||
$" List of all plugins currently loaded by CounterStrikeSharp: {_pluginManager.GetLoadedPlugins().Count()} plugins loaded.");
|
||||
|
||||
foreach (var plugin in _pluginManager.GetLoadedPlugins())
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendFormat(" [#{0}:{1}]: \"{2}\" ({3})", plugin.PluginId,
|
||||
plugin.State.ToString().ToUpper(), plugin.Plugin.ModuleName,
|
||||
plugin.Plugin.ModuleVersion);
|
||||
if (!string.IsNullOrEmpty(plugin.Plugin.ModuleAuthor))
|
||||
plugin.State.ToString().ToUpper(), plugin.Plugin?.ModuleName ?? "Unknown",
|
||||
plugin.Plugin?.ModuleVersion ?? "Unknown");
|
||||
if (!string.IsNullOrEmpty(plugin.Plugin?.ModuleAuthor))
|
||||
sb.AppendFormat(" by {0}", plugin.Plugin.ModuleAuthor);
|
||||
if (!string.IsNullOrEmpty(plugin.Plugin.ModuleDescription))
|
||||
if (!string.IsNullOrEmpty(plugin.Plugin?.ModuleDescription))
|
||||
{
|
||||
sb.Append("\n");
|
||||
sb.Append(" ");
|
||||
sb.Append(plugin.Plugin.ModuleDescription);
|
||||
}
|
||||
|
||||
info.ReplyToCommand(sb.ToString(), true);
|
||||
info.ReplyToCommand(sb.ToString());
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -153,22 +152,14 @@ namespace CounterStrikeSharp.API.Core
|
||||
if (info.ArgCount < 3)
|
||||
{
|
||||
info.ReplyToCommand(
|
||||
"Valid usage: css_plugins start/load [relative plugin path || absolute plugin path] (e.g \"TestPlugin\", \"plugins/TestPlugin/TestPlugin.dll\")\n",
|
||||
true);
|
||||
"Valid usage: css_plugins start/load [relative plugin path || absolute plugin path] (e.g \"TestPlugin\", \"plugins/TestPlugin/TestPlugin.dll\")\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// If our arugment doesn't end in ".dll" - try and construct a path similar to PluginName/PluginName.dll.
|
||||
// If our argument doesn't end in ".dll" - try and construct a path similar to PluginName/PluginName.dll.
|
||||
// We'll assume we have a full path if we have ".dll".
|
||||
var path = info.GetArg(2);
|
||||
if (!path.EndsWith(".dll"))
|
||||
{
|
||||
path = Path.Combine(_scriptHostConfiguration.RootPath, $"plugins/{path}/{path}.dll");
|
||||
}
|
||||
else
|
||||
{
|
||||
path = Path.Combine(_scriptHostConfiguration.RootPath, path);
|
||||
}
|
||||
path = Path.Combine(_scriptHostConfiguration.RootPath, !path.EndsWith(".dll") ? $"plugins/{path}/{path}.dll" : path);
|
||||
|
||||
var plugin = _pluginContextQueryHandler.FindPluginByModulePath(path);
|
||||
|
||||
@@ -177,16 +168,19 @@ namespace CounterStrikeSharp.API.Core
|
||||
try
|
||||
{
|
||||
_pluginManager.LoadPlugin(path);
|
||||
plugin = _pluginContextQueryHandler.FindPluginByModulePath(path);
|
||||
plugin.Plugin.OnAllPluginsLoaded(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
info.ReplyToCommand($"Could not load plugin \"{path}\"", true);
|
||||
info.ReplyToCommand($"Could not load plugin \"{path}\"");
|
||||
Logger.LogError(e, "Could not load plugin \"{Path}\"", path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin.Load(false);
|
||||
plugin.Plugin.OnAllPluginsLoaded(false);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -198,16 +192,21 @@ namespace CounterStrikeSharp.API.Core
|
||||
if (info.ArgCount < 3)
|
||||
{
|
||||
info.ReplyToCommand(
|
||||
"Valid usage: css_plugins stop/unload [plugin name || #plugin id] (e.g \"TestPlugin\", \"1\")\n",
|
||||
true);
|
||||
"Valid usage: css_plugins stop/unload [plugin name || #plugin id] (e.g \"TestPlugin\", \"1\")\n");
|
||||
break;
|
||||
}
|
||||
|
||||
var pluginIdentifier = info.GetArg(2);
|
||||
IPluginContext? plugin = _pluginContextQueryHandler.FindPluginByIdOrName(pluginIdentifier);
|
||||
string path;
|
||||
path = Path.Combine(_scriptHostConfiguration.RootPath,
|
||||
!pluginIdentifier.EndsWith(".dll") ? $"plugins/{pluginIdentifier}/{pluginIdentifier}.dll" : pluginIdentifier);
|
||||
|
||||
var plugin = _pluginContextQueryHandler.FindPluginByIdOrName(pluginIdentifier)
|
||||
?? _pluginContextQueryHandler.FindPluginByModulePath(path);
|
||||
|
||||
if (plugin == null)
|
||||
{
|
||||
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\"", true);
|
||||
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\"");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -221,8 +220,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
if (info.ArgCount < 3)
|
||||
{
|
||||
info.ReplyToCommand(
|
||||
"Valid usage: css_plugins restart/reload [plugin name || #plugin id] (e.g \"TestPlugin\", \"#1\")\n",
|
||||
true);
|
||||
"Valid usage: css_plugins restart/reload [plugin name || #plugin id] (e.g \"TestPlugin\", \"#1\")\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -231,12 +229,13 @@ namespace CounterStrikeSharp.API.Core
|
||||
|
||||
if (plugin == null)
|
||||
{
|
||||
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\"", true);
|
||||
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\"");
|
||||
break;
|
||||
}
|
||||
|
||||
plugin.Unload(true);
|
||||
plugin.Load(true);
|
||||
plugin.Plugin.OnAllPluginsLoaded(true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -245,25 +244,21 @@ namespace CounterStrikeSharp.API.Core
|
||||
" list - List all plugins currently loaded.\n" +
|
||||
" start / load - Loads a plugin not currently loaded.\n" +
|
||||
" stop / unload - Unloads a plugin currently loaded.\n" +
|
||||
" restart / reload - Reloads a plugin currently loaded."
|
||||
, true);
|
||||
" restart / reload - Reloads a plugin currently loaded.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandHelper(usage: "[language code, e.g. \"de\", \"pl\", \"en\"]",
|
||||
whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
||||
private void OnLangCommand(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
if (player == null) return;
|
||||
|
||||
SteamID steamId = (SteamID)player.SteamID;
|
||||
var steamId = (SteamID)player.SteamID;
|
||||
|
||||
if (command.ArgCount == 1)
|
||||
{
|
||||
var language = _playerLanguageManager.GetLanguage(steamId);
|
||||
command.ReplyToCommand(string.Format("Current language is \"{0}\" ({1})", language.Name,
|
||||
language.NativeName));
|
||||
command.ReplyToCommand($"Current language is \"{language.Name}\" ({language.NativeName})");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -302,6 +297,11 @@ namespace CounterStrikeSharp.API.Core
|
||||
" stop / unload - Unloads a plugin currently loaded.\n" +
|
||||
" restart / reload - Reloads a plugin currently loaded.",
|
||||
});
|
||||
_commandManager.RegisterCommand(new("css_lang", "Set Counter-Strike Sharp language.", OnLangCommand)
|
||||
{
|
||||
ExecutableBy = CommandUsage.CLIENT_AND_SERVER,
|
||||
UsageHint = "[language code, e.g. \"de\", \"pl\", \"en\"]",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@ using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Events;
|
||||
using CounterStrikeSharp.API.Modules.Timers;
|
||||
using CounterStrikeSharp.API.Modules.Config;
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.UserMessages;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -72,6 +74,10 @@ namespace CounterStrikeSharp.API.Core
|
||||
public virtual void Unload(bool hotReload)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnAllPluginsLoaded(bool hotReload)
|
||||
{
|
||||
}
|
||||
|
||||
public class CallbackSubscriber : IDisposable
|
||||
{
|
||||
@@ -110,16 +116,10 @@ namespace CounterStrikeSharp.API.Core
|
||||
|
||||
public readonly Dictionary<Delegate, CallbackSubscriber> Handlers =
|
||||
new Dictionary<Delegate, CallbackSubscriber>();
|
||||
|
||||
public readonly Dictionary<Delegate, CallbackSubscriber> CommandHandlers =
|
||||
new Dictionary<Delegate, CallbackSubscriber>();
|
||||
|
||||
public readonly Dictionary<Delegate, CallbackSubscriber> CommandListeners =
|
||||
new Dictionary<Delegate, CallbackSubscriber>();
|
||||
|
||||
public readonly Dictionary<Delegate, CallbackSubscriber> ConvarChangeHandlers =
|
||||
new Dictionary<Delegate, CallbackSubscriber>();
|
||||
|
||||
public readonly Dictionary<Delegate, CallbackSubscriber> Listeners =
|
||||
new Dictionary<Delegate, CallbackSubscriber>();
|
||||
|
||||
@@ -129,6 +129,8 @@ namespace CounterStrikeSharp.API.Core
|
||||
internal readonly Dictionary<Delegate, EntityIO.EntityOutputCallback> EntitySingleOutputHooks =
|
||||
new Dictionary<Delegate, EntityIO.EntityOutputCallback>();
|
||||
|
||||
public readonly List<CommandDefinition> CommandDefinitions = new List<CommandDefinition>();
|
||||
|
||||
public readonly List<Timer> Timers = new List<Timer>();
|
||||
|
||||
public delegate HookResult GameEventHandler<T>(T @event, GameEventInfo info) where T : GameEvent;
|
||||
@@ -154,7 +156,23 @@ namespace CounterStrikeSharp.API.Core
|
||||
var name = typeof(T).GetCustomAttribute<EventNameAttribute>()?.Name;
|
||||
RegisterEventHandlerInternal(name, handler, hookMode == HookMode.Post);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// De-registers a game event handler.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="RegisterEventHandler{T}"/>
|
||||
public void DeregisterEventHandler<T>(GameEventHandler<T> handler, HookMode hookMode = HookMode.Post) where T : GameEvent
|
||||
{
|
||||
var name = typeof(T).GetCustomAttribute<EventNameAttribute>()!.Name;
|
||||
|
||||
if (!Handlers.TryGetValue(handler, out var subscriber)) return;
|
||||
|
||||
NativeAPI.UnhookEvent(name, subscriber.GetInputArgument(), hookMode == HookMode.Post);
|
||||
FunctionReference.Remove(subscriber.GetReferenceIdentifier());
|
||||
Handlers.Remove(handler);
|
||||
}
|
||||
|
||||
[Obsolete("Use the generic version of this method")]
|
||||
public void DeregisterEventHandler(string name, Delegate handler, bool post)
|
||||
{
|
||||
if (!Handlers.TryGetValue(handler, out var subscriber)) return;
|
||||
@@ -174,14 +192,22 @@ namespace CounterStrikeSharp.API.Core
|
||||
public void AddCommand(string name, string description, CommandInfo.CommandCallback handler)
|
||||
{
|
||||
var definition = new CommandDefinition(name, description, handler);
|
||||
CommandDefinitions.Add(definition);
|
||||
CommandManager.RegisterCommand(definition);
|
||||
}
|
||||
|
||||
private void AddCommand(CommandDefinition definition)
|
||||
{
|
||||
CommandDefinitions.Add(definition);
|
||||
CommandManager.RegisterCommand(definition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a command listener which will be called before or after the command is executed on the server by a player.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the command, e.g. `jointeam`</param>
|
||||
/// <param name="handler">Code to run when command is executed. Return <see cref="HookResult.Handled"/> or higher to prevent command execution.</param>
|
||||
/// <param name="mode">Whether to hook before or after the command is executed.</param>
|
||||
public void AddCommandListener(string? name, CommandInfo.CommandListenerCallback handler, HookMode mode = HookMode.Pre)
|
||||
{
|
||||
var wrappedHandler = new Func<int, IntPtr, HookResult>((i, ptr) =>
|
||||
@@ -197,19 +223,27 @@ namespace CounterStrikeSharp.API.Core
|
||||
CommandListeners[handler] = subscriber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a server command.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the command.</param>
|
||||
/// <param name="handler">The callback function to be invoked when the command is executed.</param>
|
||||
public void RemoveCommand(string name, CommandInfo.CommandCallback handler)
|
||||
{
|
||||
if (CommandHandlers.ContainsKey(handler))
|
||||
var definition = CommandDefinitions.FirstOrDefault(
|
||||
definition => definition.Name == name && definition.Callback == handler);
|
||||
|
||||
if (definition != null)
|
||||
{
|
||||
var subscriber = CommandHandlers[handler];
|
||||
|
||||
NativeAPI.RemoveCommand(name, subscriber.GetInputArgument());
|
||||
|
||||
FunctionReference.Remove(subscriber.GetReferenceIdentifier());
|
||||
CommandHandlers.Remove(handler);
|
||||
CommandDefinitions.Remove(definition);
|
||||
CommandManager.RemoveCommand(definition);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a command listener.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="AddCommandListener"/>
|
||||
public void RemoveCommandListener(string name, CommandInfo.CommandListenerCallback handler, HookMode mode)
|
||||
{
|
||||
if (CommandListeners.ContainsKey(handler))
|
||||
@@ -223,39 +257,24 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
public void HookConVarChange(ConVar convar, ConVar.ConVarChangedCallback handler)
|
||||
{
|
||||
var wrappedHandler = new Action<IntPtr, string, string>((ptr, oldVal, newVal) =>
|
||||
{
|
||||
handler?.Invoke(new ConVar(ptr), oldVal, newVal);
|
||||
});
|
||||
|
||||
var subscriber = new CallbackSubscriber(convar, handler, wrappedHandler);
|
||||
NativeAPI.HookConvarChange(convar.Handle, subscriber.GetInputArgument());
|
||||
ConvarChangeHandlers[handler] = subscriber;
|
||||
}
|
||||
|
||||
public void UnhookConVarChange(ConVar convar, ConVar.ConVarChangedCallback handler)
|
||||
{
|
||||
if (ConvarChangeHandlers.ContainsKey(handler))
|
||||
{
|
||||
var subscriber = ConvarChangeHandlers[handler];
|
||||
|
||||
NativeAPI.UnhookConvarChange(convar.Handle, subscriber.GetInputArgument());
|
||||
FunctionReference.Remove(subscriber.GetReferenceIdentifier());
|
||||
CommandHandlers.Remove(handler);
|
||||
}
|
||||
}*/
|
||||
|
||||
// Adds global listener, e.g. OnTick, OnClientConnect
|
||||
/// <summary>
|
||||
/// Registers a global listener, e.g. <see cref="Listeners.OnTick"/>, <see cref="Listeners.OnClientConnect"/>.
|
||||
/// </summary>
|
||||
/// <param name="handler"></param>
|
||||
/// <typeparam name="T">Listener delegate type</typeparam>
|
||||
/// <exception cref="ArgumentException">Invalid listener <see cref="T"/> provided</exception>
|
||||
/// <example>
|
||||
/// <code lang="C#">
|
||||
/// RegisterListener<Listeners.OnTick>(OnTick);
|
||||
/// </code>
|
||||
/// </example>
|
||||
public void RegisterListener<T>(T handler) where T : Delegate
|
||||
{
|
||||
var listenerName = typeof(T).GetCustomAttribute<ListenerNameAttribute>()?.Name;
|
||||
if (string.IsNullOrEmpty(listenerName))
|
||||
{
|
||||
throw new Exception("Listener of type T is invalid and does not have a name attribute");
|
||||
throw new ArgumentException("Listener of type T is invalid and does not have a name attribute",
|
||||
nameof(T));
|
||||
}
|
||||
|
||||
var parameterTypes = typeof(T).GetMethod("Invoke").GetParameters().Select(p => p.ParameterType).ToArray();
|
||||
@@ -286,6 +305,34 @@ namespace CounterStrikeSharp.API.Core
|
||||
Listeners[handler] = subscriber;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a global listener.
|
||||
/// </summary>
|
||||
/// <param name="handler"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <exception cref="ArgumentException">Invalid listener <see cref="T"/> provided</exception>
|
||||
public void RemoveListener<T>(T handler) where T : Delegate
|
||||
{
|
||||
var listenerName = typeof(T).GetCustomAttribute<ListenerNameAttribute>()?.Name;
|
||||
if (string.IsNullOrEmpty(listenerName))
|
||||
{
|
||||
throw new ArgumentException("Listener of type T is invalid and does not have a name attribute",
|
||||
nameof(T));
|
||||
}
|
||||
|
||||
if (!Listeners.TryGetValue(handler, out var subscriber)) return;
|
||||
|
||||
NativeAPI.RemoveListener(listenerName, subscriber.GetInputArgument());
|
||||
FunctionReference.Remove(subscriber.GetReferenceIdentifier());
|
||||
Listeners.Remove(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a global listener.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="handler"></param>
|
||||
[Obsolete("Use the generic version of this method")]
|
||||
public void RemoveListener(string name, Delegate handler)
|
||||
{
|
||||
if (!Listeners.TryGetValue(handler, out var subscriber)) return;
|
||||
@@ -295,6 +342,14 @@ namespace CounterStrikeSharp.API.Core
|
||||
Listeners.Remove(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a timer that will call the given callback after the specified amount of seconds.
|
||||
/// By default will only run once unless the <see cref="TimerFlags.REPEAT"/> flag is set.
|
||||
/// </summary>
|
||||
/// <param name="interval">Interval/Delay in seconds</param>
|
||||
/// <param name="callback">Code to run when timer elapses</param>
|
||||
/// <param name="flags">Controls if the timer is a one-off, repeat or stops on map change etc.</param>
|
||||
/// <returns>An instance of the <see cref="Timer"/></returns>
|
||||
public Timer AddTimer(float interval, Action callback, TimerFlags? flags = null)
|
||||
{
|
||||
var timer = new Timer(interval, callback, flags ?? 0);
|
||||
@@ -302,12 +357,17 @@ namespace CounterStrikeSharp.API.Core
|
||||
return timer;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Registers all attribute handlers on the given instance.
|
||||
/// Can be used to register event handlers, console commands, entity outputs etc. from classes that are not derived from `BasePlugin`.
|
||||
/// </summary>
|
||||
/// <param name="instance"></param>
|
||||
public void RegisterAllAttributes(object instance)
|
||||
{
|
||||
this.RegisterAttributeHandlers(instance);
|
||||
this.RegisterConsoleCommandAttributeHandlers(instance);
|
||||
this.RegisterEntityOutputAttributeHandlers(instance);
|
||||
this.RegisterFakeConVars(instance);
|
||||
}
|
||||
|
||||
public void InitializeConfig(object instance, Type pluginType)
|
||||
@@ -336,7 +396,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all game event handlers that are decorated with the `[GameEventHandler]` attribute.
|
||||
/// Registers all game event handlers that are decorated with the <see cref="GameEventHandlerAttribute"/> attribute.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance of the object where the event handlers are defined.</param>
|
||||
public void RegisterAttributeHandlers(object instance)
|
||||
@@ -366,6 +426,10 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all console command handlers that are decorated with the <see cref="ConsoleCommandAttribute"/> attribute.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance of the object where the console command handlers are defined.</param>
|
||||
public void RegisterConsoleCommandAttributeHandlers(object instance)
|
||||
{
|
||||
var eventHandlers = instance.GetType()
|
||||
@@ -393,6 +457,10 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers all entity output handlers that are decorated with the <see cref="EntityOutputHookAttribute"/> attribute.
|
||||
/// </summary>
|
||||
/// <param name="instance">The instance of the object where entity output hook handlers are defined.</param>
|
||||
public void RegisterEntityOutputAttributeHandlers(object instance)
|
||||
{
|
||||
var handlers = instance.GetType()
|
||||
@@ -410,6 +478,49 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterFakeConVars(Type type, object instance = null)
|
||||
{
|
||||
var convars = type
|
||||
.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
|
||||
.Where(prop => prop.FieldType.IsGenericType &&
|
||||
prop.FieldType.GetGenericTypeDefinition() == typeof(FakeConVar<>));
|
||||
|
||||
foreach (var prop in convars)
|
||||
{
|
||||
object propValue = prop.GetValue(instance); // FakeConvar<?> instance
|
||||
var propValueType = prop.FieldType.GenericTypeArguments[0];
|
||||
var name = prop.FieldType.GetProperty("Name", BindingFlags.Public | BindingFlags.Instance)
|
||||
.GetValue(propValue);
|
||||
|
||||
var description = prop.FieldType.GetProperty("Description", BindingFlags.Public | BindingFlags.Instance)
|
||||
.GetValue(propValue);
|
||||
|
||||
MethodInfo executeCommandMethod = prop.FieldType
|
||||
.GetMethod("ExecuteCommand", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
|
||||
this.AddCommand((string)name, (string) description, (caller, command) =>
|
||||
{
|
||||
executeCommandMethod.Invoke(propValue, new object[] {caller, command});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to bind a fake ConVar to a plugin command. Only required for ConVars that are not public properties of the plugin class.
|
||||
/// </summary>
|
||||
/// <param name="convar"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public void RegisterFakeConVars(object instance)
|
||||
{
|
||||
RegisterFakeConVars(instance.GetType(), instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hooks an <a href="https://developer.valvesoftware.com/wiki/Inputs_and_Outputs">entity output</a>.
|
||||
/// </summary>
|
||||
/// <param name="classname">Classname to hook, or `*` for wildcard</param>
|
||||
/// <param name="outputName">Output name to hook, or `*` for wildcard</param>
|
||||
/// <param name="handler">Handler to call</param>
|
||||
public void HookEntityOutput(string classname, string outputName, EntityIO.EntityOutputHandler handler, HookMode mode = HookMode.Pre)
|
||||
{
|
||||
var subscriber = new CallbackSubscriber(handler, handler,
|
||||
@@ -418,7 +529,29 @@ namespace CounterStrikeSharp.API.Core
|
||||
NativeAPI.HookEntityOutput(classname, outputName, subscriber.GetInputArgument(), mode);
|
||||
EntityOutputHooks[handler] = subscriber;
|
||||
}
|
||||
|
||||
public void HookUserMessage(int messageId, UserMessage.UserMessageHandler handler, HookMode mode = HookMode.Pre)
|
||||
{
|
||||
var subscriber = new CallbackSubscriber(handler, handler,
|
||||
() => UnhookUserMessage(messageId, handler));
|
||||
|
||||
NativeAPI.HookUsermessage(messageId, subscriber.GetInputArgument(), mode);
|
||||
Handlers[handler] = subscriber;
|
||||
}
|
||||
|
||||
public void UnhookUserMessage(int messageId, UserMessage.UserMessageHandler handler, HookMode mode = HookMode.Pre)
|
||||
{
|
||||
if (!Handlers.TryGetValue(handler, out var subscriber)) return;
|
||||
|
||||
NativeAPI.UnhookUsermessage(messageId, subscriber.GetInputArgument(), mode);
|
||||
FunctionReference.Remove(subscriber.GetReferenceIdentifier());
|
||||
Handlers.Remove(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unhooks an entity output.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="HookEntityOutput"/>
|
||||
public void UnhookEntityOutput(string classname, string outputName, EntityIO.EntityOutputHandler handler, HookMode mode = HookMode.Pre)
|
||||
{
|
||||
if (!EntityOutputHooks.TryGetValue(handler, out var subscriber)) return;
|
||||
@@ -428,6 +561,12 @@ namespace CounterStrikeSharp.API.Core
|
||||
EntityOutputHooks.Remove(handler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hooks an entity output for a single entity instance.
|
||||
/// </summary>
|
||||
/// <param name="entityInstance">Entity instance to hook</param>
|
||||
/// <param name="outputName">Output name to hook, or `*` for wildcard</param>
|
||||
/// <param name="handler">Handler to call</param>
|
||||
public void HookSingleEntityOutput(CEntityInstance entityInstance, string outputName, EntityIO.EntityOutputHandler handler)
|
||||
{
|
||||
// since we wrap around the plugin handler we need to do this to ensure that the plugin callback is only called
|
||||
@@ -451,6 +590,10 @@ namespace CounterStrikeSharp.API.Core
|
||||
EntitySingleOutputHooks[handler] = new EntityIO.EntityOutputCallback(entityInstance.DesignerName, outputName, internalHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unhooks an entity output for a single entity instance.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="HookSingleEntityOutput"/>
|
||||
public void UnhookSingleEntityOutput(CEntityInstance entityInstance, string outputName, EntityIO.EntityOutputHandler handler)
|
||||
{
|
||||
UnhookSingleEntityOutputInternal(entityInstance.DesignerName, outputName, handler);
|
||||
@@ -478,21 +621,12 @@ namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
subscriber.Dispose();
|
||||
}
|
||||
|
||||
foreach (var subscriber in CommandHandlers.Values)
|
||||
{
|
||||
subscriber.Dispose();
|
||||
}
|
||||
|
||||
foreach (var subscriber in CommandListeners.Values)
|
||||
{
|
||||
subscriber.Dispose();
|
||||
}
|
||||
|
||||
foreach (var kv in ConvarChangeHandlers)
|
||||
{
|
||||
}
|
||||
|
||||
foreach (var subscriber in Listeners.Values)
|
||||
{
|
||||
subscriber.Dispose();
|
||||
@@ -503,6 +637,11 @@ namespace CounterStrikeSharp.API.Core
|
||||
subscriber.Dispose();
|
||||
}
|
||||
|
||||
foreach (var definition in CommandDefinitions)
|
||||
{
|
||||
CommandManager.RemoveCommand(definition);
|
||||
}
|
||||
|
||||
foreach (var timer in Timers)
|
||||
{
|
||||
timer.Kill();
|
||||
@@ -511,4 +650,4 @@ namespace CounterStrikeSharp.API.Core
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace CounterStrikeSharp.API.Core.Capabilities;
|
||||
|
||||
public static class Capabilities
|
||||
{
|
||||
public static void RegisterPluginCapability<T>(PluginCapability<T> capability, Func<T> supplier)
|
||||
{
|
||||
if (!PluginCapability<T>.Providers.ContainsKey(capability.Name))
|
||||
{
|
||||
PluginCapability<T>.Providers.Add(capability.Name, new());
|
||||
}
|
||||
|
||||
PluginCapability<T>.Providers[capability.Name].Add(supplier);
|
||||
}
|
||||
|
||||
public static void RegisterPlayerCapability<T>(PlayerCapability<T> capability,
|
||||
Func<CCSPlayerController, T> supplier)
|
||||
{
|
||||
if (!PlayerCapability<T>.Providers.ContainsKey(capability.Name))
|
||||
{
|
||||
PlayerCapability<T>.Providers.Add(capability.Name, new());
|
||||
}
|
||||
|
||||
PlayerCapability<T>.Providers[capability.Name].Add(supplier);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core.Capabilities;
|
||||
|
||||
public sealed class PlayerCapability<T>
|
||||
{
|
||||
public string Name { get; }
|
||||
internal static readonly Dictionary<string, List<Func<CCSPlayerController, T>>> Providers = new();
|
||||
|
||||
public PlayerCapability(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public T? Get(CCSPlayerController entity)
|
||||
{
|
||||
foreach (var provider in Providers[Name])
|
||||
{
|
||||
return provider(entity);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core.Capabilities;
|
||||
|
||||
public sealed class PluginCapability<T>
|
||||
{
|
||||
public string Name { get; }
|
||||
internal static readonly Dictionary<string, List<Func<T>>> Providers = new();
|
||||
|
||||
public PluginCapability(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public T? Get()
|
||||
{
|
||||
foreach (var provider in Providers[Name])
|
||||
{
|
||||
return provider();
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
@@ -70,8 +70,13 @@ public class CommandManager : ICommandManager
|
||||
|
||||
if (_commandDefinitions.TryGetValue(name, out var handler))
|
||||
{
|
||||
foreach (var command in handler)
|
||||
foreach (var command in handler.ToList())
|
||||
{
|
||||
if (!handler.Contains(command))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var methodInfo = command.Callback?.GetMethodInfo();
|
||||
|
||||
// We do not need to do permission checks on commands executed from the server console.
|
||||
@@ -106,6 +111,11 @@ public class CommandManager : ICommandManager
|
||||
|
||||
foreach (var attr in permissionsToCheck)
|
||||
{
|
||||
if (attr.Permissions.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
attr.Command = name;
|
||||
if (!attr.CanExecuteCommand(caller))
|
||||
{
|
||||
|
||||
@@ -46,12 +46,21 @@ namespace CounterStrikeSharp.API.Core
|
||||
|
||||
[JsonPropertyName("FollowCS2ServerGuidelines")]
|
||||
public bool FollowCS2ServerGuidelines { get; set; } = true;
|
||||
|
||||
|
||||
[JsonPropertyName("PluginHotReloadEnabled")]
|
||||
public bool PluginHotReloadEnabled { get; set; } = true;
|
||||
|
||||
|
||||
[JsonPropertyName("PluginAutoLoadEnabled")]
|
||||
public bool PluginAutoLoadEnabled { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("ServerLanguage")]
|
||||
public string ServerLanguage { get; set; } = "en";
|
||||
|
||||
[JsonPropertyName("UnlockConCommands")]
|
||||
public bool UnlockConCommands { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("UnlockConVars")]
|
||||
public bool UnlockConVars { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -94,8 +103,18 @@ namespace CounterStrikeSharp.API.Core
|
||||
/// When enabled, plugins are automatically reloaded when their .dll file is updated.
|
||||
/// </summary>
|
||||
public static bool PluginHotReloadEnabled => _coreConfig.PluginHotReloadEnabled;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// When enabled, plugins are automatically loaded from the plugins directory on server start.
|
||||
/// </summary>
|
||||
public static bool PluginAutoLoadEnabled => _coreConfig.PluginAutoLoadEnabled;
|
||||
|
||||
public static string ServerLanguage => _coreConfig.ServerLanguage;
|
||||
|
||||
public static bool UnlockConCommands => _coreConfig.UnlockConCommands;
|
||||
|
||||
public static bool UnlockConVars => _coreConfig.UnlockConVars;
|
||||
|
||||
}
|
||||
|
||||
public partial class CoreConfig : IStartupService
|
||||
@@ -131,28 +150,29 @@ namespace CounterStrikeSharp.API.Core
|
||||
ReloadCoreConfigCommand));
|
||||
_commandsRegistered = true;
|
||||
}
|
||||
|
||||
if (!File.Exists(_coreConfigPath))
|
||||
|
||||
if (File.Exists(_coreConfigPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = JsonSerializer.Deserialize<CoreConfigData>(File.ReadAllText(_coreConfigPath),
|
||||
new JsonSerializerOptions() { ReadCommentHandling = JsonCommentHandling.Skip });
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
_coreConfig = data;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to load core configuration, fallback values will be used");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Core configuration could not be found at path \"{CoreConfigPath}\", fallback values will be used.",
|
||||
_coreConfigPath);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var data = JsonSerializer.Deserialize<CoreConfigData>(File.ReadAllText(_coreConfigPath),
|
||||
new JsonSerializerOptions() { ReadCommentHandling = JsonCommentHandling.Skip });
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
_coreConfig = data;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to load core configuration, fallback values will be used");
|
||||
}
|
||||
|
||||
var serverCulture = CultureInfo.GetCultures(CultureTypes.AllCultures)
|
||||
@@ -172,13 +192,13 @@ namespace CounterStrikeSharp.API.Core
|
||||
serverCulture = CultureInfo.InvariantCulture;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CultureInfo.DefaultThreadCurrentUICulture = serverCulture;
|
||||
CultureInfo.DefaultThreadCurrentCulture = serverCulture;
|
||||
CultureInfo.CurrentUICulture = serverCulture;
|
||||
CultureInfo.CurrentCulture = serverCulture;
|
||||
|
||||
|
||||
_logger.LogInformation("Successfully loaded core configuration");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,87 +14,121 @@
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the lifetime of a function reference.
|
||||
/// </summary>
|
||||
public enum FunctionLifetime
|
||||
{
|
||||
/// <summary>Delegate will be removed after the first invocation.</summary>
|
||||
SingleUse,
|
||||
|
||||
/// <summary>Delegate will remain in memory for the lifetime of the application (or until <see cref="FunctionReference.Remove"/> is called).</summary>
|
||||
Permanent
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a reference to a function that can be called from native code.
|
||||
/// </summary>
|
||||
public class FunctionReference
|
||||
{
|
||||
private readonly Delegate m_method;
|
||||
|
||||
public unsafe delegate void CallbackDelegate(fxScriptContext* context);
|
||||
private CallbackDelegate s_callback;
|
||||
|
||||
private FunctionReference(Delegate method)
|
||||
private static readonly ConcurrentDictionary<int, FunctionReference> IdToFunctionReferencesMap = new();
|
||||
private static readonly ConcurrentDictionary<Delegate, FunctionReference> TargetMethodToFunctionReferencesMap = new();
|
||||
|
||||
private static readonly object ReferenceCounterLock = new();
|
||||
private static int _referenceCounter;
|
||||
|
||||
private readonly Delegate _targetMethod;
|
||||
private readonly CallbackDelegate _nativeCallback;
|
||||
|
||||
private readonly TaskCompletionSource _taskCompletionSource = new();
|
||||
|
||||
private FunctionReference(Delegate method, FunctionLifetime lifetime)
|
||||
{
|
||||
m_method = method;
|
||||
|
||||
unsafe
|
||||
{
|
||||
var dg = new CallbackDelegate((fxScriptContext* context) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var scriptContext = new ScriptContext(context);
|
||||
|
||||
if (method.Method.GetParameters().FirstOrDefault()?.ParameterType == typeof(ScriptContext))
|
||||
{
|
||||
var returnO = m_method.DynamicInvoke(scriptContext);
|
||||
if (returnO != null)
|
||||
{
|
||||
scriptContext.SetResult(returnO, context);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var paramsList = method.Method.GetParameters().Select((x, i) =>
|
||||
{
|
||||
var param = method.Method.GetParameters()[i];
|
||||
object obj = null;
|
||||
if (typeof(NativeObject).IsAssignableFrom(param.ParameterType))
|
||||
{
|
||||
obj = Activator.CreateInstance(param.ParameterType,
|
||||
new[] {scriptContext.GetArgument(typeof(IntPtr), i)});
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = scriptContext.GetArgument(param.ParameterType, i);
|
||||
}
|
||||
return obj;
|
||||
}).ToArray();
|
||||
|
||||
var returnObj = m_method.DynamicInvoke(paramsList);
|
||||
|
||||
if (returnObj != null)
|
||||
{
|
||||
scriptContext.SetResult(returnObj, context);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Application.Instance.Logger.LogError(e, "Error invoking callback");
|
||||
}
|
||||
});
|
||||
s_callback = dg;
|
||||
}
|
||||
|
||||
Lifetime = lifetime;
|
||||
_targetMethod = method;
|
||||
_nativeCallback = CreateWrappedCallback();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="FunctionLifetime"/>
|
||||
/// </summary>
|
||||
public FunctionLifetime Lifetime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// For <see cref="FunctionLifetime.SingleUse"/> function references, this task will complete when
|
||||
/// the function has finished invoking.
|
||||
/// </summary>
|
||||
public Task CompletionTask => _taskCompletionSource.Task;
|
||||
|
||||
public int Identifier { get; private set; }
|
||||
|
||||
public static FunctionReference Create(Delegate method)
|
||||
private unsafe CallbackDelegate CreateWrappedCallback()
|
||||
{
|
||||
if (references.ContainsKey(method))
|
||||
return context =>
|
||||
{
|
||||
return references[method];
|
||||
try
|
||||
{
|
||||
var scriptContext = new ScriptContext(context);
|
||||
|
||||
// Allow for manual handling of the script context
|
||||
if (_targetMethod.Method.GetParameters().FirstOrDefault()?.ParameterType == typeof(ScriptContext))
|
||||
{
|
||||
var returnValue = _targetMethod.DynamicInvoke(scriptContext);
|
||||
if (returnValue != null)
|
||||
{
|
||||
scriptContext.SetResult(returnValue, context);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var parameterList = _targetMethod.Method.GetParameters().Select((_, i) =>
|
||||
{
|
||||
var parameter = _targetMethod.Method.GetParameters()[i];
|
||||
return scriptContext.GetArgument(parameter.ParameterType, i);
|
||||
}).ToArray();
|
||||
|
||||
var returnObj = _targetMethod.DynamicInvoke(parameterList);
|
||||
|
||||
if (returnObj != null)
|
||||
{
|
||||
scriptContext.SetResult(returnObj, context);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Application.Instance.Logger.LogError(e, "Error invoking callback");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Lifetime == FunctionLifetime.SingleUse)
|
||||
{
|
||||
RemoveSelf();
|
||||
}
|
||||
|
||||
_taskCompletionSource.TrySetResult();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static FunctionReference Create(Delegate method, FunctionLifetime lifetime = FunctionLifetime.Permanent)
|
||||
{
|
||||
// We always want to create a new reference if the lifetime is single use.
|
||||
if (lifetime == FunctionLifetime.Permanent && TargetMethodToFunctionReferencesMap.TryGetValue(method, out var existingReference))
|
||||
{
|
||||
return existingReference;
|
||||
}
|
||||
|
||||
var reference = new FunctionReference(method);
|
||||
var reference = new FunctionReference(method, lifetime);
|
||||
var referenceId = Register(reference);
|
||||
|
||||
reference.Identifier = referenceId;
|
||||
@@ -102,44 +136,41 @@ namespace CounterStrikeSharp.API.Core
|
||||
return reference;
|
||||
}
|
||||
|
||||
private static Dictionary<int, FunctionReference> ms_references = new Dictionary<int, FunctionReference>();
|
||||
private static int ms_referenceId;
|
||||
|
||||
private static Dictionary<Delegate, FunctionReference> references =
|
||||
new Dictionary<Delegate, FunctionReference>();
|
||||
|
||||
private static int Register(FunctionReference reference)
|
||||
{
|
||||
var thisRefId = ms_referenceId;
|
||||
ms_references[thisRefId] = reference;
|
||||
references[reference.m_method] = reference;
|
||||
|
||||
unchecked { ms_referenceId++; }
|
||||
|
||||
return thisRefId;
|
||||
}
|
||||
|
||||
public static FunctionReference Get(int reference)
|
||||
{
|
||||
if (ms_references.ContainsKey(reference))
|
||||
lock (ReferenceCounterLock)
|
||||
{
|
||||
return ms_references[reference];
|
||||
}
|
||||
var thisRefId = _referenceCounter;
|
||||
IdToFunctionReferencesMap[thisRefId] = reference;
|
||||
TargetMethodToFunctionReferencesMap[reference._targetMethod] = reference;
|
||||
|
||||
return null;
|
||||
unchecked
|
||||
{
|
||||
_referenceCounter++;
|
||||
}
|
||||
|
||||
return thisRefId;
|
||||
}
|
||||
}
|
||||
|
||||
public IntPtr GetFunctionPointer()
|
||||
|
||||
public IntPtr GetFunctionPointer() => Marshal.GetFunctionPointerForDelegate(_nativeCallback);
|
||||
|
||||
private void RemoveSelf()
|
||||
{
|
||||
IntPtr cb = Marshal.GetFunctionPointerForDelegate(s_callback);
|
||||
return cb;
|
||||
Remove(Identifier);
|
||||
}
|
||||
|
||||
public static void Remove(int reference)
|
||||
{
|
||||
if (ms_references.TryGetValue(reference, out var funcRef))
|
||||
if (IdToFunctionReferencesMap.TryGetValue(reference, out var functionReference))
|
||||
{
|
||||
ms_references.Remove(reference);
|
||||
if (TargetMethodToFunctionReferencesMap.ContainsKey(functionReference._targetMethod))
|
||||
{
|
||||
TargetMethodToFunctionReferencesMap.Remove(functionReference._targetMethod, out _);
|
||||
}
|
||||
|
||||
IdToFunctionReferencesMap.Remove(reference, out _);
|
||||
|
||||
Application.Instance.Logger.LogDebug("Removing function/callback reference: {Reference}", reference);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,12 @@ public interface IScriptHostConfiguration
|
||||
/// </summary>
|
||||
string PluginPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the absolute path to the directory that contains CounterStrikeSharp plugin shared APIS.
|
||||
/// e.g. /game/csgo/addons/counterstrikesharp/shared
|
||||
/// </summary>
|
||||
string SharedPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the absolute path to the directory that contains CounterStrikeSharp configs.
|
||||
/// e.g. /game/csgo/addons/counterstrikesharp/configs
|
||||
|
||||
@@ -7,12 +7,14 @@ internal sealed class ScriptHostConfiguration : IScriptHostConfiguration
|
||||
{
|
||||
public string RootPath { get; }
|
||||
public string PluginPath { get; }
|
||||
public string SharedPath { get; }
|
||||
public string ConfigsPath { get; }
|
||||
public string GameDataPath { get; }
|
||||
|
||||
public ScriptHostConfiguration(IHostEnvironment hostEnvironment)
|
||||
{
|
||||
RootPath = Path.Join(new[] { hostEnvironment.ContentRootPath });
|
||||
SharedPath = Path.Join(new[] { hostEnvironment.ContentRootPath, "shared" });
|
||||
PluginPath = Path.Join(new[] { hostEnvironment.ContentRootPath, "plugins" });
|
||||
ConfigsPath = Path.Join(new[] { hostEnvironment.ContentRootPath, "configs" });
|
||||
GameDataPath = Path.Join(new[] { hostEnvironment.ContentRootPath, "gamedata" });
|
||||
|
||||
@@ -28,17 +28,23 @@ namespace CounterStrikeSharp.API.Core
|
||||
public interface IPlugin : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the plugin.
|
||||
/// Name of the plugin as it will appear in the plugin list.
|
||||
/// </summary>
|
||||
string ModuleName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Module version.
|
||||
/// Module version as it will appear in the plugin list.
|
||||
/// </summary>
|
||||
string ModuleVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Author of the plugin as it will appear in the plugin list.
|
||||
/// </summary>
|
||||
string ModuleAuthor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Brief description of the plugin as it will appear in the plugin list.
|
||||
/// </summary>
|
||||
string ModuleDescription { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -53,12 +59,23 @@ namespace CounterStrikeSharp.API.Core
|
||||
/// </summary>
|
||||
void Unload(bool hotReload);
|
||||
|
||||
/// <summary>
|
||||
/// Will be called by CounterStrikeSharp after all plugins have been loaded.
|
||||
/// This will also be called for convenience after a reload or a late l oad, so that you don't have to handle
|
||||
/// re-wiring everything.
|
||||
/// </summary>
|
||||
/// <param name="hotReload"></param>
|
||||
void OnAllPluginsLoaded(bool hotReload);
|
||||
|
||||
/// <summary>
|
||||
/// The path to the plugin's DLL file.
|
||||
/// </summary>
|
||||
string ModulePath { get; internal set; }
|
||||
|
||||
ILogger Logger { get; set; }
|
||||
|
||||
|
||||
IStringLocalizer Localizer { get; set; }
|
||||
|
||||
|
||||
ICommandManager CommandManager { get; set; }
|
||||
|
||||
void RegisterAllAttributes(object instance);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
@@ -154,5 +155,20 @@ namespace CounterStrikeSharp.API.Core
|
||||
/// <param name="simulating"><see langword="true"/> if simulating, <see langword="false"/> otherwise</param>
|
||||
[ListenerName("OnServerPreWorldUpdate")]
|
||||
public delegate void OnServerPreWorldUpdate(bool simulating);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called when the server precaching resources (only when initial startup / changing map).
|
||||
/// </summary>
|
||||
/// <param name="manifest">Resource Manifest</param>
|
||||
[ListenerName("OnServerPrecacheResources")]
|
||||
public delegate void OnServerPrecacheResources(ResourceManifest manifest);
|
||||
|
||||
/// <summary>
|
||||
/// Called when checking transmit on entities.
|
||||
/// </summary>
|
||||
/// <param name="infoList">Transmit info list</param>
|
||||
[ListenerName("CheckTransmit")]
|
||||
public delegate void CheckTransmit([CastFrom(typeof(nint))]CCheckTransmitInfoList infoList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
@@ -6,14 +7,27 @@ namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
public partial class CBaseEntity
|
||||
{
|
||||
public void Teleport(Vector position, QAngle angles, Vector velocity)
|
||||
/// <exception cref="InvalidOperationException">Entity is not valid</exception>
|
||||
/// <exception cref="ArgumentNullException">No valid argument</exception>
|
||||
public void Teleport(Vector? position = null, QAngle? angles = null, Vector? velocity = null)
|
||||
{
|
||||
VirtualFunction.CreateVoid<IntPtr, IntPtr, IntPtr, IntPtr>(Handle, GameData.GetOffset("CBaseEntity_Teleport"))(
|
||||
Handle, position.Handle, angles.Handle, velocity.Handle);
|
||||
Guard.IsValidEntity(this);
|
||||
|
||||
if (position == null && angles == null && velocity == null)
|
||||
throw new ArgumentNullException("No valid argument");
|
||||
|
||||
nint _position = position?.Handle ?? 0;
|
||||
nint _angles = angles?.Handle ?? 0;
|
||||
nint _velocity = velocity?.Handle ?? 0;
|
||||
|
||||
VirtualFunction.CreateVoid<IntPtr, IntPtr, IntPtr, IntPtr>(Handle, GameData.GetOffset("CBaseEntity_Teleport"))(Handle, _position, _angles, _velocity);
|
||||
}
|
||||
|
||||
/// <exception cref="InvalidOperationException">Entity is not valid</exception>
|
||||
public void DispatchSpawn()
|
||||
{
|
||||
Guard.IsValidEntity(this);
|
||||
|
||||
VirtualFunctions.CBaseEntity_DispatchSpawn(Handle, IntPtr.Zero);
|
||||
}
|
||||
|
||||
@@ -25,7 +39,13 @@ public partial class CBaseEntity
|
||||
/// <summary>
|
||||
/// Shorthand for accessing an entity's CBodyComponent?.SceneNode?.AbsRotation;
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">Entity is not valid</exception>
|
||||
public QAngle? AbsRotation => CBodyComponent?.SceneNode?.AbsRotation;
|
||||
|
||||
public T? GetVData<T>() where T : CEntitySubclassVDataBase => (T)Activator.CreateInstance(typeof(T), Marshal.ReadIntPtr(SubclassID.Handle + 4));
|
||||
}
|
||||
public T? GetVData<T>() where T : CEntitySubclassVDataBase
|
||||
{
|
||||
Guard.IsValidEntity(this);
|
||||
|
||||
return (T)Activator.CreateInstance(typeof(T), Marshal.ReadIntPtr(SubclassID.Handle + 4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,11 @@ namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
public partial class CBaseModelEntity
|
||||
{
|
||||
/// <exception cref="InvalidOperationException">Entity is not valid</exception>
|
||||
public void SetModel(string model)
|
||||
{
|
||||
Guard.IsValidEntity(this);
|
||||
|
||||
VirtualFunctions.SetModel(Handle, model);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
|
||||
using CounterStrikeSharp.API.Modules.Cvars;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
@@ -10,10 +9,13 @@ namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
public partial class CBasePlayerController
|
||||
{
|
||||
public void SetPawn(CBasePlayerPawn? pawn)
|
||||
{
|
||||
if (pawn is null) return;
|
||||
if (!pawn.IsValid) return;
|
||||
VirtualFunctions.CBasePlayerController_SetPawnFunc.Invoke(this, pawn, true, false);
|
||||
}
|
||||
/// <exception cref="InvalidOperationException">Entity is not valid</exception>
|
||||
public void SetPawn(CBasePlayerPawn? pawn)
|
||||
{
|
||||
Guard.IsValidEntity(this);
|
||||
|
||||
if (pawn is null) return;
|
||||
if (!pawn.IsValid) return;
|
||||
VirtualFunctions.CBasePlayerController_SetPawnFunc.Invoke(this, pawn, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,17 +10,24 @@ public partial class CBasePlayerPawn
|
||||
/// </summary>
|
||||
/// <param name="explode"></param>
|
||||
/// <param name="force"></param>
|
||||
/// <exception cref="InvalidOperationException">Entity is not valid</exception>
|
||||
public void CommitSuicide(bool explode, bool force)
|
||||
{
|
||||
Guard.IsValidEntity(this);
|
||||
|
||||
VirtualFunction.CreateVoid<IntPtr, bool, bool>(Handle, GameData.GetOffset("CBasePlayerPawn_CommitSuicide"))(Handle, explode, force);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Remove Player Item
|
||||
/// </summary>
|
||||
/// <param name="weapon"></param>
|
||||
/// <exception cref="InvalidOperationException">Entity is not valid</exception>
|
||||
public void RemovePlayerItem(CBasePlayerWeapon weapon)
|
||||
{
|
||||
Guard.IsValidEntity(this);
|
||||
Guard.IsValidEntity(weapon);
|
||||
|
||||
VirtualFunctions.RemovePlayerItemVirtual(Handle, weapon.Handle);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
@@ -26,6 +27,35 @@ public partial class CCSGameRules
|
||||
/// </summary>
|
||||
public void TerminateRound(float delay, RoundEndReason roundEndReason)
|
||||
{
|
||||
VirtualFunctions.TerminateRound(Handle, roundEndReason, delay);
|
||||
VirtualFunctions.TerminateRound(Handle, roundEndReason, delay, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public T? FindPickerEntity<T>(CBasePlayerController player)
|
||||
where T : CBaseEntity
|
||||
{
|
||||
VirtualFunctionWithReturn<CCSGameRules, CBasePlayerController, CBaseEntity?> CCSGameRules_FindPickerEntity = new (Handle, GameData.GetOffset("CCSGameRules_FindPickerEntity"));
|
||||
CBaseEntity? entity = CCSGameRules_FindPickerEntity.Invoke(this, player);
|
||||
|
||||
if (entity == null || !entity.IsValid)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return entity.As<T>();
|
||||
}
|
||||
|
||||
public CCSPlayerController? GetClientAimTarget(CCSPlayerController player)
|
||||
{
|
||||
CCSPlayerPawn? pawn = FindPickerEntity<CCSPlayerPawn>(player);
|
||||
|
||||
if (pawn == null || !pawn.IsValid)
|
||||
return null;
|
||||
|
||||
if (pawn.DesignerName == "player")
|
||||
{
|
||||
return pawn.OriginalController.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user