mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-03-08 23:59:06 +00:00
Compare commits
2 Commits
b6c876d709
...
CS2-Simple
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7121f15e8 | ||
|
|
1c033f6462 |
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1 +0,0 @@
|
|||||||
ko_fi: daffyy
|
|
||||||
95
.github/workflows/build.yml
vendored
95
.github/workflows/build.yml
vendored
@@ -1,95 +0,0 @@
|
|||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
paths-ignore:
|
|
||||||
- '**/README.md'
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
paths-ignore:
|
|
||||||
- '**/README.md'
|
|
||||||
|
|
||||||
env:
|
|
||||||
BUILD_NUMBER: ${{ github.run_number }}
|
|
||||||
PROJECT_PATH_CS2_SIMPLEADMIN: "CS2-SimpleAdmin/CS2-SimpleAdmin.csproj"
|
|
||||||
PROJECT_PATH_CS2_SIMPLEADMINAPI: "CS2-SimpleAdminApi/CS2-SimpleAdminApi.csproj"
|
|
||||||
PROJECT_NAME_CS2_SIMPLEADMIN: "CS2-SimpleAdmin"
|
|
||||||
PROJECT_NAME_CS2_SIMPLEADMINAPI: "CS2-SimpleAdminApi"
|
|
||||||
OUTPUT_PATH: "./counterstrikesharp"
|
|
||||||
TMP_PATH: "./tmp"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
permissions: write-all
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
dotnet-version: 8.0.x
|
|
||||||
- name: Restore CS2-SimpleAdmin
|
|
||||||
run: dotnet restore ${{ env.PROJECT_PATH_CS2_SIMPLEADMIN }}
|
|
||||||
- name: Build CS2-SimpleAdmin
|
|
||||||
run: dotnet build ${{ env.PROJECT_PATH_CS2_SIMPLEADMIN }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}
|
|
||||||
- name: Restore CS2-SimpleAdminApi
|
|
||||||
run: dotnet restore ${{ env.PROJECT_PATH_CS2_SIMPLEADMINAPI }}
|
|
||||||
- name: Build CS2-SimpleAdminApi
|
|
||||||
run: dotnet build ${{ env.PROJECT_PATH_CS2_SIMPLEADMINAPI }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}
|
|
||||||
|
|
||||||
publish:
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
permissions: write-all
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
dotnet-version: 8.0.x
|
|
||||||
- name: Restore CS2-SimpleAdmin
|
|
||||||
run: dotnet restore ${{ env.PROJECT_PATH_CS2_SIMPLEADMIN }}
|
|
||||||
- name: Build CS2-SimpleAdmin
|
|
||||||
run: dotnet build ${{ env.PROJECT_PATH_CS2_SIMPLEADMIN }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}
|
|
||||||
- name: Restore CS2-SimpleAdminApi
|
|
||||||
run: dotnet restore ${{ env.PROJECT_PATH_CS2_SIMPLEADMINAPI }}
|
|
||||||
- name: Build CS2-SimpleAdminApi
|
|
||||||
run: dotnet build ${{ env.PROJECT_PATH_CS2_SIMPLEADMINAPI }} -c Release -o ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}
|
|
||||||
- name: Clean files
|
|
||||||
run: |
|
|
||||||
rm -f \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}/CounterStrikeSharp.API.dll \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}/McMaster.NETCore.Plugins.dll \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}/Microsoft.DotNet.PlatformAbstractions.dll \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}/Microsoft.Extensions.DependencyModel.dll \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}/CS2-SimpleAdminApi.* \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}/Microsoft.* \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}/CounterStrikeSharp.API.dll \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}/McMaster.NETCore.Plugins.dll \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}/Microsoft.DotNet.PlatformAbstractions.dll \
|
|
||||||
${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }}/Microsoft.Extensions.DependencyModel.dll
|
|
||||||
- name: Combine projects
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ env.OUTPUT_PATH }}/plugins
|
|
||||||
mkdir -p ${{ env.OUTPUT_PATH }}/shared
|
|
||||||
cp -r ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }} ${{ env.OUTPUT_PATH }}/plugins/
|
|
||||||
cp -r ${{ env.TMP_PATH }}/${{ env.PROJECT_NAME_CS2_SIMPLEADMINAPI }} ${{ env.OUTPUT_PATH }}/shared/
|
|
||||||
- name: Zip combined
|
|
||||||
uses: thedoctor0/zip-release@0.7.6
|
|
||||||
with:
|
|
||||||
type: 'zip'
|
|
||||||
filename: '${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}-${{ env.BUILD_NUMBER }}.zip'
|
|
||||||
path: ${{ env.OUTPUT_PATH }}
|
|
||||||
- name: Publish combined release
|
|
||||||
uses: ncipollo/release-action@v1.14.0
|
|
||||||
with:
|
|
||||||
artifacts: "${{ env.PROJECT_NAME_CS2_SIMPLEADMIN }}-${{ env.BUILD_NUMBER }}.zip"
|
|
||||||
name: "CS2-SimpleAdmin - Build ${{ env.BUILD_NUMBER }}"
|
|
||||||
tag: "build-${{ env.BUILD_NUMBER }}"
|
|
||||||
body: |
|
|
||||||
Place files in addons/counterstrikesharp
|
|
||||||
After first launch, configure the plugins in the respective configs:
|
|
||||||
- CS2-SimpleAdmin: addons/counterstrikesharp/configs/plugins/CS2-SimpleAdmin/CS2-SimpleAdmin.json
|
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,8 +0,0 @@
|
|||||||
bin/
|
|
||||||
obj/
|
|
||||||
.vs/
|
|
||||||
.git
|
|
||||||
.vscode/
|
|
||||||
.idea/
|
|
||||||
CS2-SimpleAdmin.sln.DotSettings.user
|
|
||||||
Modules/CS2-SimpleAdmin_ExampleModule/CS2-SimpleAdmin_ExampleModule.sln.DotSettings.user
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 17
|
|
||||||
VisualStudioVersion = 17.8.34309.116
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2-SimpleAdmin", "CS2-SimpleAdmin\CS2-SimpleAdmin.csproj", "{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CS2-SimpleAdminApi", "CS2-SimpleAdminApi\CS2-SimpleAdminApi.csproj", "{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{CC7C3B4D-26C9-4DE7-B4E1-0864350468D0}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{8BEF0C35-7E4E-4BAF-B632-8584FAFCA922}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {86114444-059F-4DB8-9A55-E6D1BB76238D}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
BIN
CS2-SimpleAdmin/3rd_party/MenuManagerApi — old.dll
vendored
BIN
CS2-SimpleAdmin/3rd_party/MenuManagerApi — old.dll
vendored
Binary file not shown.
BIN
CS2-SimpleAdmin/3rd_party/MenuManagerApi.dll
vendored
BIN
CS2-SimpleAdmin/3rd_party/MenuManagerApi.dll
vendored
Binary file not shown.
@@ -1,132 +0,0 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
|
||||||
using CS2_SimpleAdmin.Managers;
|
|
||||||
using CS2_SimpleAdminApi;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin.Api;
|
|
||||||
|
|
||||||
public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
|
|
||||||
{
|
|
||||||
public PlayerInfo GetPlayerInfo(CCSPlayerController player)
|
|
||||||
{
|
|
||||||
if (!player.UserId.HasValue)
|
|
||||||
throw new KeyNotFoundException("Player with specific UserId not found");
|
|
||||||
|
|
||||||
return CS2_SimpleAdmin.PlayersInfo[player.UserId.Value];
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetConnectionString() => CS2_SimpleAdmin.Instance.DbConnectionString;
|
|
||||||
public string GetServerAddress() => CS2_SimpleAdmin.IpAddress;
|
|
||||||
public int? GetServerId() => CS2_SimpleAdmin.ServerId;
|
|
||||||
|
|
||||||
public Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration, bool Passed)>> GetPlayerMuteStatus(CCSPlayerController player)
|
|
||||||
{
|
|
||||||
return PlayerPenaltyManager.GetAllPlayerPenalties(player.Slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
public event Action<PlayerInfo, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltied;
|
|
||||||
public event Action<SteamID, PlayerInfo?, PenaltyType, string, int, int?, int?>? OnPlayerPenaltiedAdded;
|
|
||||||
public event Action<string, string?, bool, object>? OnAdminShowActivity;
|
|
||||||
|
|
||||||
public void OnPlayerPenaltiedEvent(PlayerInfo player, PlayerInfo? admin, PenaltyType penaltyType, string reason,
|
|
||||||
int duration, int? penaltyId) => OnPlayerPenaltied?.Invoke(player, admin, penaltyType, reason, duration, penaltyId, CS2_SimpleAdmin.ServerId);
|
|
||||||
|
|
||||||
public void OnPlayerPenaltiedAddedEvent(SteamID player, PlayerInfo? admin, PenaltyType penaltyType, string reason,
|
|
||||||
int duration, int? penaltyId) => OnPlayerPenaltiedAdded?.Invoke(player, admin, penaltyType, reason, duration, penaltyId, CS2_SimpleAdmin.ServerId);
|
|
||||||
|
|
||||||
public void OnAdminShowActivityEvent(string messageKey, string? callerName = null, bool dontPublish = false, params object[] messageArgs) => OnAdminShowActivity?.Invoke(messageKey, callerName, dontPublish, messageArgs);
|
|
||||||
|
|
||||||
public void IssuePenalty(CCSPlayerController player, CCSPlayerController? admin, PenaltyType penaltyType, string reason, int duration = -1)
|
|
||||||
{
|
|
||||||
switch (penaltyType)
|
|
||||||
{
|
|
||||||
case PenaltyType.Ban:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.Ban(admin, player, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Kick:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.Kick(admin, player, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Gag:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.Gag(admin, player, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Mute:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.Mute(admin, player, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Silence:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.Silence(admin, player, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Warn:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.Warn(admin, player, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(penaltyType), penaltyType, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void IssuePenalty(SteamID steamid, CCSPlayerController? admin, PenaltyType penaltyType, string reason, int duration = -1)
|
|
||||||
{
|
|
||||||
switch (penaltyType)
|
|
||||||
{
|
|
||||||
case PenaltyType.Ban:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.AddBan(admin, steamid, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Gag:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.AddGag(admin, steamid, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Mute:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.AddMute(admin, steamid, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Silence:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.AddSilence(admin, steamid, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PenaltyType.Warn:
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.AddWarn(admin, steamid, duration, reason);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(penaltyType), penaltyType, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LogCommand(CCSPlayerController? caller, string command)
|
|
||||||
{
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LogCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsAdminSilent(CCSPlayerController player)
|
|
||||||
{
|
|
||||||
return CS2_SimpleAdmin.SilentPlayers.Contains(player.Slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ShowAdminActivity(string messageKey, string? callerName = null, bool dontPublish = false, params object[] messageArgs)
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(messageKey, callerName, dontPublish, messageArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Core.Attributes;
|
|
||||||
using CounterStrikeSharp.API.Core.Capabilities;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands.Targeting;
|
|
||||||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
|
||||||
using CS2_SimpleAdmin.Managers;
|
|
||||||
using CS2_SimpleAdminApi;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MySqlConnector;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
[MinimumApiVersion(300)]
|
|
||||||
public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdminConfig>
|
|
||||||
{
|
|
||||||
internal static CS2_SimpleAdmin Instance { get; private set; } = new();
|
|
||||||
|
|
||||||
public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)");
|
|
||||||
public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)";
|
|
||||||
public override string ModuleAuthor => "daffyy & Dliix66";
|
|
||||||
public override string ModuleVersion => "1.7.6a";
|
|
||||||
|
|
||||||
public override void Load(bool hotReload)
|
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
|
|
||||||
RegisterEvents();
|
|
||||||
|
|
||||||
if (hotReload)
|
|
||||||
{
|
|
||||||
ServerLoaded = false;
|
|
||||||
_serverLoading = false;
|
|
||||||
OnGameServerSteamAPIActivated();
|
|
||||||
OnMapStart(string.Empty);
|
|
||||||
|
|
||||||
AddTimer(2.0f, () =>
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
var playerManager = new PlayerManager();
|
|
||||||
|
|
||||||
Helper.GetValidPlayers().ForEach(player =>
|
|
||||||
{
|
|
||||||
playerManager.LoadPlayerData(player);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_cBasePlayerControllerSetPawnFunc = new MemoryFunctionVoid<CBasePlayerController, CCSPlayerPawn, bool, bool>(GameData.GetSignature("CBasePlayerController_SetPawn"));
|
|
||||||
|
|
||||||
SimpleAdminApi = new Api.CS2_SimpleAdminApi();
|
|
||||||
Capabilities.RegisterPluginCapability(ICS2_SimpleAdminApi.PluginCapability, () => SimpleAdminApi);
|
|
||||||
|
|
||||||
new PlayerManager().CheckPlayersTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnAllPluginsLoaded(bool hotReload)
|
|
||||||
{
|
|
||||||
AddTimer(5.0f, () => ReloadAdmins(null));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MenuApi = MenuCapability.Get();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError("Unable to load required plugins ... \n{exception}", ex.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterCommands.InitializeCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnConfigParsed(CS2_SimpleAdminConfig config)
|
|
||||||
{
|
|
||||||
Instance = this;
|
|
||||||
_logger = Logger;
|
|
||||||
|
|
||||||
if (config.DatabaseHost.Length < 1 || config.DatabaseName.Length < 1 || config.DatabaseUser.Length < 1)
|
|
||||||
{
|
|
||||||
throw new Exception("[CS2-SimpleAdmin] You need to setup Database credentials in config!");
|
|
||||||
}
|
|
||||||
|
|
||||||
MySqlConnectionStringBuilder builder = new()
|
|
||||||
{
|
|
||||||
Server = config.DatabaseHost,
|
|
||||||
Database = config.DatabaseName,
|
|
||||||
UserID = config.DatabaseUser,
|
|
||||||
Password = config.DatabasePassword,
|
|
||||||
Port = (uint)config.DatabasePort,
|
|
||||||
SslMode = Enum.TryParse(config.DatabaseSSlMode, true, out MySqlSslMode sslMode) ? sslMode : MySqlSslMode.Preferred,
|
|
||||||
Pooling = true,
|
|
||||||
MinimumPoolSize = 0,
|
|
||||||
MaximumPoolSize = 640,
|
|
||||||
};
|
|
||||||
|
|
||||||
DbConnectionString = builder.ConnectionString;
|
|
||||||
Database = new Database.Database(DbConnectionString);
|
|
||||||
|
|
||||||
if (!Database.CheckDatabaseConnection(out var exception))
|
|
||||||
{
|
|
||||||
if (exception != null)
|
|
||||||
Logger.LogError("Problem with database connection! \n{exception}", exception);
|
|
||||||
|
|
||||||
Unload(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Task.Run(() => Database.DatabaseMigration());
|
|
||||||
|
|
||||||
Config = config;
|
|
||||||
Helper.UpdateConfig(config);
|
|
||||||
|
|
||||||
if (!Directory.Exists(ModuleDirectory + "/data"))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(ModuleDirectory + "/data");
|
|
||||||
}
|
|
||||||
|
|
||||||
_localizer = Localizer;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Config.Discord.DiscordLogWebhook))
|
|
||||||
DiscordWebhookClientLog = new DiscordManager(Config.Discord.DiscordLogWebhook);
|
|
||||||
|
|
||||||
PluginInfo.ShowAd(ModuleVersion);
|
|
||||||
if (Config.EnableUpdateCheck)
|
|
||||||
Task.Run(async () => await PluginInfo.CheckVersion(ModuleVersion, _logger));
|
|
||||||
|
|
||||||
PermissionManager = new PermissionManager(Database);
|
|
||||||
BanManager = new BanManager(Database);
|
|
||||||
MuteManager = new MuteManager(Database);
|
|
||||||
WarnManager = new WarnManager(Database);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TargetResult? GetTarget(CommandInfo command)
|
|
||||||
{
|
|
||||||
var matches = command.GetArgTargetResult(1);
|
|
||||||
|
|
||||||
if (!matches.Any())
|
|
||||||
{
|
|
||||||
command.ReplyToCommand($"Target {command.GetArg(1)} not found.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.GetArg(1).StartsWith('@'))
|
|
||||||
return matches;
|
|
||||||
|
|
||||||
if (matches.Count() == 1)
|
|
||||||
return matches;
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Multiple targets found for \"{command.GetArg(1)}\".");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<RootNamespace>CS2_SimpleAdmin</RootNamespace>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.305" />
|
|
||||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
|
||||||
<PackageReference Include="MySqlConnector" Version="2.4.0" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="*" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\CS2-SimpleAdminApi\CS2-SimpleAdminApi.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="lang\**\*.*" CopyToOutputDirectory="PreserveNewest" />
|
|
||||||
<None Update="Database\Migrations\010_CreateWarnsTable.sql">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="Database\Migrations\*.sql" CopyToOutputDirectory="PreserveNewest" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="admin_help.txt" CopyToOutputDirectory="PreserveNewest" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="MenuManagerApi">
|
|
||||||
<HintPath>3rd_party\MenuManagerApi.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,214 +0,0 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public static class RegisterCommands
|
|
||||||
{
|
|
||||||
private delegate void CommandCallback(CCSPlayerController? caller, CommandInfo.CommandCallback callback);
|
|
||||||
|
|
||||||
private static readonly string CommandsPath = Path.Combine(CS2_SimpleAdmin.ConfigDirectory, "Commands.json");
|
|
||||||
private static readonly List<CommandMapping> CommandMappings =
|
|
||||||
[
|
|
||||||
new CommandMapping("css_ban", CS2_SimpleAdmin.Instance.OnBanCommand),
|
|
||||||
new CommandMapping("css_addban", CS2_SimpleAdmin.Instance.OnAddBanCommand),
|
|
||||||
new CommandMapping("css_banip", CS2_SimpleAdmin.Instance.OnBanIpCommand),
|
|
||||||
new CommandMapping("css_unban", CS2_SimpleAdmin.Instance.OnUnbanCommand),
|
|
||||||
new CommandMapping("css_warn", CS2_SimpleAdmin.Instance.OnWarnCommand),
|
|
||||||
new CommandMapping("css_unwarn", CS2_SimpleAdmin.Instance.OnUnwarnCommand),
|
|
||||||
|
|
||||||
new CommandMapping("css_asay", CS2_SimpleAdmin.Instance.OnAdminToAdminSayCommand),
|
|
||||||
new CommandMapping("css_cssay", CS2_SimpleAdmin.Instance.OnAdminCustomSayCommand),
|
|
||||||
new CommandMapping("css_say", CS2_SimpleAdmin.Instance.OnAdminSayCommand),
|
|
||||||
new CommandMapping("css_psay", CS2_SimpleAdmin.Instance.OnAdminPrivateSayCommand),
|
|
||||||
new CommandMapping("css_csay", CS2_SimpleAdmin.Instance.OnAdminCenterSayCommand),
|
|
||||||
new CommandMapping("css_hsay", CS2_SimpleAdmin.Instance.OnAdminHudSayCommand),
|
|
||||||
|
|
||||||
new CommandMapping("css_penalties", CS2_SimpleAdmin.Instance.OnPenaltiesCommand),
|
|
||||||
new CommandMapping("css_admin", CS2_SimpleAdmin.Instance.OnAdminCommand),
|
|
||||||
new CommandMapping("css_adminhelp", CS2_SimpleAdmin.Instance.OnAdminHelpCommand),
|
|
||||||
new CommandMapping("css_addadmin", CS2_SimpleAdmin.Instance.OnAddAdminCommand),
|
|
||||||
new CommandMapping("css_deladmin", CS2_SimpleAdmin.Instance.OnDelAdminCommand),
|
|
||||||
new CommandMapping("css_addgroup", CS2_SimpleAdmin.Instance.OnAddGroup),
|
|
||||||
new CommandMapping("css_delgroup", CS2_SimpleAdmin.Instance.OnDelGroupCommand),
|
|
||||||
new CommandMapping("css_reloadadmins", CS2_SimpleAdmin.Instance.OnRelAdminCommand),
|
|
||||||
new CommandMapping("css_hide", CS2_SimpleAdmin.Instance.OnHideCommand),
|
|
||||||
new CommandMapping("css_hidecomms", CS2_SimpleAdmin.Instance.OnHideCommsCommand),
|
|
||||||
new CommandMapping("css_who", CS2_SimpleAdmin.Instance.OnWhoCommand),
|
|
||||||
new CommandMapping("css_disconnected", CS2_SimpleAdmin.Instance.OnDisconnectedCommand),
|
|
||||||
new CommandMapping("css_warns", CS2_SimpleAdmin.Instance.OnWarnsCommand),
|
|
||||||
new CommandMapping("css_players", CS2_SimpleAdmin.Instance.OnPlayersCommand),
|
|
||||||
new CommandMapping("css_kick", CS2_SimpleAdmin.Instance.OnKickCommand),
|
|
||||||
new CommandMapping("css_map", CS2_SimpleAdmin.Instance.OnMapCommand),
|
|
||||||
new CommandMapping("css_wsmap", CS2_SimpleAdmin.Instance.OnWorkshopMapCommand),
|
|
||||||
new CommandMapping("css_cvar", CS2_SimpleAdmin.Instance.OnCvarCommand),
|
|
||||||
new CommandMapping("css_rcon", CS2_SimpleAdmin.Instance.OnRconCommand),
|
|
||||||
new CommandMapping("css_rr", CS2_SimpleAdmin.Instance.OnRestartCommand),
|
|
||||||
|
|
||||||
new CommandMapping("css_gag", CS2_SimpleAdmin.Instance.OnGagCommand),
|
|
||||||
new CommandMapping("css_addgag", CS2_SimpleAdmin.Instance.OnAddGagCommand),
|
|
||||||
new CommandMapping("css_ungag", CS2_SimpleAdmin.Instance.OnUngagCommand),
|
|
||||||
new CommandMapping("css_mute", CS2_SimpleAdmin.Instance.OnMuteCommand),
|
|
||||||
new CommandMapping("css_addmute", CS2_SimpleAdmin.Instance.OnAddMuteCommand),
|
|
||||||
new CommandMapping("css_unmute", CS2_SimpleAdmin.Instance.OnUnmuteCommand),
|
|
||||||
new CommandMapping("css_silence", CS2_SimpleAdmin.Instance.OnSilenceCommand),
|
|
||||||
new CommandMapping("css_addsilence", CS2_SimpleAdmin.Instance.OnAddSilenceCommand),
|
|
||||||
new CommandMapping("css_unsilence", CS2_SimpleAdmin.Instance.OnUnsilenceCommand),
|
|
||||||
|
|
||||||
new CommandMapping("css_vote", CS2_SimpleAdmin.Instance.OnVoteCommand),
|
|
||||||
|
|
||||||
new CommandMapping("css_noclip", CS2_SimpleAdmin.Instance.OnNoclipCommand),
|
|
||||||
new CommandMapping("css_freeze", CS2_SimpleAdmin.Instance.OnFreezeCommand),
|
|
||||||
new CommandMapping("css_unfreeze", CS2_SimpleAdmin.Instance.OnUnfreezeCommand),
|
|
||||||
new CommandMapping("css_godmode", CS2_SimpleAdmin.Instance.OnGodCommand),
|
|
||||||
|
|
||||||
new CommandMapping("css_slay", CS2_SimpleAdmin.Instance.OnSlayCommand),
|
|
||||||
new CommandMapping("css_slap", CS2_SimpleAdmin.Instance.OnSlapCommand),
|
|
||||||
new CommandMapping("css_give", CS2_SimpleAdmin.Instance.OnGiveCommand),
|
|
||||||
new CommandMapping("css_strip", CS2_SimpleAdmin.Instance.OnStripCommand),
|
|
||||||
new CommandMapping("css_hp", CS2_SimpleAdmin.Instance.OnHpCommand),
|
|
||||||
new CommandMapping("css_speed", CS2_SimpleAdmin.Instance.OnSpeedCommand),
|
|
||||||
new CommandMapping("css_gravity", CS2_SimpleAdmin.Instance.OnGravityCommand),
|
|
||||||
new CommandMapping("css_resize", CS2_SimpleAdmin.Instance.OnResizeCommand),
|
|
||||||
new CommandMapping("css_money", CS2_SimpleAdmin.Instance.OnMoneyCommand),
|
|
||||||
new CommandMapping("css_team", CS2_SimpleAdmin.Instance.OnTeamCommand),
|
|
||||||
new CommandMapping("css_rename", CS2_SimpleAdmin.Instance.OnRenameCommand),
|
|
||||||
new CommandMapping("css_prename", CS2_SimpleAdmin.Instance.OnPrenameCommand),
|
|
||||||
new CommandMapping("css_respawn", CS2_SimpleAdmin.Instance.OnRespawnCommand),
|
|
||||||
new CommandMapping("css_tp", CS2_SimpleAdmin.Instance.OnGotoCommand),
|
|
||||||
new CommandMapping("css_bring", CS2_SimpleAdmin.Instance.OnBringCommand),
|
|
||||||
new CommandMapping("css_pluginsmanager", CS2_SimpleAdmin.Instance.OnPluginManagerCommand),
|
|
||||||
new CommandMapping("css_adminvoice", CS2_SimpleAdmin.Instance.OnAdminVoiceCommand)
|
|
||||||
];
|
|
||||||
|
|
||||||
public static void InitializeCommands()
|
|
||||||
{
|
|
||||||
if (!File.Exists(CommandsPath))
|
|
||||||
{
|
|
||||||
CreateConfig();
|
|
||||||
InitializeCommands();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Register();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CreateConfig()
|
|
||||||
{
|
|
||||||
var commands = new CommandsConfig
|
|
||||||
{
|
|
||||||
Commands = new Dictionary<string, Command>
|
|
||||||
{
|
|
||||||
{ "css_ban", new Command { Aliases = ["css_ban"] } },
|
|
||||||
{ "css_addban", new Command { Aliases = ["css_addban"] } },
|
|
||||||
{ "css_banip", new Command { Aliases = ["css_banip"] } },
|
|
||||||
{ "css_unban", new Command { Aliases = ["css_unban"] } },
|
|
||||||
{ "css_warn", new Command { Aliases = ["css_warn"] } },
|
|
||||||
{ "css_unwarn", new Command { Aliases = ["css_unwarn"] } },
|
|
||||||
{ "css_asay", new Command { Aliases = ["css_asay"] } },
|
|
||||||
{ "css_cssay", new Command { Aliases = ["css_cssay"] } },
|
|
||||||
{ "css_say", new Command { Aliases = ["css_say"] } },
|
|
||||||
{ "css_psay", new Command { Aliases = ["css_psay"] } },
|
|
||||||
{ "css_csay", new Command { Aliases = ["css_csay"] } },
|
|
||||||
{ "css_hsay", new Command { Aliases = ["css_hsay"] } },
|
|
||||||
{ "css_penalties", new Command { Aliases = ["css_penalties", "css_mypenalties", "css_comms"] } },
|
|
||||||
{ "css_admin", new Command { Aliases = ["css_admin"] } },
|
|
||||||
{ "css_adminhelp", new Command { Aliases = ["css_adminhelp"] } },
|
|
||||||
{ "css_addadmin", new Command { Aliases = ["css_addadmin"] } },
|
|
||||||
{ "css_deladmin", new Command { Aliases = ["css_deladmin"] } },
|
|
||||||
{ "css_addgroup", new Command { Aliases = ["css_addgroup"] } },
|
|
||||||
{ "css_delgroup", new Command { Aliases = ["css_delgroup"] } },
|
|
||||||
{ "css_reloadadmins", new Command { Aliases = ["css_reloadadmins"] } },
|
|
||||||
{ "css_hide", new Command { Aliases = ["css_hide", "css_stealth"] } },
|
|
||||||
{ "css_hidecomms", new Command { Aliases = ["css_hidecomms"] } },
|
|
||||||
{ "css_who", new Command { Aliases = ["css_who"] } },
|
|
||||||
{ "css_disconnected", new Command { Aliases = ["css_disconnected", "css_last"] } },
|
|
||||||
{ "css_warns", new Command { Aliases = ["css_warns"] } },
|
|
||||||
{ "css_players", new Command { Aliases = ["css_players"] } },
|
|
||||||
{ "css_kick", new Command { Aliases = ["css_kick"] } },
|
|
||||||
{ "css_map", new Command { Aliases = ["css_map", "css_changemap"] } },
|
|
||||||
{ "css_wsmap", new Command { Aliases = ["css_wsmap", "css_changewsmap", "css_workshop"] } },
|
|
||||||
{ "css_cvar", new Command { Aliases = ["css_cvar"] } },
|
|
||||||
{ "css_rcon", new Command { Aliases = ["css_rcon"] } },
|
|
||||||
{ "css_rr", new Command { Aliases = ["css_rr", "css_rg", "css_restart", "css_restartgame"] } },
|
|
||||||
{ "css_gag", new Command { Aliases = ["css_gag"] } },
|
|
||||||
{ "css_addgag", new Command { Aliases = ["css_addgag"] } },
|
|
||||||
{ "css_ungag", new Command { Aliases = ["css_ungag"] } },
|
|
||||||
{ "css_mute", new Command { Aliases = ["css_mute"] } },
|
|
||||||
{ "css_addmute", new Command { Aliases = ["css_addmute"] } },
|
|
||||||
{ "css_unmute", new Command { Aliases = ["css_unmute"] } },
|
|
||||||
{ "css_silence", new Command { Aliases = ["css_silence"] } },
|
|
||||||
{ "css_addsilence", new Command { Aliases = ["css_addsilence"] } },
|
|
||||||
{ "css_unsilence", new Command { Aliases = ["css_unsilence"] } },
|
|
||||||
{ "css_vote", new Command { Aliases = ["css_vote"] } },
|
|
||||||
{ "css_noclip", new Command { Aliases = ["css_noclip"] } },
|
|
||||||
{ "css_freeze", new Command { Aliases = ["css_freeze"] } },
|
|
||||||
{ "css_unfreeze", new Command { Aliases = ["css_unfreeze"] } },
|
|
||||||
{ "css_godmode", new Command { Aliases = ["css_godmode"] } },
|
|
||||||
{ "css_slay", new Command { Aliases = ["css_slay"] } },
|
|
||||||
{ "css_slap", new Command { Aliases = ["css_slap"] } },
|
|
||||||
{ "css_give", new Command { Aliases = ["css_give"] } },
|
|
||||||
{ "css_strip", new Command { Aliases = ["css_strip"] } },
|
|
||||||
{ "css_hp", new Command { Aliases = ["css_hp"] } },
|
|
||||||
{ "css_speed", new Command { Aliases = ["css_speed"] } },
|
|
||||||
{ "css_gravity", new Command { Aliases = ["css_gravity"] } },
|
|
||||||
{ "css_resize", new Command { Aliases = ["css_resize", "css_size"] } },
|
|
||||||
{ "css_money", new Command { Aliases = ["css_money"] } },
|
|
||||||
{ "css_team", new Command { Aliases = ["css_team"] } },
|
|
||||||
{ "css_rename", new Command { Aliases = ["css_rename"] } },
|
|
||||||
{ "css_prename", new Command { Aliases = ["css_prename"] } },
|
|
||||||
{ "css_respawn", new Command { Aliases = ["css_respawn"] } },
|
|
||||||
{ "css_tp", new Command { Aliases = ["css_tp", "css_tpto", "css_goto"] } },
|
|
||||||
{ "css_bring", new Command { Aliases = ["css_bring", "css_tphere"] } },
|
|
||||||
{ "css_pluginsmanager", new Command { Aliases = ["css_pluginsmanager", "css_pluginmanager"] } },
|
|
||||||
{ "css_adminvoice", new Command { Aliases = ["css_adminvoice", "css_listenall"] } }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var json = JsonConvert.SerializeObject(commands, Formatting.Indented);
|
|
||||||
File.WriteAllText(CommandsPath, json);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Register()
|
|
||||||
{
|
|
||||||
var json = File.ReadAllText(CommandsPath);
|
|
||||||
var commandsConfig = JsonConvert.DeserializeObject<CommandsConfig>(json);
|
|
||||||
|
|
||||||
if (commandsConfig?.Commands == null) return;
|
|
||||||
|
|
||||||
foreach (var command in commandsConfig.Commands)
|
|
||||||
{
|
|
||||||
if (command.Value.Aliases == null) continue;
|
|
||||||
|
|
||||||
CS2_SimpleAdmin._logger?.LogInformation(
|
|
||||||
$"Registering command: `{command.Key}` with aliases: `{string.Join(", ", command.Value.Aliases)}`");
|
|
||||||
|
|
||||||
var mapping = CommandMappings.FirstOrDefault(m => m.CommandKey == command.Key);
|
|
||||||
if (mapping == null || command.Value.Aliases.Length == 0) continue;
|
|
||||||
|
|
||||||
foreach (var alias in command.Value.Aliases)
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin.Instance.AddCommand(alias, "", mapping.Callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CommandsConfig
|
|
||||||
{
|
|
||||||
public Dictionary<string, Command>? Commands { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Command
|
|
||||||
{
|
|
||||||
public string[]? Aliases { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CommandMapping(string commandKey, CommandInfo.CommandCallback callback)
|
|
||||||
{
|
|
||||||
public string CommandKey { get; } = commandKey;
|
|
||||||
public CommandInfo.CommandCallback Callback { get; } = callback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,512 +0,0 @@
|
|||||||
using CounterStrikeSharp.API;
|
|
||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
|
||||||
using CounterStrikeSharp.API.ValveConstants.Protobuf;
|
|
||||||
using CS2_SimpleAdmin.Managers;
|
|
||||||
using CS2_SimpleAdmin.Menus;
|
|
||||||
using CS2_SimpleAdminApi;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public partial class CS2_SimpleAdmin
|
|
||||||
{
|
|
||||||
[RequiresPermissions("@css/ban")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnBanCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
if (command.ArgCount < 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, Connected: PlayerConnectedState.PlayerConnected, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
var time = Helper.ParsePenaltyTime(command.GetArg(2));
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
|
|
||||||
{
|
|
||||||
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_ban"] ?? "Ban"}: {player.PlayerName}", player,
|
|
||||||
ManagePlayersMenu.BanMenu);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ban(caller, player, time, reason, callerName, BanManager, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Ban(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, BanManager? banManager = null, CommandInfo? command = null, bool silent = false)
|
|
||||||
{
|
|
||||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
if (!CheckValidBan(caller, time)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
||||||
? caller.PlayerName
|
|
||||||
: (_localizer?["sa_console"] ?? "Console");
|
|
||||||
|
|
||||||
// Get player and admin information
|
|
||||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Asynchronously handle banning logic
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await BanManager.BanPlayer(playerInfo, adminInfo, reason, time);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update banned players list
|
|
||||||
if (playerInfo.IpAddress != null && !BannedPlayers.Contains(playerInfo.IpAddress))
|
|
||||||
BannedPlayers.Add(playerInfo.IpAddress);
|
|
||||||
if (!BannedPlayers.Contains(player.SteamID.ToString()))
|
|
||||||
BannedPlayers.Add(player.SteamID.ToString());
|
|
||||||
|
|
||||||
// Determine message keys and arguments based on ban time
|
|
||||||
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) = time == 0
|
|
||||||
? ("sa_player_ban_message_perm", "sa_admin_ban_message_perm",
|
|
||||||
[reason, "CALLER"],
|
|
||||||
["CALLER", player.PlayerName, reason])
|
|
||||||
: ("sa_player_ban_message_time", "sa_admin_ban_message_time",
|
|
||||||
new object[] { reason, time, "CALLER" },
|
|
||||||
new object[] { "CALLER", player.PlayerName, reason, time });
|
|
||||||
|
|
||||||
// Display center message to the player
|
|
||||||
Helper.DisplayCenterMessage(player, messageKey, callerName, centerArgs);
|
|
||||||
|
|
||||||
// Display admin activity message if necessary
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schedule a kick timer
|
|
||||||
if (player.UserId.HasValue)
|
|
||||||
{
|
|
||||||
Helper.KickPlayer(player.UserId.Value, NetworkDisconnectionReason.NETWORK_DISCONNECT_KICKBANADDED, Config.OtherSettings.KickTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute ban command if necessary
|
|
||||||
if (UnlockedCommands)
|
|
||||||
{
|
|
||||||
Server.ExecuteCommand($"banid 1 {new SteamID(player.SteamID).SteamId3}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!silent)
|
|
||||||
{
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_ban {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Ban, _localizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddBan(CCSPlayerController? caller, SteamID steamid, int time, string reason, BanManager? banManager = null)
|
|
||||||
{
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
||||||
? caller.PlayerName
|
|
||||||
: (_localizer?["sa_console"] ?? "Console");
|
|
||||||
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Ban(caller, player, time, reason, callerName, silent: true);
|
|
||||||
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(steamid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous ban operation if player is not online or not found
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await BanManager.AddBanBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Ban, _localizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/ban")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnAddBanCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
|
|
||||||
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
|
||||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand("Invalid SteamID64.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var steamid = steamId.SteamId64.ToString();
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
||||||
|
|
||||||
if (!CheckValidBan(caller, time)) return;
|
|
||||||
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue
|
|
||||||
? PlayersInfo[caller.UserId.Value]
|
|
||||||
: null;
|
|
||||||
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid);
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Ban(caller, player, time, reason, callerName, silent: true);
|
|
||||||
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous ban operation if player is not online or not found
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await BanManager.AddBanBySteamid(steamid, adminInfo, reason, time);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Ban, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Ban, _localizer);
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Ban has been added offline.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
if (UnlockedCommands)
|
|
||||||
Server.ExecuteCommand($"banid 1 {steamId.SteamId3}");
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/ban")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<ip> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnBanIpCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
var callerName = caller?.PlayerName ?? _localizer?["sa_console"] ?? "Console";
|
|
||||||
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
|
||||||
var ipAddress = command.GetArg(1);
|
|
||||||
|
|
||||||
if (!Helper.IsValidIp(ipAddress))
|
|
||||||
{
|
|
||||||
command.ReplyToCommand($"Invalid IP address.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
||||||
|
|
||||||
if (!CheckValidBan(caller, time)) return;
|
|
||||||
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue
|
|
||||||
? PlayersInfo[caller.UserId.Value]
|
|
||||||
: null;
|
|
||||||
|
|
||||||
var matches = Helper.GetPlayerFromIp(ipAddress);
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Ban(caller, player, time, reason, callerName, silent: true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Asynchronous ban operation if player is not online or not found
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await BanManager.AddBanByIp(ipAddress, adminInfo, reason, time);
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Player with ip {ipAddress} is not online. Ban has been added offline.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckValidBan(CCSPlayerController? caller, int duration)
|
|
||||||
{
|
|
||||||
if (caller == null) return true;
|
|
||||||
|
|
||||||
var canPermBan = AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/permban");
|
|
||||||
|
|
||||||
if (duration <= 0 && canPermBan == false)
|
|
||||||
{
|
|
||||||
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_perm_restricted"]}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (duration <= Config.OtherSettings.MaxBanDuration || canPermBan) return true;
|
|
||||||
|
|
||||||
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_max_duration_exceeded", Config.OtherSettings.MaxBanDuration]}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/unban")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnUnbanCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
if (command.GetArg(1).Length <= 1)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand($"Too short pattern to search.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pattern = command.GetArg(1);
|
|
||||||
var reason = command.ArgCount >= 2
|
|
||||||
? string.Join(" ", Enumerable.Range(2, command.ArgCount - 2).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
Task.Run(async () => await BanManager.UnbanPlayer(pattern, callerSteamId, reason));
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Unbanned player with pattern {pattern}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/kick")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnWarnCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null)
|
|
||||||
return;
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
if (command.ArgCount < 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player.Connected == PlayerConnectedState.PlayerConnected && !player.IsHLTV).ToList();
|
|
||||||
|
|
||||||
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WarnManager warnManager = new(Database);
|
|
||||||
|
|
||||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
Warn(caller, player, time, reason, callerName, warnManager, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Warn(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, WarnManager? warnManager = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
if (!CheckValidBan(caller, time)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
||||||
? caller.PlayerName
|
|
||||||
: (_localizer?["sa_console"] ?? "Console");
|
|
||||||
|
|
||||||
// Freeze player pawn if alive
|
|
||||||
if (player.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE)
|
|
||||||
{
|
|
||||||
player.PlayerPawn?.Value?.Freeze();
|
|
||||||
AddTimer(5.0f, () => player.PlayerPawn?.Value?.Unfreeze(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get player and admin information
|
|
||||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Asynchronously handle warning logic
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
warnManager ??= new WarnManager(Database);
|
|
||||||
int? penaltyId = await warnManager.WarnPlayer(playerInfo, adminInfo, reason, time);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Warn, reason, time, penaltyId);
|
|
||||||
|
|
||||||
// Check for warn thresholds and execute punish command if applicable
|
|
||||||
var totalWarns = await warnManager.GetPlayerWarnsCount(player.SteamID.ToString());
|
|
||||||
if (Config.WarnThreshold.Count > 0)
|
|
||||||
{
|
|
||||||
string? punishCommand = null;
|
|
||||||
var lastKey = Config.WarnThreshold.Keys.Max();
|
|
||||||
|
|
||||||
if (totalWarns >= lastKey)
|
|
||||||
punishCommand = Config.WarnThreshold[lastKey];
|
|
||||||
else if (Config.WarnThreshold.TryGetValue(totalWarns, out var value))
|
|
||||||
punishCommand = value;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(punishCommand))
|
|
||||||
{
|
|
||||||
await Server.NextFrameAsync(() =>
|
|
||||||
{
|
|
||||||
Server.ExecuteCommand(punishCommand.Replace("USERID", playerInfo.UserId.ToString()).Replace("STEAMID64", playerInfo.SteamId?.ToString()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Determine message keys and arguments based on warning time
|
|
||||||
var (messageKey, activityMessageKey, centerArgs, adminActivityArgs) = time == 0
|
|
||||||
? ("sa_player_warn_message_perm", "sa_admin_warn_message_perm",
|
|
||||||
new object[] { reason, "CALLER" },
|
|
||||||
new object[] { "CALLER", player.PlayerName, reason })
|
|
||||||
: ("sa_player_warn_message_time", "sa_admin_warn_message_time",
|
|
||||||
[reason, time, "CALLER"],
|
|
||||||
["CALLER", player.PlayerName, reason, time]);
|
|
||||||
|
|
||||||
// Display center message to the playser
|
|
||||||
Helper.DisplayCenterMessage(player, messageKey, callerName, centerArgs);
|
|
||||||
|
|
||||||
// Display admin activity message if necessary
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the warning command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_warn {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Send Discord notification for the warning
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Warn, _localizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddWarn(CCSPlayerController? caller, SteamID steamid, int time, string reason, WarnManager? warnManager = null)
|
|
||||||
{
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
||||||
? caller.PlayerName
|
|
||||||
: (_localizer?["sa_console"] ?? "Console");
|
|
||||||
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Warn(caller, player, time, reason, callerName);
|
|
||||||
//command.ReplyToCommand($"Banned player {player.PlayerName}.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(steamid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous ban operation if player is not online or not found
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await WarnManager.AddWarnBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Warn, reason, time, penaltyId);
|
|
||||||
|
|
||||||
// Check for warn thresholds and execute punish command if applicable
|
|
||||||
var totalWarns = await WarnManager.GetPlayerWarnsCount(steamid.SteamId64.ToString());
|
|
||||||
if (Config.WarnThreshold.Count > 0)
|
|
||||||
{
|
|
||||||
string? punishCommand = null;
|
|
||||||
var lastKey = Config.WarnThreshold.Keys.Max();
|
|
||||||
|
|
||||||
if (totalWarns >= lastKey)
|
|
||||||
punishCommand = Config.WarnThreshold[lastKey];
|
|
||||||
else if (Config.WarnThreshold.TryGetValue(totalWarns, out var value))
|
|
||||||
punishCommand = value;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(punishCommand))
|
|
||||||
{
|
|
||||||
await Server.NextFrameAsync(() =>
|
|
||||||
{
|
|
||||||
Server.ExecuteCommand(punishCommand.Replace("STEAMID64", steamid.SteamId64.ToString()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Warn, _localizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/kick")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid or name or ip>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnUnwarnCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
if (command.GetArg(1).Length <= 1)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand($"Too short pattern to search.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pattern = command.GetArg(1);
|
|
||||||
|
|
||||||
Task.Run(async () => await WarnManager.UnwarnPlayer(pattern));
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
command.ReplyToCommand($"Unwarned player with pattern {pattern}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Core.Translations;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Memory;
|
|
||||||
using CounterStrikeSharp.API.Modules.Utils;
|
|
||||||
using System.Text;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public partial class CS2_SimpleAdmin
|
|
||||||
{
|
|
||||||
[CommandHelper(1, "<message>")]
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
public void OnAdminToAdminSayCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
var utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]);
|
|
||||||
var utf8String = Encoding.UTF8.GetString(utf8BytesString);
|
|
||||||
|
|
||||||
foreach (var player in Helper.GetValidPlayers()
|
|
||||||
.Where(p => AdminManager.PlayerHasPermissions(new SteamID(p.SteamID), "@css/chat")))
|
|
||||||
{
|
|
||||||
if (_localizer != null)
|
|
||||||
player.PrintToChat(_localizer["sa_adminchat_template_admin",
|
|
||||||
caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName,
|
|
||||||
utf8String]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<message>")]
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
public void OnAdminCustomSayCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (command.GetCommandString[command.GetCommandString.IndexOf(' ')..].Length == 0) return;
|
|
||||||
|
|
||||||
var utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]);
|
|
||||||
var utf8String = Encoding.UTF8.GetString(utf8BytesString);
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
foreach (var player in Helper.GetValidPlayers())
|
|
||||||
{
|
|
||||||
player.PrintToChat(utf8String.ReplaceColorTags());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<message>")]
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
public void OnAdminSayCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (command.GetCommandString[command.GetCommandString.IndexOf(' ')..].Length == 0) return;
|
|
||||||
|
|
||||||
var utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]);
|
|
||||||
var utf8String = Encoding.UTF8.GetString(utf8BytesString);
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
foreach (var player in Helper.GetValidPlayers())
|
|
||||||
{
|
|
||||||
player.SendLocalizedMessage(_localizer,
|
|
||||||
"sa_adminsay_prefix",
|
|
||||||
utf8String.ReplaceColorTags());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(2, "<#userid or name> <message>")]
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
public void OnAdminPrivateSayCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
//Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
var range = command.GetArg(0).Length + command.GetArg(1).Length + 2;
|
|
||||||
var message = command.GetCommandString[range..];
|
|
||||||
|
|
||||||
var utf8BytesString = Encoding.UTF8.GetBytes(message);
|
|
||||||
var utf8String = Encoding.UTF8.GetString(utf8BytesString);
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
player.PrintToChat($"({callerName}) {utf8String}".ReplaceColorTags());
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($" Private message sent!");
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<message>")]
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
public void OnAdminCenterSayCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]);
|
|
||||||
var utf8String = Encoding.UTF8.GetString(utf8BytesString);
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
Helper.PrintToCenterAll(utf8String.ReplaceColorTags());
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<message>")]
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
public void OnAdminHudSayCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var utf8BytesString = Encoding.UTF8.GetBytes(command.GetCommandString[command.GetCommandString.IndexOf(' ')..]);
|
|
||||||
var utf8String = Encoding.UTF8.GetString(utf8BytesString);
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
VirtualFunctions.ClientPrintAll(
|
|
||||||
HudDestination.Alert,
|
|
||||||
utf8String.ReplaceColorTags(),
|
|
||||||
0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,838 +0,0 @@
|
|||||||
using CounterStrikeSharp.API;
|
|
||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
|
||||||
using CS2_SimpleAdmin.Managers;
|
|
||||||
using CS2_SimpleAdmin.Menus;
|
|
||||||
using CS2_SimpleAdminApi;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public partial class CS2_SimpleAdmin
|
|
||||||
{
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnGagCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Helper.ParsePenaltyTime(command.GetArg(2));
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (!caller!.CanTarget(player)) return;
|
|
||||||
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
|
|
||||||
{
|
|
||||||
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_gag"] ?? "Gag"}: {player.PlayerName}", player,
|
|
||||||
ManagePlayersMenu.GagMenu);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gag(caller, player, time, reason, callerName, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Gag(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null, bool silent = false)
|
|
||||||
{
|
|
||||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
if (!CheckValidMute(caller, time)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Get player and admin information
|
|
||||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Asynchronously handle gag logic
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add penalty to the player's penalty manager
|
|
||||||
PlayerPenaltyManager.AddPenalty(player.Slot, PenaltyType.Gag, Time.ActualDateTime().AddMinutes(time), time);
|
|
||||||
|
|
||||||
// Determine message keys and arguments based on gag time (permanent or timed)
|
|
||||||
var (messageKey, activityMessageKey, playerArgs, adminActivityArgs) = time == 0
|
|
||||||
? ("sa_player_gag_message_perm", "sa_admin_gag_message_perm",
|
|
||||||
[reason, "CALLER"],
|
|
||||||
["CALLER", player.PlayerName, reason])
|
|
||||||
: ("sa_player_gag_message_time", "sa_admin_gag_message_time",
|
|
||||||
new object[] { reason, time, "CALLER" },
|
|
||||||
new object[] { "CALLER", player.PlayerName, reason, time });
|
|
||||||
|
|
||||||
// Display center message to the gagged player
|
|
||||||
Helper.DisplayCenterMessage(player, messageKey, callerName, playerArgs);
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment the player's total gags count
|
|
||||||
PlayersInfo[player.UserId.Value].TotalGags++;
|
|
||||||
|
|
||||||
// Log the gag command and send Discord notification
|
|
||||||
if (!silent)
|
|
||||||
{
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_gag {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Gag, _localizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddGag(CCSPlayerController? caller, SteamID steamid, int time, string reason, MuteManager? muteManager = null)
|
|
||||||
{
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
||||||
? caller.PlayerName
|
|
||||||
: (_localizer?["sa_console"] ?? "Console");
|
|
||||||
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Gag(caller, player, time, reason, callerName, silent: true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(steamid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous ban operation if player is not online or not found
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time, 3);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Gag, _localizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnAddGagCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
// Set caller name
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Validate command arguments
|
|
||||||
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
|
||||||
|
|
||||||
// Validate and extract SteamID
|
|
||||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand("Invalid SteamID64.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var steamid = steamId.SteamId64.ToString();
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
||||||
if (!CheckValidMute(caller, time)) return;
|
|
||||||
|
|
||||||
// Get player and admin info
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Attempt to match player based on SteamID
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid);
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
// Check if caller can target the player
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Perform the gag for an online player
|
|
||||||
Gag(caller, player, time, reason, callerName, silent: true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous gag operation for offline players
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Gag, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Gag, _localizer);
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Gag has been added offline.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the gag command and respond to the command
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid or name> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnUngagCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
|
||||||
var pattern = command.GetArg(1);
|
|
||||||
var reason = command.ArgCount >= 2
|
|
||||||
? string.Join(" ", Enumerable.Range(2, command.ArgCount - 2).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
if (pattern.Length <= 1)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand($"Too short pattern to search.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Check if pattern is a valid SteamID64
|
|
||||||
if (Helper.ValidateSteamId(pattern, out var steamId) && steamId != null)
|
|
||||||
{
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamId.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
PlayerPenaltyManager.RemovePenaltiesByType(player.Slot, PenaltyType.Gag);
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(player.SteamID.ToString(), callerSteamId, reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Ungaged player {player.PlayerName}.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not a valid SteamID64, check by player name
|
|
||||||
var nameMatches = Helper.GetPlayerFromName(pattern);
|
|
||||||
var namePlayer = nameMatches.Count == 1 ? nameMatches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (namePlayer != null && namePlayer.IsValid)
|
|
||||||
{
|
|
||||||
PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Gag);
|
|
||||||
|
|
||||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalGags > 0)
|
|
||||||
PlayersInfo[namePlayer.UserId.Value].TotalGags--;
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(namePlayer.SteamID.ToString(), callerSteamId, reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Ungaged player {namePlayer.PlayerName}.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(pattern, callerSteamId, reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Ungaged offline player with pattern {pattern}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnMuteCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Helper.ParsePenaltyTime(command.GetArg(2));
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (!caller!.CanTarget(player)) return;
|
|
||||||
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
|
|
||||||
{
|
|
||||||
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_mute"] ?? "Mute"}: {player.PlayerName}", player,
|
|
||||||
ManagePlayersMenu.MuteMenu);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mute(caller, player, time, reason, callerName, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Mute(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null, bool silent = false)
|
|
||||||
{
|
|
||||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
if (!CheckValidMute(caller, time)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Get player and admin information
|
|
||||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Set player's voice flags to muted
|
|
||||||
player.VoiceFlags = VoiceFlags.Muted;
|
|
||||||
|
|
||||||
// Asynchronously handle mute logic
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 1);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add penalty to the player's penalty manager
|
|
||||||
PlayerPenaltyManager.AddPenalty(player.Slot, PenaltyType.Mute, Time.ActualDateTime().AddMinutes(time), time);
|
|
||||||
|
|
||||||
// Determine message keys and arguments based on mute time (permanent or timed)
|
|
||||||
var (messageKey, activityMessageKey, playerArgs, adminActivityArgs) = time == 0
|
|
||||||
? ("sa_player_mute_message_perm", "sa_admin_mute_message_perm",
|
|
||||||
[reason, "CALLER"],
|
|
||||||
["CALLER", player.PlayerName, reason])
|
|
||||||
: ("sa_player_mute_message_time", "sa_admin_mute_message_time",
|
|
||||||
new object[] { reason, time, "CALLER" },
|
|
||||||
new object[] { "CALLER", player.PlayerName, reason, time });
|
|
||||||
|
|
||||||
// Display center message to the muted player
|
|
||||||
Helper.DisplayCenterMessage(player, messageKey, callerName, playerArgs);
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment the player's total mutes count
|
|
||||||
PlayersInfo[player.UserId.Value].TotalMutes++;
|
|
||||||
|
|
||||||
// Log the mute command and send Discord notification
|
|
||||||
if (!silent)
|
|
||||||
{
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_mute {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Mute, _localizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnAddMuteCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
// Set caller name
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Validate command arguments
|
|
||||||
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
|
||||||
|
|
||||||
// Validate and extract SteamID
|
|
||||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand("Invalid SteamID64.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var steamid = steamId.SteamId64.ToString();
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
||||||
if (!CheckValidMute(caller, time)) return;
|
|
||||||
|
|
||||||
// Get player and admin info
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Attempt to match player based on SteamID
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid);
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
// Check if caller can target the player
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Perform the mute for an online player
|
|
||||||
Mute(caller, player, time, reason, callerName, silent: true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous mute operation for offline players
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 1);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Mute, _localizer);
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Mute has been added offline.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the mute command and respond to the command
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddMute(CCSPlayerController? caller, SteamID steamid, int time, string reason, MuteManager? muteManager = null)
|
|
||||||
{
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
||||||
? caller.PlayerName
|
|
||||||
: (_localizer?["sa_console"] ?? "Console");
|
|
||||||
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Mute(caller, player, time, reason, callerName, silent: true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(steamid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous ban operation if player is not online or not found
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time, 1);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Mute, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Mute, _localizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnUnmuteCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
|
||||||
var pattern = command.GetArg(1);
|
|
||||||
var reason = command.ArgCount >= 2
|
|
||||||
? string.Join(" ", Enumerable.Range(2, command.ArgCount - 2).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
if (pattern.Length <= 1)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand("Too short pattern to search.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Check if pattern is a valid SteamID64
|
|
||||||
if (Helper.ValidateSteamId(pattern, out var steamId) && steamId != null)
|
|
||||||
{
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamId.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
PlayerPenaltyManager.RemovePenaltiesByType(player.Slot, PenaltyType.Mute);
|
|
||||||
player.VoiceFlags = VoiceFlags.Normal;
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(player.SteamID.ToString(), callerSteamId, reason, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Unmuted player {player.PlayerName}.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not a valid SteamID64, check by player name
|
|
||||||
var nameMatches = Helper.GetPlayerFromName(pattern);
|
|
||||||
var namePlayer = nameMatches.Count == 1 ? nameMatches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (namePlayer != null && namePlayer.IsValid)
|
|
||||||
{
|
|
||||||
PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Mute);
|
|
||||||
namePlayer.VoiceFlags = VoiceFlags.Normal;
|
|
||||||
|
|
||||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalMutes > 0)
|
|
||||||
PlayersInfo[namePlayer.UserId.Value].TotalMutes--;
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(namePlayer.SteamID.ToString(), callerSteamId, reason, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Unmuted player {namePlayer.PlayerName}.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(pattern, callerSteamId, reason, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Unmuted offline player with pattern {pattern}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnSilenceCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
if (playersToTarget.Count > 1 && Config.OtherSettings.DisableDangerousCommands || playersToTarget.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Helper.ParsePenaltyTime(command.GetArg(2));
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (!caller!.CanTarget(player)) return;
|
|
||||||
if (time < 0 && caller != null && caller.IsValid && Config.OtherSettings.ShowBanMenuIfNoTime)
|
|
||||||
{
|
|
||||||
DurationMenu.OpenMenu(caller, $"{_localizer?["sa_silence"] ?? "Silence"}: {player.PlayerName}", player,
|
|
||||||
ManagePlayersMenu.SilenceMenu);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Silence(caller, player, time, reason, callerName, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Silence(CCSPlayerController? caller, CCSPlayerController player, int time, string reason, string? callerName = null, CommandInfo? command = null, bool silent = false)
|
|
||||||
{
|
|
||||||
if (Database == null || !player.IsValid || !player.UserId.HasValue) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
if (!CheckValidMute(caller, time)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Get player and admin information
|
|
||||||
var playerInfo = PlayersInfo[player.UserId.Value];
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Asynchronously handle silence logic
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.MutePlayer(playerInfo, adminInfo, reason, time, 2); // Assuming 2 is the type for silence
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedEvent(playerInfo, adminInfo, PenaltyType.Silence, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add penalty to the player's penalty manager
|
|
||||||
PlayerPenaltyManager.AddPenalty(player.Slot, PenaltyType.Silence, Time.ActualDateTime().AddMinutes(time), time);
|
|
||||||
player.VoiceFlags = VoiceFlags.Muted;
|
|
||||||
|
|
||||||
// Determine message keys and arguments based on silence time (permanent or timed)
|
|
||||||
var (messageKey, activityMessageKey, playerArgs, adminActivityArgs) = time == 0
|
|
||||||
? ("sa_player_silence_message_perm", "sa_admin_silence_message_perm",
|
|
||||||
[reason, "CALLER"],
|
|
||||||
["CALLER", player.PlayerName, reason])
|
|
||||||
: ("sa_player_silence_message_time", "sa_admin_silence_message_time",
|
|
||||||
new object[] { reason, time, "CALLER" },
|
|
||||||
new object[] { "CALLER", player.PlayerName, reason, time });
|
|
||||||
|
|
||||||
// Display center message to the silenced player
|
|
||||||
Helper.DisplayCenterMessage(player, messageKey, callerName, playerArgs);
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment the player's total silences count
|
|
||||||
PlayersInfo[player.UserId.Value].TotalSilences++;
|
|
||||||
|
|
||||||
// Log the silence command and send Discord notification
|
|
||||||
if (!silent)
|
|
||||||
{
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_silence {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time} {reason}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, player, reason, time, PenaltyType.Silence, _localizer);
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [time in minutes/0 perm] [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnAddSilenceCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
// Set caller name
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Validate command arguments
|
|
||||||
if (command.ArgCount < 2 || string.IsNullOrEmpty(command.GetArg(1))) return;
|
|
||||||
|
|
||||||
// Validate and extract SteamID
|
|
||||||
if (!Helper.ValidateSteamId(command.GetArg(1), out var steamId) || steamId == null)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand("Invalid SteamID64.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var steamid = steamId.SteamId64.ToString();
|
|
||||||
var reason = command.ArgCount >= 3
|
|
||||||
? string.Join(" ", Enumerable.Range(3, command.ArgCount - 3).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
var time = Math.Max(0, Helper.ParsePenaltyTime(command.GetArg(2)));
|
|
||||||
if (!CheckValidMute(caller, time)) return;
|
|
||||||
|
|
||||||
// Get player and admin info
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
// Attempt to match player based on SteamID
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid);
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
// Check if caller can target the player
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Perform the silence for an online player
|
|
||||||
Silence(caller, player, time, reason, callerName, silent: true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(new SteamID(steamId.SteamId64)))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous silence operation for offline players
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid, adminInfo, reason, time, 2);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamId, adminInfo, PenaltyType.Silence, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid, reason, time, PenaltyType.Silence, _localizer);
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Player with steamid {steamid} is not online. Silence has been added offline.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the silence command and respond to the command
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddSilence(CCSPlayerController? caller, SteamID steamid, int time, string reason, MuteManager? muteManager = null)
|
|
||||||
{
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = !string.IsNullOrEmpty(caller?.PlayerName)
|
|
||||||
? caller.PlayerName
|
|
||||||
: (_localizer?["sa_console"] ?? "Console");
|
|
||||||
|
|
||||||
var adminInfo = caller != null && caller.UserId.HasValue ? PlayersInfo[caller.UserId.Value] : null;
|
|
||||||
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamid.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Silence(caller, player, time, reason, callerName, silent: true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(steamid))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Asynchronous ban operation if player is not online or not found
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
int? penaltyId = await MuteManager.AddMuteBySteamid(steamid.SteamId64.ToString(), adminInfo, reason, time, 2);
|
|
||||||
SimpleAdminApi?.OnPlayerPenaltiedAddedEvent(steamid, adminInfo, PenaltyType.Silence, reason, time, penaltyId);
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.SendDiscordPenaltyMessage(caller, steamid.SteamId64.ToString(), reason, time, PenaltyType.Silence, _localizer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/chat")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<steamid or name> [reason]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnUnsilenceCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (Database == null) return;
|
|
||||||
|
|
||||||
var callerSteamId = caller?.SteamID.ToString() ?? _localizer?["sa_console"] ?? "Console";
|
|
||||||
var pattern = command.GetArg(1);
|
|
||||||
var reason = command.ArgCount >= 2
|
|
||||||
? string.Join(" ", Enumerable.Range(2, command.ArgCount - 2).Select(command.GetArg)).Trim()
|
|
||||||
: _localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
reason = string.IsNullOrWhiteSpace(reason) ? _localizer?["sa_unknown"] ?? "Unknown" : reason;
|
|
||||||
|
|
||||||
if (pattern.Length <= 1)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand("Too short pattern to search.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Check if pattern is a valid SteamID64
|
|
||||||
if (Helper.ValidateSteamId(pattern, out var steamId) && steamId != null)
|
|
||||||
{
|
|
||||||
var matches = Helper.GetPlayerFromSteamid64(steamId.SteamId64.ToString());
|
|
||||||
var player = matches.Count == 1 ? matches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (player != null && player.IsValid)
|
|
||||||
{
|
|
||||||
PlayerPenaltyManager.RemovePenaltiesByType(player.Slot, PenaltyType.Silence);
|
|
||||||
|
|
||||||
// Reset voice flags to normal
|
|
||||||
player.VoiceFlags = VoiceFlags.Normal;
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(player.SteamID.ToString(), callerSteamId, reason, 2); // Unmute by type 2 (silence)
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Unsilenced player {player.PlayerName}.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not a valid SteamID64, check by player name
|
|
||||||
var nameMatches = Helper.GetPlayerFromName(pattern);
|
|
||||||
var namePlayer = nameMatches.Count == 1 ? nameMatches.FirstOrDefault() : null;
|
|
||||||
|
|
||||||
if (namePlayer != null && namePlayer.IsValid)
|
|
||||||
{
|
|
||||||
PlayerPenaltyManager.RemovePenaltiesByType(namePlayer.Slot, PenaltyType.Silence);
|
|
||||||
|
|
||||||
// Reset voice flags to normal
|
|
||||||
namePlayer.VoiceFlags = VoiceFlags.Normal;
|
|
||||||
|
|
||||||
if (namePlayer.UserId.HasValue && PlayersInfo[namePlayer.UserId.Value].TotalSilences > 0)
|
|
||||||
PlayersInfo[namePlayer.UserId.Value].TotalSilences--;
|
|
||||||
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(namePlayer.SteamID.ToString(), callerSteamId, reason, 2); // Unmute by type 2 (silence)
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Unsilenced player {namePlayer.PlayerName}.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await MuteManager.UnmutePlayer(pattern, callerSteamId, reason, 2); // Unmute by type 2 (silence)
|
|
||||||
});
|
|
||||||
|
|
||||||
command.ReplyToCommand($"Unsilenced offline player with pattern {pattern}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckValidMute(CCSPlayerController? caller, int duration)
|
|
||||||
{
|
|
||||||
if (caller == null) return true;
|
|
||||||
|
|
||||||
var canPermMute = AdminManager.PlayerHasPermissions(new SteamID(caller.SteamID), "@css/permmute");
|
|
||||||
|
|
||||||
if (duration <= 0 && canPermMute == false)
|
|
||||||
{
|
|
||||||
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_perm_restricted"]}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (duration <= Config.OtherSettings.MaxMuteDuration || canPermMute) return true;
|
|
||||||
|
|
||||||
caller.PrintToChat($"{_localizer!["sa_prefix"]} {_localizer["sa_ban_max_duration_exceeded", Config.OtherSettings.MaxMuteDuration]}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Core.Translations;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Menu;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public partial class CS2_SimpleAdmin
|
|
||||||
{
|
|
||||||
[RequiresPermissions("@css/generic")]
|
|
||||||
[CommandHelper(minArgs: 2, usage: "<question> [... options ...]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnVoteCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
if (command.ArgCount < 2 || _localizer == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
VoteAnswers.Clear();
|
|
||||||
|
|
||||||
var question = command.GetArg(1);
|
|
||||||
var answersCount = command.ArgCount;
|
|
||||||
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
for (var i = 2; i <= answersCount - 1; i++)
|
|
||||||
{
|
|
||||||
VoteAnswers.Add(command.GetArg(i), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var player in Helper.GetValidPlayers())
|
|
||||||
{
|
|
||||||
using (new WithTemporaryCulture(player.GetLanguage()))
|
|
||||||
{
|
|
||||||
IMenu? voteMenu = Helper.CreateMenu(_localizer["sa_admin_vote_menu_title", question]);
|
|
||||||
if (voteMenu == null)
|
|
||||||
return;
|
|
||||||
//ChatMenu voteMenu = new(_localizer!["sa_admin_vote_menu_title", question]);
|
|
||||||
|
|
||||||
for (var i = 2; i <= answersCount - 1; i++)
|
|
||||||
{
|
|
||||||
voteMenu.AddMenuOption(command.GetArg(i), Helper.HandleVotes);
|
|
||||||
}
|
|
||||||
|
|
||||||
voteMenu.PostSelectAction = PostSelectAction.Close;
|
|
||||||
|
|
||||||
Helper.PrintToCenterAll(_localizer["sa_admin_vote_message", caller == null ? _localizer["sa_console"] : caller.PlayerName, question]);
|
|
||||||
|
|
||||||
player.SendLocalizedMessage(_localizer,
|
|
||||||
"sa_admin_vote_message",
|
|
||||||
caller == null ? _localizer["sa_console"] : caller.PlayerName,
|
|
||||||
question);
|
|
||||||
|
|
||||||
voteMenu.Open(player);
|
|
||||||
|
|
||||||
//MenuManager.OpenChatMenu(player, voteMenu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VoteInProgress = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VoteInProgress)
|
|
||||||
{
|
|
||||||
AddTimer(30, () =>
|
|
||||||
{
|
|
||||||
foreach (var player in Helper.GetValidPlayers())
|
|
||||||
{
|
|
||||||
if (_localizer != null)
|
|
||||||
player.SendLocalizedMessage(_localizer,
|
|
||||||
"sa_admin_vote_message_results",
|
|
||||||
question);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var (key, value) in VoteAnswers)
|
|
||||||
{
|
|
||||||
foreach (var player in Helper.GetValidPlayers())
|
|
||||||
{
|
|
||||||
if (_localizer != null)
|
|
||||||
player.SendLocalizedMessage(_localizer,
|
|
||||||
"sa_admin_vote_message_results_answer",
|
|
||||||
key,
|
|
||||||
value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VoteAnswers.Clear();
|
|
||||||
VoteInProgress = false;
|
|
||||||
}, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,257 +0,0 @@
|
|||||||
using System.Globalization;
|
|
||||||
using CounterStrikeSharp.API;
|
|
||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public partial class CS2_SimpleAdmin
|
|
||||||
{
|
|
||||||
[CommandHelper(1, "<#userid or name>")]
|
|
||||||
[RequiresPermissions("@css/cheats")]
|
|
||||||
public void OnNoclipCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player =>
|
|
||||||
player.IsValid &&
|
|
||||||
player is { IsHLTV: false, Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
NoClip(caller, player, callerName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void NoClip(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!player.IsValid) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Toggle no-clip mode for the player
|
|
||||||
player.Pawn.Value?.ToggleNoclip();
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the no-clip notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_noclip_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
{
|
|
||||||
Helper.LogCommand(caller, $"css_noclip {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/cheats")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnGodCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is {IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
God(caller, player, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void God(CCSPlayerController? caller, CCSPlayerController player, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Toggle god mode for the player
|
|
||||||
if (!GodPlayers.Add(player.Slot))
|
|
||||||
{
|
|
||||||
GodPlayers.Remove(player.Slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_god {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message key and arguments for the god mode notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_god_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name> [duration]")]
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
public void OnFreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
int.TryParse(command.GetArg(2), out var time);
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
Freeze(caller, player, time, callerName, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name> [size]")]
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
public void OnResizeCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var size);
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (!caller!.CanTarget(player)) return;
|
|
||||||
|
|
||||||
var sceneNode = player.PlayerPawn.Value!.CBodyComponent?.SceneNode;
|
|
||||||
if (sceneNode == null) return;
|
|
||||||
|
|
||||||
sceneNode.GetSkeletonInstance().Scale = size;
|
|
||||||
player.PlayerPawn.Value.AcceptInput("SetScale", null, null, size.ToString(CultureInfo.InvariantCulture));
|
|
||||||
|
|
||||||
Server.NextFrame(() =>
|
|
||||||
{
|
|
||||||
Utilities.SetStateChanged(player.PlayerPawn.Value, "CBaseEntity", "m_CBodyComponent");
|
|
||||||
});
|
|
||||||
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_resize_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Freeze(CCSPlayerController? caller, CCSPlayerController player, int time, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!player.IsValid) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Freeze player pawn
|
|
||||||
player.Pawn.Value?.Freeze();
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the freeze notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_freeze_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schedule unfreeze for the player if time is specified
|
|
||||||
if (time > 0)
|
|
||||||
{
|
|
||||||
Instance.AddTimer(time, () => player.Pawn.Value?.Unfreeze(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the command and send Discord notification
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_freeze {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {time}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name>")]
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
public void OnUnfreezeCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
Unfreeze(caller, player, callerName, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Unfreeze(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!player.IsValid) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Unfreeze player pawn
|
|
||||||
player.Pawn.Value?.Unfreeze();
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the unfreeze notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_unfreeze_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the command and send Discord notification
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_unfreeze {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,880 +0,0 @@
|
|||||||
using System.Globalization;
|
|
||||||
using CounterStrikeSharp.API;
|
|
||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
|
||||||
using CounterStrikeSharp.API.Modules.Memory;
|
|
||||||
using CounterStrikeSharp.API.Modules.Utils;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public partial class CS2_SimpleAdmin
|
|
||||||
{
|
|
||||||
internal static readonly Dictionary<int, float> SpeedPlayers = [];
|
|
||||||
internal static readonly Dictionary<CCSPlayerController, float> GravityPlayers = [];
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnSlayCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is {IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
Slay(caller, player, callerName, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Slay(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Make the player commit suicide
|
|
||||||
player.CommitSuicide(false, true);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the slay notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_slay_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the command and send Discord notification
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_slay {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/cheats")]
|
|
||||||
[CommandHelper(minArgs: 2, usage: "<#userid or name> <weapon>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnGiveCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
var weaponName = command.GetArg(2);
|
|
||||||
|
|
||||||
// check if item is typed
|
|
||||||
// if (weaponName.Length < 2)
|
|
||||||
// {
|
|
||||||
// command.ReplyToCommand($"No weapon typed.");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// check if weapon is knife
|
|
||||||
if (weaponName.Contains("_knife") || weaponName.Contains("bayonet"))
|
|
||||||
{
|
|
||||||
if (CoreConfig.FollowCS2ServerGuidelines)
|
|
||||||
{
|
|
||||||
command.ReplyToCommand($"Cannot Give {weaponName} because it's illegal to be given.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
GiveWeapon(caller, player, weaponName, callerName, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, string weaponName, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
var weapons = WeaponHelper.GetWeaponsByPartialName(weaponName);
|
|
||||||
|
|
||||||
switch (weapons.Count)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
return;
|
|
||||||
case > 1:
|
|
||||||
{
|
|
||||||
var weaponList = string.Join(", ", weapons.Select(w => w.EnumMemberValue));
|
|
||||||
command?.ReplyToCommand($"Found weapons with a similar name: {weaponList}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give weapon to the player
|
|
||||||
player.GiveNamedItem(weapons.First().EnumValue);
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_giveweapon {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {weaponName}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the weapon give notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_give_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName, weaponName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void GiveWeapon(CCSPlayerController? caller, CCSPlayerController player, CsItem weapon, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Give weapon to the player
|
|
||||||
player.GiveNamedItem(weapon);
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_giveweapon {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {weapon.ToString()}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the weapon give notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_give_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName, weapon.ToString() });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnStripCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
StripWeapons(caller, player, callerName, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void StripWeapons(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Check if player is valid, alive, and connected
|
|
||||||
if (!player.IsValid || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE || player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Strip weapons from the player
|
|
||||||
player.RemoveWeapons();
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_strip {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the weapon strip notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_strip_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <health>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnHpCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
int.TryParse(command.GetArg(2), out var health);
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
SetHp(caller, player, health, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SetHp(CCSPlayerController? caller, CCSPlayerController player, int health, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!player.IsValid || player.IsHLTV) return;
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Set player's health
|
|
||||||
player.SetHp(health);
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_hp {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {health}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the HP set notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_hp_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <speed>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnSpeedCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var speed);
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
SetSpeed(caller, player, speed, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SetSpeed(CCSPlayerController? caller, CCSPlayerController player, float speed, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Set player's speed
|
|
||||||
player.SetSpeed(speed);
|
|
||||||
|
|
||||||
if (speed == 1f)
|
|
||||||
SpeedPlayers.Remove(player.Slot);
|
|
||||||
else
|
|
||||||
SpeedPlayers[player.Slot] = speed;
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_speed {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {speed}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the speed set notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_speed_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <gravity>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnGravityCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
float.TryParse(command.GetArg(2), NumberStyles.Float, CultureInfo.InvariantCulture, out var gravity);
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
SetGravity(caller, player, gravity, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SetGravity(CCSPlayerController? caller, CCSPlayerController player, float gravity, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Set player's gravity
|
|
||||||
player.SetGravity(gravity);
|
|
||||||
|
|
||||||
if (gravity == 1f)
|
|
||||||
GravityPlayers.Remove(player);
|
|
||||||
else
|
|
||||||
GravityPlayers[player] = gravity;
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_gravity {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {gravity}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the gravity set notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_gravity_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> <money>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnMoneyCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
int.TryParse(command.GetArg(2), out var money);
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
SetMoney(caller, player, money, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SetMoney(CCSPlayerController? caller, CCSPlayerController player, int money, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Set player's money
|
|
||||||
player.SetMoney(money);
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_money {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {money}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message keys and arguments for the money set notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_money_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller == null || !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/slay")]
|
|
||||||
[CommandHelper(minArgs: 1, usage: "<#userid or name> [damage]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnSlapCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var damage = 0;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player.IsValid && player is { IsHLTV: false, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).ToList();
|
|
||||||
|
|
||||||
if (command.ArgCount >= 2)
|
|
||||||
{
|
|
||||||
int.TryParse(command.GetArg(2), out damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
Slap(caller, player, damage, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Slap(CCSPlayerController? caller, CCSPlayerController player, int damage, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Apply slap damage to the player
|
|
||||||
player.Pawn.Value?.Slap(damage);
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_slap {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)} {damage}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message key and arguments for the slap notification
|
|
||||||
var (activityMessageKey, adminActivityArgs) =
|
|
||||||
("sa_admin_slap_message",
|
|
||||||
new object[] { "CALLER", player.PlayerName });
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
|
|
||||||
|
|
||||||
if (_localizer != null)
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RequiresPermissions("@css/kick")]
|
|
||||||
[CommandHelper(minArgs: 2, usage: "<#userid or name> [<ct/tt/spec>] [-k]", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
|
|
||||||
public void OnTeamCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
var teamName = command.GetArg(2).ToLower();
|
|
||||||
string _teamName;
|
|
||||||
var teamNum = CsTeam.Spectator;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
switch (teamName)
|
|
||||||
{
|
|
||||||
case "ct":
|
|
||||||
case "counterterrorist":
|
|
||||||
teamNum = CsTeam.CounterTerrorist;
|
|
||||||
_teamName = "CT";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "t":
|
|
||||||
case "tt":
|
|
||||||
case "terrorist":
|
|
||||||
teamNum = CsTeam.Terrorist;
|
|
||||||
_teamName = "TT";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "swap":
|
|
||||||
_teamName = "SWAP";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
teamNum = CsTeam.Spectator;
|
|
||||||
_teamName = "SPEC";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var kill = command.GetArg(3).ToLower().Equals("-k");
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
ChangeTeam(caller, player, _teamName, teamNum, kill, command);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void ChangeTeam(CCSPlayerController? caller, CCSPlayerController player, string teamName, CsTeam teamNum, bool kill, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
// Check if the player is valid and connected
|
|
||||||
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Ensure the caller can target the player
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller != null ? caller.PlayerName : _localizer?["sa_console"] ?? "Console";
|
|
||||||
|
|
||||||
// Change team based on the provided teamName and conditions
|
|
||||||
if (!teamName.Equals("swap", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
if (player.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE && teamNum != CsTeam.Spectator && !kill && Instance.Config.OtherSettings.TeamSwitchType == 1)
|
|
||||||
player.SwitchTeam(teamNum);
|
|
||||||
else
|
|
||||||
player.ChangeTeam(teamNum);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (player.TeamNum != (byte)CsTeam.Spectator)
|
|
||||||
{
|
|
||||||
var _teamNum = (CsTeam)player.TeamNum == CsTeam.Terrorist ? CsTeam.CounterTerrorist : CsTeam.Terrorist;
|
|
||||||
teamName = _teamNum == CsTeam.Terrorist ? "TT" : "CT";
|
|
||||||
if (player.PlayerPawn?.Value?.LifeState == (int)LifeState_t.LIFE_ALIVE && !kill && Instance.Config.OtherSettings.TeamSwitchType == 1)
|
|
||||||
player.SwitchTeam(_teamNum);
|
|
||||||
else
|
|
||||||
player.ChangeTeam(_teamNum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_team {player.PlayerName} {teamName}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message key and arguments for the team change notification
|
|
||||||
var activityMessageKey = "sa_admin_team_message";
|
|
||||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, teamName };
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
|
|
||||||
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name> <new name>")]
|
|
||||||
[RequiresPermissions("@css/kick")]
|
|
||||||
public void OnRenameCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Get the new name from the command arguments
|
|
||||||
var newName = command.GetArg(2);
|
|
||||||
|
|
||||||
// Check if the new name is valid
|
|
||||||
if (string.IsNullOrEmpty(newName))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Retrieve the targets based on the command
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
// Filter out valid players from the targets
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Process each player to rename
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
// Check if the player is connected and can be targeted
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected || !caller!.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Determine message key and arguments for the rename notification
|
|
||||||
var activityMessageKey = "sa_admin_rename_message";
|
|
||||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, newName };
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
|
|
||||||
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
|
|
||||||
// Rename the player
|
|
||||||
player.Rename(newName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name> <new name>")]
|
|
||||||
[RequiresPermissions("@css/ban")]
|
|
||||||
public void OnPrenameCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
// Set default caller name if not provided
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Get the new name from the command arguments
|
|
||||||
var newName = command.GetArg(2);
|
|
||||||
|
|
||||||
// Retrieve the targets based on the command
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
|
|
||||||
// Filter out valid players from the targets
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Process each player to rename
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
// Check if the player is connected and can be targeted
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected || !caller!.CanTarget(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Determine message key and arguments for the rename notification
|
|
||||||
var activityMessageKey = "sa_admin_rename_message";
|
|
||||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName, newName };
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller != null && !SilentPlayers.Contains(caller.Slot))
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine if the new name is valid and update the renamed players list
|
|
||||||
if (!string.IsNullOrEmpty(newName))
|
|
||||||
{
|
|
||||||
RenamedPlayers[player.SteamID] = newName;
|
|
||||||
player.Rename(newName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RenamedPlayers.Remove(player.SteamID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name>")]
|
|
||||||
[RequiresPermissions("@css/cheats")]
|
|
||||||
public void OnRespawnCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
var callerName = caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null) return;
|
|
||||||
var playersToTarget = targets.Players.Where(player => player is { IsValid: true, IsHLTV: false }).ToList();
|
|
||||||
|
|
||||||
playersToTarget.ForEach(player =>
|
|
||||||
{
|
|
||||||
if (player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (caller!.CanTarget(player))
|
|
||||||
{
|
|
||||||
Respawn(caller, player, callerName, command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void Respawn(CCSPlayerController? caller, CCSPlayerController player, string? callerName = null, CommandInfo? command = null)
|
|
||||||
{
|
|
||||||
// Check if the caller can target the player
|
|
||||||
if (!caller.CanTarget(player)) return;
|
|
||||||
|
|
||||||
// Set default caller name if not provided
|
|
||||||
callerName ??= caller == null ? _localizer?["sa_console"] ?? "Console" : caller.PlayerName;
|
|
||||||
|
|
||||||
// Ensure the player's pawn is valid before attempting to respawn
|
|
||||||
if (_cBasePlayerControllerSetPawnFunc == null || player.PlayerPawn.Value == null || !player.PlayerPawn.IsValid) return;
|
|
||||||
|
|
||||||
// Perform the respawn operation
|
|
||||||
var playerPawn = player.PlayerPawn.Value;
|
|
||||||
_cBasePlayerControllerSetPawnFunc.Invoke(player, playerPawn, true, false);
|
|
||||||
VirtualFunction.CreateVoid<CCSPlayerController>(player.Handle, GameData.GetOffset("CCSPlayerController_Respawn"))(player);
|
|
||||||
|
|
||||||
if (player.UserId.HasValue && PlayersInfo.TryGetValue(player.UserId.Value, out var value) && value.DiePosition != null)
|
|
||||||
playerPawn.Teleport(value.DiePosition?.Position, value.DiePosition?.Angle);
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
if (command == null)
|
|
||||||
Helper.LogCommand(caller, $"css_respawn {(string.IsNullOrEmpty(player.PlayerName) ? player.SteamID.ToString() : player.PlayerName)}");
|
|
||||||
else
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Determine message key and arguments for the respawn notification
|
|
||||||
var activityMessageKey = "sa_admin_respawn_message";
|
|
||||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
|
|
||||||
|
|
||||||
// Display admin activity message to other players
|
|
||||||
if (caller != null && SilentPlayers.Contains(caller.Slot)) return;
|
|
||||||
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, callerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name>")]
|
|
||||||
[RequiresPermissions("@css/kick")]
|
|
||||||
public void OnGotoCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
// Check if the caller is valid and has a live pawn
|
|
||||||
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE) return;
|
|
||||||
|
|
||||||
// Get the target players
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null || targets.Count() > 1) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players
|
|
||||||
.Where(player => player is { IsValid: true, IsHLTV: false })
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Process each player to teleport
|
|
||||||
foreach (var player in playersToTarget.Where(player => player is { Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).Where(caller.CanTarget))
|
|
||||||
{
|
|
||||||
if (caller.PlayerPawn.Value == null || player.PlayerPawn.Value == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Teleport the caller to the player and toggle noclip
|
|
||||||
caller.TeleportPlayer(player);
|
|
||||||
// caller.PlayerPawn.Value.ToggleNoclip();
|
|
||||||
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
|
|
||||||
// Set a timer to toggle collision back after 4 seconds
|
|
||||||
AddTimer(4, () =>
|
|
||||||
{
|
|
||||||
if (!caller.IsValid || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prepare message key and arguments for the teleport notification
|
|
||||||
var activityMessageKey = "sa_admin_tp_message";
|
|
||||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
|
|
||||||
|
|
||||||
// Show admin activity
|
|
||||||
if (!SilentPlayers.Contains(caller.Slot) && _localizer != null)
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandHelper(1, "<#userid or name>")]
|
|
||||||
[RequiresPermissions("@css/kick")]
|
|
||||||
public void OnBringCommand(CCSPlayerController? caller, CommandInfo command)
|
|
||||||
{
|
|
||||||
// Check if the caller is valid and has a live pawn
|
|
||||||
if (caller == null || caller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Get the target players
|
|
||||||
var targets = GetTarget(command);
|
|
||||||
if (targets == null || targets.Count() > 1) return;
|
|
||||||
|
|
||||||
var playersToTarget = targets.Players
|
|
||||||
.Where(player => player is { IsValid: true, IsHLTV: false })
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Log the command
|
|
||||||
Helper.LogCommand(caller, command);
|
|
||||||
|
|
||||||
// Process each player to teleport
|
|
||||||
foreach (var player in playersToTarget.Where(player => player is { Connected: PlayerConnectedState.PlayerConnected, PlayerPawn.Value.LifeState: (int)LifeState_t.LIFE_ALIVE }).Where(caller.CanTarget))
|
|
||||||
{
|
|
||||||
if (caller.PlayerPawn.Value == null || player.PlayerPawn.Value == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Teleport the player to the caller and toggle noclip
|
|
||||||
player.TeleportPlayer(caller);
|
|
||||||
// caller.PlayerPawn.Value.ToggleNoclip();
|
|
||||||
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_DISSOLVING;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
|
|
||||||
// Set a timer to toggle collision back after 4 seconds
|
|
||||||
AddTimer(4, () =>
|
|
||||||
{
|
|
||||||
if (!player.IsValid || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
caller.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(caller, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(caller, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
player.PlayerPawn.Value.Collision.CollisionAttribute.CollisionGroup = (byte)CollisionGroup.COLLISION_GROUP_PLAYER;
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(player, "CCollisionProperty", "m_CollisionGroup");
|
|
||||||
Utilities.SetStateChanged(player, "VPhysicsCollisionAttribute_t", "m_nCollisionGroup");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prepare message key and arguments for the bring notification
|
|
||||||
var activityMessageKey = "sa_admin_bring_message";
|
|
||||||
var adminActivityArgs = new object[] { "CALLER", player.PlayerName };
|
|
||||||
|
|
||||||
// Show admin activity
|
|
||||||
if (!SilentPlayers.Contains(caller.Slot) && _localizer != null)
|
|
||||||
{
|
|
||||||
Helper.ShowAdminActivity(activityMessageKey, caller.PlayerName, false, adminActivityArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,295 +0,0 @@
|
|||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public class DurationItem
|
|
||||||
{
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public required string Name { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("duration")]
|
|
||||||
public int Duration { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AdminFlag
|
|
||||||
{
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public required string Name { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("flag")]
|
|
||||||
public required string Flag { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DiscordPenaltySetting
|
|
||||||
{
|
|
||||||
[JsonPropertyName("name")]
|
|
||||||
public required string Name { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("value")]
|
|
||||||
public string? Value { get; set; } = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Discord
|
|
||||||
{
|
|
||||||
[JsonPropertyName("DiscordLogWebhook")]
|
|
||||||
public string DiscordLogWebhook { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("DiscordPenaltyBanSettings")]
|
|
||||||
public DiscordPenaltySetting[] DiscordPenaltyBanSettings { get; set; } =
|
|
||||||
[
|
|
||||||
new DiscordPenaltySetting { Name = "Color", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Webhook", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ThumbnailUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ImageUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Footer", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Time", Value = "{relative}" },
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("DiscordPenaltyMuteSettings")]
|
|
||||||
public DiscordPenaltySetting[] DiscordPenaltyMuteSettings { get; set; } =
|
|
||||||
[
|
|
||||||
new DiscordPenaltySetting { Name = "Color", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Webhook", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ThumbnailUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ImageUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Footer", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Time", Value = "{relative}" },
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("DiscordPenaltyGagSettings")]
|
|
||||||
public DiscordPenaltySetting[] DiscordPenaltyGagSettings { get; set; } =
|
|
||||||
[
|
|
||||||
new DiscordPenaltySetting { Name = "Color", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Webhook", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ThumbnailUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ImageUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Footer", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Time", Value = "{relative}" },
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("DiscordPenaltySilenceSettings")]
|
|
||||||
public DiscordPenaltySetting[] DiscordPenaltySilenceSettings { get; set; } =
|
|
||||||
[
|
|
||||||
new DiscordPenaltySetting { Name = "Color", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Webhook", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ThumbnailUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ImageUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Footer", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Time", Value = "{relative}" },
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("DiscordPenaltyWarnSettings")]
|
|
||||||
public DiscordPenaltySetting[] DiscordPenaltyWarnSettings { get; set; } =
|
|
||||||
[
|
|
||||||
new DiscordPenaltySetting { Name = "Color", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Webhook", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ThumbnailUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "ImageUrl", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Footer", Value = "" },
|
|
||||||
new DiscordPenaltySetting { Name = "Time", Value = "{relative}" },
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CustomServerCommandData
|
|
||||||
{
|
|
||||||
[JsonPropertyName("Flag")]
|
|
||||||
public string Flag { get; set; } = "@css/generic";
|
|
||||||
|
|
||||||
[JsonPropertyName("DisplayName")]
|
|
||||||
public string DisplayName { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("Command")]
|
|
||||||
public string Command { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("ExecuteOnClient")]
|
|
||||||
public bool ExecuteOnClient { get; set; } = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MenuConfig
|
|
||||||
{
|
|
||||||
[JsonPropertyName("MenuType")] public string MenuType { get; set; } = "selectable";
|
|
||||||
|
|
||||||
[JsonPropertyName("Durations")]
|
|
||||||
public DurationItem[] Durations { get; set; } =
|
|
||||||
[
|
|
||||||
new DurationItem { Name = "1 minute", Duration = 1 },
|
|
||||||
new DurationItem { Name = "5 minutes", Duration = 5 },
|
|
||||||
new DurationItem { Name = "15 minutes", Duration = 15 },
|
|
||||||
new DurationItem { Name = "1 hour", Duration = 60 },
|
|
||||||
new DurationItem { Name = "1 day", Duration = 60 * 24 },
|
|
||||||
new DurationItem { Name = "7 days", Duration = 60 * 24 * 7 },
|
|
||||||
new DurationItem { Name = "14 days", Duration = 60 * 24 * 14 },
|
|
||||||
new DurationItem { Name = "30 days", Duration = 60 * 24 * 30 },
|
|
||||||
new DurationItem { Name = "Permanent", Duration = 0 }
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("BanReasons")]
|
|
||||||
public List<string> BanReasons { get; set; } =
|
|
||||||
[
|
|
||||||
"Hacking",
|
|
||||||
"Voice Abuse",
|
|
||||||
"Chat Abuse",
|
|
||||||
"Admin disrespect",
|
|
||||||
"Other"
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("KickReasons")]
|
|
||||||
public List<string> KickReasons { get; set; } =
|
|
||||||
[
|
|
||||||
"Voice Abuse",
|
|
||||||
"Chat Abuse",
|
|
||||||
"Admin disrespect",
|
|
||||||
"Other"
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("WarnReasons")]
|
|
||||||
public List<string> WarnReasons { get; set; } =
|
|
||||||
[
|
|
||||||
"Voice Abuse",
|
|
||||||
"Chat Abuse",
|
|
||||||
"Admin disrespect",
|
|
||||||
"Other"
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("MuteReasons")]
|
|
||||||
public List<string> MuteReasons { get; set; } =
|
|
||||||
[
|
|
||||||
"Advertising",
|
|
||||||
"Spamming",
|
|
||||||
"Spectator camera abuse",
|
|
||||||
"Hate",
|
|
||||||
"Admin disrespect",
|
|
||||||
"Other"
|
|
||||||
];
|
|
||||||
|
|
||||||
[JsonPropertyName("AdminFlags")]
|
|
||||||
public AdminFlag[] AdminFlags { get; set; } =
|
|
||||||
[
|
|
||||||
new AdminFlag { Name = "Generic", Flag = "@css/generic" },
|
|
||||||
new AdminFlag { Name = "Chat", Flag = "@css/chat" },
|
|
||||||
new AdminFlag { Name = "Change Map", Flag = "@css/changemap" },
|
|
||||||
new AdminFlag { Name = "Slay", Flag = "@css/slay" },
|
|
||||||
new AdminFlag { Name = "Kick", Flag = "@css/kick" },
|
|
||||||
new AdminFlag { Name = "Ban", Flag = "@css/ban" },
|
|
||||||
new AdminFlag { Name = "Perm Ban", Flag = "@css/permban" },
|
|
||||||
new AdminFlag { Name = "Unban", Flag = "@css/unban" },
|
|
||||||
new AdminFlag { Name = "Show IP", Flag = "@css/showip" },
|
|
||||||
new AdminFlag { Name = "Cvar", Flag = "@css/cvar" },
|
|
||||||
new AdminFlag { Name = "Rcon", Flag = "@css/rcon" },
|
|
||||||
new AdminFlag { Name = "Root (all flags)", Flag = "@css/root" }
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OtherSettings
|
|
||||||
{
|
|
||||||
[JsonPropertyName("ShowActivityType")]
|
|
||||||
public int ShowActivityType { get; set; } = 2;
|
|
||||||
|
|
||||||
[JsonPropertyName("TeamSwitchType")]
|
|
||||||
public int TeamSwitchType { get; set; } = 1;
|
|
||||||
|
|
||||||
[JsonPropertyName("KickTime")]
|
|
||||||
public int KickTime { get; set; } = 5;
|
|
||||||
|
|
||||||
[JsonPropertyName("BanType")]
|
|
||||||
public int BanType { get; set; } = 1;
|
|
||||||
|
|
||||||
[JsonPropertyName("TimeMode")]
|
|
||||||
public int TimeMode { get; set; } = 1;
|
|
||||||
|
|
||||||
[JsonPropertyName("DisableDangerousCommands")]
|
|
||||||
public bool DisableDangerousCommands { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonPropertyName("MaxBanDuration")]
|
|
||||||
public int MaxBanDuration { get; set; } = 60 * 24 * 7;
|
|
||||||
|
|
||||||
[JsonPropertyName("MaxMuteDuration")]
|
|
||||||
public int MaxMuteDuration { get; set; } = 60 * 24 * 7;
|
|
||||||
|
|
||||||
[JsonPropertyName("ExpireOldIpBans")]
|
|
||||||
public int ExpireOldIpBans { get; set; } = 0;
|
|
||||||
|
|
||||||
[JsonPropertyName("ReloadAdminsEveryMapChange")]
|
|
||||||
public bool ReloadAdminsEveryMapChange { get; set; } = false;
|
|
||||||
|
|
||||||
[JsonPropertyName("DisconnectedPlayersHistoryCount")]
|
|
||||||
public int DisconnectedPlayersHistoryCount { get; set; } = 10;
|
|
||||||
|
|
||||||
[JsonPropertyName("NotifyPenaltiesToAdminOnConnect")]
|
|
||||||
public bool NotifyPenaltiesToAdminOnConnect { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonPropertyName("ShowBanMenuIfNoTime")]
|
|
||||||
public bool ShowBanMenuIfNoTime { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonPropertyName("UserMessageGagChatType")]
|
|
||||||
public bool UserMessageGagChatType { get; set; } = false;
|
|
||||||
|
|
||||||
[JsonPropertyName("CheckMultiAccountsByIp")]
|
|
||||||
public bool CheckMultiAccountsByIp { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonPropertyName("AdditionalCommandsToLog")]
|
|
||||||
public List<string> AdditionalCommandsToLog { get; set; } = new();
|
|
||||||
[JsonPropertyName("IgnoredIps")]
|
|
||||||
public List<string> IgnoredIps { get; set; } = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CS2_SimpleAdminConfig : BasePluginConfig
|
|
||||||
{
|
|
||||||
[JsonPropertyName("ConfigVersion")] public override int Version { get; set; } = 24;
|
|
||||||
|
|
||||||
[JsonPropertyName("DatabaseHost")]
|
|
||||||
public string DatabaseHost { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("DatabasePort")]
|
|
||||||
public int DatabasePort { get; set; } = 3306;
|
|
||||||
|
|
||||||
[JsonPropertyName("DatabaseUser")]
|
|
||||||
public string DatabaseUser { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("DatabasePassword")]
|
|
||||||
public string DatabasePassword { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("DatabaseName")]
|
|
||||||
public string DatabaseName { get; set; } = "";
|
|
||||||
|
|
||||||
[JsonPropertyName("DatabaseSSlMode")]
|
|
||||||
public string DatabaseSSlMode { get; set; } = "preferred";
|
|
||||||
|
|
||||||
[JsonPropertyName("OtherSettings")]
|
|
||||||
public OtherSettings OtherSettings { get; set; } = new();
|
|
||||||
|
|
||||||
[JsonPropertyName("EnableMetrics")]
|
|
||||||
public bool EnableMetrics { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonPropertyName("EnableUpdateCheck")]
|
|
||||||
public bool EnableUpdateCheck { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonPropertyName("Timezone")]
|
|
||||||
public string Timezone { get; set; } = "UTC";
|
|
||||||
|
|
||||||
[JsonPropertyName("WarnThreshold")]
|
|
||||||
public Dictionary<int, string> WarnThreshold { get; set; } = new()
|
|
||||||
{
|
|
||||||
{ 998, "css_addban STEAMID64 60 \"3/4 Warn\"" },
|
|
||||||
{ 999, "css_ban #USERID 120 \"4/4 Warn\"" },
|
|
||||||
};
|
|
||||||
|
|
||||||
[JsonPropertyName("MultiServerMode")]
|
|
||||||
public bool MultiServerMode { get; set; } = true;
|
|
||||||
|
|
||||||
[JsonPropertyName("Discord")]
|
|
||||||
public Discord Discord { get; set; } = new();
|
|
||||||
|
|
||||||
[JsonPropertyName("DefaultMaps")]
|
|
||||||
public List<string> DefaultMaps { get; set; } = new();
|
|
||||||
|
|
||||||
[JsonPropertyName("WorkshopMaps")]
|
|
||||||
public Dictionary<string, long?> WorkshopMaps { get; set; } = new();
|
|
||||||
|
|
||||||
[JsonPropertyName("CustomServerCommands")]
|
|
||||||
public List<CustomServerCommandData> CustomServerCommands { get; set; } = new();
|
|
||||||
|
|
||||||
[JsonPropertyName("MenuConfig")]
|
|
||||||
public MenuConfig MenuConfigs { get; set; } = new();
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MySqlConnector;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin.Database;
|
|
||||||
|
|
||||||
public class Database(string dbConnectionString)
|
|
||||||
{
|
|
||||||
public MySqlConnection GetConnection()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var connection = new MySqlConnection(dbConnectionString);
|
|
||||||
connection.Open();
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin._logger?.LogCritical($"Unable to connect to database: {ex.Message}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<MySqlConnection> GetConnectionAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var connection = new MySqlConnection(dbConnectionString);
|
|
||||||
await connection.OpenAsync();
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
CS2_SimpleAdmin._logger?.LogCritical($"Unable to connect to database: {ex.Message}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DatabaseMigration()
|
|
||||||
{
|
|
||||||
Migration migrator = new(this);
|
|
||||||
migrator.ExecuteMigrations();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CheckDatabaseConnection(out string? exception)
|
|
||||||
{
|
|
||||||
using var connection = GetConnection();
|
|
||||||
exception = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return connection.Ping();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
exception = ex.Message;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MySqlConnector;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin.Database;
|
|
||||||
|
|
||||||
public class Migration(Database database)
|
|
||||||
{
|
|
||||||
public void ExecuteMigrations()
|
|
||||||
{
|
|
||||||
var migrationsDirectory = CS2_SimpleAdmin.Instance.ModuleDirectory + "/Database/Migrations";
|
|
||||||
|
|
||||||
var files = Directory.GetFiles(migrationsDirectory, "*.sql")
|
|
||||||
.OrderBy(f => f);
|
|
||||||
|
|
||||||
using var connection = database.GetConnection();
|
|
||||||
|
|
||||||
// Create sa_migrations table if not exists
|
|
||||||
using var cmd = new MySqlCommand("""
|
|
||||||
CREATE TABLE IF NOT EXISTS `sa_migrations` (
|
|
||||||
`id` INT PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
`version` VARCHAR(255) NOT NULL
|
|
||||||
);
|
|
||||||
""", connection);
|
|
||||||
|
|
||||||
cmd.ExecuteNonQuery();
|
|
||||||
|
|
||||||
// Get the last applied migration version
|
|
||||||
var lastAppliedVersion = GetLastAppliedVersion(connection);
|
|
||||||
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
var version = Path.GetFileNameWithoutExtension(file);
|
|
||||||
|
|
||||||
// Check if the migration has already been applied
|
|
||||||
if (string.Compare(version, lastAppliedVersion, StringComparison.OrdinalIgnoreCase) <= 0) continue;
|
|
||||||
var sqlScript = File.ReadAllText(file);
|
|
||||||
|
|
||||||
using var cmdMigration = new MySqlCommand(sqlScript, connection);
|
|
||||||
cmdMigration.ExecuteNonQuery();
|
|
||||||
|
|
||||||
// Update the last applied migration version
|
|
||||||
UpdateLastAppliedVersion(connection, version);
|
|
||||||
|
|
||||||
CS2_SimpleAdmin._logger?.LogInformation($"Migration \"{version}\" successfully applied.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetLastAppliedVersion(MySqlConnection connection)
|
|
||||||
{
|
|
||||||
using var cmd = new MySqlCommand("SELECT `version` FROM `sa_migrations` ORDER BY `id` DESC LIMIT 1;", connection);
|
|
||||||
var result = cmd.ExecuteScalar();
|
|
||||||
return result?.ToString() ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void UpdateLastAppliedVersion(MySqlConnection connection, string version)
|
|
||||||
{
|
|
||||||
using var cmd = new MySqlCommand("INSERT INTO `sa_migrations` (`version`) VALUES (@Version);", connection);
|
|
||||||
cmd.Parameters.AddWithValue("@Version", version);
|
|
||||||
cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `sa_bans` (
|
|
||||||
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
`player_name` VARCHAR(128),
|
|
||||||
`player_steamid` VARCHAR(64),
|
|
||||||
`player_ip` VARCHAR(128),
|
|
||||||
`admin_steamid` VARCHAR(64) NOT NULL,
|
|
||||||
`admin_name` VARCHAR(128) NOT NULL,
|
|
||||||
`reason` VARCHAR(255) NOT NULL,
|
|
||||||
`duration` INT NOT NULL,
|
|
||||||
`ends` TIMESTAMP NULL,
|
|
||||||
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`server_id` INT NULL,
|
|
||||||
`status` ENUM('ACTIVE', 'UNBANNED', 'EXPIRED', '') NOT NULL DEFAULT 'ACTIVE'
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sa_mutes` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`player_name` varchar(128) NULL,
|
|
||||||
`player_steamid` varchar(64) NOT NULL,
|
|
||||||
`admin_steamid` varchar(64) NOT NULL,
|
|
||||||
`admin_name` varchar(128) NOT NULL,
|
|
||||||
`reason` varchar(255) NOT NULL,
|
|
||||||
`duration` int(11) NOT NULL,
|
|
||||||
`ends` timestamp NULL,
|
|
||||||
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`type` enum('GAG','MUTE','SILENCE','') NOT NULL DEFAULT 'GAG',
|
|
||||||
`server_id` INT NULL,
|
|
||||||
`status` enum('ACTIVE','UNMUTED','EXPIRED','') NOT NULL DEFAULT 'ACTIVE',
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sa_admins` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`player_name` varchar(128) NOT NULL,
|
|
||||||
`player_steamid` varchar(64) NOT NULL,
|
|
||||||
`flags` TEXT NULL,
|
|
||||||
`immunity` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`server_id` INT NULL,
|
|
||||||
`ends` timestamp NULL,
|
|
||||||
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sa_servers` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`hostname` varchar(128) NOT NULL,
|
|
||||||
`address` varchar(64) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `address` (`address`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `sa_admins_flags` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`admin_id` int(11) NOT NULL,
|
|
||||||
`flag` varchar(64) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
FOREIGN KEY (`admin_id`) REFERENCES `sa_admins` (`id`) ON DELETE CASCADE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
ALTER TABLE `sa_admins` CHANGE `flags` `flags` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL;
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
ALTER TABLE `sa_bans` CHANGE `player_name` `player_name` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`;
|
|
||||||
ALTER TABLE `sa_mutes` CHANGE `player_name` `player_name` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`;
|
|
||||||
ALTER TABLE `sa_admins` CHANGE `player_name` `player_name` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`;
|
|
||||||
ALTER TABLE `sa_servers` CHANGE `hostname` `hostname` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL AFTER `id`;
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
INSERT INTO sa_admins_flags (admin_id, flag)
|
|
||||||
SELECT
|
|
||||||
min_admins.admin_id,
|
|
||||||
TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(sa_admins.flags, ',', numbers.n), ',', -1)) AS flag
|
|
||||||
FROM (
|
|
||||||
SELECT MIN(id) AS admin_id, player_steamid, server_id
|
|
||||||
FROM sa_admins
|
|
||||||
WHERE player_steamid != 'Console'
|
|
||||||
GROUP BY player_steamid, server_id
|
|
||||||
) AS min_admins
|
|
||||||
JOIN sa_admins ON min_admins.player_steamid = sa_admins.player_steamid
|
|
||||||
JOIN (
|
|
||||||
SELECT 1 AS n UNION ALL
|
|
||||||
SELECT 2 UNION ALL
|
|
||||||
SELECT 3 UNION ALL
|
|
||||||
SELECT 4 UNION ALL
|
|
||||||
SELECT 5 UNION ALL
|
|
||||||
SELECT 6 UNION ALL
|
|
||||||
SELECT 7 UNION ALL
|
|
||||||
SELECT 8 UNION ALL
|
|
||||||
SELECT 9 UNION ALL
|
|
||||||
SELECT 10 UNION ALL
|
|
||||||
SELECT 11 UNION ALL
|
|
||||||
SELECT 12 UNION ALL
|
|
||||||
SELECT 13 UNION ALL
|
|
||||||
SELECT 14 UNION ALL
|
|
||||||
SELECT 15 UNION ALL
|
|
||||||
SELECT 16 UNION ALL
|
|
||||||
SELECT 17 UNION ALL
|
|
||||||
SELECT 18 UNION ALL
|
|
||||||
SELECT 19 UNION ALL
|
|
||||||
SELECT 20
|
|
||||||
) AS numbers
|
|
||||||
ON CHAR_LENGTH(sa_admins.flags) - CHAR_LENGTH(REPLACE(sa_admins.flags, ',', '')) >= numbers.n - 1
|
|
||||||
AND (min_admins.server_id = sa_admins.server_id OR (min_admins.server_id IS NULL AND sa_admins.server_id IS NULL))
|
|
||||||
WHERE sa_admins.id IS NOT NULL;
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `sa_unbans` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`ban_id` int(11) NOT NULL,
|
|
||||||
`admin_id` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`reason` varchar(255) NOT NULL DEFAULT 'Unknown',
|
|
||||||
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sa_unmutes` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`mute_id` int(11) NOT NULL,
|
|
||||||
`admin_id` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`reason` varchar(255) NOT NULL DEFAULT 'Unknown',
|
|
||||||
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
INSERT INTO `sa_admins` (`id`, `player_name`, `player_steamid`, `flags`, `immunity`, `server_id`, `ends`, `created`)
|
|
||||||
VALUES (-1, 'Console', 'Console', '', '0', NULL, NULL, NOW());
|
|
||||||
|
|
||||||
UPDATE `sa_admins` SET `id` = 0 WHERE `id` = -1;
|
|
||||||
|
|
||||||
ALTER TABLE `sa_bans` ADD `unban_id` INT NULL AFTER `server_id`;
|
|
||||||
ALTER TABLE `sa_mutes` ADD `unmute_id` INT NULL AFTER `server_id`;
|
|
||||||
ALTER TABLE `sa_bans` ADD FOREIGN KEY (`unban_id`) REFERENCES `sa_unbans`(`id`) ON DELETE CASCADE;
|
|
||||||
ALTER TABLE `sa_mutes` ADD FOREIGN KEY (`unmute_id`) REFERENCES `sa_unmutes`(`id`) ON DELETE CASCADE;
|
|
||||||
ALTER TABLE `sa_unbans` ADD FOREIGN KEY (`admin_id`) REFERENCES `sa_admins`(`id`) ON DELETE CASCADE;
|
|
||||||
ALTER TABLE `sa_unmutes` ADD FOREIGN KEY (`admin_id`) REFERENCES `sa_admins`(`id`) ON DELETE CASCADE;
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `sa_groups` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(255) NOT NULL,
|
|
||||||
`immunity` int(11) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sa_groups_flags` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`group_id` int(11) NOT NULL,
|
|
||||||
`flag` varchar(64) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `sa_groups_servers` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`group_id` int(11) NOT NULL,
|
|
||||||
`server_id` int(11) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
|
|
||||||
ALTER TABLE `sa_admins` ADD `group_id` INT NULL AFTER `created`;
|
|
||||||
|
|
||||||
ALTER TABLE `sa_groups_flags` ADD FOREIGN KEY (`group_id`) REFERENCES `sa_groups`(`id`) ON DELETE CASCADE;
|
|
||||||
ALTER TABLE `sa_groups_servers` ADD FOREIGN KEY (`group_id`) REFERENCES `sa_groups`(`id`) ON DELETE CASCADE;
|
|
||||||
ALTER TABLE `sa_admins` ADD FOREIGN KEY (`group_id`) REFERENCES `sa_groups`(`id`) ON DELETE SET NULL;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE `sa_groups_servers` CHANGE `server_id` `server_id` INT(11) NULL;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE `sa_mutes` ADD `passed` INT NULL AFTER `duration`;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `sa_players_ips` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`steamid` bigint(20) NOT NULL,
|
|
||||||
`address` varchar(64) NOT NULL,
|
|
||||||
`used_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `steamid` (`steamid`,`address`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `sa_warns` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`player_name` varchar(128) DEFAULT NULL,
|
|
||||||
`player_steamid` varchar(64) NOT NULL,
|
|
||||||
`admin_steamid` varchar(64) NOT NULL,
|
|
||||||
`admin_name` varchar(128) NOT NULL,
|
|
||||||
`reason` varchar(255) NOT NULL,
|
|
||||||
`duration` int(11) NOT NULL,
|
|
||||||
`ends` timestamp NOT NULL,
|
|
||||||
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
`server_id` int(11) DEFAULT NULL,
|
|
||||||
`status` enum('ACTIVE','EXPIRED','') NOT NULL DEFAULT 'ACTIVE',
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
ALTER TABLE `sa_servers` ADD `rcon_password` varchar(128) NULL AFTER `hostname`;
|
|
||||||
@@ -1,489 +0,0 @@
|
|||||||
using CounterStrikeSharp.API;
|
|
||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
|
||||||
using CounterStrikeSharp.API.Modules.Utils;
|
|
||||||
using CS2_SimpleAdmin.Managers;
|
|
||||||
using CS2_SimpleAdmin.Models;
|
|
||||||
using CS2_SimpleAdminApi;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System.Text;
|
|
||||||
using CounterStrikeSharp.API.Core.Translations;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.UserMessages;
|
|
||||||
using CounterStrikeSharp.API.ValveConstants.Protobuf;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public partial class CS2_SimpleAdmin
|
|
||||||
{
|
|
||||||
private bool _serverLoading;
|
|
||||||
|
|
||||||
private void RegisterEvents()
|
|
||||||
{
|
|
||||||
RegisterListener<Listeners.OnMapStart>(OnMapStart);
|
|
||||||
RegisterListener<Listeners.OnClientConnect>(OnClientConnect);
|
|
||||||
RegisterListener<Listeners.OnGameServerSteamAPIActivated>(OnGameServerSteamAPIActivated);
|
|
||||||
if (Config.OtherSettings.UserMessageGagChatType)
|
|
||||||
HookUserMessage(118, HookUmChat);
|
|
||||||
|
|
||||||
AddCommandListener(null, ComamndListenerHandler);
|
|
||||||
// AddCommandListener("callvote", OnCommandCallVote);
|
|
||||||
// AddCommandListener("say", OnCommandSay);
|
|
||||||
// AddCommandListener("say_team", OnCommandTeamSay);
|
|
||||||
}
|
|
||||||
|
|
||||||
// private HookResult OnCommandCallVote(CCSPlayerController? caller, CommandInfo info)
|
|
||||||
// {
|
|
||||||
// var voteType = info.GetArg(1).ToLower();
|
|
||||||
//
|
|
||||||
// if (voteType != "kick")
|
|
||||||
// return HookResult.Continue;
|
|
||||||
//
|
|
||||||
// var target = int.TryParse(info.GetArg(2), out var userId)
|
|
||||||
// ? Utilities.GetPlayerFromUserid(userId)
|
|
||||||
// : null;
|
|
||||||
//
|
|
||||||
// if (target == null || !target.IsValid || target.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
// return HookResult.Continue;
|
|
||||||
//
|
|
||||||
// return !AdminManager.CanPlayerTarget(caller, target) ? HookResult.Stop : HookResult.Continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void OnGameServerSteamAPIActivated()
|
|
||||||
{
|
|
||||||
if (_serverLoading)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_serverLoading = true;
|
|
||||||
new ServerManager().LoadServerData();
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEventHandler(HookMode.Pre)]
|
|
||||||
public HookResult OnClientDisconnect(EventPlayerDisconnect @event, GameEventInfo info)
|
|
||||||
{
|
|
||||||
if (@event.Reason is 149 or 6)
|
|
||||||
info.DontBroadcast = true;
|
|
||||||
|
|
||||||
var player = @event.Userid;
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
Logger.LogCritical("[OnClientDisconnect] Before");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
Logger.LogCritical("[OnClientDisconnect] After Check");
|
|
||||||
#endif
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DisconnectedPlayers.Count >= Config.OtherSettings.DisconnectedPlayersHistoryCount)
|
|
||||||
DisconnectedPlayers.RemoveAt(0);
|
|
||||||
|
|
||||||
var steamId = new SteamID(player.SteamID);
|
|
||||||
var disconnectedPlayer = DisconnectedPlayers.FirstOrDefault(p => p.SteamId == steamId);
|
|
||||||
|
|
||||||
if (disconnectedPlayer != null)
|
|
||||||
{
|
|
||||||
disconnectedPlayer.Name = player.PlayerName;
|
|
||||||
disconnectedPlayer.IpAddress = player.IpAddress?.Split(":")[0];
|
|
||||||
disconnectedPlayer.DisconnectTime = Time.ActualDateTime();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DisconnectedPlayers.Add(new DisconnectedPlayer(steamId, player.PlayerName, player.IpAddress?.Split(":")[0], Time.ActualDateTime()));
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerPenaltyManager.RemoveAllPenalties(player.Slot);
|
|
||||||
|
|
||||||
SilentPlayers.Remove(player.Slot);
|
|
||||||
GodPlayers.Remove(player.Slot);
|
|
||||||
SpeedPlayers.Remove(player.Slot);
|
|
||||||
GravityPlayers.Remove(player);
|
|
||||||
|
|
||||||
if (player.UserId.HasValue)
|
|
||||||
PlayersInfo.TryRemove(player.UserId.Value, out _);
|
|
||||||
|
|
||||||
if (!PermissionManager.AdminCache.TryGetValue(steamId, out var data)
|
|
||||||
|| !(data.ExpirationTime <= Time.ActualDateTime()))
|
|
||||||
{
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
AdminManager.RemovePlayerPermissions(steamId, PermissionManager.AdminCache[steamId].Flags.ToArray());
|
|
||||||
AdminManager.RemovePlayerFromGroup(steamId, true, PermissionManager.AdminCache[steamId].Flags.ToArray());
|
|
||||||
var adminData = AdminManager.GetPlayerAdminData(steamId);
|
|
||||||
|
|
||||||
if (adminData == null || data.Flags.ToList().Count != 0 && adminData.Groups.ToList().Count != 0)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
AdminManager.ClearPlayerPermissions(steamId);
|
|
||||||
AdminManager.RemovePlayerAdminData(steamId);
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError($"An error occurred in OnClientDisconnect: {ex.Message}");
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnClientConnect(int playerslot, string name, string ipaddress)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
Logger.LogCritical("[OnClientConnect]");
|
|
||||||
#endif
|
|
||||||
if (!CS2_SimpleAdmin.BannedPlayers.Contains(ipaddress.Split(":")[0]))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Server.NextFrame((() =>
|
|
||||||
{
|
|
||||||
var player = Utilities.GetPlayerFromSlot(playerslot);
|
|
||||||
if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Helper.KickPlayer(player, NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED);
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Server.NextFrame(() =>
|
|
||||||
// {
|
|
||||||
// var player = Utilities.GetPlayerFromSlot(playerslot);
|
|
||||||
//
|
|
||||||
// if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
// return;
|
|
||||||
//
|
|
||||||
// new PlayerManager().LoadPlayerData(player);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEventHandler]
|
|
||||||
public HookResult OnPlayerFullConnect(EventPlayerConnectFull @event, GameEventInfo info)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
Logger.LogCritical("[OnPlayerFullConnect]");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var player = @event.Userid;
|
|
||||||
|
|
||||||
if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
// if (player.UserId.HasValue && PlayersInfo.TryGetValue(player.UserId.Value, out PlayerInfo? value) &&
|
|
||||||
// value.WaitingForKick)
|
|
||||||
// return HookResult.Continue;
|
|
||||||
|
|
||||||
new PlayerManager().LoadPlayerData(player);
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEventHandler]
|
|
||||||
public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
Logger.LogCritical("[OnRoundStart]");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GodPlayers.Clear();
|
|
||||||
SpeedPlayers.Clear();
|
|
||||||
GravityPlayers.Clear();
|
|
||||||
|
|
||||||
foreach (var player in PlayersInfo.Values)
|
|
||||||
{
|
|
||||||
player.DiePosition = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddTimer(0.41f, () =>
|
|
||||||
{
|
|
||||||
foreach (var list in RenamedPlayers)
|
|
||||||
{
|
|
||||||
var player = Utilities.GetPlayerFromSteamId(list.Key);
|
|
||||||
|
|
||||||
if (player == null || !player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (player.PlayerName.Equals(list.Value))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
player.Rename(list.Value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HookResult HookUmChat(UserMessage um)
|
|
||||||
{
|
|
||||||
var author = Utilities.GetPlayerFromIndex(um.ReadInt("entityindex"));
|
|
||||||
if (author == null || !author.IsValid || author.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (!PlayerPenaltyManager.IsPenalized(author.Slot, PenaltyType.Gag, out DateTime? endDateTime) &&
|
|
||||||
!PlayerPenaltyManager.IsPenalized(author.Slot, PenaltyType.Silence, out endDateTime))
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (_localizer != null && endDateTime is not null)
|
|
||||||
author.SendLocalizedMessage(_localizer, "sa_player_penalty_chat_active", endDateTime.Value.ToString("g", author.GetLanguage()));
|
|
||||||
return HookResult.Stop;
|
|
||||||
|
|
||||||
// um.Recipients.Clear();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private HookResult ComamndListenerHandler(CCSPlayerController? player, CommandInfo info)
|
|
||||||
{
|
|
||||||
if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
var command = info.GetArg(0).ToLower();
|
|
||||||
|
|
||||||
if (Config.OtherSettings.AdditionalCommandsToLog.Contains(command))
|
|
||||||
Helper.LogCommand(player, info);
|
|
||||||
|
|
||||||
switch (command)
|
|
||||||
{
|
|
||||||
case "css_admins_reload":
|
|
||||||
AddTimer(1.0f, () => ReloadAdmins(null));
|
|
||||||
return HookResult.Continue;
|
|
||||||
case "callvote":
|
|
||||||
{
|
|
||||||
var voteType = info.GetArg(1).ToLower();
|
|
||||||
|
|
||||||
if (voteType != "kick")
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
var target = int.TryParse(info.GetArg(2), out var userId)
|
|
||||||
? Utilities.GetPlayerFromUserid(userId)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (target == null || !target.IsValid || target.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
return !player.CanTarget(target) ? HookResult.Stop : HookResult.Continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!command.Contains("say"))
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (!Config.OtherSettings.UserMessageGagChatType)
|
|
||||||
{
|
|
||||||
if (PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag, out DateTime? endDateTime) ||
|
|
||||||
PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence, out endDateTime))
|
|
||||||
{
|
|
||||||
if (_localizer != null && endDateTime is not null)
|
|
||||||
player.SendLocalizedMessage(_localizer, "sa_player_penalty_chat_active", endDateTime.Value.ToString("g", player.GetLanguage()));
|
|
||||||
return HookResult.Stop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.GetArg(1).StartsWith($"/")
|
|
||||||
|| info.GetArg(1).StartsWith($"!"))
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (info.GetArg(1).Length == 0)
|
|
||||||
return HookResult.Stop;
|
|
||||||
|
|
||||||
if (command == "say" && info.GetArg(1).StartsWith($"@") &&
|
|
||||||
AdminManager.PlayerHasPermissions(new SteamID(player.SteamID), "@css/chat"))
|
|
||||||
{
|
|
||||||
player.ExecuteClientCommandFromServer($"css_say {info.GetArg(1).Remove(0, 1)}");
|
|
||||||
return HookResult.Stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command != "say_team" || !info.GetArg(1).StartsWith($"@")) return HookResult.Continue;
|
|
||||||
|
|
||||||
StringBuilder sb = new();
|
|
||||||
if (AdminManager.PlayerHasPermissions(new SteamID(player.SteamID), "@css/chat"))
|
|
||||||
{
|
|
||||||
sb.Append(_localizer!["sa_adminchat_template_admin", player.PlayerName, info.GetArg(1).Remove(0, 1)]);
|
|
||||||
foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && p is { IsBot: false, IsHLTV: false } && AdminManager.PlayerHasPermissions(new SteamID(p.SteamID), "@css/chat")))
|
|
||||||
{
|
|
||||||
p.PrintToChat(sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(_localizer!["sa_adminchat_template_player", player.PlayerName, info.GetArg(1).Remove(0, 1)]);
|
|
||||||
player.PrintToChat(sb.ToString());
|
|
||||||
foreach (var p in Utilities.GetPlayers().Where(p => p is { IsValid: true, IsBot: false, IsHLTV: false } && AdminManager.PlayerHasPermissions(new SteamID(p.SteamID), "@css/chat")))
|
|
||||||
{
|
|
||||||
p.PrintToChat(sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HookResult.Stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*public HookResult OnCommandSay(CCSPlayerController? player, CommandInfo info)
|
|
||||||
{
|
|
||||||
if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (info.GetArg(1).StartsWith($"/")
|
|
||||||
|| info.GetArg(1).StartsWith($"!"))
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (info.GetArg(1).Length == 0)
|
|
||||||
return HookResult.Handled;
|
|
||||||
|
|
||||||
if (PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag) || PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence))
|
|
||||||
return HookResult.Handled;
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public HookResult OnCommandTeamSay(CCSPlayerController? player, CommandInfo info)
|
|
||||||
{
|
|
||||||
if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (info.GetArg(1).StartsWith($"/")
|
|
||||||
|| info.GetArg(1).StartsWith($"!"))
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (info.GetArg(1).Length == 0)
|
|
||||||
return HookResult.Handled;
|
|
||||||
|
|
||||||
if (PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Gag, out _) || PlayerPenaltyManager.IsPenalized(player.Slot, PenaltyType.Silence, out _))
|
|
||||||
return HookResult.Stop;
|
|
||||||
|
|
||||||
if (!info.GetArg(1).StartsWith($"@")) return HookResult.Continue;
|
|
||||||
|
|
||||||
StringBuilder sb = new();
|
|
||||||
|
|
||||||
if (AdminManager.PlayerHasPermissions(new SteamID(player.SteamID), "@css/chat"))
|
|
||||||
{
|
|
||||||
sb.Append(_localizer!["sa_adminchat_template_admin", player.PlayerName, info.GetArg(1).Remove(0, 1)]);
|
|
||||||
foreach (var p in Utilities.GetPlayers().Where(p => p.IsValid && p is { IsBot: false, IsHLTV: false } && AdminManager.PlayerHasPermissions(new SteamID(p.SteamID), "@css/chat")))
|
|
||||||
{
|
|
||||||
p.PrintToChat(sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append(_localizer!["sa_adminchat_template_player", player.PlayerName, info.GetArg(1).Remove(0, 1)]);
|
|
||||||
player.PrintToChat(sb.ToString());
|
|
||||||
foreach (var p in Utilities.GetPlayers().Where(p => p is { IsValid: true, IsBot: false, IsHLTV: false } && AdminManager.PlayerHasPermissions(new SteamID(p.SteamID), "@css/chat")))
|
|
||||||
{
|
|
||||||
p.PrintToChat(sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HookResult.Handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMapStart(string mapName)
|
|
||||||
{
|
|
||||||
if (Config.OtherSettings.ReloadAdminsEveryMapChange && ServerLoaded && ServerId != null)
|
|
||||||
AddTimer(5.0f, () => ReloadAdmins(null));
|
|
||||||
|
|
||||||
AddTimer(1.0f, () => new ServerManager().CheckHibernationStatus());
|
|
||||||
|
|
||||||
// AddTimer(34, () =>
|
|
||||||
// {
|
|
||||||
// if (!ServerLoaded)
|
|
||||||
// OnGameServerSteamAPIActivated();
|
|
||||||
// });
|
|
||||||
|
|
||||||
GodPlayers.Clear();
|
|
||||||
SilentPlayers.Clear();
|
|
||||||
SpeedPlayers.Clear();
|
|
||||||
GravityPlayers.Clear();
|
|
||||||
|
|
||||||
PlayerPenaltyManager.RemoveAllPenalties();
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEventHandler]
|
|
||||||
public HookResult OnPlayerHurt(EventPlayerHurt @event, GameEventInfo info)
|
|
||||||
{
|
|
||||||
var player = @event.Userid;
|
|
||||||
|
|
||||||
if (player is null || @event.Attacker is null || player.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE || player.PlayerPawn.Value == null)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (SpeedPlayers.TryGetValue(player.Slot, out var speedPlayer))
|
|
||||||
AddTimer(0.15f, () => player.SetSpeed(speedPlayer));
|
|
||||||
|
|
||||||
if (!GodPlayers.Contains(player.Slot)) return HookResult.Continue;
|
|
||||||
|
|
||||||
player.PlayerPawn.Value.Health = player.PlayerPawn.Value.MaxHealth;
|
|
||||||
player.PlayerPawn.Value.ArmorValue = 100;
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEventHandler]
|
|
||||||
public HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info)
|
|
||||||
{
|
|
||||||
var player = @event.Userid;
|
|
||||||
|
|
||||||
if (player?.UserId == null || !player.IsValid || player.IsHLTV || player.Connected != PlayerConnectedState.PlayerConnected)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
SpeedPlayers.Remove(player.Slot);
|
|
||||||
GravityPlayers.Remove(player);
|
|
||||||
|
|
||||||
if (!PlayersInfo.ContainsKey(player.UserId.Value) || @event.Attacker == null)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
var playerPosition = player.PlayerPawn.Value?.AbsOrigin;
|
|
||||||
var playerRotation = player.PlayerPawn.Value?.AbsRotation;
|
|
||||||
|
|
||||||
PlayersInfo[player.UserId.Value].DiePosition = new DiePosition(
|
|
||||||
new Vector(
|
|
||||||
playerPosition?.X ?? 0,
|
|
||||||
playerPosition?.Y ?? 0,
|
|
||||||
playerPosition?.Z ?? 0
|
|
||||||
),
|
|
||||||
new QAngle(
|
|
||||||
playerRotation?.X ?? 0,
|
|
||||||
playerRotation?.Y ?? 0,
|
|
||||||
playerRotation?.Z ?? 0
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEventHandler(HookMode.Pre)]
|
|
||||||
public HookResult OnPlayerTeam(EventPlayerTeam @event, GameEventInfo info)
|
|
||||||
{
|
|
||||||
var player = @event.Userid;
|
|
||||||
|
|
||||||
if (player == null || !player.IsValid || player.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (!SilentPlayers.Contains(player.Slot))
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
info.DontBroadcast = true;
|
|
||||||
|
|
||||||
if (@event.Team > 1)
|
|
||||||
SilentPlayers.Remove(player.Slot);
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GameEventHandler]
|
|
||||||
public HookResult OnPlayerInfo(EventPlayerInfo @event, GameEventInfo _)
|
|
||||||
{
|
|
||||||
var player = @event.Userid;
|
|
||||||
|
|
||||||
if (player is null || !player.IsValid || player.IsBot)
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
if (!RenamedPlayers.TryGetValue(player.SteamID, out var name)) return HookResult.Continue;
|
|
||||||
|
|
||||||
if (player.PlayerName.Equals(name))
|
|
||||||
return HookResult.Continue;
|
|
||||||
|
|
||||||
player.Rename(name);
|
|
||||||
|
|
||||||
return HookResult.Continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,257 +0,0 @@
|
|||||||
using CounterStrikeSharp.API;
|
|
||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Core.Translations;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
|
||||||
using CounterStrikeSharp.API.Modules.Memory;
|
|
||||||
using Microsoft.Extensions.Localization;
|
|
||||||
using System.Text;
|
|
||||||
using CounterStrikeSharp.API.Modules.UserMessages;
|
|
||||||
using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
public static class PlayerExtensions
|
|
||||||
{
|
|
||||||
public static void Slap(this CBasePlayerPawn pawn, int damage = 0)
|
|
||||||
{
|
|
||||||
PerformSlap(pawn, damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Print(this CCSPlayerController controller, string message = "")
|
|
||||||
{
|
|
||||||
StringBuilder _message = new(CS2_SimpleAdmin._localizer!["sa_prefix"]);
|
|
||||||
_message.Append(message);
|
|
||||||
controller.PrintToChat(_message.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanTarget(this CCSPlayerController? controller, CCSPlayerController? target)
|
|
||||||
{
|
|
||||||
if (controller is null || target is null) return true;
|
|
||||||
if (target.IsBot) return true;
|
|
||||||
|
|
||||||
return AdminManager.CanPlayerTarget(controller, target) ||
|
|
||||||
AdminManager.CanPlayerTarget(new SteamID(controller.SteamID),
|
|
||||||
new SteamID(target.SteamID)) ||
|
|
||||||
AdminManager.GetPlayerImmunity(controller) >= AdminManager.GetPlayerImmunity(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanTarget(this CCSPlayerController? controller, SteamID steamId)
|
|
||||||
{
|
|
||||||
if (controller is null) return true;
|
|
||||||
|
|
||||||
return AdminManager.CanPlayerTarget(new SteamID(controller.SteamID), steamId) ||
|
|
||||||
AdminManager.GetPlayerImmunity(controller) >= AdminManager.GetPlayerImmunity(steamId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetSpeed(this CCSPlayerController? controller, float speed)
|
|
||||||
{
|
|
||||||
var playerPawnValue = controller?.PlayerPawn.Value;
|
|
||||||
if (playerPawnValue == null) return;
|
|
||||||
|
|
||||||
playerPawnValue.VelocityModifier = speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetGravity(this CCSPlayerController? controller, float gravity)
|
|
||||||
{
|
|
||||||
var playerPawnValue = controller?.PlayerPawn.Value;
|
|
||||||
if (playerPawnValue == null) return;
|
|
||||||
|
|
||||||
playerPawnValue.GravityScale = gravity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetMoney(this CCSPlayerController? controller, int money)
|
|
||||||
{
|
|
||||||
var moneyServices = controller?.InGameMoneyServices;
|
|
||||||
if (moneyServices == null) return;
|
|
||||||
|
|
||||||
moneyServices.Account = money;
|
|
||||||
|
|
||||||
if (controller != null) Utilities.SetStateChanged(controller, "CCSPlayerController", "m_pInGameMoneyServices");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetHp(this CCSPlayerController? controller, int health = 100)
|
|
||||||
{
|
|
||||||
if (controller == null) return;
|
|
||||||
if (health <= 0 || controller.PlayerPawn.Value == null || controller.PlayerPawn?.Value?.LifeState != (int)LifeState_t.LIFE_ALIVE) return;
|
|
||||||
|
|
||||||
controller.PlayerPawn.Value.Health = health;
|
|
||||||
|
|
||||||
if (health > 100)
|
|
||||||
{
|
|
||||||
controller.PlayerPawn.Value.MaxHealth = health;
|
|
||||||
}
|
|
||||||
|
|
||||||
Utilities.SetStateChanged(controller.PlayerPawn.Value, "CBaseEntity", "m_iHealth");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Bury(this CBasePlayerPawn pawn, float depth = 10f)
|
|
||||||
{
|
|
||||||
var newPos = new Vector(pawn.AbsOrigin!.X, pawn.AbsOrigin.Y,
|
|
||||||
pawn.AbsOrigin!.Z - depth);
|
|
||||||
|
|
||||||
pawn.Teleport(newPos, pawn.AbsRotation!, pawn.AbsVelocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Unbury(this CBasePlayerPawn pawn, float depth = 15f)
|
|
||||||
{
|
|
||||||
var newPos = new Vector(pawn.AbsOrigin!.X, pawn.AbsOrigin.Y,
|
|
||||||
pawn.AbsOrigin!.Z + depth);
|
|
||||||
|
|
||||||
pawn.Teleport(newPos, pawn.AbsRotation!, pawn.AbsVelocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Freeze(this CBasePlayerPawn pawn)
|
|
||||||
{
|
|
||||||
pawn.MoveType = MoveType_t.MOVETYPE_INVALID;
|
|
||||||
Schema.SetSchemaValue(pawn.Handle, "CBaseEntity", "m_nActualMoveType", 11); // invalid
|
|
||||||
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_MoveType");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Unfreeze(this CBasePlayerPawn pawn)
|
|
||||||
{
|
|
||||||
pawn.MoveType = MoveType_t.MOVETYPE_WALK;
|
|
||||||
Schema.SetSchemaValue(pawn.Handle, "CBaseEntity", "m_nActualMoveType", 2); // walk
|
|
||||||
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_MoveType");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ToggleNoclip(this CBasePlayerPawn pawn)
|
|
||||||
{
|
|
||||||
if (pawn.MoveType == MoveType_t.MOVETYPE_NOCLIP)
|
|
||||||
{
|
|
||||||
pawn.MoveType = MoveType_t.MOVETYPE_WALK;
|
|
||||||
Schema.SetSchemaValue(pawn.Handle, "CBaseEntity", "m_nActualMoveType", 2); // walk
|
|
||||||
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_MoveType");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pawn.MoveType = MoveType_t.MOVETYPE_NOCLIP;
|
|
||||||
Schema.SetSchemaValue(pawn.Handle, "CBaseEntity", "m_nActualMoveType", 8); // noclip
|
|
||||||
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_MoveType");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Rename(this CCSPlayerController? controller, string newName = "Unknown")
|
|
||||||
{
|
|
||||||
newName ??= CS2_SimpleAdmin._localizer?["sa_unknown"] ?? "Unknown";
|
|
||||||
|
|
||||||
if (controller != null)
|
|
||||||
{
|
|
||||||
var playerName = new SchemaString<CBasePlayerController>(controller, "m_iszPlayerName");
|
|
||||||
playerName.Set(newName + " ");
|
|
||||||
|
|
||||||
CS2_SimpleAdmin.Instance.AddTimer(0.25f, () =>
|
|
||||||
{
|
|
||||||
Utilities.SetStateChanged(controller, "CCSPlayerController", "m_szClan");
|
|
||||||
Utilities.SetStateChanged(controller, "CBasePlayerController", "m_iszPlayerName");
|
|
||||||
});
|
|
||||||
|
|
||||||
CS2_SimpleAdmin.Instance.AddTimer(0.3f, () =>
|
|
||||||
{
|
|
||||||
playerName.Set(newName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CS2_SimpleAdmin.Instance.AddTimer(0.4f, () =>
|
|
||||||
{
|
|
||||||
if (controller != null) Utilities.SetStateChanged(controller, "CBasePlayerController", "m_iszPlayerName");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void TeleportPlayer(this CCSPlayerController? controller, CCSPlayerController? target)
|
|
||||||
{
|
|
||||||
if (controller?.PlayerPawn.Value == null && target?.PlayerPawn.Value == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (
|
|
||||||
controller?.PlayerPawn.Value is { AbsOrigin: not null, AbsRotation: not null } &&
|
|
||||||
target?.PlayerPawn.Value is { AbsOrigin: not null, AbsRotation: not null }
|
|
||||||
)
|
|
||||||
{
|
|
||||||
controller.PlayerPawn.Value.Teleport(
|
|
||||||
target.PlayerPawn.Value.AbsOrigin,
|
|
||||||
target.PlayerPawn.Value.AbsRotation,
|
|
||||||
target.PlayerPawn.Value.AbsVelocity
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PerformSlap(CBasePlayerPawn pawn, int damage = 0)
|
|
||||||
{
|
|
||||||
if (pawn.LifeState != (int)LifeState_t.LIFE_ALIVE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var controller = pawn.Controller.Value?.As<CCSPlayerController>();
|
|
||||||
|
|
||||||
/* Teleport in a random direction - thank you, Mani!*/
|
|
||||||
/* Thank you AM & al!*/
|
|
||||||
var random = new Random();
|
|
||||||
var vel = new Vector(pawn.AbsVelocity.X, pawn.AbsVelocity.Y, pawn.AbsVelocity.Z);
|
|
||||||
|
|
||||||
vel.X += (random.Next(180) + 50) * (random.Next(2) == 1 ? -1 : 1);
|
|
||||||
vel.Y += (random.Next(180) + 50) * (random.Next(2) == 1 ? -1 : 1);
|
|
||||||
vel.Z += random.Next(200) + 100;
|
|
||||||
|
|
||||||
pawn.AbsVelocity.X = vel.X;
|
|
||||||
pawn.AbsVelocity.Y = vel.Y;
|
|
||||||
pawn.AbsVelocity.Z = vel.Z;
|
|
||||||
|
|
||||||
if (controller != null && controller.IsValid)
|
|
||||||
{
|
|
||||||
var shakeMessage = UserMessage.FromPartialName("Shake");
|
|
||||||
shakeMessage.SetFloat("duration", 1);
|
|
||||||
shakeMessage.SetFloat("amplitude", 10);
|
|
||||||
shakeMessage.SetFloat("frequency", 1f);
|
|
||||||
shakeMessage.SetInt("command", 0);
|
|
||||||
shakeMessage.Recipients.Add(controller);
|
|
||||||
shakeMessage.Send();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (damage <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pawn.Health -= damage;
|
|
||||||
Utilities.SetStateChanged(pawn, "CBaseEntity", "m_iHealth");
|
|
||||||
|
|
||||||
if (pawn.Health <= 0)
|
|
||||||
pawn.CommitSuicide(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SendLocalizedMessage(this CCSPlayerController? controller, IStringLocalizer? localizer,
|
|
||||||
string messageKey, params object[] messageArgs)
|
|
||||||
{
|
|
||||||
if (controller == null || localizer == null) return;
|
|
||||||
|
|
||||||
using (new WithTemporaryCulture(controller.GetLanguage()))
|
|
||||||
{
|
|
||||||
StringBuilder sb = new();
|
|
||||||
sb.Append(localizer[messageKey, messageArgs]);
|
|
||||||
|
|
||||||
foreach (var part in Helper.SeparateLines(sb.ToString()))
|
|
||||||
{
|
|
||||||
var lineWithPrefix = localizer["sa_prefix"] + part.Trim();
|
|
||||||
controller.PrintToChat(lineWithPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SendLocalizedMessageCenter(this CCSPlayerController? controller, IStringLocalizer? localizer,
|
|
||||||
string messageKey, params object[] messageArgs)
|
|
||||||
{
|
|
||||||
if (controller == null || localizer == null) return;
|
|
||||||
|
|
||||||
using (new WithTemporaryCulture(controller.GetLanguage()))
|
|
||||||
{
|
|
||||||
StringBuilder sb = new();
|
|
||||||
sb.Append(localizer[messageKey, messageArgs]);
|
|
||||||
|
|
||||||
foreach (var part in Helper.SeparateLines(sb.ToString()))
|
|
||||||
{
|
|
||||||
string _part;
|
|
||||||
_part = Helper.CenterMessage(part);
|
|
||||||
var lineWithPrefix = localizer["sa_prefix"] + _part;
|
|
||||||
controller.PrintToChat(lineWithPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,975 +0,0 @@
|
|||||||
using CounterStrikeSharp.API;
|
|
||||||
using CounterStrikeSharp.API.Core;
|
|
||||||
using CounterStrikeSharp.API.Core.Translations;
|
|
||||||
using CounterStrikeSharp.API.Modules.Admin;
|
|
||||||
using CounterStrikeSharp.API.Modules.Commands;
|
|
||||||
using CounterStrikeSharp.API.Modules.Cvars;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities;
|
|
||||||
using CounterStrikeSharp.API.Modules.Memory;
|
|
||||||
using CounterStrikeSharp.API.Modules.Menu;
|
|
||||||
using CounterStrikeSharp.API.ValveConstants.Protobuf;
|
|
||||||
using CS2_SimpleAdminApi;
|
|
||||||
using Microsoft.Extensions.Localization;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using CounterStrikeSharp.API.Core.Plugin.Host;
|
|
||||||
using CounterStrikeSharp.API.Modules.Entities.Constants;
|
|
||||||
using CS2_SimpleAdmin.Managers;
|
|
||||||
using MenuManager;
|
|
||||||
|
|
||||||
namespace CS2_SimpleAdmin;
|
|
||||||
|
|
||||||
internal static class Helper
|
|
||||||
{
|
|
||||||
private static readonly string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? "";
|
|
||||||
private static readonly string CfgPath = $"{Server.GameDirectory}/csgo/addons/counterstrikesharp/configs/plugins/{AssemblyName}/{AssemblyName}.json";
|
|
||||||
|
|
||||||
private delegate nint CNetworkSystemUpdatePublicIp(nint a1);
|
|
||||||
|
|
||||||
private static CNetworkSystemUpdatePublicIp? _networkSystemUpdatePublicIp;
|
|
||||||
|
|
||||||
public static bool IsDebugBuild
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List< | |||||||