Files
CounterStrikeSharp/managed/CounterStrikeSharp.API/Modules/Admin/AdminGroup.cs
2024-01-21 12:01:27 +10:00

222 lines
9.0 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Entities;
using CounterStrikeSharp.API.Modules.Utils;
namespace CounterStrikeSharp.API.Modules.Admin
{
public partial class AdminData
{
[JsonPropertyName("groups")] public HashSet<string> Groups { get; init; } = new();
}
public partial class AdminGroupData
{
[JsonPropertyName("flags")] public required HashSet<string> Flags { get; init; }
[JsonPropertyName("immunity")] public uint Immunity { get; set; } = 0;
[JsonPropertyName("command_overrides")] public Dictionary<string, bool> CommandOverrides { get; init; } = new();
}
public static partial class AdminManager
{
private static Dictionary<string, AdminGroupData> Groups = new();
public static void LoadAdminGroups(string adminGroupsPath)
{
try
{
if (!File.Exists(adminGroupsPath))
{
Console.WriteLine("Admin groups file not found. Skipping admin groups load.");
return;
}
var groupsFromFile = JsonSerializer.Deserialize<Dictionary<string, AdminGroupData>>(File.ReadAllText(adminGroupsPath), new JsonSerializerOptions() { ReadCommentHandling = JsonCommentHandling.Skip });
if (groupsFromFile == null) { throw new FileNotFoundException(); }
foreach (var (key, groupDef) in groupsFromFile)
{
if (Groups.ContainsKey(key))
{
Groups[key].Flags.UnionWith(groupDef.Flags);
if (groupDef.Immunity > Groups[key].Immunity)
{
Groups[key].Immunity = groupDef.Immunity;
}
}
else
{
Groups.Add(key, groupDef);
}
}
Console.WriteLine($"Loaded {Groups.Count} admin groups.");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to load admin groups: {ex}");
}
// Loop over each of the admins. If one of our admins is in a group,
// add the flags from the group to their admin definition and change
// the admin's immunity if it's higher.
foreach (var (admin, data) in Admins)
{
var groups = data.Groups;
foreach (var group in groups)
{
// roflmuffin is probably smart enough to condense this function down ;)
if (Groups.TryGetValue(group, out var groupData))
{
AddPlayerPermissions(admin, groupData.Flags.ToArray());
if (groupData.Immunity > data.Immunity)
{
data.Immunity = groupData.Immunity;
}
}
}
}
}
/// <summary>
/// Checks to see if the player is part of an admin group.
/// </summary>
/// <param name="player">Player controller.</param>
/// <param name="groups">Groups to check for.</param>
/// <returns>True if a player is part of all of the groups provided, false if not.</returns>
public static bool PlayerInGroup(CCSPlayerController? player, params string[] groups)
{
// This is here for cases where the server console is attempting to call commands.
// The server console should have access to all commands, regardless of groups.
if (player == null) return true;
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return false; }
var playerData = GetPlayerAdminData(player.AuthorizedSteamID);
if (playerData == null) return false;
var playerGroups = groups.ToHashSet();
foreach (var domain in playerData.Flags)
{
if (playerData.DomainHasRootFlag(domain.Key))
{
playerGroups.ExceptWith(groups.Where(group => group.Contains(domain.Key + '/')));
}
}
return playerData.Groups.IsSupersetOf(playerGroups);
}
/// <summary>
/// Checks to see if the player is part of an admin group.
/// </summary>
/// <param name="steamId">SteamID of the player.</param>
/// <param name="groups">Groups to check for.</param>
/// <returns>True if a player is part of all of the groups provided, false if not.</returns>
public static bool PlayerInGroup(SteamID? steamId, params string[] groups)
{
if (steamId == null) return false;
var playerData = GetPlayerAdminData(steamId);
if (playerData == null) return false;
var playerGroups = groups.ToHashSet<string>();
foreach (var domain in playerData.Flags)
{
if (playerData.DomainHasRootFlag(domain.Key))
{
playerGroups.ExceptWith(groups.Where(group => group.Contains(domain.Key + '/')));
}
}
return playerData.Groups.IsSupersetOf(playerGroups);
}
/// <summary>
/// Adds a player to a group. This does NOT modify the immunity of the player (see SetPlayerImmunity).
/// </summary>
/// <param name="player">Player controller.</param>
/// <param name="groups">Groups to add the player to.</param>
public static void AddPlayerToGroup(CCSPlayerController? player, params string[] groups)
{
if (player == null) return;
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return; }
AddPlayerToGroup(player.AuthorizedSteamID, groups);
}
/// <summary>
/// Adds a player to a group. This does NOT modify the immunity of the player (see SetPlayerImmunity).
/// </summary>
/// <param name="steamId">SteamID of the player.</param>
/// <param name="groups">Groups to add the player to.</param>
public static void AddPlayerToGroup(SteamID? steamId, params string[] groups)
{
if (steamId == null) return;
var data = GetPlayerAdminData(steamId);
if (data == null)
{
data = new AdminData()
{
Identity = steamId.SteamId64.ToString(),
Flags = new(),
Groups = new(groups)
};
}
foreach (var group in groups)
{
if (Groups.TryGetValue(group, out var groupDef))
{
AddPlayerPermissions(steamId, groupDef.Flags.ToArray());
groupDef.CommandOverrides.ToList().ForEach(x => data.CommandOverrides[x.Key] = x.Value);
}
}
Admins[steamId] = data;
}
/// <summary>
/// Removes a player from a group.
/// </summary>
/// <param name="player">Player controller.</param>
/// <param name="removeInheritedFlags">If true, all of the flags that the player inherited from being in the group will be removed.</param>
/// <param name="groups"></param>
public static void RemovePlayerFromGroup(CCSPlayerController? player, bool removeInheritedFlags = true, params string[] groups)
{
if (player == null) return;
if (!player.IsValid || player.Connected != PlayerConnectedState.PlayerConnected || player.IsBot || player.IsHLTV) { return; }
RemovePlayerFromGroup(player.AuthorizedSteamID, true, groups);
}
/// <summary>
/// Removes a player from a group.
/// </summary>
/// <param name="steamId">SteamID of the player.</param>
/// <param name="removeInheritedFlags">If true, all of the flags that the player inherited from being in the group will be removed.</param>
/// <param name="groups"></param>
public static void RemovePlayerFromGroup(SteamID? steamId, bool removeInheritedFlags = true, params string[] groups)
{
if (steamId == null) return;
var data = GetPlayerAdminData(steamId);
if (data == null) return;
data.Groups.ExceptWith(groups);
if (removeInheritedFlags)
{
foreach (var group in groups)
{
if (Groups.TryGetValue(group, out var groupDef))
{
RemovePlayerPermissions(steamId, groupDef.Flags.ToArray());
}
}
}
Admins[steamId] = data;
}
}
}