mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-07 00:16:36 -08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2b8044b8c | ||
|
|
eb9f5667d8 | ||
|
|
b9ca63a603 | ||
|
|
8fc926eacf | ||
|
|
5695c3f922 | ||
|
|
9071d51ecd | ||
|
|
0a32962f4a | ||
|
|
271705b377 | ||
|
|
cdcddbb5f3 | ||
|
|
91f51d0c5c | ||
|
|
e97f804294 | ||
|
|
4f805b18e2 |
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 }}"
|
||||
15
.github/workflows/discord-notify.yml
vendored
15
.github/workflows/discord-notify.yml
vendored
@@ -1,15 +0,0 @@
|
||||
name: Notify Discord on Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send Notification to Discord
|
||||
uses: Ilshidur/action-discord@2.4.0
|
||||
with:
|
||||
args: "A new release of CS# has been tagged! View it here: ${{ github.event.release.html_url }}"
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
@@ -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": {
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
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>
|
||||
@@ -182,7 +182,7 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -209,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;
|
||||
}
|
||||
|
||||
@@ -233,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -16,125 +16,149 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Menu
|
||||
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||
|
||||
public enum PostSelectAction
|
||||
{
|
||||
public abstract class BaseMenu : IMenu
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public List<ChatMenuOption> MenuOptions { get; } = new();
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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; }
|
||||
// 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 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;
|
||||
}
|
||||
|
||||
public abstract class BaseMenuInstance : IMenuInstance
|
||||
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()
|
||||
{
|
||||
public int NumPerPage => 6;
|
||||
public Stack<int> PrevPageOffsets { get; } = new();
|
||||
public IMenu Menu { get; }
|
||||
public CCSPlayerController Player { get; }
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public int Page { get; set; }
|
||||
public int CurrentOffset { get; set; }
|
||||
public void OnKeyPress(CCSPlayerController player, int key)
|
||||
{
|
||||
if (player.Handle != Player.Handle) return;
|
||||
|
||||
protected BaseMenuInstance(CCSPlayerController player, IMenu menu)
|
||||
if (key == 8 && HasNextButton)
|
||||
{
|
||||
Menu = menu;
|
||||
Player = player;
|
||||
NextPage();
|
||||
return;
|
||||
}
|
||||
|
||||
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()
|
||||
if (key == 7 && HasPrevButton)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
PrevPage();
|
||||
return;
|
||||
}
|
||||
|
||||
public void OnKeyPress(CCSPlayerController player, int key)
|
||||
if (key == 9)
|
||||
{
|
||||
if (player.Handle != Player.Handle) return;
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == 8 && HasNextButton)
|
||||
{
|
||||
NextPage();
|
||||
return;
|
||||
}
|
||||
var desiredValue = key;
|
||||
|
||||
if (key == 1 && HasPrevButton)
|
||||
{
|
||||
PrevPage();
|
||||
return;
|
||||
}
|
||||
var menuItemIndex = CurrentOffset + desiredValue - 1;
|
||||
|
||||
if (key == 9)
|
||||
{
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
var desiredValue = key;
|
||||
if (HasPrevButton) desiredValue = key - 1;
|
||||
|
||||
var menuItemIndex = CurrentOffset + desiredValue - 1;
|
||||
|
||||
if (menuItemIndex >= 0 && menuItemIndex < Menu.MenuOptions.Count)
|
||||
{
|
||||
var menuOption = Menu.MenuOptions[menuItemIndex];
|
||||
if (menuItemIndex >= 0 && menuItemIndex < Menu.MenuOptions.Count)
|
||||
{
|
||||
var menuOption = Menu.MenuOptions[menuItemIndex];
|
||||
|
||||
if (!menuOption.Disabled)
|
||||
if (!menuOption.Disabled)
|
||||
{
|
||||
menuOption.OnSelect(Player, menuOption);
|
||||
switch (Menu.PostSelectAction)
|
||||
{
|
||||
menuOption.OnSelect(Player, menuOption);
|
||||
Reset();
|
||||
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 NextPage()
|
||||
{
|
||||
PrevPageOffsets.Push(CurrentOffset);
|
||||
CurrentOffset += MenuItemsPerPage;
|
||||
Page++;
|
||||
Display();
|
||||
}
|
||||
|
||||
public void PrevPage()
|
||||
{
|
||||
Page--;
|
||||
CurrentOffset = PrevPageOffsets.Pop();
|
||||
Display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -17,109 +17,109 @@
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Menu
|
||||
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||
|
||||
public class CenterHtmlMenu : BaseMenu
|
||||
{
|
||||
public class CenterHtmlMenu : BaseMenu
|
||||
public CenterHtmlMenu(string title) : base(ModifyTitle(title))
|
||||
{
|
||||
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;
|
||||
}
|
||||
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)
|
||||
private static string ModifyTitle(string title)
|
||||
{
|
||||
if (title.Length > 32)
|
||||
{
|
||||
if (title.Length > 32)
|
||||
{
|
||||
Application.Instance.Logger.LogWarning("Title should not be longer than 32 characters for a CenterHtmlMenu");
|
||||
return title[..32];
|
||||
}
|
||||
|
||||
return title;
|
||||
Application.Instance.Logger.LogWarning("Title should not be longer than 32 characters for a CenterHtmlMenu");
|
||||
return title[..32];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
public class CenterHtmlMenuInstance : BaseMenuInstance
|
||||
private static string ModifyOptionDisplay(string display)
|
||||
{
|
||||
private readonly BasePlugin _plugin;
|
||||
|
||||
public CenterHtmlMenuInstance(BasePlugin plugin, CCSPlayerController player, IMenu menu) : base(player, menu)
|
||||
if (display.Length > 26)
|
||||
{
|
||||
_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;
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
builder.AppendFormat("<font color='green'>!1</font> -> Prev");
|
||||
builder.AppendLine("<br>");
|
||||
keyOffset++;
|
||||
}
|
||||
|
||||
for (var i = CurrentOffset; i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count); i++)
|
||||
{
|
||||
var option = Menu.MenuOptions[i];
|
||||
builder.Append($"<font color='green'>!{keyOffset++}</font> {option.Text}");
|
||||
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);
|
||||
Application.Instance.Logger.LogWarning("Display should not be longer than 26 characters for a CenterHtmlMenu item");
|
||||
return display[..26];
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -16,63 +16,61 @@
|
||||
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Menu
|
||||
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||
|
||||
public class ChatMenu: BaseMenu
|
||||
{
|
||||
public class ChatMenu: BaseMenu
|
||||
public ChatMenu(string title) : base(title)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class ChatMenuInstance : BaseMenuInstance
|
||||
{
|
||||
public ChatMenuInstance(CCSPlayerController player, ChatMenu menu) : base(player, menu)
|
||||
{
|
||||
public ChatMenu(string title) : base(title)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class ChatMenuInstance : BaseMenuInstance
|
||||
public override void Display()
|
||||
{
|
||||
public ChatMenuInstance(CCSPlayerController player, ChatMenu menu) : base(player, menu)
|
||||
Player.PrintToChat(Menu.Title);
|
||||
Player.PrintToChat("---");
|
||||
|
||||
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}");
|
||||
}
|
||||
|
||||
public override void Display()
|
||||
if (HasPrevButton)
|
||||
{
|
||||
Player.PrintToChat(Menu.Title);
|
||||
Player.PrintToChat("---");
|
||||
|
||||
var keyOffset = 1;
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!1 {ChatColors.Default}-> Prev");
|
||||
keyOffset++;
|
||||
}
|
||||
|
||||
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 (HasNextButton)
|
||||
{
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!8 {ChatColors.Default}-> Next");
|
||||
}
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!7 {ChatColors.Default}-> Prev");
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChatMenus
|
||||
{
|
||||
[Obsolete("Use MenuManager.OpenChatMenu instead")]
|
||||
public static void OpenMenu(CCSPlayerController player, ChatMenu menu)
|
||||
|
||||
if (HasNextButton)
|
||||
{
|
||||
MenuManager.OpenChatMenu(player, menu);
|
||||
}
|
||||
|
||||
[Obsolete("Use MenuManager.OnKeyPress instead")]
|
||||
public static void OnKeyPress(CCSPlayerController player, int key)
|
||||
{
|
||||
MenuManager.OnKeyPress(player, key);
|
||||
Player.PrintToChat($" {ChatColors.Yellow}!8 {ChatColors.Default}-> Next");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChatMenus
|
||||
{
|
||||
[Obsolete("Use MenuManager.OpenChatMenu instead")]
|
||||
public static void OpenMenu(CCSPlayerController player, ChatMenu menu)
|
||||
{
|
||||
MenuManager.OpenChatMenu(player, menu);
|
||||
}
|
||||
|
||||
[Obsolete("Use MenuManager.OnKeyPress instead")]
|
||||
public static void OnKeyPress(CCSPlayerController player, int key)
|
||||
{
|
||||
MenuManager.OnKeyPress(player, key);
|
||||
}
|
||||
}
|
||||
@@ -14,48 +14,45 @@
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Menu
|
||||
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||
|
||||
public class ConsoleMenu : BaseMenu
|
||||
{
|
||||
public class ConsoleMenu : BaseMenu
|
||||
public ConsoleMenu(string title) : base(title)
|
||||
{
|
||||
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;
|
||||
|
||||
if (HasPrevButton)
|
||||
{
|
||||
Player.PrintToConsole($"!1 -> Prev");
|
||||
keyOffset++;
|
||||
}
|
||||
|
||||
for (var i = CurrentOffset;
|
||||
i < Math.Min(CurrentOffset + MenuItemsPerPage, Menu.MenuOptions.Count);
|
||||
i++)
|
||||
{
|
||||
var option = Menu.MenuOptions[i];
|
||||
|
||||
Player.PrintToConsole(
|
||||
$" {(option.Disabled ? "[Enabled]" : "[Disabled] - ")} !{keyOffset++} {option.Text}");
|
||||
}
|
||||
|
||||
if (HasNextButton)
|
||||
{
|
||||
Player.PrintToConsole($"!8 -> Next");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,29 +16,41 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CounterStrikeSharp.API.Modules.Menu
|
||||
{
|
||||
public interface IMenu
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public List<ChatMenuOption> MenuOptions { get; }
|
||||
|
||||
public ChatMenuOption AddMenuOption(string display, Action<CCSPlayerController, ChatMenuOption> onSelect, bool disabled = false);
|
||||
}
|
||||
namespace CounterStrikeSharp.API.Modules.Menu;
|
||||
|
||||
public interface IMenuInstance
|
||||
public interface IMenu
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public List<ChatMenuOption> MenuOptions { get; }
|
||||
public PostSelectAction PostSelectAction
|
||||
{
|
||||
protected IMenu Menu { get; }
|
||||
protected CCSPlayerController? Player { 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 Display();
|
||||
public void OnKeyPress(CCSPlayerController player, int key);
|
||||
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);
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public static class MenuManager
|
||||
return !ActiveMenus.TryGetValue(player.Handle, out var value) ? null : value;
|
||||
}
|
||||
|
||||
private static void ResetMenus(CCSPlayerController player)
|
||||
public static void CloseActiveMenu(CCSPlayerController player)
|
||||
{
|
||||
if (ActiveMenus.TryGetValue(player.Handle, out var activeMenu))
|
||||
{
|
||||
@@ -41,26 +41,26 @@ public static class MenuManager
|
||||
|
||||
ActiveMenus.Remove(player.Handle);
|
||||
}
|
||||
|
||||
|
||||
public static void OpenChatMenu(CCSPlayerController player, ChatMenu menu)
|
||||
{
|
||||
ResetMenus(player);
|
||||
CloseActiveMenu(player);
|
||||
|
||||
ActiveMenus[player.Handle] = new ChatMenuInstance(player, menu);
|
||||
ActiveMenus[player.Handle].Display();
|
||||
}
|
||||
|
||||
|
||||
public static void OpenCenterHtmlMenu(BasePlugin plugin, CCSPlayerController player, CenterHtmlMenu menu)
|
||||
{
|
||||
ResetMenus(player);
|
||||
CloseActiveMenu(player);
|
||||
|
||||
ActiveMenus[player.Handle] = new CenterHtmlMenuInstance(plugin, player, menu);
|
||||
ActiveMenus[player.Handle].Display();
|
||||
}
|
||||
|
||||
|
||||
public static void OpenConsoleMenu(CCSPlayerController player, ConsoleMenu menu)
|
||||
{
|
||||
ResetMenus(player);
|
||||
CloseActiveMenu(player);
|
||||
|
||||
ActiveMenus[player.Handle] = new ConsoleMenuInstance(player, menu);
|
||||
ActiveMenus[player.Handle].Display();
|
||||
@@ -68,9 +68,6 @@ public static class MenuManager
|
||||
|
||||
public static void OnKeyPress(CCSPlayerController player, int key)
|
||||
{
|
||||
if (ActiveMenus.TryGetValue(player.Handle, out var activeMenu))
|
||||
{
|
||||
activeMenu.OnKeyPress(player, key);
|
||||
}
|
||||
GetActiveMenu(player)?.OnKeyPress(player, key);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user