diff --git a/Content.Client/Administration/UI/AdminMenuWindow.xaml b/Content.Client/Administration/UI/AdminMenuWindow.xaml index 49eb9c0de60375..311d67b826c7a2 100644 --- a/Content.Client/Administration/UI/AdminMenuWindow.xaml +++ b/Content.Client/Administration/UI/AdminMenuWindow.xaml @@ -5,13 +5,15 @@ xmlns:atmosTab="clr-namespace:Content.Client.Administration.UI.Tabs.AtmosTab" xmlns:tabs="clr-namespace:Content.Client.Administration.UI.Tabs" xmlns:playerTab="clr-namespace:Content.Client.Administration.UI.Tabs.PlayerTab" - xmlns:objectsTab="clr-namespace:Content.Client.Administration.UI.Tabs.ObjectsTab"> + xmlns:objectsTab="clr-namespace:Content.Client.Administration.UI.Tabs.ObjectsTab" + xmlns:panic="clr-namespace:Content.Client.Administration.UI.Tabs.PanicBunkerTab"> + diff --git a/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs b/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs index d4dfcc2042e143..c3ea67a3edb91d 100644 --- a/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs +++ b/Content.Client/Administration/UI/AdminMenuWindow.xaml.cs @@ -12,7 +12,7 @@ public sealed partial class AdminMenuWindow : DefaultWindow public AdminMenuWindow() { - MinSize = new Vector2(500, 250); + MinSize = new Vector2(650, 250); Title = Loc.GetString("admin-menu-title"); RobustXamlLoader.Load(this); MasterTabContainer.SetTabTitle(0, Loc.GetString("admin-menu-admin-tab")); @@ -20,8 +20,9 @@ public AdminMenuWindow() MasterTabContainer.SetTabTitle(2, Loc.GetString("admin-menu-atmos-tab")); MasterTabContainer.SetTabTitle(3, Loc.GetString("admin-menu-round-tab")); MasterTabContainer.SetTabTitle(4, Loc.GetString("admin-menu-server-tab")); - MasterTabContainer.SetTabTitle(5, Loc.GetString("admin-menu-players-tab")); - MasterTabContainer.SetTabTitle(6, Loc.GetString("admin-menu-objects-tab")); + MasterTabContainer.SetTabTitle(5, Loc.GetString("admin-menu-panic-bunker-tab")); + MasterTabContainer.SetTabTitle(6, Loc.GetString("admin-menu-players-tab")); + MasterTabContainer.SetTabTitle(7, Loc.GetString("admin-menu-objects-tab")); } protected override void Dispose(bool disposing) diff --git a/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerStatusWindow.xaml b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerStatusWindow.xaml new file mode 100644 index 00000000000000..633bef05148927 --- /dev/null +++ b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerStatusWindow.xaml @@ -0,0 +1,6 @@ + + diff --git a/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerStatusWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerStatusWindow.xaml.cs new file mode 100644 index 00000000000000..ec16bf6aea7d60 --- /dev/null +++ b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerStatusWindow.xaml.cs @@ -0,0 +1,14 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Administration.UI.Tabs.PanicBunkerTab; + +[GenerateTypedNameReferences] +public sealed partial class PanicBunkerStatusWindow : DefaultWindow +{ + public PanicBunkerStatusWindow() + { + RobustXamlLoader.Load(this); + } +} diff --git a/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerTab.xaml b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerTab.xaml new file mode 100644 index 00000000000000..89827d06424680 --- /dev/null +++ b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerTab.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerTab.xaml.cs b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerTab.xaml.cs new file mode 100644 index 00000000000000..e9d3b95c5d8d97 --- /dev/null +++ b/Content.Client/Administration/UI/Tabs/PanicBunkerTab/PanicBunkerTab.xaml.cs @@ -0,0 +1,54 @@ +using Content.Shared.Administration.Events; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Console; + +namespace Content.Client.Administration.UI.Tabs.PanicBunkerTab; + +[GenerateTypedNameReferences] +public sealed partial class PanicBunkerTab : Control +{ + [Dependency] private readonly IConsoleHost _console = default!; + + public PanicBunkerTab() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + DisableAutomaticallyButton.ToolTip = Loc.GetString("admin-ui-panic-bunker-disable-automatically-tooltip"); + + MinAccountAge.OnTextEntered += args => + { + if (string.IsNullOrWhiteSpace(args.Text) || !int.TryParse(args.Text, out var minutes)) + return; + + _console.ExecuteCommand($"panicbunker_min_account_age {minutes}"); + }; + + MinOverallHours.OnTextEntered += args => + { + if (string.IsNullOrWhiteSpace(args.Text) || !int.TryParse(args.Text, out var hours)) + return; + + _console.ExecuteCommand($"panicbunker_min_overall_hours {hours}"); + }; + } + + public void UpdateStatus(PanicBunkerStatus status) + { + EnabledButton.Pressed = status.Enabled; + EnabledButton.Text = Loc.GetString(status.Enabled + ? "admin-ui-panic-bunker-enabled" + : "admin-ui-panic-bunker-disabled" + ); + EnabledButton.ModulateSelfOverride = status.Enabled ? Color.Red : null; + + DisableAutomaticallyButton.Pressed = status.DisableWithAdmins; + EnableAutomaticallyButton.Pressed = status.EnableWithoutAdmins; + CountDeadminnedButton.Pressed = status.CountDeadminnedAdmins; + ShowReasonButton.Pressed = status.ShowReason; + MinAccountAge.Text = status.MinAccountAgeHours.ToString(); + MinOverallHours.Text = status.MinOverallHours.ToString(); + } +} diff --git a/Content.Client/Administration/UI/Tabs/ServerTab.xaml b/Content.Client/Administration/UI/Tabs/ServerTab.xaml index 7e15bc27539a16..b9984058358c4b 100644 --- a/Content.Client/Administration/UI/Tabs/ServerTab.xaml +++ b/Content.Client/Administration/UI/Tabs/ServerTab.xaml @@ -8,6 +8,5 @@ - diff --git a/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs b/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs index b83a3d1ec03018..24b92e42ce784d 100644 --- a/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs +++ b/Content.Client/Administration/UI/Tabs/ServerTab.xaml.cs @@ -18,7 +18,6 @@ public ServerTab() _config.OnValueChanged(CCVars.OocEnabled, OocEnabledChanged, true); _config.OnValueChanged(CCVars.LoocEnabled, LoocEnabledChanged, true); - _config.OnValueChanged(CCVars.PanicBunkerEnabled, BunkerEnabledChanged, true); } private void OocEnabledChanged(bool value) @@ -31,11 +30,6 @@ private void LoocEnabledChanged(bool value) SetLoocButton.Pressed = value; } - private void BunkerEnabledChanged(bool value) - { - SetPanicbunkerButton.Pressed = value; - } - protected override void Dispose(bool disposing) { base.Dispose(disposing); @@ -44,7 +38,6 @@ protected override void Dispose(bool disposing) { _config.UnsubValueChanged(CCVars.OocEnabled, OocEnabledChanged); _config.UnsubValueChanged(CCVars.LoocEnabled, LoocEnabledChanged); - _config.UnsubValueChanged(CCVars.PanicBunkerEnabled, BunkerEnabledChanged); } } } diff --git a/Content.Client/UserInterface/Systems/Admin/AdminUIController.cs b/Content.Client/UserInterface/Systems/Admin/AdminUIController.cs index 47b93fdb09a34b..4a7a57e5272f2c 100644 --- a/Content.Client/UserInterface/Systems/Admin/AdminUIController.cs +++ b/Content.Client/UserInterface/Systems/Admin/AdminUIController.cs @@ -2,11 +2,13 @@ using Content.Client.Administration.Systems; using Content.Client.Administration.UI; using Content.Client.Administration.UI.Tabs.ObjectsTab; +using Content.Client.Administration.UI.Tabs.PanicBunkerTab; using Content.Client.Administration.UI.Tabs.PlayerTab; using Content.Client.Gameplay; using Content.Client.Lobby; using Content.Client.UserInterface.Controls; using Content.Client.Verbs.UI; +using Content.Shared.Administration.Events; using Content.Shared.Input; using JetBrains.Annotations; using Robust.Client.Console; @@ -30,6 +32,25 @@ public sealed class AdminUIController : UIController, IOnStateEntered UIManager.GetActiveUIWidgetOrNull()?.AdminButton; + private PanicBunkerStatus? _panicBunker; + + public override void Initialize() + { + base.Initialize(); + SubscribeNetworkEvent(OnPanicBunkerUpdated); + } + + private void OnPanicBunkerUpdated(PanicBunkerChangedEvent msg, EntitySessionEventArgs args) + { + var showDialog = _panicBunker == null && msg.Status.Enabled; + _panicBunker = msg.Status; + _window?.PanicBunkerControl.UpdateStatus(msg.Status); + + if (showDialog) + { + UIManager.CreateWindow().OpenCentered(); + } + } public void OnStateEntered(GameplayState state) { @@ -73,6 +94,9 @@ private void EnsureWindow() _window = UIManager.CreateWindow(); LayoutContainer.SetAnchorPreset(_window, LayoutContainer.LayoutPreset.Center); + if (_panicBunker != null) + _window.PanicBunkerControl.UpdateStatus(_panicBunker); + _window.PlayerTabControl.OnEntryPressed += PlayerTabEntryPressed; _window.ObjectsTabControl.OnEntryPressed += ObjectsTabEntryPressed; _window.OnOpen += OnWindowOpen; diff --git a/Content.Server/Administration/Commands/PanicBunkerCommand.cs b/Content.Server/Administration/Commands/PanicBunkerCommand.cs index 0273ac313d688a..de3f3cbaea2b6b 100644 --- a/Content.Server/Administration/Commands/PanicBunkerCommand.cs +++ b/Content.Server/Administration/Commands/PanicBunkerCommand.cs @@ -6,36 +6,187 @@ namespace Content.Server.Administration.Commands; [AdminCommand(AdminFlags.Server)] -public sealed class PanicBunkerCommand : IConsoleCommand +public sealed class PanicBunkerCommand : LocalizedCommands { [Dependency] private readonly IConfigurationManager _cfg = default!; - public string Command => "panicbunker"; - public string Description => "Enables or disables the panic bunker functionality."; - public string Help => "panicbunker"; - public void Execute(IConsoleShell shell, string argStr, string[] args) + public override string Command => "panicbunker"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + var toggle = Toggle(CCVars.PanicBunkerEnabled, shell, args, _cfg); + if (toggle == null) + return; + + shell.WriteLine(Loc.GetString(toggle.Value ? "panicbunker-command-enabled" : "panicbunker-command-disabled")); + } + + public static bool? Toggle(CVarDef cvar, IConsoleShell shell, string[] args, IConfigurationManager config) { if (args.Length > 1) { shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1))); - return; + return null; } - var enabled = _cfg.GetCVar(CCVars.PanicBunkerEnabled); - + var enabled = config.GetCVar(cvar); + if (args.Length == 0) { enabled = !enabled; } - + if (args.Length == 1 && !bool.TryParse(args[0], out enabled)) { shell.WriteError(Loc.GetString("shell-argument-must-be-boolean")); + return null; + } + + config.SetCVar(cvar, enabled); + return enabled; + } +} + +[AdminCommand(AdminFlags.Server)] +public sealed class PanicBunkerDisableWithAdminsCommand : LocalizedCommands +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override string Command => "panicbunker_disable_with_admins"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerDisableWithAdmins, shell, args, _cfg); + if (toggle == null) + return; + + shell.WriteLine(Loc.GetString(toggle.Value + ? "panicbunker-command-disable-with-admins-enabled" + : "panicbunker-command-disable-with-admins-disabled" + )); + } +} + +[AdminCommand(AdminFlags.Server)] +public sealed class PanicBunkerEnableWithoutAdminsCommand : LocalizedCommands +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override string Command => "panicbunker_enable_without_admins"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerEnableWithoutAdmins, shell, args, _cfg); + if (toggle == null) + return; + + shell.WriteLine(Loc.GetString(toggle.Value + ? "panicbunker-command-enable-without-admins-enabled" + : "panicbunker-command-enable-without-admins-disabled" + )); + } +} + +[AdminCommand(AdminFlags.Server)] +public sealed class PanicBunkerCountDeadminnedCommand : LocalizedCommands +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override string Command => "panicbunker_count_deadminned_admins"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerCountDeadminnedAdmins, shell, args, _cfg); + if (toggle == null) + return; + + shell.WriteLine(Loc.GetString(toggle.Value + ? "panicbunker-command-count-deadminned-admins-enabled" + : "panicbunker-command-count-deadminned-admins-disabled" + )); + } +} + +[AdminCommand(AdminFlags.Server)] +public sealed class PanicBunkerShowReasonCommand : LocalizedCommands +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override string Command => "panicbunker_show_reason"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + var toggle = PanicBunkerCommand.Toggle(CCVars.PanicBunkerShowReason, shell, args, _cfg); + if (toggle == null) + return; + + shell.WriteLine(Loc.GetString(toggle.Value + ? "panicbunker-command-show-reason-enabled" + : "panicbunker-command-show-reason-disabled" + )); + } +} + +[AdminCommand(AdminFlags.Server)] +public sealed class PanicBunkerMinAccountAgeCommand : LocalizedCommands +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override string Command => "panicbunker_min_account_age"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length == 0) + { + var current = _cfg.GetCVar(CCVars.PanicBunkerMinAccountAge); + shell.WriteLine(Loc.GetString("panicbunker-command-min-account-age-is", ("hours", current / 60))); + } + + if (args.Length > 1) + { + shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1))); + return; + } + + if (!int.TryParse(args[0], out var hours)) + { + shell.WriteError(Loc.GetString("shell-argument-must-be-number")); + return; + } + + _cfg.SetCVar(CCVars.PanicBunkerMinAccountAge, hours * 60); + shell.WriteLine(Loc.GetString("panicbunker-command-min-account-age-set", ("hours", hours))); + } +} + +[AdminCommand(AdminFlags.Server)] +public sealed class PanicBunkerMinOverallHoursCommand : LocalizedCommands +{ + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override string Command => "panicbunker_min_overall_hours"; + + public override void Execute(IConsoleShell shell, string argStr, string[] args) + { + if (args.Length == 0) + { + var current = _cfg.GetCVar(CCVars.PanicBunkerMinOverallHours); + shell.WriteLine(Loc.GetString("panicbunker-command-min-overall-hours-is", ("minutes", current))); + } + + if (args.Length > 1) + { + shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1))); + return; + } + + if (!int.TryParse(args[0], out var hours)) + { + shell.WriteError(Loc.GetString("shell-argument-must-be-number")); return; } - _cfg.SetCVar(CCVars.PanicBunkerEnabled, enabled); - - shell.WriteLine(Loc.GetString(enabled ? "panicbunker-command-enabled" : "panicbunker-command-disabled")); + _cfg.SetCVar(CCVars.PanicBunkerMinOverallHours, hours); + shell.WriteLine(Loc.GetString("panicbunker-command-overall-hours-age-set", ("hours", hours))); } } diff --git a/Content.Server/Administration/Systems/AdminSystem.cs b/Content.Server/Administration/Systems/AdminSystem.cs index d54a7a2092a630..8851680aea6336 100644 --- a/Content.Server/Administration/Systems/AdminSystem.cs +++ b/Content.Server/Administration/Systems/AdminSystem.cs @@ -1,15 +1,18 @@ using System.Linq; using Content.Server.Administration.Managers; +using Content.Server.Chat.Managers; using Content.Server.IdentityManagement; using Content.Server.Mind; using Content.Shared.Administration; using Content.Shared.Administration.Events; +using Content.Shared.CCVar; using Content.Shared.GameTicking; using Content.Shared.IdentityManagement; using Content.Shared.Roles; using Content.Shared.Roles.Jobs; using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Configuration; using Robust.Shared.Enums; using Robust.Shared.Network; using Robust.Shared.Player; @@ -18,8 +21,10 @@ namespace Content.Server.Administration.Systems { public sealed class AdminSystem : EntitySystem { - [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IAdminManager _adminManager = default!; + [Dependency] private readonly IChatManager _chat = default!; + [Dependency] private readonly IConfigurationManager _config = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly SharedJobSystem _jobs = default!; [Dependency] private readonly MindSystem _minds = default!; [Dependency] private readonly SharedRoleSystem _role = default!; @@ -32,6 +37,7 @@ public sealed class AdminSystem : EntitySystem public IReadOnlySet RoundActivePlayers => _roundActivePlayers; private readonly HashSet _roundActivePlayers = new(); + private readonly PanicBunkerStatus _panicBunker = new(); public override void Initialize() { @@ -39,6 +45,15 @@ public override void Initialize() _playerManager.PlayerStatusChanged += OnPlayerStatusChanged; _adminManager.OnPermsChanged += OnAdminPermsChanged; + + _config.OnValueChanged(CCVars.PanicBunkerEnabled, OnPanicBunkerChanged, true); + _config.OnValueChanged(CCVars.PanicBunkerDisableWithAdmins, OnPanicBunkerDisableWithAdminsChanged, true); + _config.OnValueChanged(CCVars.PanicBunkerEnableWithoutAdmins, OnPanicBunkerEnableWithoutAdminsChanged, true); + _config.OnValueChanged(CCVars.PanicBunkerCountDeadminnedAdmins, OnPanicBunkerCountDeadminnedAdminsChanged, true); + _config.OnValueChanged(CCVars.PanicBunkerShowReason, OnShowReasonChanged, true); + _config.OnValueChanged(CCVars.PanicBunkerMinAccountAge, OnPanicBunkerMinAccountAgeChanged, true); + _config.OnValueChanged(CCVars.PanicBunkerMinOverallHours, OnPanicBunkerMinOverallHoursChanged, true); + SubscribeLocalEvent(OnIdentityChanged); SubscribeLocalEvent(OnPlayerAttached); SubscribeLocalEvent(OnPlayerDetached); @@ -114,7 +129,9 @@ private void OnRoleEvent(RoleEvent ev) private void OnAdminPermsChanged(AdminPermsChangedEventArgs obj) { - if(!obj.IsAdmin) + UpdatePanicBunker(); + + if (!obj.IsAdmin) { RaiseNetworkEvent(new FullPlayerListEvent(), obj.Player.ConnectedClient); return; @@ -127,14 +144,16 @@ private void OnPlayerDetached(PlayerDetachedEvent ev) { // If disconnected then the player won't have a connected entity to get character name from. // The disconnected state gets sent by OnPlayerStatusChanged. - if(ev.Player.Status == SessionStatus.Disconnected) return; + if (ev.Player.Status == SessionStatus.Disconnected) + return; UpdatePlayerList(ev.Player); } private void OnPlayerAttached(PlayerAttachedEvent ev) { - if(ev.Player.Status == SessionStatus.Disconnected) return; + if (ev.Player.Status == SessionStatus.Disconnected) + return; _roundActivePlayers.Add(ev.Player.UserId); UpdatePlayerList(ev.Player); @@ -145,11 +164,20 @@ public override void Shutdown() base.Shutdown(); _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged; _adminManager.OnPermsChanged -= OnAdminPermsChanged; + + _config.UnsubValueChanged(CCVars.PanicBunkerEnabled, OnPanicBunkerChanged); + _config.UnsubValueChanged(CCVars.PanicBunkerDisableWithAdmins, OnPanicBunkerDisableWithAdminsChanged); + _config.UnsubValueChanged(CCVars.PanicBunkerEnableWithoutAdmins, OnPanicBunkerEnableWithoutAdminsChanged); + _config.UnsubValueChanged(CCVars.PanicBunkerCountDeadminnedAdmins, OnPanicBunkerCountDeadminnedAdminsChanged); + _config.UnsubValueChanged(CCVars.PanicBunkerShowReason, OnShowReasonChanged); + _config.UnsubValueChanged(CCVars.PanicBunkerMinAccountAge, OnPanicBunkerMinAccountAgeChanged); + _config.UnsubValueChanged(CCVars.PanicBunkerMinOverallHours, OnPanicBunkerMinOverallHoursChanged); } private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) { UpdatePlayerList(e.Session); + UpdatePanicBunker(); } private void SendFullPlayerList(IPlayerSession playerSession) @@ -186,5 +214,80 @@ private PlayerInfo GetPlayerInfo(IPlayerData data, IPlayerSession? session) return new PlayerInfo(name, entityName, identityName, startingRole, antag, GetNetEntity(session?.AttachedEntity), data.UserId, connected, _roundActivePlayers.Contains(data.UserId)); } + + private void OnPanicBunkerChanged(bool enabled) + { + _panicBunker.Enabled = enabled; + _chat.SendAdminAlert(Loc.GetString(enabled + ? "admin-ui-panic-bunker-enabled-admin-alert" + : "admin-ui-panic-bunker-disabled-admin-alert" + )); + + SendPanicBunkerStatusAll(); + } + + private void OnPanicBunkerDisableWithAdminsChanged(bool enabled) + { + _panicBunker.DisableWithAdmins = enabled; + UpdatePanicBunker(); + } + + private void OnPanicBunkerEnableWithoutAdminsChanged(bool enabled) + { + _panicBunker.EnableWithoutAdmins = enabled; + UpdatePanicBunker(); + } + + private void OnPanicBunkerCountDeadminnedAdminsChanged(bool enabled) + { + _panicBunker.CountDeadminnedAdmins = enabled; + UpdatePanicBunker(); + } + + private void OnShowReasonChanged(bool enabled) + { + _panicBunker.ShowReason = enabled; + SendPanicBunkerStatusAll(); + } + + private void OnPanicBunkerMinAccountAgeChanged(int minutes) + { + _panicBunker.MinAccountAgeHours = minutes / 60; + SendPanicBunkerStatusAll(); + } + + private void OnPanicBunkerMinOverallHoursChanged(int hours) + { + _panicBunker.MinOverallHours = hours; + SendPanicBunkerStatusAll(); + } + + private void UpdatePanicBunker() + { + var admins = _panicBunker.CountDeadminnedAdmins + ? _adminManager.AllAdmins + : _adminManager.ActiveAdmins; + var hasAdmins = admins.Any(); + + if (hasAdmins && _panicBunker.DisableWithAdmins) + { + _config.SetCVar(CCVars.PanicBunkerEnabled, false); + } + else if (!hasAdmins && _panicBunker.EnableWithoutAdmins) + { + _config.SetCVar(CCVars.PanicBunkerEnabled, true); + } + + SendPanicBunkerStatusAll(); + } + + private void SendPanicBunkerStatusAll() + { + var ev = new PanicBunkerChangedEvent(_panicBunker); + foreach (var admin in _adminManager.AllAdmins) + { + RaiseNetworkEvent(ev, admin); + } + } } } diff --git a/Content.Shared/Administration/Events/PanicBunkerChangedEvent.cs b/Content.Shared/Administration/Events/PanicBunkerChangedEvent.cs new file mode 100644 index 00000000000000..f809b67bc8d20d --- /dev/null +++ b/Content.Shared/Administration/Events/PanicBunkerChangedEvent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Administration.Events; + +[Serializable, NetSerializable] +public sealed class PanicBunkerStatus +{ + public bool Enabled; + public bool DisableWithAdmins; + public bool EnableWithoutAdmins; + public bool CountDeadminnedAdmins; + public bool ShowReason; + public int MinAccountAgeHours; + public int MinOverallHours; +} + +[Serializable, NetSerializable] +public sealed class PanicBunkerChangedEvent : EntityEventArgs +{ + public PanicBunkerStatus Status; + + public PanicBunkerChangedEvent(PanicBunkerStatus status) + { + Status = status; + } +} diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index ccc8b6d51dc6a4..0cf374fe4dea80 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -248,6 +248,26 @@ public static readonly CVarDef public static readonly CVarDef PanicBunkerEnabled = CVarDef.Create("game.panic_bunker.enabled", false, CVar.NOTIFY | CVar.REPLICATED); + /// + /// Whether or not the panic bunker will disable when an admin comes online. + /// + public static readonly CVarDef PanicBunkerDisableWithAdmins = + CVarDef.Create("game.panic_bunker.disable_with_admins", false, CVar.SERVERONLY); + + /// + /// Whether or not the panic bunker will enable when no admins are online. + /// + public static readonly CVarDef PanicBunkerEnableWithoutAdmins = + CVarDef.Create("game.panic_bunker.enable_without_admins", false, CVar.SERVERONLY); + + /// + /// Whether or not the panic bunker will count deadminned admins for + /// and + /// + /// + public static readonly CVarDef PanicBunkerCountDeadminnedAdmins = + CVarDef.Create("game.panic_bunker.count_deadminned_admins", false, CVar.SERVERONLY); + /// /// Show reason of disconnect for user or not. /// diff --git a/Resources/Changelog/Admin.yml b/Resources/Changelog/Admin.yml index 81bc934176c7ef..aafb784ddc1ca9 100644 --- a/Resources/Changelog/Admin.yml +++ b/Resources/Changelog/Admin.yml @@ -7,3 +7,10 @@ Entries: - {message: 'Created the admin changelog.', type: Add} id: 1 time: '2023-10-08T04:26:00.0000000+00:00' +- author: DrSmugleaf + changes: + - {message: 'Added a new panic bunker UI in the F7 admin panel.', type: Add} + - {message: 'Added being able to toggle the panic bunker automatically depending on + if admins are online or not.', type: Add} + id: 2 + time: '2023-10-12T22:46:00.0000000+00:00' diff --git a/Resources/Locale/en-US/administration/commands/panicbunker.ftl b/Resources/Locale/en-US/administration/commands/panicbunker.ftl index 46896500b8e8f4..c16748c9926a91 100644 --- a/Resources/Locale/en-US/administration/commands/panicbunker.ftl +++ b/Resources/Locale/en-US/administration/commands/panicbunker.ftl @@ -1,2 +1,34 @@ +cmd-panicbunker-desc = Toggles the panic bunker, which enables stricter restrictions on who's allowed to join the server. +cmd-panicbunker-help = Usage: panicbunker panicbunker-command-enabled = Panic bunker has been enabled. panicbunker-command-disabled = Panic bunker has been disabled. + +cmd-panicbunker_disable_with_admins-desc = Toggles whether or not the panic bunker will disable when an admin connects. +cmd-panicbunker_disable_with_admins-help = Usage: panicbunker_disable_with_admins +panicbunker-command-disable-with-admins-enabled = The panic bunker will automatically disable with admins online. +panicbunker-command-disable-with-admins-disabled = The panic bunker will not automatically disable with admins online. + +cmd-panicbunker_enable_without_admins-desc = Toggles whether or not the panic bunker will enable when the last admin disconnects. +cmd-panicbunker_enable_without_admins-help = Usage: panicbunker_enable_without_admins +panicbunker-command-enable-without-admins-enabled = The panic bunker will automatically enable without admins online. +panicbunker-command-enable-without-admins-disabled = The panic bunker will not automatically enable without admins online. + +cmd-panicbunker_count_deadminned_admins-desc = Toggles whether or not to count deadminned admins when automatically enabling and disabling the panic bunker. +cmd-panicbunker_count_deadminned_admins-help = Usage: panicbunker_count_deadminned_admins +panicbunker-command-count-deadminned-admins-enabled = The panic bunker will count deadminned admins when made to automatically enable and disable. +panicbunker-command-count-deadminned-admins-disabled = The panic bunker will not count deadminned admins when made to automatically enable and disable. + +cmd-panicbunker_show_reason-desc = Toggles whether or not to show connecting clients the reason why the panic bunker blocked them from joining. +cmd-panicbunker_show_reason-help = Usage: panicbunker_show_reason +panicbunker-command-show-reason-enabled = The panic bunker will now show a reason to users it blocks from connecting. +panicbunker-command-show-reason-disabled = The panic bunker will no longer show a reason to users it blocks from connecting. + +cmd-panicbunker_min_account_age-desc = Gets or sets the minimum account age in hours that an account must have to be allowed to connect with the panic bunker enabled. +cmd-panicbunker_min_account_age-help = Usage: panicbunker_min_account_age +panicbunker-command-min-account-age-is = The minimum account age for the panic bunker is {$hours} hours. +panicbunker-command-min-account-age-set = Set the minimum account age for the panic bunker to {$hours} hours. + +cmd-panicbunker_min_overall_hours-desc = Gets or sets the minimum overall playtime in hours that an account must have to be allowed to connect with the panic bunker enabled. +cmd-panicbunker_min_overall_hours-help = Usage: panicbunker_min_overall_hours +panicbunker-command-min-overall-hours-is = The minimum overall playtime for the panic bunker is {$hours} hours. +panicbunker-command-min-overall-hours-set = Set the minimum overall playtime for the panic bunker to {$hours} hours. diff --git a/Resources/Locale/en-US/administration/ui/admin-menu-window.ftl b/Resources/Locale/en-US/administration/ui/admin-menu-window.ftl index ce256a2cd532a8..c759e4c2cb16f2 100644 --- a/Resources/Locale/en-US/administration/ui/admin-menu-window.ftl +++ b/Resources/Locale/en-US/administration/ui/admin-menu-window.ftl @@ -6,5 +6,6 @@ admin-menu-adminbus-tab = Adminbus admin-menu-atmos-tab = Atmos admin-menu-round-tab = Round admin-menu-server-tab = Server +admin-menu-panic-bunker-tab = Panic Bunker admin-menu-players-tab = Players admin-menu-objects-tab = Objects diff --git a/Resources/Locale/en-US/administration/ui/tabs/panicbunker-tab.ftl b/Resources/Locale/en-US/administration/ui/tabs/panicbunker-tab.ftl new file mode 100644 index 00000000000000..730d0c2e3b3412 --- /dev/null +++ b/Resources/Locale/en-US/administration/ui/tabs/panicbunker-tab.ftl @@ -0,0 +1,24 @@ +admin-ui-panic-bunker-window-title = Panic Bunker + +admin-ui-panic-bunker-enabled = Panic Bunker Enabled +admin-ui-panic-bunker-disabled = Panic Bunker Disabled +admin-ui-panic-bunker-tooltip = The panic bunker restricts players from joining if their account is too new or they do not have enough overall playtime on this server. + +admin-ui-panic-bunker-disable-automatically = Disable Automatically +admin-ui-panic-bunker-disable-automatically-tooltip = Disables the panic bunker automatically when an admin connects. +admin-ui-panic-bunker-enable-automatically = Enable Automatically +admin-ui-panic-bunker-enable-automatically-tooltip = Enables the panic bunker automatically when no admins are online. + +admin-ui-panic-bunker-count-deadminned-admins = Count Deadmins +admin-ui-panic-bunker-count-deadminned-admins-tooltip = Count deadminned admins when automatically enabling and disabling the panic bunker. + +admin-ui-panic-bunker-show-reason = Show Reason +admin-ui-panic-bunker-show-reason-tooltip = Show the user why they were blocked from connecting by the panic bunker. + +admin-ui-panic-bunker-min-account-age = Min. Account Age +admin-ui-panic-bunker-min-overall-hours = Min. Overall Playtime + +admin-ui-panic-bunker-is-enabled = The panic bunker is currently enabled. + +admin-ui-panic-bunker-enabled-admin-alert = The panic bunker has been enabled. +admin-ui-panic-bunker-disabled-admin-alert = The panic bunker has been disabled. diff --git a/Resources/Locale/en-US/administration/ui/tabs/server-tab.ftl b/Resources/Locale/en-US/administration/ui/tabs/server-tab.ftl index 713af85fa5bc98..7a41cbe2c751d7 100644 --- a/Resources/Locale/en-US/administration/ui/tabs/server-tab.ftl +++ b/Resources/Locale/en-US/administration/ui/tabs/server-tab.ftl @@ -1,4 +1,3 @@ server-shutdown = Shutdown server-ooc-toggle = Toggle OOC server-looc-toggle = Toggle LOOC -server-panicbunker-toggle = Toggle Panic bunker diff --git a/Resources/Locale/en-US/generic.ftl b/Resources/Locale/en-US/generic.ftl index 0ecfefdd1cbb29..7b3e0d3684ef8e 100644 --- a/Resources/Locale/en-US/generic.ftl +++ b/Resources/Locale/en-US/generic.ftl @@ -8,3 +8,5 @@ generic-unknown = unknown generic-unknown-title = Unknown generic-error = error generic-invalid = invalid + +generic-hours = hours diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 1d141ba58a467b..57f0e3c4db6acb 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -584,6 +584,7 @@ public sealed partial class $CLASS$ : Shared$CLASS$ { True True True + True True True True