mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-02-17 18:39:07 +00:00
Refactor database layer and add module/plugin improvements
Reworked the database layer to support both MySQL and SQLite via new provider classes and migration scripts for each backend. Updated the build workflow to support building and packaging additional modules, including StealthModule and BanSoundModule, and improved artifact handling. Refactored command registration to allow dynamic registration/unregistration and improved API event handling. Updated dependencies, project structure, and configuration checks for better reliability and extensibility. Added new language files, updated versioning, and removed obsolete files.
**⚠️ Warning: SQLite support is currently experimental.
Using this version requires reconfiguration of your database settings!
Plugin now uses UTC time. Please adjust your configurations accordingly!
**
This commit is contained in:
BIN
Modules/CS2-SimpleAdmin_StealthModule/CS2-SimpleAdminApi.dll
Normal file
BIN
Modules/CS2-SimpleAdmin_StealthModule/CS2-SimpleAdminApi.dll
Normal file
Binary file not shown.
@@ -0,0 +1,219 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||
using CounterStrikeSharp.API.Core.Capabilities;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using CS2_SimpleAdminApi;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CS2_SimpleAdmin_StealthModule;
|
||||
|
||||
public class CS2_SimpleAdmin_StealthModule: BasePlugin, IPluginConfig<PluginConfig>
|
||||
{
|
||||
public override string ModuleName => "[CS2-SimpleAdmin] Stealth Module";
|
||||
public override string ModuleVersion => "v1.0.2";
|
||||
public override string ModuleAuthor => "daffyy";
|
||||
|
||||
private static ICS2_SimpleAdminApi? _sharedApi;
|
||||
private readonly PluginCapability<ICS2_SimpleAdminApi> _pluginCapability = new("simpleadmin:api");
|
||||
|
||||
internal static readonly HashSet<CCSPlayerController> Players = [];
|
||||
// private readonly HashSet<int> _admins = [];
|
||||
// private readonly HashSet<CCSPlayerController> _spectatedPlayers = [];
|
||||
|
||||
public PluginConfig Config { get; set; }
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
RegisterListener<Listeners.CheckTransmit>(OnCheckTransmit);
|
||||
|
||||
// Old method
|
||||
// if (Config.BlockStatusCommand)
|
||||
// RegisterListener<Listeners.OnServerPostEntityThink>(OnServerPostEntityThink);
|
||||
|
||||
if (hotReload)
|
||||
{
|
||||
Players.Clear();
|
||||
var players = Utilities.GetPlayers().Where(p => p.IsValid && !p.IsBot).ToList();
|
||||
|
||||
foreach (var player in players)
|
||||
{
|
||||
var steamId = new SteamID(player.SteamID);
|
||||
// if (Config.Permissions.Any(permission => AdminManager.PlayerHasPermissions(steamId, permission)))
|
||||
// _admins.Add(player.Slot);
|
||||
|
||||
Players.Add(player);
|
||||
}
|
||||
}
|
||||
|
||||
// Old method
|
||||
// AddTimer(3, RefreshSpectatedPlayers, TimerFlags.REPEAT);
|
||||
}
|
||||
|
||||
// Old method
|
||||
// private void RefreshSpectatedPlayers()
|
||||
// {
|
||||
// _spectatedPlayers.Clear();
|
||||
//
|
||||
// foreach (var admin in _admins)
|
||||
// {
|
||||
// var observer = admin.GetSpectatingPlayer();
|
||||
// if (observer != null)
|
||||
// _spectatedPlayers.Add(observer);
|
||||
// }
|
||||
// }
|
||||
|
||||
public void OnConfigParsed(PluginConfig config)
|
||||
{
|
||||
Config = config;
|
||||
}
|
||||
|
||||
public override void OnAllPluginsLoaded(bool hotReload)
|
||||
{
|
||||
try
|
||||
{
|
||||
_sharedApi = _pluginCapability.Get();
|
||||
if (_sharedApi == null) throw new NullReferenceException("_sharedApi is null");
|
||||
|
||||
if (Config.BlockStatusCommand)
|
||||
_sharedApi.OnAdminToggleSilent += OnAdminToggleSilent;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Logger.LogError("CS2-SimpleAdmin SharedApi not found");
|
||||
Unload(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAdminToggleSilent(int slot, bool status)
|
||||
{
|
||||
Server.ExecuteCommand(status ? $"mm_excludeslot {slot}" : $"mm_removeexcludeslot {slot}");
|
||||
}
|
||||
|
||||
// Old method
|
||||
// private void OnServerPostEntityThink()
|
||||
// {
|
||||
// if (Players.Count <= 2 || _sharedApi is not null && _sharedApi.ListSilentAdminsSlots().Count == 0) return;
|
||||
// foreach (var player in _spectatedPlayers)
|
||||
// {
|
||||
// if (player?.IsValid != true || player.IsBot) continue;
|
||||
// player.PrintToConsole(" ");
|
||||
// }
|
||||
// }
|
||||
|
||||
private void OnCheckTransmit(CCheckTransmitInfoList infolist)
|
||||
{
|
||||
if (Players.Count <= 2 || _sharedApi is not null && _sharedApi.ListSilentAdminsSlots().Count == 0) return;
|
||||
|
||||
var validObserverPawns = Players
|
||||
.Select(p => new { p.Slot, ObserverPawn = p.ObserverPawn.Value })
|
||||
.Where(p => p.ObserverPawn?.IsValid == true) // safe check
|
||||
.ToArray();
|
||||
|
||||
foreach (var (info, player) in infolist)
|
||||
{
|
||||
if (player == null || player.IsHLTV)
|
||||
continue;
|
||||
|
||||
var entities = info.TransmitEntities;
|
||||
foreach (var target in validObserverPawns)
|
||||
{
|
||||
if (target.Slot == player.Slot)
|
||||
continue;
|
||||
|
||||
var observer = target.ObserverPawn;
|
||||
if (observer == null) continue; // extra safety
|
||||
|
||||
if (entities.Contains((int)observer.Index))
|
||||
entities.Remove((int)observer.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult EventPlayerTeam(EventPlayerTeam @event, GameEventInfo info)
|
||||
{
|
||||
if (ShouldSuppressBroadcast(@event.Userid))
|
||||
info.DontBroadcast = true;
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult EventPlayerConnectFull(EventPlayerConnectFull @event, GameEventInfo info)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player?.IsValid != true || player.IsBot) return HookResult.Continue;
|
||||
|
||||
Players.Add(player);
|
||||
|
||||
var steamId = new SteamID(player.SteamID);
|
||||
if (!Config.Permissions.Any(permission => AdminManager.PlayerHasPermissions(steamId, permission)))
|
||||
return HookResult.Continue;
|
||||
|
||||
// _admins.Add(player.Slot);
|
||||
|
||||
if (!Config.HideAdminsOnJoin) return HookResult.Continue;
|
||||
|
||||
AddTimer(0.75f, () =>
|
||||
{
|
||||
player.ChangeTeam(CsTeam.Spectator);
|
||||
});
|
||||
|
||||
AddTimer(1.25f, () =>
|
||||
{
|
||||
player.ExecuteClientCommandFromServer("css_hide");
|
||||
});
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult EventPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo info)
|
||||
{
|
||||
var player = @event.Userid;
|
||||
if (player?.IsValid != true || player.IsBot) return HookResult.Continue;
|
||||
|
||||
if (Config.BlockStatusCommand && _sharedApi != null && _sharedApi.IsAdminSilent(player))
|
||||
Server.ExecuteCommand($"mm_removeexcludeslot {player.Slot}");
|
||||
|
||||
Players.Remove(player);
|
||||
// _admins.Remove(player.Slot);
|
||||
|
||||
if (ShouldSuppressBroadcast(@event.Userid))
|
||||
info.DontBroadcast = true;
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult EventPlayerDeath(EventPlayerDeath @event, GameEventInfo info)
|
||||
{
|
||||
if (ShouldSuppressBroadcast(@event.Userid, true))
|
||||
info.DontBroadcast = true;
|
||||
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
private bool ShouldSuppressBroadcast(CCSPlayerController? player, bool checkTeam = false)
|
||||
{
|
||||
if (player?.IsValid != true || player.IsBot)
|
||||
return false;
|
||||
|
||||
if (_sharedApi is not null && _sharedApi.IsAdminSilent(player))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (checkTeam && player.TeamNum > 1)
|
||||
return false;
|
||||
|
||||
var steamId = new SteamID(player.SteamID);
|
||||
return Config.Permissions.Any(permission => AdminManager.PlayerHasPermissions(steamId, permission));
|
||||
}
|
||||
|
||||
// private IEnumerable<CCSPlayerController> GetNonAdmins()
|
||||
// => Players.Where(p => !_admins.Contains(p));
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>CS2_SimpleAdmin_ExampleModule</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.340" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="CS2-SimpleAdminApi">
|
||||
<HintPath>CS2-SimpleAdminApi.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS2-SimpleAdmin_StealthModule", "CS2-SimpleAdmin_StealthModule.csproj", "{25E0ED51-29BB-4FDD-B40A-62F894A56815}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{25E0ED51-29BB-4FDD-B40A-62F894A56815}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{25E0ED51-29BB-4FDD-B40A-62F894A56815}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{25E0ED51-29BB-4FDD-B40A-62F894A56815}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{25E0ED51-29BB-4FDD-B40A-62F894A56815}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
31
Modules/CS2-SimpleAdmin_StealthModule/Extensions.cs
Normal file
31
Modules/CS2-SimpleAdmin_StealthModule/Extensions.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
|
||||
namespace CS2_SimpleAdmin_StealthModule;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static CCSPlayerController? GetSpectatingPlayer(this CCSPlayerController player)
|
||||
{
|
||||
if (player.Pawn.Value is not { IsValid: true } pawn)
|
||||
return null;
|
||||
|
||||
if (player.ControllingBot)
|
||||
return null;
|
||||
|
||||
if (pawn.ObserverServices is not { } observerServices)
|
||||
return null;
|
||||
|
||||
if (observerServices.ObserverTarget?.Value?.As<CCSPlayerPawn>() is not { IsValid: true } observerPawn)
|
||||
return null;
|
||||
|
||||
return observerPawn.OriginalController.Value is not { IsValid: true } observerController ? null : observerController;
|
||||
}
|
||||
|
||||
public static List<CCSPlayerController> GetSpectators(this CCSPlayerController player)
|
||||
{
|
||||
return CS2_SimpleAdmin_StealthModule.Players
|
||||
.Where(p => p.GetSpectatingPlayer()?.Slot == player.Slot)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
11
Modules/CS2-SimpleAdmin_StealthModule/PluginConfig.cs
Normal file
11
Modules/CS2-SimpleAdmin_StealthModule/PluginConfig.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using CounterStrikeSharp.API.Core;
|
||||
|
||||
namespace CS2_SimpleAdmin_StealthModule;
|
||||
|
||||
public class PluginConfig : IBasePluginConfig
|
||||
{
|
||||
public int Version { get; set; } = 1;
|
||||
public List<string> Permissions { get; set; } = ["@css/ban"];
|
||||
public bool BlockStatusCommand { get; set; } = true;
|
||||
public bool HideAdminsOnJoin { get; set; } = true;
|
||||
}
|
||||
Reference in New Issue
Block a user