mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-06 08:03:12 -08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2b8044b8c | ||
|
|
eb9f5667d8 | ||
|
|
b9ca63a603 | ||
|
|
8fc926eacf | ||
|
|
5695c3f922 | ||
|
|
9071d51ecd | ||
|
|
0a32962f4a | ||
|
|
271705b377 | ||
|
|
cdcddbb5f3 | ||
|
|
91f51d0c5c | ||
|
|
e97f804294 | ||
|
|
4f805b18e2 | ||
|
|
e1f9b5635e | ||
|
|
59bff4f500 | ||
|
|
a2581d8e91 | ||
|
|
e7d190a6f7 | ||
|
|
5513d5710a | ||
|
|
e5c223699c | ||
|
|
fa37c222d9 | ||
|
|
3b633fafc7 | ||
|
|
765c56a38a |
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 *)
|
||||
|
||||
- name: Release
|
||||
id: release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: v${{ needs.build_managed.outputs.buildnumber }}
|
||||
@@ -208,4 +209,11 @@ jobs:
|
||||
- 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.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 }}"
|
||||
1
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
||||
* @roflmuffin
|
||||
@@ -128,4 +128,4 @@ Build
|
||||
```bash
|
||||
cmake --build . --config Debug
|
||||
```
|
||||
|
||||
<img src="https://repobeats.axiom.co/api/embed/a96f228b8fa98c032070fa8dd831c967334ee553.svg" width="100%" />
|
||||
|
||||
@@ -22,21 +22,21 @@
|
||||
},
|
||||
"CCSPlayerController_ChangeTeam": {
|
||||
"offsets": {
|
||||
"windows": 90,
|
||||
"linux": 89
|
||||
"windows": 93,
|
||||
"linux": 92
|
||||
}
|
||||
},
|
||||
"CCSPlayerController_Respawn": {
|
||||
"offsets": {
|
||||
"windows": 242,
|
||||
"linux": 244
|
||||
"windows": 244,
|
||||
"linux": 246
|
||||
}
|
||||
},
|
||||
"CCSPlayerPawn_Respawn": {
|
||||
"CBasePlayerController_SetPawn": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x40\\x53\\x48\\x83\\xEC\\x20\\x8B\\x91\\x38\\x0B\\x00\\x00\\x48\\x8B\\xD9",
|
||||
"linux": "\\x8B\\x8F\\x40\\x0E\\x00\\x00\\x83\\xF9\\xFF\\x0F\\x84\\xD9\\x01"
|
||||
"library": "server",
|
||||
"windows": "\\x44\\x88\\x4C\\x24\\x2A\\x55\\x57",
|
||||
"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": {
|
||||
@@ -70,8 +70,15 @@
|
||||
"CBaseModelEntity_SetModel": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x89\\x5C\\x24\\x10\\x48\\x89\\x7C\\x24\\x20\\x55\\x48\\x8B\\xEC\\x48\\x83\\xEC\\x50",
|
||||
"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"
|
||||
"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\\x18\\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": {
|
||||
@@ -82,7 +89,7 @@
|
||||
},
|
||||
"CCSPlayer_ItemServices_RemoveWeapons": {
|
||||
"offsets": {
|
||||
"windows": 21,
|
||||
"windows": 19,
|
||||
"linux": 20
|
||||
}
|
||||
},
|
||||
@@ -95,14 +102,14 @@
|
||||
"CCSGameRules_TerminateRound": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x8B\\xC4\\x4C\\x89\\x48\\x20\\x55\\x56",
|
||||
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x55\\x49\\x89\\xFD\\x41\\x54\\x53\\x48\\x81\\xEC\\xE8"
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"UTIL_CreateEntityByName": {
|
||||
"signatures": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
@@ -110,7 +117,7 @@
|
||||
"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\\x4B\\x55\\x48\\x89\\xE5\\x41\\x56"
|
||||
"linux": "\\x48\\x85\\xFF\\x74\\x2A\\x55\\x48\\x89\\xE5\\x41\\x56"
|
||||
}
|
||||
},
|
||||
"CEntityInstance_AcceptInput": {
|
||||
@@ -123,14 +130,14 @@
|
||||
"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": "\\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"
|
||||
}
|
||||
},
|
||||
"CBasePlayerPawn_CommitSuicide": {
|
||||
"offsets": {
|
||||
"windows": 357,
|
||||
"linux": 357
|
||||
"windows": 359,
|
||||
"linux": 359
|
||||
}
|
||||
},
|
||||
"CBasePlayerPawn_RemovePlayerItem": {
|
||||
@@ -189,15 +196,15 @@
|
||||
},
|
||||
"GameEventManager": {
|
||||
"offsets": {
|
||||
"windows": 91,
|
||||
"linux": 91
|
||||
"windows": 93,
|
||||
"linux": 93
|
||||
}
|
||||
},
|
||||
"CEntityIOOutput_FireOutputInternal": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "\\x48\\x8B\\xC4\\x4C\\x89\\x48\\x20\\x55\\x57\\x41\\x54\\x41\\x56",
|
||||
"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);
|
||||
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);
|
||||
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]
|
||||
|
||||
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++)
|
||||
{
|
||||
CommandUtils.AddStandaloneCommand("css_" + i, "Command Key Handler", (player, info) =>
|
||||
CommandUtils.AddStandaloneCommand($"css_{i}", "Command Key Handler", (player, info) =>
|
||||
{
|
||||
if (player == null) return;
|
||||
var key = Convert.ToInt32(info.GetArg(0).Split("_")[1]);
|
||||
ChatMenus.OnKeyPress(player, key);
|
||||
|
||||
MenuManager.OnKeyPress(player, key);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -151,7 +152,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
case "start":
|
||||
case "load":
|
||||
{
|
||||
if (info.ArgCount < 2)
|
||||
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",
|
||||
@@ -181,7 +182,8 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
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
|
||||
@@ -195,7 +197,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
case "stop":
|
||||
case "unload":
|
||||
{
|
||||
if (info.ArgCount < 2)
|
||||
if (info.ArgCount < 3)
|
||||
{
|
||||
info.ReplyToCommand(
|
||||
"Valid usage: css_plugins stop/unload [plugin name || #plugin id] (e.g \"TestPlugin\", \"1\")\n",
|
||||
@@ -207,7 +209,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
IPluginContext? plugin = _pluginContextQueryHandler.FindPluginByIdOrName(pluginIdentifier);
|
||||
if (plugin == null)
|
||||
{
|
||||
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\")", true);
|
||||
info.ReplyToCommand($"Could not unload plugin \"{pluginIdentifier}\"", true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,7 +220,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
case "restart":
|
||||
case "reload":
|
||||
{
|
||||
if (info.ArgCount < 2)
|
||||
if (info.ArgCount < 3)
|
||||
{
|
||||
info.ReplyToCommand(
|
||||
"Valid usage: css_plugins restart/reload [plugin name || #plugin id] (e.g \"TestPlugin\", \"#1\")\n",
|
||||
@@ -231,7 +233,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
|
||||
if (plugin == null)
|
||||
{
|
||||
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\")", true);
|
||||
info.ReplyToCommand($"Could not reload plugin \"{pluginIdentifier}\"", true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -288,7 +290,7 @@ namespace CounterStrikeSharp.API.Core
|
||||
CommandUtils.AddStandaloneCommand("css", "Counter-Strike Sharp options.", OnCSSCommand);
|
||||
CommandUtils.AddStandaloneCommand("css_plugins", "Counter-Strike Sharp plugin options.",
|
||||
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>
|
||||
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 int? UserId
|
||||
{
|
||||
get
|
||||
{
|
||||
return NativeAPI.GetUseridFromIndex((int)this.Index);
|
||||
}
|
||||
}
|
||||
|
||||
public CsTeam Team => (CsTeam)this.TeamNum;
|
||||
public int? UserId => NativeAPI.GetUseridFromIndex((int)Index);
|
||||
public CsTeam Team => (CsTeam)TeamNum;
|
||||
|
||||
public IntPtr GiveNamedItem(string item)
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return 0;
|
||||
if (PlayerPawn.Value == null) return 0;
|
||||
if (!PlayerPawn.Value.IsValid) return 0;
|
||||
if (PlayerPawn.Value.ItemServices == null) return 0;
|
||||
|
||||
@@ -37,7 +31,7 @@ public partial class CCSPlayerController
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
return this.GiveNamedItem(itemString);
|
||||
return GiveNamedItem(itemString);
|
||||
}
|
||||
|
||||
public void PrintToConsole(string message)
|
||||
@@ -47,12 +41,12 @@ public partial class CCSPlayerController
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
@@ -74,14 +68,16 @@ public partial class CCSPlayerController
|
||||
public void DropActiveWeapon()
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) return;
|
||||
if (!PlayerPawn.Value.IsValid) return;
|
||||
if (PlayerPawn.Value.ItemServices == null) return;
|
||||
if (PlayerPawn.Value.WeaponServices == null) return;
|
||||
if (!PlayerPawn.Value.WeaponServices.ActiveWeapon.IsValid) return;
|
||||
|
||||
CCSPlayer_ItemServices itemServices = new CCSPlayer_ItemServices(PlayerPawn.Value.ItemServices.Handle);
|
||||
CCSPlayer_WeaponServices weponServices = new CCSPlayer_WeaponServices(PlayerPawn.Value.WeaponServices.Handle);
|
||||
itemServices.DropActivePlayerWeapon(weponServices.ActiveWeapon.Value);
|
||||
CCSPlayer_WeaponServices weaponServices = new CCSPlayer_WeaponServices(PlayerPawn.Value.WeaponServices.Handle);
|
||||
|
||||
itemServices.DropActivePlayerWeapon(weaponServices.ActiveWeapon.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -90,6 +86,7 @@ public partial class CCSPlayerController
|
||||
public void RemoveWeapons()
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) return;
|
||||
if (!PlayerPawn.Value.IsValid) return;
|
||||
if (PlayerPawn.Value.ItemServices == null) return;
|
||||
|
||||
@@ -105,6 +102,7 @@ public partial class CCSPlayerController
|
||||
public void CommitSuicide(bool explode, bool force)
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) return;
|
||||
if (!PlayerPawn.Value.IsValid) return;
|
||||
|
||||
PlayerPawn.Value.CommitSuicide(explode, force);
|
||||
@@ -116,9 +114,11 @@ public partial class CCSPlayerController
|
||||
public void Respawn()
|
||||
{
|
||||
if (!PlayerPawn.IsValid) return;
|
||||
if (PlayerPawn.Value == null) 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);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public partial class CCSPlayerController
|
||||
/// <param name="team">The team to switch to</param>
|
||||
public void SwitchTeam(CsTeam team)
|
||||
{
|
||||
VirtualFunctions.SwitchTeam(this.Handle, (byte)team);
|
||||
VirtualFunctions.SwitchTeam(Handle, (byte)team);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -153,7 +153,7 @@ public partial class CCSPlayerController
|
||||
/// <returns>ConVar string value</returns>
|
||||
public string GetConVarValue(string conVar)
|
||||
{
|
||||
return NativeAPI.GetClientConvarValue(this.Slot, conVar);
|
||||
return NativeAPI.GetClientConvarValue(Slot, 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)");
|
||||
}
|
||||
|
||||
NativeAPI.SetFakeClientConvarValue(this.Slot, conVar, value);
|
||||
NativeAPI.SetFakeClientConvarValue(Slot, conVar, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -228,8 +228,8 @@ public partial class CCSPlayerController
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.IsValid) return null;
|
||||
var authorizedSteamId = NativeAPI.GetPlayerAuthorizedSteamid(this.Slot);
|
||||
if (!IsValid) return null;
|
||||
var authorizedSteamId = NativeAPI.GetPlayerAuthorizedSteamid(Slot);
|
||||
if ((long)authorizedSteamId == -1) return null;
|
||||
|
||||
return (SteamID)authorizedSteamId;
|
||||
@@ -244,8 +244,8 @@ public partial class CCSPlayerController
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!this.IsValid) return null;
|
||||
var ipAddress = NativeAPI.GetPlayerIpAddress(this.Slot);
|
||||
if (!IsValid) return null;
|
||||
var ipAddress = NativeAPI.GetPlayerIpAddress(Slot);
|
||||
if (string.IsNullOrWhiteSpace(ipAddress)) return null;
|
||||
|
||||
return ipAddress;
|
||||
@@ -258,9 +258,6 @@ public partial class CCSPlayerController
|
||||
public VoiceFlags VoiceFlags
|
||||
{
|
||||
get => (VoiceFlags)NativeAPI.GetClientVoiceFlags(Handle);
|
||||
set
|
||||
{
|
||||
NativeAPI.SetClientVoiceFlags(Handle, (Byte)value);
|
||||
}
|
||||
set => NativeAPI.SetClientVoiceFlags(Handle, (Byte)value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
using System;
|
||||
using CounterStrikeSharp.API.Modules.Memory;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core;
|
||||
|
||||
public partial class CCSPlayerPawn
|
||||
{
|
||||
/// <summary>
|
||||
/// Respawn player
|
||||
/// </summary>
|
||||
public void Respawn()
|
||||
{
|
||||
if (!Controller.IsValid) return;
|
||||
if (!Controller.Value.IsValid) return;
|
||||
/// <summary>
|
||||
/// Respawn player
|
||||
/// </summary>
|
||||
|
||||
VirtualFunctions.CCSPlayerPawn_Respawn(Handle);
|
||||
VirtualFunction.CreateVoid<IntPtr>(Controller.Value.Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(Controller.Value.Handle);
|
||||
}
|
||||
}
|
||||
[Obsolete("Use CCSPlayerController.Respawn() instead")]
|
||||
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>
|
||||
<NoWarn>$(NoWarn);CS1591;CP0003</NoWarn>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateCompatibilitySuppressionFile>true</GenerateCompatibilitySuppressionFile>
|
||||
<Authors>Roflmuffin</Authors>
|
||||
<Description>Official server side runtime assembly for CounterStrikeSharp</Description>
|
||||
<PackageProjectUrl>http://docs.cssharp.dev/</PackageProjectUrl>
|
||||
@@ -17,7 +18,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApiCompatValidateAssemblies>true</ApiCompatValidateAssemblies>
|
||||
<ApiCompatContractAssembly>.\ApiCompat\v133.dll</ApiCompatContractAssembly>
|
||||
<ApiCompatContractAssembly>.\ApiCompat\v151.dll</ApiCompatContractAssembly>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<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.
|
||||
// The server console should have access to all commands, regardless of groups.
|
||||
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);
|
||||
if (playerData == null) return false;
|
||||
@@ -136,20 +136,20 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
return playerData.Groups.IsSupersetOf(playerGroups);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a player to a group.
|
||||
/// </summary>
|
||||
/// <param name="player">Player controller.</param>
|
||||
/// <param name="groups">Groups to add the player to.</param>
|
||||
public static void AddPlayerToGroup(CCSPlayerController? player, params string[] groups)
|
||||
/// <summary>
|
||||
/// Adds a player to a group. This does NOT modify the immunity of the player (see SetPlayerImmunity).
|
||||
/// </summary>
|
||||
/// <param name="player">Player controller.</param>
|
||||
/// <param name="groups">Groups to add the player to.</param>
|
||||
public static void AddPlayerToGroup(CCSPlayerController? player, params string[] groups)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <param name="steamId">SteamID of the player.</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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -167,22 +167,43 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grabs the admin data for a player that was loaded from "configs/admins.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)
|
||||
/// <summary>
|
||||
/// Grabs the admin data for a player that was loaded from "configs/admins.json" and "configs/admins_groups.json".
|
||||
/// </summary>
|
||||
/// <param name="player">Player controller</param>
|
||||
/// <returns>AdminData class if data found, null if not.</returns>
|
||||
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;
|
||||
return Admins.GetValueOrDefault(steamId);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
/// <summary>
|
||||
/// Removes a players admin data. This is not saved to "configs/admins.json"
|
||||
/// </summary>
|
||||
/// <param name="player">Player controller</param>
|
||||
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;
|
||||
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.
|
||||
// The server console should have access to all commands, regardless of permissions.
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -260,7 +281,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
// 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.
|
||||
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);
|
||||
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.
|
||||
// The server console should have access to all commands, regardless of permissions.
|
||||
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);
|
||||
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.
|
||||
// The server console should have access to all commands, regardless of permissions.
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -362,7 +383,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
public static void AddPlayerPermissions(CCSPlayerController? player, params string[] flags)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -400,7 +421,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
public static void RemovePlayerPermissions(CCSPlayerController? player, params string[] flags)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -427,7 +448,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
public static void ClearPlayerPermissions(CCSPlayerController? player)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -457,7 +478,7 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
public static void SetPlayerImmunity(CCSPlayerController? player, uint value)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -477,13 +498,44 @@ namespace CounterStrikeSharp.API.Modules.Admin
|
||||
Admins[steamId] = data;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
/// <summary>
|
||||
/// Returns the immunity value for a player.
|
||||
/// </summary>
|
||||
/// <param name="player">Player controller.</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(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.
|
||||
if (caller == null) return true;
|
||||
|
||||
@@ -90,11 +90,11 @@ public class Target
|
||||
case TargetType.TeamSpec:
|
||||
return player.TeamNum == (byte)CsTeam.Spectator;
|
||||
case TargetType.GroupAll:
|
||||
return true;
|
||||
return !player.IsHLTV;
|
||||
case TargetType.GroupBots:
|
||||
return player.IsBot;
|
||||
case TargetType.GroupHumans:
|
||||
return !player.IsBot;
|
||||
return !player.IsBot && !player.IsHLTV;
|
||||
case TargetType.GroupAlive:
|
||||
return player.PlayerPawn is { IsValid: true, Value.LifeState: (byte)LifeState_t.LIFE_ALIVE };
|
||||
case TargetType.GroupDead:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* 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
|
||||
@@ -36,9 +36,12 @@ namespace CounterStrikeSharp.API.Modules.Entities.Constants
|
||||
TerroristsSurrender = 0x11u, // this also triggers match cancelled
|
||||
CTsSurrender = 0x12u, // this also triggers match cancelled
|
||||
|
||||
TerroristsPlanned = 0x13u,
|
||||
TerroristsPlanted = 0x13u,
|
||||
CTsReachedHostage = 0x14u,
|
||||
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"));
|
||||
|
||||
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<CEntityInstance, CTakeDamageInfo> CBaseEntity_TakeDamageOldFunc = new (GameData.GetSignature("CBaseEntity_TakeDamageOld"));
|
||||
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 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 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;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
/*
|
||||
* This file is part of CounterStrikeSharp.
|
||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
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
|
||||
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)
|
||||
public ChatMenuInstance(CCSPlayerController player, ChatMenu menu) : base(player, menu)
|
||||
{
|
||||
_menu = menu;
|
||||
_player = player;
|
||||
}
|
||||
|
||||
private bool HasPrevButton => _page > 0;
|
||||
private bool HasNextButton => (_currentOffset + _numPerPage) < _menu.MenuOptions.Count;
|
||||
private int MenuItemsPerPage => _numPerPage + 2 - (HasNextButton ? 1 : 0) - (HasPrevButton ? 1 : 0);
|
||||
|
||||
public void Display()
|
||||
public override void Display()
|
||||
{
|
||||
_player.PrintToChat(_menu.Title);
|
||||
_player.PrintToChat("---");
|
||||
Player.PrintToChat(Menu.Title);
|
||||
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)
|
||||
{
|
||||
_player.PrintToChat($" {ChatColors.Yellow}[!1] {ChatColors.Default}-> Prev");
|
||||
keyOffset++;
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!7 {ChatColors.Default}-> Prev");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
_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
|
||||
{
|
||||
private static readonly Dictionary<IntPtr, ChatMenuInstance> ActiveMenus = new();
|
||||
|
||||
[Obsolete("Use MenuManager.OpenChatMenu instead")]
|
||||
public static void OpenMenu(CCSPlayerController player, ChatMenu menu)
|
||||
{
|
||||
ActiveMenus[player.Handle] = new ChatMenuInstance(player, menu);
|
||||
ActiveMenus[player.Handle].Display();
|
||||
MenuManager.OpenChatMenu(player, menu);
|
||||
}
|
||||
|
||||
[Obsolete("Use MenuManager.OnKeyPress instead")]
|
||||
public static void OnKeyPress(CCSPlayerController player, int key)
|
||||
{
|
||||
if (!ActiveMenus.ContainsKey(player.Handle)) return;
|
||||
|
||||
ActiveMenus[player.Handle].OnKeyPress(player, key);
|
||||
MenuManager.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()
|
||||
{
|
||||
// Chat Menu Example
|
||||
// [Legacy] Chat Menu Example
|
||||
var largeMenu = new ChatMenu("Test Menu");
|
||||
for (int i = 1; i < 26; i++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user