mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-07 00:16:36 -08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8967c40bed | ||
|
|
12c6f4d0a1 | ||
|
|
f2b8044b8c | ||
|
|
eb9f5667d8 | ||
|
|
b9ca63a603 | ||
|
|
8fc926eacf | ||
|
|
5695c3f922 | ||
|
|
9071d51ecd | ||
|
|
0a32962f4a | ||
|
|
271705b377 | ||
|
|
cdcddbb5f3 | ||
|
|
91f51d0c5c | ||
|
|
e97f804294 | ||
|
|
4f805b18e2 | ||
|
|
e1f9b5635e | ||
|
|
59bff4f500 | ||
|
|
a2581d8e91 | ||
|
|
e7d190a6f7 | ||
|
|
5513d5710a | ||
|
|
e5c223699c | ||
|
|
fa37c222d9 |
10
.github/workflows/cmake-single-platform.yml
vendored
10
.github/workflows/cmake-single-platform.yml
vendored
@@ -196,6 +196,7 @@ jobs:
|
|||||||
(cd build/windows && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ needs.build_managed.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
(cd build/windows && zip -qq -r ../../counterstrikesharp-with-runtime-build-${{ needs.build_managed.outputs.buildnumber }}-windows-${{ env.GITHUB_SHA_SHORT }}.zip *)
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
|
id: release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
tag_name: v${{ needs.build_managed.outputs.buildnumber }}
|
tag_name: v${{ needs.build_managed.outputs.buildnumber }}
|
||||||
@@ -208,4 +209,11 @@ jobs:
|
|||||||
- name: Publish NuGet package
|
- name: Publish NuGet package
|
||||||
run: |
|
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 }}.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.build_managed.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 }}"
|
||||||
@@ -128,4 +128,4 @@ Build
|
|||||||
```bash
|
```bash
|
||||||
cmake --build . --config Debug
|
cmake --build . --config Debug
|
||||||
```
|
```
|
||||||
|
<img src="https://repobeats.axiom.co/api/embed/a96f228b8fa98c032070fa8dd831c967334ee553.svg" width="100%" />
|
||||||
|
|||||||
@@ -22,28 +22,28 @@
|
|||||||
},
|
},
|
||||||
"CCSPlayerController_ChangeTeam": {
|
"CCSPlayerController_ChangeTeam": {
|
||||||
"offsets": {
|
"offsets": {
|
||||||
"windows": 90,
|
"windows": 93,
|
||||||
"linux": 89
|
"linux": 92
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CCSPlayerController_Respawn": {
|
"CCSPlayerController_Respawn": {
|
||||||
"offsets": {
|
"offsets": {
|
||||||
"windows": 242,
|
"windows": 245,
|
||||||
"linux": 244
|
"linux": 247
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CCSPlayerPawn_Respawn": {
|
"CBasePlayerController_SetPawn": {
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x40\\x53\\x48\\x83\\xEC\\x20\\x8B\\x91\\x38\\x0B\\x00\\x00\\x48\\x8B\\xD9",
|
"windows": "\\x44\\x88\\x4C\\x24\\x20\\x55\\x57\\x41\\x54\\x41\\x56\\x41\\x57\\x48\\x8D\\x6C\\x24\\x2A\\x48\\x81\\xEC\\x2A",
|
||||||
"linux": "\\x8B\\x8F\\x40\\x0E\\x00\\x00\\x83\\xF9\\xFF\\x0F\\x84\\xD9\\x01"
|
"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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CCSPlayerPawnBase_PostThink": {
|
"CCSPlayerPawnBase_PostThink": {
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x48\\x8B\\xC4\\x48\\x89\\x48\\x08\\x55\\x53\\x56\\x57\\x41\\x56\\x48\\x8D\\xA8\\xD8\\xFE\\xFF\\xFF",
|
"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\\x49\\x89\\xFF\\x41\\x56\\x41\\x55\\x41\\x54\\x53\\x48\\x81\\xEC\\x2A\\x2A\\x2A\\x2A\\xE8\\x2A\\x2A\\x2A\\x2A\\x4C"
|
"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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"GiveNamedItem": {
|
"GiveNamedItem": {
|
||||||
@@ -70,8 +70,15 @@
|
|||||||
"CBaseModelEntity_SetModel": {
|
"CBaseModelEntity_SetModel": {
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x48\\x89\\x7C\\x24\\x20\\x55\\x48\\x8B\\xEC\\x48\\x83\\xEC\\x50",
|
"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\\x2A\\x2A\\x48\\x83\\x2A\\x2A\\x2A\\x8D\\x05\\x2A\\x2A\\x2A\\x00\\x48\\x8B\\x30\\x48\\x8B\\x06\\xFF\\x2A\\x2A\\x48\\x8B\\x45\\x2A\\x48\\x8D\\x2A\\x2A\\x4C\\x89\\x2A\\x48\\x89\\x45\\x2A\\x2A\\x68\\xFC"
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CCSPlayer_ItemServices_DropActivePlayerWeapon": {
|
"CCSPlayer_ItemServices_DropActivePlayerWeapon": {
|
||||||
@@ -82,7 +89,7 @@
|
|||||||
},
|
},
|
||||||
"CCSPlayer_ItemServices_RemoveWeapons": {
|
"CCSPlayer_ItemServices_RemoveWeapons": {
|
||||||
"offsets": {
|
"offsets": {
|
||||||
"windows": 21,
|
"windows": 19,
|
||||||
"linux": 20
|
"linux": 20
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -95,14 +102,14 @@
|
|||||||
"CCSGameRules_TerminateRound": {
|
"CCSGameRules_TerminateRound": {
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x48\\x8B\\xC4\\x4C\\x89\\x48\\x20\\x55\\x56",
|
"windows": "\\x48\\x8B\\xC4\\x4C\\x89\\x48\\x20\\x55\\x57",
|
||||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x49\\x89\\xFD\\x41\\x54\\x53\\x48\\x81\\xEC\\xE8"
|
"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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"UTIL_CreateEntityByName": {
|
"UTIL_CreateEntityByName": {
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x48\\x83\\xEC\\x48\\xC6\\x44\\x24\\x30\\x00\\x4C\\x8B\\xC1",
|
"windows": "\\x48\\x83\\xEC\\x48\\xC6\\x44\\x24\\x30\\x00",
|
||||||
"linux": "\\x48\\x8D\\x05\\x2A\\x2A\\x2A\\x2A\\x55\\x48\\x89\\xFA"
|
"linux": "\\x48\\x8D\\x05\\x2A\\x2A\\x2A\\x2A\\x55\\x48\\x89\\xFA"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -110,7 +117,7 @@
|
|||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x57\\x48\\x83\\xEC\\x30\\x48\\x8B\\xDA\\x48\\x8B\\xF9\\x48\\x85\\xC9",
|
"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\\x4B\\x55\\x48\\x89\\xE5\\x41\\x56"
|
"linux": "\\x48\\x85\\xFF\\x74\\x2A\\x55\\x48\\x89\\xE5\\x41\\x56"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CEntityInstance_AcceptInput": {
|
"CEntityInstance_AcceptInput": {
|
||||||
@@ -129,8 +136,8 @@
|
|||||||
},
|
},
|
||||||
"CBasePlayerPawn_CommitSuicide": {
|
"CBasePlayerPawn_CommitSuicide": {
|
||||||
"offsets": {
|
"offsets": {
|
||||||
"windows": 357,
|
"windows": 360,
|
||||||
"linux": 357
|
"linux": 360
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CBasePlayerPawn_RemovePlayerItem": {
|
"CBasePlayerPawn_RemovePlayerItem": {
|
||||||
@@ -164,7 +171,7 @@
|
|||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x40\\x53\\x57\\x41\\x55\\x48\\x83\\xEC\\x40",
|
"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"
|
"linux": "\\x55\\xBA\\xFF\\xFF\\xFF\\xFF\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x49\\x89\\xF5\\x41"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"StateChanged": {
|
"StateChanged": {
|
||||||
@@ -189,15 +196,15 @@
|
|||||||
},
|
},
|
||||||
"GameEventManager": {
|
"GameEventManager": {
|
||||||
"offsets": {
|
"offsets": {
|
||||||
"windows": 91,
|
"windows": 93,
|
||||||
"linux": 91
|
"linux": 93
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CEntityIOOutput_FireOutputInternal": {
|
"CEntityIOOutput_FireOutputInternal": {
|
||||||
"signatures": {
|
"signatures": {
|
||||||
"library": "server",
|
"library": "server",
|
||||||
"windows": "\\x48\\x8B\\xC4\\x4C\\x89\\x48\\x20\\x55\\x57\\x41\\x54\\x41\\x56",
|
"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\\x53\\x48\\x83\\xEC\\x58\\x4C\\x8B\\x6F\\x08"
|
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x41\\x54\\x49\\x89\\xD4\\x53\\x48\\x89\\xF3\\x48\\x83\\xEC\\x58"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ public class AdminTests
|
|||||||
{
|
{
|
||||||
var adminData = AdminManager.GetPlayerAdminData((SteamID)76561197960265731);
|
var adminData = AdminManager.GetPlayerAdminData((SteamID)76561197960265731);
|
||||||
Assert.NotNull(adminData);
|
Assert.NotNull(adminData);
|
||||||
Assert.Equal(125u, adminData.Immunity); // Group immunity is 125, Admin immunity is 100
|
Assert.Equal(125u, AdminManager.GetPlayerImmunity((SteamID)76561197960265731)); // Group immunity is 125, Admin immunity is 100
|
||||||
AdminManager.SetPlayerImmunity((SteamID)76561197960265731, 150u);
|
AdminManager.SetPlayerImmunity((SteamID)76561197960265731, 150u);
|
||||||
Assert.Equal(150u, adminData.Immunity); // Group immunity is 125, Admin immunity is 100
|
Assert.Equal(150u, AdminManager.GetPlayerImmunity((SteamID)76561197960265731)); // Group immunity is 125, Admin immunity is 100
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
Binary file not shown.
BIN
managed/CounterStrikeSharp.API/ApiCompat/v151.dll
Normal file
BIN
managed/CounterStrikeSharp.API/ApiCompat/v151.dll
Normal file
Binary file not shown.
22
managed/CounterStrikeSharp.API/CompatibilitySuppressions.xml
Normal file
22
managed/CounterStrikeSharp.API/CompatibilitySuppressions.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
|
||||||
|
<Suppressions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<Suppression>
|
||||||
|
<DiagnosticId>CP0002</DiagnosticId>
|
||||||
|
<Target>F:CounterStrikeSharp.API.Modules.Memory.VirtualFunctions.CCSPlayerPawn_Respawn</Target>
|
||||||
|
<Left>.\ApiCompat\v151.dll</Left>
|
||||||
|
<Right>obj\Debug\net7.0\CounterStrikeSharp.API.dll</Right>
|
||||||
|
</Suppression>
|
||||||
|
<Suppression>
|
||||||
|
<DiagnosticId>CP0002</DiagnosticId>
|
||||||
|
<Target>F:CounterStrikeSharp.API.Modules.Memory.VirtualFunctions.CCSPlayerPawn_RespawnFunc</Target>
|
||||||
|
<Left>.\ApiCompat\v151.dll</Left>
|
||||||
|
<Right>obj\Debug\net7.0\CounterStrikeSharp.API.dll</Right>
|
||||||
|
</Suppression>
|
||||||
|
<Suppression>
|
||||||
|
<DiagnosticId>CP0002</DiagnosticId>
|
||||||
|
<Target>M:CounterStrikeSharp.API.Core.CCSPlayerPawn.Respawn</Target>
|
||||||
|
<Left>.\ApiCompat\v151.dll</Left>
|
||||||
|
<Right>obj\Debug\net7.0\CounterStrikeSharp.API.dll</Right>
|
||||||
|
</Suppression>
|
||||||
|
</Suppressions>
|
||||||
@@ -85,11 +85,12 @@ namespace CounterStrikeSharp.API.Core
|
|||||||
|
|
||||||
for (var i = 1; i <= 9; i++)
|
for (var i = 1; i <= 9; i++)
|
||||||
{
|
{
|
||||||
CommandUtils.AddStandaloneCommand("css_" + i, "Command Key Handler", (player, info) =>
|
CommandUtils.AddStandaloneCommand($"css_{i}", "Command Key Handler", (player, info) =>
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
var key = Convert.ToInt32(info.GetArg(0).Split("_")[1]);
|
var key = Convert.ToInt32(info.GetArg(0).Split("_")[1]);
|
||||||
ChatMenus.OnKeyPress(player, key);
|
|
||||||
|
MenuManager.OnKeyPress(player, key);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +182,8 @@ namespace CounterStrikeSharp.API.Core
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
info.ReplyToCommand($"Could not load plugin \"{path}\")", true);
|
info.ReplyToCommand($"Could not load plugin \"{path}\"", true);
|
||||||
|
Logger.LogError(e, "Could not load plugin \"{Path}\"", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -207,7 +209,7 @@ namespace CounterStrikeSharp.API.Core
|
|||||||
IPluginContext? plugin = _pluginContextQueryHandler.FindPluginByIdOrName(pluginIdentifier);
|
IPluginContext? plugin = _pluginContextQueryHandler.FindPluginByIdOrName(pluginIdentifier);
|
||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
{
|
{
|
||||||
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\")", true);
|
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\"", true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +233,7 @@ namespace CounterStrikeSharp.API.Core
|
|||||||
|
|
||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
{
|
{
|
||||||
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\")", true);
|
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\"", true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +290,7 @@ namespace CounterStrikeSharp.API.Core
|
|||||||
CommandUtils.AddStandaloneCommand("css", "Counter-Strike Sharp options.", OnCSSCommand);
|
CommandUtils.AddStandaloneCommand("css", "Counter-Strike Sharp options.", OnCSSCommand);
|
||||||
CommandUtils.AddStandaloneCommand("css_plugins", "Counter-Strike Sharp plugin options.",
|
CommandUtils.AddStandaloneCommand("css_plugins", "Counter-Strike Sharp plugin options.",
|
||||||
OnCSSPluginCommand);
|
OnCSSPluginCommand);
|
||||||
CommandUtils.AddStandaloneCommand("css_lang", "Set Counter-Strike Sharp language", OnLangCommand);
|
CommandUtils.AddStandaloneCommand("css_lang", "Set Counter-Strike Sharp language.", OnLangCommand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,5 +27,5 @@ public partial class CBaseEntity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public QAngle? AbsRotation => CBodyComponent?.SceneNode?.AbsRotation;
|
public QAngle? AbsRotation => CBodyComponent?.SceneNode?.AbsRotation;
|
||||||
|
|
||||||
public T? GetVData<T>() where T : CEntitySubclassVDataBase => (T)Activator.CreateInstance(typeof(T), Marshal.ReadIntPtr(SubclassID.Handle + 8));
|
public T? GetVData<T>() where T : CEntitySubclassVDataBase => (T)Activator.CreateInstance(typeof(T), Marshal.ReadIntPtr(SubclassID.Handle + 4));
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
using CounterStrikeSharp.API.Modules.Cvars;
|
||||||
|
using CounterStrikeSharp.API.Modules.Entities;
|
||||||
|
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
||||||
|
using CounterStrikeSharp.API.Modules.Memory;
|
||||||
|
using CounterStrikeSharp.API.Modules.Utils;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,19 +10,13 @@ namespace CounterStrikeSharp.API.Core;
|
|||||||
|
|
||||||
public partial class CCSPlayerController
|
public partial class CCSPlayerController
|
||||||
{
|
{
|
||||||
public int? UserId
|
public int? UserId => NativeAPI.GetUseridFromIndex((int)Index);
|
||||||
{
|
public CsTeam Team => (CsTeam)TeamNum;
|
||||||
get
|
|
||||||
{
|
|
||||||
return NativeAPI.GetUseridFromIndex((int)this.Index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CsTeam Team => (CsTeam)this.TeamNum;
|
|
||||||
|
|
||||||
public IntPtr GiveNamedItem(string item)
|
public IntPtr GiveNamedItem(string item)
|
||||||
{
|
{
|
||||||
if (!PlayerPawn.IsValid) return 0;
|
if (!PlayerPawn.IsValid) return 0;
|
||||||
|
if (PlayerPawn.Value == null) return 0;
|
||||||
if (!PlayerPawn.Value.IsValid) return 0;
|
if (!PlayerPawn.Value.IsValid) return 0;
|
||||||
if (PlayerPawn.Value.ItemServices == null) return 0;
|
if (PlayerPawn.Value.ItemServices == null) return 0;
|
||||||
|
|
||||||
@@ -37,7 +31,7 @@ public partial class CCSPlayerController
|
|||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.GiveNamedItem(itemString);
|
return GiveNamedItem(itemString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintToConsole(string message)
|
public void PrintToConsole(string message)
|
||||||
@@ -47,12 +41,12 @@ public partial class CCSPlayerController
|
|||||||
|
|
||||||
public void PrintToChat(string message)
|
public void PrintToChat(string message)
|
||||||
{
|
{
|
||||||
VirtualFunctions.ClientPrint(this.Handle, HudDestination.Chat, message, 0, 0, 0, 0);
|
VirtualFunctions.ClientPrint(Handle, HudDestination.Chat, message, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintToCenter(string message)
|
public void PrintToCenter(string message)
|
||||||
{
|
{
|
||||||
VirtualFunctions.ClientPrint(this.Handle, HudDestination.Center, message, 0, 0, 0, 0);
|
VirtualFunctions.ClientPrint(Handle, HudDestination.Center, message, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintToCenterHtml(string message) => PrintToCenterHtml(message, 5);
|
public void PrintToCenterHtml(string message) => PrintToCenterHtml(message, 5);
|
||||||
@@ -74,14 +68,16 @@ public partial class CCSPlayerController
|
|||||||
public void DropActiveWeapon()
|
public void DropActiveWeapon()
|
||||||
{
|
{
|
||||||
if (!PlayerPawn.IsValid) return;
|
if (!PlayerPawn.IsValid) return;
|
||||||
|
if (PlayerPawn.Value == null) return;
|
||||||
if (!PlayerPawn.Value.IsValid) return;
|
if (!PlayerPawn.Value.IsValid) return;
|
||||||
if (PlayerPawn.Value.ItemServices == null) return;
|
if (PlayerPawn.Value.ItemServices == null) return;
|
||||||
if (PlayerPawn.Value.WeaponServices == null) return;
|
if (PlayerPawn.Value.WeaponServices == null) return;
|
||||||
if (!PlayerPawn.Value.WeaponServices.ActiveWeapon.IsValid) return;
|
if (!PlayerPawn.Value.WeaponServices.ActiveWeapon.IsValid) return;
|
||||||
|
|
||||||
CCSPlayer_ItemServices itemServices = new CCSPlayer_ItemServices(PlayerPawn.Value.ItemServices.Handle);
|
CCSPlayer_ItemServices itemServices = new CCSPlayer_ItemServices(PlayerPawn.Value.ItemServices.Handle);
|
||||||
CCSPlayer_WeaponServices weponServices = new CCSPlayer_WeaponServices(PlayerPawn.Value.WeaponServices.Handle);
|
CCSPlayer_WeaponServices weaponServices = new CCSPlayer_WeaponServices(PlayerPawn.Value.WeaponServices.Handle);
|
||||||
itemServices.DropActivePlayerWeapon(weponServices.ActiveWeapon.Value);
|
|
||||||
|
itemServices.DropActivePlayerWeapon(weaponServices.ActiveWeapon.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -90,6 +86,7 @@ public partial class CCSPlayerController
|
|||||||
public void RemoveWeapons()
|
public void RemoveWeapons()
|
||||||
{
|
{
|
||||||
if (!PlayerPawn.IsValid) return;
|
if (!PlayerPawn.IsValid) return;
|
||||||
|
if (PlayerPawn.Value == null) return;
|
||||||
if (!PlayerPawn.Value.IsValid) return;
|
if (!PlayerPawn.Value.IsValid) return;
|
||||||
if (PlayerPawn.Value.ItemServices == null) return;
|
if (PlayerPawn.Value.ItemServices == null) return;
|
||||||
|
|
||||||
@@ -105,6 +102,7 @@ public partial class CCSPlayerController
|
|||||||
public void CommitSuicide(bool explode, bool force)
|
public void CommitSuicide(bool explode, bool force)
|
||||||
{
|
{
|
||||||
if (!PlayerPawn.IsValid) return;
|
if (!PlayerPawn.IsValid) return;
|
||||||
|
if (PlayerPawn.Value == null) return;
|
||||||
if (!PlayerPawn.Value.IsValid) return;
|
if (!PlayerPawn.Value.IsValid) return;
|
||||||
|
|
||||||
PlayerPawn.Value.CommitSuicide(explode, force);
|
PlayerPawn.Value.CommitSuicide(explode, force);
|
||||||
@@ -116,9 +114,11 @@ public partial class CCSPlayerController
|
|||||||
public void Respawn()
|
public void Respawn()
|
||||||
{
|
{
|
||||||
if (!PlayerPawn.IsValid) return;
|
if (!PlayerPawn.IsValid) return;
|
||||||
|
if (PlayerPawn.Value == null) return;
|
||||||
if (!PlayerPawn.Value.IsValid) return;
|
if (!PlayerPawn.Value.IsValid) return;
|
||||||
|
|
||||||
VirtualFunctions.CCSPlayerPawn_Respawn(PlayerPawn.Value.Handle);
|
// The Call To Arms update appears to have invalidated the need for CCSPlayerPawn_Respawn.
|
||||||
|
SetPawn(PlayerPawn.Value);
|
||||||
VirtualFunction.CreateVoid<IntPtr>(Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(Handle);
|
VirtualFunction.CreateVoid<IntPtr>(Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ public partial class CCSPlayerController
|
|||||||
/// <param name="team">The team to switch to</param>
|
/// <param name="team">The team to switch to</param>
|
||||||
public void SwitchTeam(CsTeam team)
|
public void SwitchTeam(CsTeam team)
|
||||||
{
|
{
|
||||||
VirtualFunctions.SwitchTeam(this.Handle, (byte)team);
|
VirtualFunctions.SwitchTeam(Handle, (byte)team);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -153,7 +153,7 @@ public partial class CCSPlayerController
|
|||||||
/// <returns>ConVar string value</returns>
|
/// <returns>ConVar string value</returns>
|
||||||
public string GetConVarValue(string conVar)
|
public string GetConVarValue(string conVar)
|
||||||
{
|
{
|
||||||
return NativeAPI.GetClientConvarValue(this.Slot, conVar);
|
return NativeAPI.GetClientConvarValue(Slot, conVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetConVarValue(ConVar? conVar)
|
public string GetConVarValue(ConVar? conVar)
|
||||||
@@ -179,7 +179,7 @@ public partial class CCSPlayerController
|
|||||||
throw new InvalidOperationException("'SetFakeClientConVar' can only be called for fake clients (bots)");
|
throw new InvalidOperationException("'SetFakeClientConVar' can only be called for fake clients (bots)");
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeAPI.SetFakeClientConvarValue(this.Slot, conVar, value);
|
NativeAPI.SetFakeClientConvarValue(Slot, conVar, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -228,8 +228,8 @@ public partial class CCSPlayerController
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!this.IsValid) return null;
|
if (!IsValid) return null;
|
||||||
var authorizedSteamId = NativeAPI.GetPlayerAuthorizedSteamid(this.Slot);
|
var authorizedSteamId = NativeAPI.GetPlayerAuthorizedSteamid(Slot);
|
||||||
if ((long)authorizedSteamId == -1) return null;
|
if ((long)authorizedSteamId == -1) return null;
|
||||||
|
|
||||||
return (SteamID)authorizedSteamId;
|
return (SteamID)authorizedSteamId;
|
||||||
@@ -244,8 +244,8 @@ public partial class CCSPlayerController
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!this.IsValid) return null;
|
if (!IsValid) return null;
|
||||||
var ipAddress = NativeAPI.GetPlayerIpAddress(this.Slot);
|
var ipAddress = NativeAPI.GetPlayerIpAddress(Slot);
|
||||||
if (string.IsNullOrWhiteSpace(ipAddress)) return null;
|
if (string.IsNullOrWhiteSpace(ipAddress)) return null;
|
||||||
|
|
||||||
return ipAddress;
|
return ipAddress;
|
||||||
@@ -258,9 +258,6 @@ public partial class CCSPlayerController
|
|||||||
public VoiceFlags VoiceFlags
|
public VoiceFlags VoiceFlags
|
||||||
{
|
{
|
||||||
get => (VoiceFlags)NativeAPI.GetClientVoiceFlags(Handle);
|
get => (VoiceFlags)NativeAPI.GetClientVoiceFlags(Handle);
|
||||||
set
|
set => NativeAPI.SetClientVoiceFlags(Handle, (Byte)value);
|
||||||
{
|
|
||||||
NativeAPI.SetClientVoiceFlags(Handle, (Byte)value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
using System;
|
using System;
|
||||||
using CounterStrikeSharp.API.Modules.Memory;
|
using CounterStrikeSharp.API.Modules.Memory;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace CounterStrikeSharp.API.Core;
|
namespace CounterStrikeSharp.API.Core;
|
||||||
|
|
||||||
public partial class CCSPlayerPawn
|
public partial class CCSPlayerPawn
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Respawn player
|
/// Respawn player
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Respawn()
|
|
||||||
{
|
|
||||||
if (!Controller.IsValid) return;
|
|
||||||
if (!Controller.Value.IsValid) return;
|
|
||||||
|
|
||||||
VirtualFunctions.CCSPlayerPawn_Respawn(Handle);
|
[Obsolete("Use CCSPlayerController.Respawn() instead")]
|
||||||
VirtualFunction.CreateVoid<IntPtr>(Controller.Value.Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(Controller.Value.Handle);
|
public void Respawn()
|
||||||
}
|
{
|
||||||
}
|
if (!Controller.IsValid) return;
|
||||||
|
if (!Controller.Value.IsValid) return;
|
||||||
|
|
||||||
|
Application.Instance.Logger.LogWarning("CCSPawn.Respawn is deprecated and does nothing, use CCSPlayerController.Respawn instead");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<EnablePackageValidation>true</EnablePackageValidation>
|
<EnablePackageValidation>true</EnablePackageValidation>
|
||||||
<NoWarn>$(NoWarn);CS1591;CP0003</NoWarn>
|
<NoWarn>$(NoWarn);CS1591;CP0003</NoWarn>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<GenerateCompatibilitySuppressionFile>true</GenerateCompatibilitySuppressionFile>
|
||||||
<Authors>Roflmuffin</Authors>
|
<Authors>Roflmuffin</Authors>
|
||||||
<Description>Official server side runtime assembly for CounterStrikeSharp</Description>
|
<Description>Official server side runtime assembly for CounterStrikeSharp</Description>
|
||||||
<PackageProjectUrl>http://docs.cssharp.dev/</PackageProjectUrl>
|
<PackageProjectUrl>http://docs.cssharp.dev/</PackageProjectUrl>
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApiCompatValidateAssemblies>true</ApiCompatValidateAssemblies>
|
<ApiCompatValidateAssemblies>true</ApiCompatValidateAssemblies>
|
||||||
<ApiCompatContractAssembly>.\ApiCompat\v133.dll</ApiCompatContractAssembly>
|
<ApiCompatContractAssembly>.\ApiCompat\v151.dll</ApiCompatContractAssembly>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Modules\Commands\CommandInfo" />
|
<None Remove="Modules\Commands\CommandInfo" />
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
// This is here for cases where the server console is attempting to call commands.
|
// This is here for cases where the server console is attempting to call commands.
|
||||||
// The server console should have access to all commands, regardless of groups.
|
// The server console should have access to all commands, regardless of groups.
|
||||||
if (player == null) return true;
|
if (player == null) return true;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) { return false; }
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return false; }
|
||||||
|
|
||||||
var playerData = GetPlayerAdminData(player.AuthorizedSteamID);
|
var playerData = GetPlayerAdminData(player.AuthorizedSteamID);
|
||||||
if (playerData == null) return false;
|
if (playerData == null) return false;
|
||||||
@@ -136,20 +136,20 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
return playerData.Groups.IsSupersetOf(playerGroups);
|
return playerData.Groups.IsSupersetOf(playerGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a player to a group.
|
/// Adds a player to a group. This does NOT modify the immunity of the player (see SetPlayerImmunity).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="player">Player controller.</param>
|
/// <param name="player">Player controller.</param>
|
||||||
/// <param name="groups">Groups to add the player to.</param>
|
/// <param name="groups">Groups to add the player to.</param>
|
||||||
public static void AddPlayerToGroup(CCSPlayerController? player, params string[] groups)
|
public static void AddPlayerToGroup(CCSPlayerController? player, params string[] groups)
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) { return; }
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return; }
|
||||||
AddPlayerToGroup(player.AuthorizedSteamID, groups);
|
AddPlayerToGroup(player.AuthorizedSteamID, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a player to a group.
|
/// Adds a player to a group. This does NOT modify the immunity of the player (see SetPlayerImmunity).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="steamId">SteamID of the player.</param>
|
/// <param name="steamId">SteamID of the player.</param>
|
||||||
/// <param name="groups">Groups to add the player to.</param>
|
/// <param name="groups">Groups to add the player to.</param>
|
||||||
@@ -187,7 +187,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
public static void RemovePlayerFromGroup(CCSPlayerController? player, bool removeInheritedFlags = true, params string[] groups)
|
public static void RemovePlayerFromGroup(CCSPlayerController? player, bool removeInheritedFlags = true, params string[] groups)
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) { return; }
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return; }
|
||||||
RemovePlayerFromGroup(player.AuthorizedSteamID, true, groups);
|
RemovePlayerFromGroup(player.AuthorizedSteamID, true, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,22 +167,43 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Grabs the admin data for a player that was loaded from "configs/admins.json".
|
/// Grabs the admin data for a player that was loaded from "configs/admins.json" and "configs/admins_groups.json".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="steamId">SteamID object of the player.</param>
|
/// <param name="player">Player controller</param>
|
||||||
/// <returns>AdminData class if data found, null if not.</returns>
|
/// <returns>AdminData class if data found, null if not.</returns>
|
||||||
public static AdminData? GetPlayerAdminData(SteamID? steamId)
|
public static AdminData? GetPlayerAdminData(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (player == null) return null;
|
||||||
|
return GetPlayerAdminData(player.AuthorizedSteamID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Grabs the admin data for a player that was loaded from "configs/admins.json" and "configs/admins_groups.json".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="steamId">SteamID object of the player.</param>
|
||||||
|
/// <returns>AdminData class if data found, null if not.</returns>
|
||||||
|
public static AdminData? GetPlayerAdminData(SteamID? steamId)
|
||||||
{
|
{
|
||||||
if (steamId == null) return null;
|
if (steamId == null) return null;
|
||||||
return Admins.GetValueOrDefault(steamId);
|
return Admins.GetValueOrDefault(steamId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a players admin data. This is not saved to "configs/admins.json"
|
/// Removes a players admin data. This is not saved to "configs/admins.json"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="steamId">Steam ID remove admin data from.</param>
|
/// <param name="player">Player controller</param>
|
||||||
public static void RemovePlayerAdminData(SteamID? steamId)
|
public static void RemovePlayerAdminData(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (player == null) return;
|
||||||
|
RemovePlayerAdminData(player.AuthorizedSteamID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a players admin data. This is not saved to "configs/admins.json"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="steamId">Steam ID remove admin data from.</param>
|
||||||
|
public static void RemovePlayerAdminData(SteamID? steamId)
|
||||||
{
|
{
|
||||||
if (steamId == null) return;
|
if (steamId == null) return;
|
||||||
Admins.Remove(steamId);
|
Admins.Remove(steamId);
|
||||||
@@ -201,7 +222,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
// This is here for cases where the server console is attempting to call commands.
|
// This is here for cases where the server console is attempting to call commands.
|
||||||
// The server console should have access to all commands, regardless of permissions.
|
// The server console should have access to all commands, regardless of permissions.
|
||||||
if (player == null) return true;
|
if (player == null) return true;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) { return false; }
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return false; }
|
||||||
return PlayerHasPermissions(player.AuthorizedSteamID, flags);
|
return PlayerHasPermissions(player.AuthorizedSteamID, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +281,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
// This is here for cases where the server console is attempting to call commands.
|
// This is here for cases where the server console is attempting to call commands.
|
||||||
// The server console should have access to all commands, regardless of permissions.
|
// The server console should have access to all commands, regardless of permissions.
|
||||||
if (player == null) return true;
|
if (player == null) return true;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) { return false; }
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return false; }
|
||||||
var playerData = GetPlayerAdminData(player.AuthorizedSteamID);
|
var playerData = GetPlayerAdminData(player.AuthorizedSteamID);
|
||||||
return playerData?.CommandOverrides.ContainsKey(command) ?? false;
|
return playerData?.CommandOverrides.ContainsKey(command) ?? false;
|
||||||
}
|
}
|
||||||
@@ -290,7 +311,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
// This is here for cases where the server console is attempting to call commands.
|
// This is here for cases where the server console is attempting to call commands.
|
||||||
// The server console should have access to all commands, regardless of permissions.
|
// The server console should have access to all commands, regardless of permissions.
|
||||||
if (player == null) return true;
|
if (player == null) return true;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) { return false; }
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return false; }
|
||||||
var playerData = GetPlayerAdminData(player.AuthorizedSteamID);
|
var playerData = GetPlayerAdminData(player.AuthorizedSteamID);
|
||||||
return playerData?.CommandOverrides.GetValueOrDefault(command) ?? false;
|
return playerData?.CommandOverrides.GetValueOrDefault(command) ?? false;
|
||||||
}
|
}
|
||||||
@@ -319,7 +340,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
// This is here for cases where the server console is attempting to call commands.
|
// This is here for cases where the server console is attempting to call commands.
|
||||||
// The server console should have access to all commands, regardless of permissions.
|
// The server console should have access to all commands, regardless of permissions.
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) { return; }
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return; }
|
||||||
SetPlayerCommandOverride(player.AuthorizedSteamID, command, state);
|
SetPlayerCommandOverride(player.AuthorizedSteamID, command, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +383,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
public static void AddPlayerPermissions(CCSPlayerController? player, params string[] flags)
|
public static void AddPlayerPermissions(CCSPlayerController? player, params string[] flags)
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) return;
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) return;
|
||||||
AddPlayerPermissions(player.AuthorizedSteamID, flags);
|
AddPlayerPermissions(player.AuthorizedSteamID, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +421,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
public static void RemovePlayerPermissions(CCSPlayerController? player, params string[] flags)
|
public static void RemovePlayerPermissions(CCSPlayerController? player, params string[] flags)
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) return;
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) return;
|
||||||
|
|
||||||
RemovePlayerPermissions(player.AuthorizedSteamID, flags);
|
RemovePlayerPermissions(player.AuthorizedSteamID, flags);
|
||||||
}
|
}
|
||||||
@@ -427,7 +448,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
public static void ClearPlayerPermissions(CCSPlayerController? player)
|
public static void ClearPlayerPermissions(CCSPlayerController? player)
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) return;
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) return;
|
||||||
|
|
||||||
ClearPlayerPermissions(player.AuthorizedSteamID);
|
ClearPlayerPermissions(player.AuthorizedSteamID);
|
||||||
}
|
}
|
||||||
@@ -457,7 +478,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
public static void SetPlayerImmunity(CCSPlayerController? player, uint value)
|
public static void SetPlayerImmunity(CCSPlayerController? player, uint value)
|
||||||
{
|
{
|
||||||
if (player == null) return;
|
if (player == null) return;
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot) return;
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) return;
|
||||||
|
|
||||||
SetPlayerImmunity(player.AuthorizedSteamID, value);
|
SetPlayerImmunity(player.AuthorizedSteamID, value);
|
||||||
}
|
}
|
||||||
@@ -477,13 +498,44 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
|||||||
Admins[steamId] = data;
|
Admins[steamId] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks to see if a player can target another player based on their immunity value.
|
/// Returns the immunity value for a player.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="caller">Caller of the command.</param>
|
/// <param name="player">Player controller.</param>
|
||||||
/// <param name="target">Target of the command.</param>
|
/// <returns> If an immunity value is present in "configs/admins_groups.json"
|
||||||
/// <returns></returns>
|
/// and in "configs/admins.json", the returned value will be the greater of the two.
|
||||||
public static bool CanPlayerTarget(CCSPlayerController? caller, CCSPlayerController? target)
|
/// If the value is overriden with SetPlayerImmunity, that value is returned instead.</returns>
|
||||||
|
public static uint GetPlayerImmunity(CCSPlayerController? player)
|
||||||
|
{
|
||||||
|
if (player == null) return 0;
|
||||||
|
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) return 0;
|
||||||
|
|
||||||
|
return GetPlayerImmunity(player.AuthorizedSteamID);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the immunity value for a player.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="steamId">Steam ID of the player.</param>
|
||||||
|
/// <returns> If an immunity value is present in "configs/admins_groups.json"
|
||||||
|
/// and in "configs/admins.json", the returned value will be the greater of the two.
|
||||||
|
/// If the value is overriden with SetPlayerImmunity, that value is returned instead.</returns>
|
||||||
|
public static uint GetPlayerImmunity(SteamID? steamId)
|
||||||
|
{
|
||||||
|
if (steamId == null) return 0;
|
||||||
|
var data = GetPlayerAdminData(steamId);
|
||||||
|
if (data == null) return 0;
|
||||||
|
|
||||||
|
return data.Immunity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks to see if a player can target another player based on their immunity value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="caller">Caller of the command.</param>
|
||||||
|
/// <param name="target">Target of the command.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool CanPlayerTarget(CCSPlayerController? caller, CCSPlayerController? target)
|
||||||
{
|
{
|
||||||
// The server console should be able to target everyone.
|
// The server console should be able to target everyone.
|
||||||
if (caller == null) return true;
|
if (caller == null) return true;
|
||||||
|
|||||||
@@ -90,11 +90,11 @@ public class Target
|
|||||||
case TargetType.TeamSpec:
|
case TargetType.TeamSpec:
|
||||||
return player.TeamNum == (byte)CsTeam.Spectator;
|
return player.TeamNum == (byte)CsTeam.Spectator;
|
||||||
case TargetType.GroupAll:
|
case TargetType.GroupAll:
|
||||||
return true;
|
return !player.IsHLTV;
|
||||||
case TargetType.GroupBots:
|
case TargetType.GroupBots:
|
||||||
return player.IsBot;
|
return player.IsBot;
|
||||||
case TargetType.GroupHumans:
|
case TargetType.GroupHumans:
|
||||||
return !player.IsBot;
|
return !player.IsBot && !player.IsHLTV;
|
||||||
case TargetType.GroupAlive:
|
case TargetType.GroupAlive:
|
||||||
return player.PlayerPawn is { IsValid: true, Value.LifeState: (byte)LifeState_t.LIFE_ALIVE };
|
return player.PlayerPawn is { IsValid: true, Value.LifeState: (byte)LifeState_t.LIFE_ALIVE };
|
||||||
case TargetType.GroupDead:
|
case TargetType.GroupDead:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of CounterStrikeSharp.
|
* This file is part of CounterStrikeSharp.
|
||||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -36,9 +36,12 @@ namespace CounterStrikeSharp.API.Modules.Entities.Constants
|
|||||||
TerroristsSurrender = 0x11u, // this also triggers match cancelled
|
TerroristsSurrender = 0x11u, // this also triggers match cancelled
|
||||||
CTsSurrender = 0x12u, // this also triggers match cancelled
|
CTsSurrender = 0x12u, // this also triggers match cancelled
|
||||||
|
|
||||||
TerroristsPlanned = 0x13u,
|
TerroristsPlanted = 0x13u,
|
||||||
CTsReachedHostage = 0x14u,
|
CTsReachedHostage = 0x14u,
|
||||||
SurvivalWin = 0x15u,
|
SurvivalWin = 0x15u,
|
||||||
SurvivalDraw = 0x16u
|
SurvivalDraw = 0x16u,
|
||||||
|
|
||||||
|
[Obsolete("Use RoundEndReason.TerroristsPlanted instead.")]
|
||||||
|
TerroristsPlanned = 0x13u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,14 +60,15 @@ public static class VirtualFunctions
|
|||||||
new(GameData.GetSignature("CBaseEntity_DispatchSpawn"));
|
new(GameData.GetSignature("CBaseEntity_DispatchSpawn"));
|
||||||
|
|
||||||
public static Action<IntPtr, IntPtr> CBaseEntity_DispatchSpawn = CBaseEntity_DispatchSpawnFunc.Invoke;
|
public static Action<IntPtr, IntPtr> CBaseEntity_DispatchSpawn = CBaseEntity_DispatchSpawnFunc.Invoke;
|
||||||
|
|
||||||
public static MemoryFunctionVoid<IntPtr> CCSPlayerPawn_RespawnFunc = new(GameData.GetSignature("CCSPlayerPawn_Respawn"));
|
|
||||||
|
|
||||||
public static Action<IntPtr> CCSPlayerPawn_Respawn = CCSPlayerPawn_RespawnFunc.Invoke;
|
public static MemoryFunctionVoid<CBasePlayerController, CBasePlayerPawn, bool, bool> CBasePlayerController_SetPawnFunc = new (GameData.GetSignature("CBasePlayerController_SetPawn"));
|
||||||
|
|
||||||
public static MemoryFunctionVoid<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOldFunc = new (GameData.GetSignature("CBaseEntity_TakeDamageOld"));
|
public static MemoryFunctionVoid<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOldFunc = new (GameData.GetSignature("CBaseEntity_TakeDamageOld"));
|
||||||
public static Action<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOld = CBaseEntity_TakeDamageOldFunc.Invoke;
|
public static Action<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOld = CBaseEntity_TakeDamageOldFunc.Invoke;
|
||||||
|
|
||||||
|
public static MemoryFunctionWithReturn<CCSPlayer_WeaponServices, CBasePlayerWeapon, bool> CCSPlayer_WeaponServices_CanUseFunc = new(GameData.GetSignature("CCSPlayer_WeaponServices_CanUse"));
|
||||||
|
public static Func<CCSPlayer_WeaponServices, CBasePlayerWeapon, bool> CCSPlayer_WeaponServices_CanUse = CCSPlayer_WeaponServices_CanUseFunc.Invoke;
|
||||||
|
|
||||||
public static MemoryFunctionVoid<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThinkFunc = new (GameData.GetSignature("CCSPlayerPawnBase_PostThink"));
|
public static MemoryFunctionVoid<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThinkFunc = new (GameData.GetSignature("CCSPlayerPawnBase_PostThink"));
|
||||||
public static Action<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThink = CCSPlayerPawnBase_PostThinkFunc.Invoke;
|
public static Action<CCSPlayerPawnBase> CCSPlayerPawnBase_PostThink = CCSPlayerPawnBase_PostThinkFunc.Invoke;
|
||||||
|
|
||||||
|
|||||||
164
managed/CounterStrikeSharp.API/Modules/Menu/BaseMenu.cs
Normal file
164
managed/CounterStrikeSharp.API/Modules/Menu/BaseMenu.cs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of CounterStrikeSharp.
|
||||||
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
public enum PostSelectAction
|
||||||
|
{
|
||||||
|
Close,
|
||||||
|
Reset,
|
||||||
|
Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class BaseMenu : IMenu
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public List<ChatMenuOption> MenuOptions { get; } = new();
|
||||||
|
public PostSelectAction PostSelectAction { get; set; } = PostSelectAction.Reset;
|
||||||
|
|
||||||
|
protected BaseMenu(string title)
|
||||||
|
{
|
||||||
|
Title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual ChatMenuOption AddMenuOption(string display, Action<CCSPlayerController, ChatMenuOption> onSelect, bool disabled = false)
|
||||||
|
{
|
||||||
|
var option = new ChatMenuOption(display, disabled, onSelect);
|
||||||
|
MenuOptions.Add(option);
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This must be called ChatMenuOption to maintain backwards compatibility with the old API
|
||||||
|
public class ChatMenuOption
|
||||||
|
{
|
||||||
|
public string Text { get; set; }
|
||||||
|
public bool Disabled { get; set; }
|
||||||
|
public Action<CCSPlayerController, ChatMenuOption> OnSelect { get; set; }
|
||||||
|
|
||||||
|
public ChatMenuOption(string display, bool disabled, Action<CCSPlayerController, ChatMenuOption> onSelect)
|
||||||
|
{
|
||||||
|
Text = display;
|
||||||
|
Disabled = disabled;
|
||||||
|
OnSelect = onSelect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class BaseMenuInstance : IMenuInstance
|
||||||
|
{
|
||||||
|
public virtual int NumPerPage => 6;
|
||||||
|
public bool CloseOnSelect { get; set; } = true;
|
||||||
|
public Stack<int> PrevPageOffsets { get; } = new();
|
||||||
|
public IMenu Menu { get; }
|
||||||
|
public CCSPlayerController Player { get; }
|
||||||
|
public int Page { get; set; }
|
||||||
|
public int CurrentOffset { get; set; }
|
||||||
|
|
||||||
|
protected BaseMenuInstance(CCSPlayerController player, IMenu menu)
|
||||||
|
{
|
||||||
|
Menu = menu;
|
||||||
|
Player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool HasPrevButton => Page > 0;
|
||||||
|
protected bool HasNextButton => CurrentOffset + NumPerPage < Menu.MenuOptions.Count;
|
||||||
|
protected int MenuItemsPerPage => NumPerPage + 2 - (HasNextButton ? 1 : 0) - (HasPrevButton ? 1 : 0);
|
||||||
|
|
||||||
|
public virtual void Display()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnKeyPress(CCSPlayerController player, int key)
|
||||||
|
{
|
||||||
|
if (player.Handle != Player.Handle) return;
|
||||||
|
|
||||||
|
if (key == 8 && HasNextButton)
|
||||||
|
{
|
||||||
|
NextPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == 7 && HasPrevButton)
|
||||||
|
{
|
||||||
|
PrevPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == 9)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var desiredValue = key;
|
||||||
|
|
||||||
|
var menuItemIndex = CurrentOffset + desiredValue - 1;
|
||||||
|
|
||||||
|
if (menuItemIndex >= 0 && menuItemIndex < Menu.MenuOptions.Count)
|
||||||
|
{
|
||||||
|
var menuOption = Menu.MenuOptions[menuItemIndex];
|
||||||
|
|
||||||
|
if (!menuOption.Disabled)
|
||||||
|
{
|
||||||
|
menuOption.OnSelect(Player, menuOption);
|
||||||
|
switch (Menu.PostSelectAction)
|
||||||
|
{
|
||||||
|
case PostSelectAction.Close:
|
||||||
|
Close();
|
||||||
|
break;
|
||||||
|
case PostSelectAction.Reset:
|
||||||
|
Reset();
|
||||||
|
break;
|
||||||
|
case PostSelectAction.Nothing:
|
||||||
|
// Do nothing
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException("The specified Select Action is not supported!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Reset()
|
||||||
|
{
|
||||||
|
CurrentOffset = 0;
|
||||||
|
Page = 0;
|
||||||
|
PrevPageOffsets.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
MenuManager.CloseActiveMenu(Player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NextPage()
|
||||||
|
{
|
||||||
|
PrevPageOffsets.Push(CurrentOffset);
|
||||||
|
CurrentOffset += MenuItemsPerPage;
|
||||||
|
Page++;
|
||||||
|
Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PrevPage()
|
||||||
|
{
|
||||||
|
Page--;
|
||||||
|
CurrentOffset = PrevPageOffsets.Pop();
|
||||||
|
Display();
|
||||||
|
}
|
||||||
|
}
|
||||||
125
managed/CounterStrikeSharp.API/Modules/Menu/CenterHtmlMenu.cs
Normal file
125
managed/CounterStrikeSharp.API/Modules/Menu/CenterHtmlMenu.cs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of CounterStrikeSharp.
|
||||||
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
public class CenterHtmlMenu : BaseMenu
|
||||||
|
{
|
||||||
|
public CenterHtmlMenu(string title) : base(ModifyTitle(title))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ChatMenuOption AddMenuOption(string display, Action<CCSPlayerController, ChatMenuOption> onSelect, bool disabled = false)
|
||||||
|
{
|
||||||
|
var option = new ChatMenuOption(ModifyOptionDisplay(display), disabled, onSelect);
|
||||||
|
MenuOptions.Add(option);
|
||||||
|
return option;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ModifyTitle(string title)
|
||||||
|
{
|
||||||
|
if (title.Length > 32)
|
||||||
|
{
|
||||||
|
Application.Instance.Logger.LogWarning("Title should not be longer than 32 characters for a CenterHtmlMenu");
|
||||||
|
return title[..32];
|
||||||
|
}
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ModifyOptionDisplay(string display)
|
||||||
|
{
|
||||||
|
if (display.Length > 26)
|
||||||
|
{
|
||||||
|
Application.Instance.Logger.LogWarning("Display should not be longer than 26 characters for a CenterHtmlMenu item");
|
||||||
|
return display[..26];
|
||||||
|
}
|
||||||
|
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CenterHtmlMenuInstance : BaseMenuInstance
|
||||||
|
{
|
||||||
|
private readonly BasePlugin _plugin;
|
||||||
|
public override int NumPerPage => 5; // one less than the actual number of items per page to avoid truncated options
|
||||||
|
|
||||||
|
public CenterHtmlMenuInstance(BasePlugin plugin, CCSPlayerController player, IMenu menu) : base(player, menu)
|
||||||
|
{
|
||||||
|
_plugin = plugin;
|
||||||
|
RemoveOnTickListener();
|
||||||
|
plugin.RegisterListener<Core.Listeners.OnTick>(Display);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Display()
|
||||||
|
{
|
||||||
|
if (MenuManager.GetActiveMenu(Player) != this)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
builder.Append($"<b><font color='yellow'>{Menu.Title}</font></b>");
|
||||||
|
builder.AppendLine("<br>");
|
||||||
|
|
||||||
|
var keyOffset = 1;
|
||||||
|
|
||||||
|
for (var i = CurrentOffset; i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count); i++)
|
||||||
|
{
|
||||||
|
var option = Menu.MenuOptions[i];
|
||||||
|
string color = option.Disabled ? "grey" : "green";
|
||||||
|
builder.Append($"<font color='{color}'>!{keyOffset++}</font> {option.Text}");
|
||||||
|
builder.AppendLine("<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasPrevButton)
|
||||||
|
{
|
||||||
|
builder.AppendFormat("<font color='yellow'>!7</font> <- Prev");
|
||||||
|
builder.AppendLine("<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasNextButton)
|
||||||
|
{
|
||||||
|
builder.AppendFormat("<font color='yellow'>!8</font> -> Next");
|
||||||
|
builder.AppendLine("<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AppendFormat("<font color='red'>!9</font> -> Close");
|
||||||
|
builder.AppendLine("<br>");
|
||||||
|
|
||||||
|
var currentPageText = builder.ToString();
|
||||||
|
Player.PrintToCenterHtml(currentPageText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Reset()
|
||||||
|
{
|
||||||
|
base.Reset();
|
||||||
|
RemoveOnTickListener();
|
||||||
|
|
||||||
|
// Send a blank message to clear the menu
|
||||||
|
Player.PrintToCenterHtml(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveOnTickListener()
|
||||||
|
{
|
||||||
|
var onTick = new Core.Listeners.OnTick(Display);
|
||||||
|
_plugin.RemoveListener("OnTick", onTick);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,164 +1,76 @@
|
|||||||
using System;
|
/*
|
||||||
using System.Collections.Generic;
|
* This file is part of CounterStrikeSharp.
|
||||||
using System.Runtime.InteropServices;
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||||
using System.Text;
|
* it under the terms of the GNU General Public License as published by
|
||||||
using CounterStrikeSharp.API;
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
using CounterStrikeSharp.API.Core;
|
* (at your option) any later version.
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
*
|
||||||
|
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
*/
|
||||||
|
|
||||||
using CounterStrikeSharp.API.Modules.Utils;
|
using CounterStrikeSharp.API.Modules.Utils;
|
||||||
|
|
||||||
namespace CounterStrikeSharp.API.Modules.Menu;
|
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
public class ChatMenuOption
|
public class ChatMenu: BaseMenu
|
||||||
{
|
{
|
||||||
public ChatMenuOption(string text, bool disabled, Action<CCSPlayerController, ChatMenuOption> onSelect)
|
public ChatMenu(string title) : base(title)
|
||||||
{
|
{
|
||||||
Text = text;
|
|
||||||
Disabled = disabled;
|
|
||||||
OnSelect = onSelect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action<CCSPlayerController, ChatMenuOption> OnSelect { get; set; }
|
|
||||||
|
|
||||||
public string Text { get; set; }
|
|
||||||
public bool Disabled { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ChatMenu
|
|
||||||
{
|
|
||||||
public string Title { get; set; }
|
|
||||||
public List<ChatMenuOption> MenuOptions { get; } = new();
|
|
||||||
|
|
||||||
public ChatMenu(string title)
|
|
||||||
{
|
|
||||||
Title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatMenuOption AddMenuOption(string display, Action<CCSPlayerController, ChatMenuOption> onSelect, bool disabled = false)
|
|
||||||
{
|
|
||||||
var option = new ChatMenuOption(display, disabled, onSelect);
|
|
||||||
MenuOptions.Add(option);
|
|
||||||
return option;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ChatMenuInstance
|
public class ChatMenuInstance : BaseMenuInstance
|
||||||
{
|
{
|
||||||
// Six items seems to be able to fit all options in the chat bot without having to open it
|
public ChatMenuInstance(CCSPlayerController player, ChatMenu menu) : base(player, menu)
|
||||||
readonly int _numPerPage = 6;
|
|
||||||
private readonly Stack<int> _prevPageOffsets = new();
|
|
||||||
private readonly ChatMenu _menu;
|
|
||||||
|
|
||||||
int _page = 0;
|
|
||||||
int _currentOffset = 0;
|
|
||||||
private CCSPlayerController _player;
|
|
||||||
|
|
||||||
public ChatMenuInstance(CCSPlayerController player, ChatMenu menu)
|
|
||||||
{
|
{
|
||||||
_menu = menu;
|
|
||||||
_player = player;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool HasPrevButton => _page > 0;
|
public override void Display()
|
||||||
private bool HasNextButton => (_currentOffset + _numPerPage) < _menu.MenuOptions.Count;
|
|
||||||
private int MenuItemsPerPage => _numPerPage + 2 - (HasNextButton ? 1 : 0) - (HasPrevButton ? 1 : 0);
|
|
||||||
|
|
||||||
public void Display()
|
|
||||||
{
|
{
|
||||||
_player.PrintToChat(_menu.Title);
|
Player.PrintToChat(Menu.Title);
|
||||||
_player.PrintToChat("---");
|
Player.PrintToChat("---");
|
||||||
|
|
||||||
int keyOffset = 1;
|
var keyOffset = 1;
|
||||||
|
|
||||||
|
for (var i = CurrentOffset;
|
||||||
|
i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count);
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
var option = Menu.MenuOptions[i];
|
||||||
|
|
||||||
|
Player.PrintToChat(
|
||||||
|
$" {(option.Disabled ? ChatColors.Grey : ChatColors.Green)} !{keyOffset++} {ChatColors.Default}{option.Text}");
|
||||||
|
}
|
||||||
|
|
||||||
if (HasPrevButton)
|
if (HasPrevButton)
|
||||||
{
|
{
|
||||||
_player.PrintToChat($" {ChatColors.Yellow}[!1] {ChatColors.Default}-> Prev");
|
Player.PrintToChat($" {ChatColors.Yellow}!7 {ChatColors.Default}-> Prev");
|
||||||
keyOffset++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = _currentOffset;
|
|
||||||
i < Math.Min(_currentOffset + MenuItemsPerPage, _menu.MenuOptions.Count);
|
|
||||||
i++)
|
|
||||||
{
|
|
||||||
var option = _menu.MenuOptions[i];
|
|
||||||
|
|
||||||
_player.PrintToChat(
|
|
||||||
$" {(option.Disabled ? ChatColors.Grey : ChatColors.Green)} [!{keyOffset++}] {ChatColors.Default}{option.Text}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasNextButton)
|
if (HasNextButton)
|
||||||
{
|
{
|
||||||
_player.PrintToChat($" {ChatColors.Yellow}[!8] {ChatColors.Default}-> Next");
|
Player.PrintToChat($" {ChatColors.Yellow}!8 {ChatColors.Default}-> Next");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnKeyPress(CCSPlayerController player, int key)
|
|
||||||
{
|
|
||||||
if (_player == null || player.Handle != _player.Handle) return;
|
|
||||||
|
|
||||||
if (key == 8 && HasNextButton)
|
|
||||||
{
|
|
||||||
NextPage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == 1 && HasPrevButton)
|
|
||||||
{
|
|
||||||
PrevPage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var desiredValue = key;
|
|
||||||
if (HasPrevButton) desiredValue = key - 1;
|
|
||||||
|
|
||||||
var menuItemIndex = _currentOffset + desiredValue - 1;
|
|
||||||
var menuOption = _menu.MenuOptions[menuItemIndex];
|
|
||||||
|
|
||||||
if (!menuOption.Disabled)
|
|
||||||
{
|
|
||||||
menuOption.OnSelect(_player, menuOption);
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
_currentOffset = 0;
|
|
||||||
_page = 0;
|
|
||||||
_prevPageOffsets.Clear();
|
|
||||||
_player = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void NextPage()
|
|
||||||
{
|
|
||||||
_prevPageOffsets.Push(_currentOffset);
|
|
||||||
_currentOffset += MenuItemsPerPage;
|
|
||||||
_page++;
|
|
||||||
Display();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PrevPage()
|
|
||||||
{
|
|
||||||
_page--;
|
|
||||||
_currentOffset = _prevPageOffsets.Pop();
|
|
||||||
Display();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ChatMenus
|
public static class ChatMenus
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<IntPtr, ChatMenuInstance> ActiveMenus = new();
|
[Obsolete("Use MenuManager.OpenChatMenu instead")]
|
||||||
|
|
||||||
public static void OpenMenu(CCSPlayerController player, ChatMenu menu)
|
public static void OpenMenu(CCSPlayerController player, ChatMenu menu)
|
||||||
{
|
{
|
||||||
ActiveMenus[player.Handle] = new ChatMenuInstance(player, menu);
|
MenuManager.OpenChatMenu(player, menu);
|
||||||
ActiveMenus[player.Handle].Display();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("Use MenuManager.OnKeyPress instead")]
|
||||||
public static void OnKeyPress(CCSPlayerController player, int key)
|
public static void OnKeyPress(CCSPlayerController player, int key)
|
||||||
{
|
{
|
||||||
if (!ActiveMenus.ContainsKey(player.Handle)) return;
|
MenuManager.OnKeyPress(player, key);
|
||||||
|
|
||||||
ActiveMenus[player.Handle].OnKeyPress(player, key);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
58
managed/CounterStrikeSharp.API/Modules/Menu/ConsoleMenu.cs
Normal file
58
managed/CounterStrikeSharp.API/Modules/Menu/ConsoleMenu.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of CounterStrikeSharp.
|
||||||
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
public class ConsoleMenu : BaseMenu
|
||||||
|
{
|
||||||
|
public ConsoleMenu(string title) : base(title)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConsoleMenuInstance : BaseMenuInstance
|
||||||
|
{
|
||||||
|
public ConsoleMenuInstance(CCSPlayerController player, IMenu menu) : base(player, menu)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Display()
|
||||||
|
{
|
||||||
|
Player.PrintToConsole(Menu.Title);
|
||||||
|
Player.PrintToConsole("---");
|
||||||
|
|
||||||
|
var keyOffset = 1;
|
||||||
|
|
||||||
|
for (var i = CurrentOffset;
|
||||||
|
i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count);
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
var option = Menu.MenuOptions[i];
|
||||||
|
|
||||||
|
Player.PrintToConsole($"{(option.Disabled ? "[Enabled]" : "[Disabled] - ")} css_{keyOffset++} {option.Text}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasPrevButton)
|
||||||
|
{
|
||||||
|
Player.PrintToConsole("css_7 -> Prev");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasNextButton)
|
||||||
|
{
|
||||||
|
Player.PrintToConsole("css_8 -> Next");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
managed/CounterStrikeSharp.API/Modules/Menu/IMenu.cs
Normal file
56
managed/CounterStrikeSharp.API/Modules/Menu/IMenu.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of CounterStrikeSharp.
|
||||||
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
public interface IMenu
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public List<ChatMenuOption> MenuOptions { get; }
|
||||||
|
public PostSelectAction PostSelectAction
|
||||||
|
{
|
||||||
|
get { throw new NotImplementedException(); }
|
||||||
|
set { throw new NotImplementedException(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatMenuOption AddMenuOption(string display, Action<CCSPlayerController, ChatMenuOption> onSelect, bool disabled = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IMenuInstance
|
||||||
|
{
|
||||||
|
protected IMenu Menu { get; }
|
||||||
|
protected CCSPlayerController? Player { get; }
|
||||||
|
protected bool CloseOnSelect { get; }
|
||||||
|
protected int Page { get; }
|
||||||
|
protected int CurrentOffset { get; }
|
||||||
|
protected int NumPerPage { get; }
|
||||||
|
protected Stack<int> PrevPageOffsets { get; }
|
||||||
|
|
||||||
|
public void NextPage();
|
||||||
|
public void PrevPage();
|
||||||
|
public void Reset();
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
// Fallback for backwards compatibility
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Display();
|
||||||
|
public void OnKeyPress(CCSPlayerController player, int key);
|
||||||
|
}
|
||||||
73
managed/CounterStrikeSharp.API/Modules/Menu/MenuManager.cs
Normal file
73
managed/CounterStrikeSharp.API/Modules/Menu/MenuManager.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of CounterStrikeSharp.
|
||||||
|
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||||
|
|
||||||
|
public static class MenuManager
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<IntPtr, IMenuInstance> ActiveMenus = new();
|
||||||
|
|
||||||
|
public static Dictionary<IntPtr, IMenuInstance> GetActiveMenus()
|
||||||
|
{
|
||||||
|
return ActiveMenus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IMenuInstance? GetActiveMenu(CCSPlayerController player)
|
||||||
|
{
|
||||||
|
return !ActiveMenus.TryGetValue(player.Handle, out var value) ? null : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CloseActiveMenu(CCSPlayerController player)
|
||||||
|
{
|
||||||
|
if (ActiveMenus.TryGetValue(player.Handle, out var activeMenu))
|
||||||
|
{
|
||||||
|
activeMenu.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveMenus.Remove(player.Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenChatMenu(CCSPlayerController player, ChatMenu menu)
|
||||||
|
{
|
||||||
|
CloseActiveMenu(player);
|
||||||
|
|
||||||
|
ActiveMenus[player.Handle] = new ChatMenuInstance(player, menu);
|
||||||
|
ActiveMenus[player.Handle].Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenCenterHtmlMenu(BasePlugin plugin, CCSPlayerController player, CenterHtmlMenu menu)
|
||||||
|
{
|
||||||
|
CloseActiveMenu(player);
|
||||||
|
|
||||||
|
ActiveMenus[player.Handle] = new CenterHtmlMenuInstance(plugin, player, menu);
|
||||||
|
ActiveMenus[player.Handle].Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenConsoleMenu(CCSPlayerController player, ConsoleMenu menu)
|
||||||
|
{
|
||||||
|
CloseActiveMenu(player);
|
||||||
|
|
||||||
|
ActiveMenus[player.Handle] = new ConsoleMenuInstance(player, menu);
|
||||||
|
ActiveMenus[player.Handle].Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnKeyPress(CCSPlayerController player, int key)
|
||||||
|
{
|
||||||
|
GetActiveMenu(player)?.OnKeyPress(player, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -331,7 +331,7 @@ namespace TestPlugin
|
|||||||
|
|
||||||
private void SetupMenus()
|
private void SetupMenus()
|
||||||
{
|
{
|
||||||
// Chat Menu Example
|
// [Legacy] Chat Menu Example
|
||||||
var largeMenu = new ChatMenu("Test Menu");
|
var largeMenu = new ChatMenu("Test Menu");
|
||||||
for (int i = 1; i < 26; i++)
|
for (int i = 1; i < 26; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user