mirror of
https://github.com/daffyyyy/CS2-SimpleAdmin.git
synced 2026-11-07 12:07:05 +01:00
Replace MenuManagerCS2 with Panorama UI Kit for the admin menus and css_vote. Layout names (menu, vote, banner, toast) are configurable under MenuConfig and preloaded on startup; MenuType is removed and ConfigVersion bumped to 26. - Drop MenuManagerApi.dll and the old chat menu classes - Reference PanoramaUiKit.Shared.dll, bump CounterStrikeSharp to 1.0.376 - Add .editorconfig and CODING_CONVENTIONS.md, apply them codebase-wide - Remove the CS2-SimpleAdmin-docs site - Rewrite README for the fork
422 lines
16 KiB
C#
422 lines
16 KiB
C#
using CounterStrikeSharp.API.Core;
|
|
using CounterStrikeSharp.API.Core.Commands;
|
|
using CounterStrikeSharp.API.Core.Translations;
|
|
using CounterStrikeSharp.API.Modules.Commands;
|
|
using CounterStrikeSharp.API.Modules.Commands.Targeting;
|
|
using CounterStrikeSharp.API.Modules.Entities;
|
|
using CS2_SimpleAdmin.Managers;
|
|
using CS2_SimpleAdmin.Menus;
|
|
using CS2_SimpleAdminApi;
|
|
using Microsoft.Extensions.Localization;
|
|
|
|
namespace CS2_SimpleAdmin.Api;
|
|
|
|
public class CS2_SimpleAdminApi : ICS2_SimpleAdminApi
|
|
{
|
|
public event Action? OnSimpleAdminReady;
|
|
public void OnSimpleAdminReadyEvent() => OnSimpleAdminReady?.Invoke();
|
|
|
|
public PlayerInfo GetPlayerInfo(CCSPlayerController player)
|
|
{
|
|
if (!player.UserId.HasValue)
|
|
{
|
|
throw new KeyNotFoundException("Player with specific UserId not found");
|
|
}
|
|
|
|
return CS2_SimpleAdmin.PlayersInfo[player.SteamID];
|
|
}
|
|
|
|
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 event Action<int, bool>? OnAdminToggleSilent;
|
|
|
|
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 OnAdminToggleSilentEvent(int slot, bool status) => OnAdminToggleSilent?.Invoke(slot, status);
|
|
|
|
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 HashSet<int> ListSilentAdminsSlots()
|
|
{
|
|
return CS2_SimpleAdmin.SilentPlayers;
|
|
}
|
|
|
|
public void RegisterCommand(string name, string? description, CommandInfo.CommandCallback callback)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
{
|
|
throw new ArgumentException("Command name cannot be null or empty.", nameof(name));
|
|
}
|
|
|
|
ArgumentNullException.ThrowIfNull(callback);
|
|
|
|
CommandDefinition definition = new CommandDefinition(name, description ?? "No description", callback);
|
|
if (!RegisterCommands._commandDefinitions.TryGetValue(name, out IList<CommandDefinition>? list))
|
|
{
|
|
list = new List<CommandDefinition>();
|
|
RegisterCommands._commandDefinitions[name] = list;
|
|
}
|
|
|
|
list.Add(definition);
|
|
}
|
|
|
|
public void UnRegisterCommand(string commandName)
|
|
{
|
|
IList<CommandDefinition> definitions = RegisterCommands._commandDefinitions[commandName];
|
|
if (definitions.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (CommandDefinition definition in definitions)
|
|
{
|
|
CS2_SimpleAdmin.Instance.RemoveCommand(commandName, definition.Callback);
|
|
}
|
|
}
|
|
|
|
public TargetResult? GetTarget(CommandInfo command)
|
|
{
|
|
return CS2_SimpleAdmin.GetTarget(command);
|
|
}
|
|
|
|
public void ShowAdminActivity(string messageKey, string? callerName = null, bool dontPublish = false,
|
|
params object[] messageArgs)
|
|
{
|
|
Helper.ShowAdminActivity(messageKey, callerName, dontPublish, messageArgs);
|
|
}
|
|
|
|
public void ShowAdminActivityTranslated(string translatedMessage, string? callerName = null,
|
|
bool dontPublish = false)
|
|
{
|
|
Helper.ShowAdminActivityTranslated(translatedMessage, callerName, dontPublish);
|
|
}
|
|
|
|
public void ShowAdminActivityLocalized(object moduleLocalizer, string messageKey, string? callerName = null,
|
|
bool dontPublish = false, params object[] messageArgs)
|
|
{
|
|
if (moduleLocalizer is not IStringLocalizer localizer)
|
|
{
|
|
throw new InvalidOperationException("moduleLocalizer must be an IStringLocalizer instance");
|
|
}
|
|
|
|
Helper.ShowAdminActivityLocalized(localizer, messageKey, callerName, dontPublish, messageArgs);
|
|
}
|
|
|
|
public void RegisterMenuCategory(string categoryId, string categoryName, string permission = "@css/generic")
|
|
{
|
|
Menus.MenuManager.Instance.RegisterCategory(categoryId, categoryName, permission);
|
|
}
|
|
|
|
public void RegisterMenuCategory(string categoryId, string categoryNameKey, string permission, object moduleLocalizer)
|
|
{
|
|
if (moduleLocalizer is not IStringLocalizer localizer)
|
|
{
|
|
throw new InvalidOperationException("moduleLocalizer must be an IStringLocalizer instance");
|
|
}
|
|
|
|
Menus.MenuManager.Instance.RegisterCategory(categoryId, categoryNameKey, permission, localizer);
|
|
}
|
|
|
|
public void RegisterMenu(string categoryId, string menuId, string menuName,
|
|
Func<CCSPlayerController, object> menuFactory, string? permission = null, string? commandName = null)
|
|
{
|
|
Menus.MenuManager.Instance.RegisterMenu(categoryId, menuId, menuName, BuilderFactory, permission, commandName);
|
|
return;
|
|
|
|
MenuBuilder BuilderFactory(CCSPlayerController player)
|
|
{
|
|
if (menuFactory(player) is not MenuBuilder menuBuilder)
|
|
{
|
|
throw new InvalidOperationException("Menu factory must return MenuBuilder");
|
|
}
|
|
|
|
return menuBuilder.WithBackButton();
|
|
}
|
|
}
|
|
|
|
public void RegisterMenu(string categoryId, string menuId, string menuName,
|
|
Func<CCSPlayerController, MenuContext, object> menuFactory, string? permission = null, string? commandName = null)
|
|
{
|
|
Menus.MenuManager.Instance.RegisterMenu(categoryId, menuId, menuName, BuilderFactory, permission, commandName);
|
|
return;
|
|
|
|
MenuBuilder BuilderFactory(CCSPlayerController player)
|
|
{
|
|
MenuContext context = new MenuContext(categoryId, menuId, menuName, permission, commandName);
|
|
|
|
if (menuFactory(player, context) is not MenuBuilder menuBuilder)
|
|
{
|
|
throw new InvalidOperationException("Menu factory must return MenuBuilder");
|
|
}
|
|
|
|
return menuBuilder.WithBackButton();
|
|
}
|
|
}
|
|
|
|
public void RegisterMenu(string categoryId, string menuId, string menuNameKey,
|
|
Func<CCSPlayerController, MenuContext, object> menuFactory, string? permission, string? commandName, object moduleLocalizer)
|
|
{
|
|
if (moduleLocalizer is not IStringLocalizer localizer)
|
|
{
|
|
throw new InvalidOperationException("moduleLocalizer must be an IStringLocalizer instance");
|
|
}
|
|
|
|
Menus.MenuManager.Instance.RegisterMenu(categoryId, menuId, menuNameKey, BuilderFactory, permission, commandName, localizer);
|
|
return;
|
|
|
|
MenuBuilder BuilderFactory(CCSPlayerController player)
|
|
{
|
|
MenuContext context = new MenuContext(categoryId, menuId, menuNameKey, permission, commandName);
|
|
|
|
if (menuFactory(player, context) is not MenuBuilder menuBuilder)
|
|
{
|
|
throw new InvalidOperationException("Menu factory must return MenuBuilder");
|
|
}
|
|
|
|
return menuBuilder.WithBackButton();
|
|
}
|
|
}
|
|
|
|
|
|
public void UnregisterMenu(string categoryId, string menuId)
|
|
{
|
|
Menus.MenuManager.Instance.UnregisterMenu(categoryId, menuId);
|
|
}
|
|
|
|
public object CreateMenuWithBack(string title, string categoryId, CCSPlayerController player)
|
|
{
|
|
return new MenuBuilder(title).WithBackButton();
|
|
}
|
|
|
|
public object CreateMenuWithBack(MenuContext context, CCSPlayerController player)
|
|
{
|
|
// Get translated title if module has localizer
|
|
string title = context.MenuTitle;
|
|
|
|
if (Menus.MenuManager.Instance.GetMenuCategories().TryGetValue(context.CategoryId, out MenuCategory? category))
|
|
{
|
|
// Check if this specific menu has a localizer
|
|
if (category.MenuLocalizers.TryGetValue(context.MenuId, out IStringLocalizer? menuLocalizer))
|
|
{
|
|
using (new WithTemporaryCulture(player.GetLanguage()))
|
|
{
|
|
title = menuLocalizer[context.MenuTitle] ?? context.MenuTitle;
|
|
}
|
|
}
|
|
// Fallback to category localizer
|
|
else if (category.ModuleLocalizer != null)
|
|
{
|
|
using (new WithTemporaryCulture(player.GetLanguage()))
|
|
{
|
|
title = category.ModuleLocalizer[context.MenuTitle] ?? context.MenuTitle;
|
|
}
|
|
}
|
|
}
|
|
|
|
return CreateMenuWithBack(title, context.CategoryId, player);
|
|
}
|
|
|
|
public List<CCSPlayerController> GetValidPlayers()
|
|
{
|
|
return Helper.GetValidPlayers();
|
|
}
|
|
|
|
public object CreateMenuWithPlayers(string title, string categoryId, CCSPlayerController admin,
|
|
Func<CCSPlayerController, bool> filter, Action<CCSPlayerController, CCSPlayerController> onSelect)
|
|
{
|
|
MenuBuilder menu = (MenuBuilder)CreateMenuWithBack(title, categoryId, admin);
|
|
IEnumerable<CCSPlayerController> players = Helper.GetValidPlayers().Where(filter);
|
|
|
|
foreach (CCSPlayerController? player in players)
|
|
{
|
|
string playerName = Helper.Truncate(player.PlayerName, 26);
|
|
menu.AddOption(playerName, _ =>
|
|
{
|
|
if (player.IsValid)
|
|
{
|
|
onSelect(admin, player);
|
|
}
|
|
});
|
|
}
|
|
|
|
return menu;
|
|
}
|
|
|
|
public object CreateMenuWithPlayers(MenuContext context, CCSPlayerController admin,
|
|
Func<CCSPlayerController, bool> filter, Action<CCSPlayerController, CCSPlayerController> onSelect)
|
|
{
|
|
// Get translated title if module has localizer
|
|
string title = context.MenuTitle;
|
|
|
|
if (Menus.MenuManager.Instance.GetMenuCategories().TryGetValue(context.CategoryId, out MenuCategory? category))
|
|
{
|
|
// Check if this specific menu has a localizer
|
|
if (category.MenuLocalizers.TryGetValue(context.MenuId, out IStringLocalizer? menuLocalizer))
|
|
{
|
|
using (new WithTemporaryCulture(admin.GetLanguage()))
|
|
{
|
|
title = menuLocalizer[context.MenuTitle] ?? context.MenuTitle;
|
|
}
|
|
}
|
|
// Fallback to category localizer
|
|
else if (category.ModuleLocalizer != null)
|
|
{
|
|
using (new WithTemporaryCulture(admin.GetLanguage()))
|
|
{
|
|
title = category.ModuleLocalizer[context.MenuTitle] ?? context.MenuTitle;
|
|
}
|
|
}
|
|
}
|
|
|
|
return CreateMenuWithPlayers(title, context.CategoryId, admin, filter, onSelect);
|
|
}
|
|
|
|
public void AddMenuOption(object menu, string name, Action<CCSPlayerController> action, bool disabled = false,
|
|
string? permission = null)
|
|
{
|
|
if (menu is not MenuBuilder menuBuilder)
|
|
{
|
|
throw new InvalidOperationException("Menu must be a MenuBuilder instance");
|
|
}
|
|
|
|
menuBuilder.AddOption(name, action, disabled, permission);
|
|
}
|
|
|
|
public void AddSubMenu(object menu, string name, Func<CCSPlayerController, object> subMenuFactory,
|
|
bool disabled = false, string? permission = null)
|
|
{
|
|
if (menu is not MenuBuilder menuBuilder)
|
|
{
|
|
throw new InvalidOperationException("Menu must be a MenuBuilder instance");
|
|
}
|
|
|
|
menuBuilder.AddSubMenu(name, player =>
|
|
{
|
|
object subMenu = subMenuFactory(player);
|
|
if (subMenu is not MenuBuilder builder)
|
|
{
|
|
throw new InvalidOperationException("SubMenu factory must return MenuBuilder");
|
|
}
|
|
|
|
return builder;
|
|
}, disabled, permission);
|
|
}
|
|
|
|
public void OpenMenu(object menu, CCSPlayerController player)
|
|
{
|
|
if (menu is not MenuBuilder menuBuilder)
|
|
{
|
|
throw new InvalidOperationException("Menu must be a MenuBuilder instance");
|
|
}
|
|
|
|
menuBuilder.OpenMenu(player);
|
|
}
|
|
}
|