]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Fix baby jail (#29896)
authorChief-Engineer <119664036+Chief-Engineer@users.noreply.github.com>
Thu, 11 Jul 2024 05:14:01 +0000 (00:14 -0500)
committerGitHub <noreply@github.com>
Thu, 11 Jul 2024 05:14:01 +0000 (15:14 +1000)
* Revert "Revert Baby Jail (#29891)"

This reverts commit 24a2866747e6de37ab2c4395bee9ea44c9211c6f.

* the fix

20 files changed:
Content.Client/Administration/UI/AdminMenuWindow.xaml
Content.Client/Administration/UI/AdminMenuWindow.xaml.cs
Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailStatusWindow.xaml [new file with mode: 0644]
Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailStatusWindow.xaml.cs [new file with mode: 0644]
Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailTab.xaml [new file with mode: 0644]
Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailTab.xaml.cs [new file with mode: 0644]
Content.Client/UserInterface/Systems/Admin/AdminUIController.cs
Content.Server.Database/Model.cs
Content.Server/Administration/Commands/BabyJailCommand.cs [new file with mode: 0644]
Content.Server/Administration/Systems/AdminSystem.cs
Content.Server/Connection/ConnectionManager.cs
Content.Server/GameTicking/GameTicker.StatusShell.cs
Content.Shared/Administration/Events/BabyJailChangedEvent.cs [new file with mode: 0644]
Content.Shared/CCVar/CCVars.cs
Resources/ConfigPresets/WizardsDen/wizardsDenGateway.toml
Resources/ConfigPresets/WizardsDen/wizardsDenLRPTide.toml
Resources/Locale/en-US/administration/commands/babyjail.ftl [new file with mode: 0644]
Resources/Locale/en-US/administration/ui/admin-menu-window.ftl
Resources/Locale/en-US/administration/ui/tabs/babyjail-tab.ftl [new file with mode: 0644]
Resources/Locale/en-US/connection-messages.ftl

index 311d67b826c7a2aad1711832d6917c95a257b322..d3d3df02d93609f7a4cb4c8804a922ab3d08135d 100644 (file)
@@ -6,7 +6,8 @@
     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:panic="clr-namespace:Content.Client.Administration.UI.Tabs.PanicBunkerTab">
+    xmlns:panic="clr-namespace:Content.Client.Administration.UI.Tabs.PanicBunkerTab"
+    xmlns:baby="clr-namespace:Content.Client.Administration.UI.Tabs.BabyJailTab">
     <TabContainer Name="MasterTabContainer">
         <adminTab:AdminTab />
         <adminbusTab:AdminbusTab />
@@ -14,6 +15,7 @@
         <tabs:RoundTab />
         <tabs:ServerTab />
         <panic:PanicBunkerTab Name="PanicBunkerControl" Access="Public" />
+        <baby:BabyJailTab Name="BabyJailControl" Access="Public" />
         <playerTab:PlayerTab Name="PlayerTabControl" Access="Public" />
         <objectsTab:ObjectsTab Name="ObjectsTabControl" Access="Public" />
     </TabContainer>
index 51330a547ec5d20b49938d566194196baf016d04..d5c43e2a500e7012aab9843e268b40ee73e152e4 100644 (file)
@@ -15,14 +15,18 @@ public sealed partial class AdminMenuWindow : DefaultWindow
         MinSize = new Vector2(650, 250);
         Title = Loc.GetString("admin-menu-title");
         RobustXamlLoader.Load(this);
-        MasterTabContainer.SetTabTitle(0, Loc.GetString("admin-menu-admin-tab"));
-        MasterTabContainer.SetTabTitle(1, Loc.GetString("admin-menu-adminbus-tab"));
-        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-panic-bunker-tab"));
-        MasterTabContainer.SetTabTitle(6, Loc.GetString("admin-menu-players-tab"));
-        MasterTabContainer.SetTabTitle(7, Loc.GetString("admin-menu-objects-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.Admin, Loc.GetString("admin-menu-admin-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.Adminbus, Loc.GetString("admin-menu-adminbus-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.Atmos, Loc.GetString("admin-menu-atmos-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.Round, Loc.GetString("admin-menu-round-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.Server, Loc.GetString("admin-menu-server-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.PanicBunker, Loc.GetString("admin-menu-panic-bunker-tab"));
+        /*
+         * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+         */
+        MasterTabContainer.SetTabTitle((int) TabIndex.BabyJail, Loc.GetString("admin-menu-baby-jail-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.Players, Loc.GetString("admin-menu-players-tab"));
+        MasterTabContainer.SetTabTitle((int) TabIndex.Objects, Loc.GetString("admin-menu-objects-tab"));
         MasterTabContainer.OnTabChanged += OnTabChanged;
     }
 
diff --git a/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailStatusWindow.xaml b/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailStatusWindow.xaml
new file mode 100644 (file)
index 0000000..b8034fa
--- /dev/null
@@ -0,0 +1,6 @@
+<controls:BabyJailStatusWindow
+    xmlns="https://spacestation14.io"
+    xmlns:controls="clr-namespace:Content.Client.Administration.UI.Tabs.BabyJailTab"
+    Title="{Loc admin-ui-baby-jail-window-title}">
+    <RichTextLabel Name="MessageLabel" Access="Public" />
+</controls:BabyJailStatusWindow>
diff --git a/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailStatusWindow.xaml.cs b/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailStatusWindow.xaml.cs
new file mode 100644 (file)
index 0000000..9e1d538
--- /dev/null
@@ -0,0 +1,21 @@
+using Content.Client.Message;
+using Content.Client.UserInterface.Controls;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.Administration.UI.Tabs.BabyJailTab;
+
+/*
+ * TODO: Remove me once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+ */
+
+[GenerateTypedNameReferences]
+public sealed partial class BabyJailStatusWindow : FancyWindow
+{
+    public BabyJailStatusWindow()
+    {
+        RobustXamlLoader.Load(this);
+        MessageLabel.SetMarkup(Loc.GetString("admin-ui-baby-jail-is-enabled"));
+    }
+}
diff --git a/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailTab.xaml b/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailTab.xaml
new file mode 100644 (file)
index 0000000..dd770c2
--- /dev/null
@@ -0,0 +1,26 @@
+<controls:BabyJailTab
+    xmlns="https://spacestation14.io"
+    xmlns:controls="clr-namespace:Content.Client.Administration.UI.Tabs.BabyJailTab"
+    xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
+    Margin="4">
+    <BoxContainer Orientation="Vertical">
+        <cc:CommandButton Name="EnabledButton" Command="babyjail" ToggleMode="True"
+                          Text="{Loc admin-ui-baby-jail-disabled}"
+                          ToolTip="{Loc admin-ui-baby-jail-tooltip}" />
+        <cc:CommandButton Name="ShowReasonButton" Command="babyjail_show_reason"
+                          ToggleMode="True" Text="{Loc admin-ui-baby-jail-show-reason}"
+                          ToolTip="{Loc admin-ui-baby-jail-show-reason-tooltip}" />
+        <BoxContainer Orientation="Vertical" Margin="0 10 0 0">
+            <BoxContainer Orientation="Horizontal" Margin="2">
+                <Label Text="{Loc admin-ui-baby-jail-max-account-age}" MinWidth="175" />
+                <LineEdit Name="MaxAccountAge" MinWidth="50" Margin="0 0 5 0" />
+                <Label Text="{Loc generic-minutes}" />
+            </BoxContainer>
+            <BoxContainer Orientation="Horizontal" Margin="2">
+                <Label Text="{Loc admin-ui-baby-jail-max-overall-minutes}" MinWidth="175" />
+                <LineEdit Name="MaxOverallMinutes" MinWidth="50" Margin="0 0 5 0" />
+                <Label Text="{Loc generic-minutes}" />
+            </BoxContainer>
+        </BoxContainer>
+    </BoxContainer>
+</controls:BabyJailTab>
diff --git a/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailTab.xaml.cs b/Content.Client/Administration/UI/Tabs/BabyJailTab/BabyJailTab.xaml.cs
new file mode 100644 (file)
index 0000000..aa9d6ce
--- /dev/null
@@ -0,0 +1,75 @@
+using Content.Shared.Administration.Events;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Console;
+
+/*
+ * TODO: Remove me once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+ */
+
+namespace Content.Client.Administration.UI.Tabs.BabyJailTab;
+
+[GenerateTypedNameReferences]
+public sealed partial class BabyJailTab : Control
+{
+    [Dependency] private readonly IConsoleHost _console = default!;
+
+    private string _maxAccountAge;
+    private string _maxOverallMinutes;
+
+    public BabyJailTab()
+    {
+        RobustXamlLoader.Load(this);
+        IoCManager.InjectDependencies(this);
+
+        MaxAccountAge.OnTextEntered += args => SendMaxAccountAge(args.Text);
+        MaxAccountAge.OnFocusExit += args => SendMaxAccountAge(args.Text);
+        _maxAccountAge = MaxAccountAge.Text;
+
+        MaxOverallMinutes.OnTextEntered += args => SendMaxOverallMinutes(args.Text);
+        MaxOverallMinutes.OnFocusExit += args => SendMaxOverallMinutes(args.Text);
+        _maxOverallMinutes = MaxOverallMinutes.Text;
+    }
+
+    private void SendMaxAccountAge(string text)
+    {
+        if (string.IsNullOrWhiteSpace(text) ||
+            text == _maxAccountAge ||
+            !int.TryParse(text, out var minutes))
+        {
+            return;
+        }
+
+        _console.ExecuteCommand($"babyjail_max_account_age {minutes}");
+    }
+
+    private void SendMaxOverallMinutes(string text)
+    {
+        if (string.IsNullOrWhiteSpace(text) ||
+            text == _maxOverallMinutes ||
+            !int.TryParse(text, out var minutes))
+        {
+            return;
+        }
+
+        _console.ExecuteCommand($"babyjail_max_overall_minutes {minutes}");
+    }
+
+    public void UpdateStatus(BabyJailStatus status)
+    {
+        EnabledButton.Pressed = status.Enabled;
+        EnabledButton.Text = Loc.GetString(status.Enabled
+            ? "admin-ui-baby-jail-enabled"
+            : "admin-ui-baby-jail-disabled"
+        );
+        EnabledButton.ModulateSelfOverride = status.Enabled ? Color.Red : null;
+        ShowReasonButton.Pressed = status.ShowReason;
+
+        MaxAccountAge.Text = status.MaxAccountAgeMinutes.ToString();
+        _maxAccountAge = MaxAccountAge.Text;
+
+        MaxOverallMinutes.Text = status.MaxOverallMinutes.ToString();
+        _maxOverallMinutes = MaxOverallMinutes.Text;
+    }
+}
index 392a1a96de2e933857c0acd28ab3cef51f3fd302..d36a91c3733283835f1bfe177075c626fe31cb00 100644 (file)
@@ -3,6 +3,7 @@ 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.BabyJailTab;
 using Content.Client.Administration.UI.Tabs.PlayerTab;
 using Content.Client.Gameplay;
 using Content.Client.Lobby;
@@ -37,11 +38,13 @@ public sealed class AdminUIController : UIController,
     private AdminMenuWindow? _window;
     private MenuButton? AdminButton => UIManager.GetActiveUIWidgetOrNull<MenuBar.Widgets.GameTopMenuBar>()?.AdminButton;
     private PanicBunkerStatus? _panicBunker;
+    private BabyJailStatus? _babyJail;
 
     public override void Initialize()
     {
         base.Initialize();
         SubscribeNetworkEvent<PanicBunkerChangedEvent>(OnPanicBunkerUpdated);
+        SubscribeNetworkEvent<BabyJailChangedEvent>(OnBabyJailUpdated);
     }
 
     private void OnPanicBunkerUpdated(PanicBunkerChangedEvent msg, EntitySessionEventArgs args)
@@ -56,6 +59,18 @@ public sealed class AdminUIController : UIController,
         }
     }
 
+    private void OnBabyJailUpdated(BabyJailChangedEvent msg, EntitySessionEventArgs args)
+    {
+        var showDialog = _babyJail == null && msg.Status.Enabled;
+        _babyJail = msg.Status;
+        _window?.BabyJailControl.UpdateStatus(msg.Status);
+
+        if (showDialog)
+        {
+            UIManager.CreateWindow<BabyJailStatusWindow>().OpenCentered();
+        }
+    }
+
     public void OnStateEntered(GameplayState state)
     {
         EnsureWindow();
@@ -101,6 +116,13 @@ public sealed class AdminUIController : UIController,
         if (_panicBunker != null)
             _window.PanicBunkerControl.UpdateStatus(_panicBunker);
 
+        /*
+         * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+         */
+
+        if (_babyJail != null)
+            _window.BabyJailControl.UpdateStatus(_babyJail);
+
         _window.PlayerTabControl.OnEntryKeyBindDown += PlayerTabEntryKeyBindDown;
         _window.ObjectsTabControl.OnEntryKeyBindDown += ObjectsTabEntryKeyBindDown;
         _window.OnOpen += OnWindowOpen;
index bd5c4f5d7e8a341ed2dce25ee6665d8d30cfee01..dea8f9558abdd9c74341c2f057bd8b654fe5c657 100644 (file)
@@ -901,6 +901,10 @@ namespace Content.Server.Database
         Whitelist = 1,
         Full = 2,
         Panic = 3,
+        /*
+         * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+         */
+        BabyJail = 4,
     }
 
     public class ServerBanHit
diff --git a/Content.Server/Administration/Commands/BabyJailCommand.cs b/Content.Server/Administration/Commands/BabyJailCommand.cs
new file mode 100644 (file)
index 0000000..058b67c
--- /dev/null
@@ -0,0 +1,139 @@
+using Content.Shared.Administration;
+using Content.Shared.CCVar;
+using Robust.Shared.Configuration;
+using Robust.Shared.Console;
+
+/*
+ * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+ */
+
+namespace Content.Server.Administration.Commands;
+
+[AdminCommand(AdminFlags.Server)]
+public sealed class BabyJailCommand : LocalizedCommands
+{
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
+
+    public override string Command => "babyjail";
+
+    public override void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        var toggle = Toggle(CCVars.BabyJailEnabled, shell, args, _cfg);
+        if (toggle == null)
+            return;
+
+        shell.WriteLine(Loc.GetString(toggle.Value ? "babyjail-command-enabled" : "babyjail-command-disabled"));
+    }
+
+    public static bool? Toggle(CVarDef<bool> cvar, IConsoleShell shell, string[] args, IConfigurationManager config)
+    {
+        if (args.Length > 1)
+        {
+            shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
+            return null;
+        }
+
+        var enabled = config.GetCVar(cvar);
+
+        switch (args.Length)
+        {
+            case 0:
+                enabled = !enabled;
+                break;
+            case 1 when !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 BabyJailShowReasonCommand : LocalizedCommands
+{
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
+
+    public override string Command => "babyjail_show_reason";
+
+    public override void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        var toggle = BabyJailCommand.Toggle(CCVars.BabyJailShowReason, shell, args, _cfg);
+        if (toggle == null)
+            return;
+
+        shell.WriteLine(Loc.GetString(toggle.Value
+            ? "babyjail-command-show-reason-enabled"
+            : "babyjail-command-show-reason-disabled"
+        ));
+    }
+}
+
+[AdminCommand(AdminFlags.Server)]
+public sealed class BabyJailMinAccountAgeCommand : LocalizedCommands
+{
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
+
+    public override string Command => "babyjail_max_account_age";
+
+    public override void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        switch (args.Length)
+        {
+            case 0:
+            {
+                var current = _cfg.GetCVar(CCVars.BabyJailMaxAccountAge);
+                shell.WriteLine(Loc.GetString("babyjail-command-max-account-age-is", ("minutes", current)));
+                break;
+            }
+            case > 1:
+                shell.WriteError(Loc.GetString("shell-need-between-arguments",("lower", 0), ("upper", 1)));
+                return;
+        }
+
+        if (!int.TryParse(args[0], out var minutes))
+        {
+            shell.WriteError(Loc.GetString("shell-argument-must-be-number"));
+            return;
+        }
+
+        _cfg.SetCVar(CCVars.BabyJailMaxAccountAge, minutes);
+        shell.WriteLine(Loc.GetString("babyjail-command-max-account-age-set", ("minutes", minutes)));
+    }
+}
+
+[AdminCommand(AdminFlags.Server)]
+public sealed class BabyJailMinOverallHoursCommand : LocalizedCommands
+{
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
+
+    public override string Command => "babyjail_max_overall_minutes";
+
+    public override void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        switch (args.Length)
+        {
+            case 0:
+            {
+                var current = _cfg.GetCVar(CCVars.BabyJailMaxOverallMinutes);
+                shell.WriteLine(Loc.GetString("babyjail-command-max-overall-minutes-is", ("minutes", current)));
+                break;
+            }
+            case > 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.BabyJailMaxOverallMinutes, hours);
+        shell.WriteLine(Loc.GetString("babyjail-command-overall-minutes-set", ("hours", hours)));
+    }
+}
index 6a59aebfd02a0483dda5332a80e00d7153664f34..16c079e4ba1d234927074855ce793d91439b6a81 100644 (file)
@@ -61,6 +61,7 @@ namespace Content.Server.Administration.Systems
 
         private readonly HashSet<NetUserId> _roundActivePlayers = new();
         public readonly PanicBunkerStatus PanicBunker = new();
+        public readonly BabyJailStatus BabyJail = new();
 
         public override void Initialize()
         {
@@ -70,6 +71,7 @@ namespace Content.Server.Administration.Systems
             _adminManager.OnPermsChanged += OnAdminPermsChanged;
             _playTime.SessionPlayTimeUpdated += OnSessionPlayTimeUpdated;
 
+            // Panic Bunker Settings
             Subs.CVar(_config, CCVars.PanicBunkerEnabled, OnPanicBunkerChanged, true);
             Subs.CVar(_config, CCVars.PanicBunkerDisableWithAdmins, OnPanicBunkerDisableWithAdminsChanged, true);
             Subs.CVar(_config, CCVars.PanicBunkerEnableWithoutAdmins, OnPanicBunkerEnableWithoutAdminsChanged, true);
@@ -78,6 +80,16 @@ namespace Content.Server.Administration.Systems
             Subs.CVar(_config, CCVars.PanicBunkerMinAccountAge, OnPanicBunkerMinAccountAgeChanged, true);
             Subs.CVar(_config, CCVars.PanicBunkerMinOverallMinutes, OnPanicBunkerMinOverallMinutesChanged, true);
 
+            /*
+             * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+             */
+
+            // Baby Jail Settings
+            Subs.CVar(_config, CCVars.BabyJailEnabled, OnBabyJailChanged, true);
+            Subs.CVar(_config, CCVars.BabyJailShowReason, OnBabyJailShowReasonChanged, true);
+            Subs.CVar(_config, CCVars.BabyJailMaxAccountAge, OnBabyJailMaxAccountAgeChanged, true);
+            Subs.CVar(_config, CCVars.BabyJailMaxOverallMinutes, OnBabyJailMaxOverallMinutesChanged, true);
+
             SubscribeLocalEvent<IdentityChangedEvent>(OnIdentityChanged);
             SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
             SubscribeLocalEvent<PlayerDetachedEvent>(OnPlayerDetached);
@@ -250,6 +262,17 @@ namespace Content.Server.Administration.Systems
             SendPanicBunkerStatusAll();
         }
 
+        private void OnBabyJailChanged(bool enabled)
+        {
+            BabyJail.Enabled = enabled;
+            _chat.SendAdminAlert(Loc.GetString(enabled
+                ? "admin-ui-baby-jail-enabled-admin-alert"
+                : "admin-ui-baby-jail-disabled-admin-alert"
+            ));
+
+            SendBabyJailStatusAll();
+        }
+
         private void OnPanicBunkerDisableWithAdminsChanged(bool enabled)
         {
             PanicBunker.DisableWithAdmins = enabled;
@@ -274,18 +297,36 @@ namespace Content.Server.Administration.Systems
             SendPanicBunkerStatusAll();
         }
 
+        private void OnBabyJailShowReasonChanged(bool enabled)
+        {
+            BabyJail.ShowReason = enabled;
+            SendBabyJailStatusAll();
+        }
+
         private void OnPanicBunkerMinAccountAgeChanged(int minutes)
         {
             PanicBunker.MinAccountAgeMinutes = minutes;
             SendPanicBunkerStatusAll();
         }
 
+        private void OnBabyJailMaxAccountAgeChanged(int minutes)
+        {
+            BabyJail.MaxAccountAgeMinutes = minutes;
+            SendBabyJailStatusAll();
+        }
+
         private void OnPanicBunkerMinOverallMinutesChanged(int minutes)
         {
             PanicBunker.MinOverallMinutes = minutes;
             SendPanicBunkerStatusAll();
         }
 
+        private void OnBabyJailMaxOverallMinutesChanged(int minutes)
+        {
+            BabyJail.MaxOverallMinutes = minutes;
+            SendBabyJailStatusAll();
+        }
+
         private void UpdatePanicBunker()
         {
             var admins = PanicBunker.CountDeadminnedAdmins
@@ -327,6 +368,15 @@ namespace Content.Server.Administration.Systems
             }
         }
 
+        private void SendBabyJailStatusAll()
+        {
+            var ev = new BabyJailChangedEvent(BabyJail);
+            foreach (var admin in _adminManager.AllAdmins)
+            {
+                RaiseNetworkEvent(ev, admin);
+            }
+        }
+
         /// <summary>
         ///     Erases a player from the round.
         ///     This removes them and any trace of them from the round, deleting their
index 42732ff1b1cdf37cadebc29b45f30185d04153f1..cf7581aa4e654db07797b3dd4325c531aa5d5f55 100644 (file)
@@ -17,6 +17,9 @@ using Robust.Shared.Network;
 using Robust.Shared.Player;
 using Robust.Shared.Timing;
 
+/*
+ * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+ */
 
 namespace Content.Server.Connection
 {
@@ -248,6 +251,14 @@ namespace Content.Server.Connection
                 }
             }
 
+            if (_cfg.GetCVar(CCVars.BabyJailEnabled) && adminData == null)
+            {
+                var result = await IsInvalidConnectionDueToBabyJail(userId, e);
+
+                if (result.IsInvalid)
+                    return (ConnectionDenyReason.BabyJail, result.Reason, null);
+            }
+
             var wasInGame = EntitySystem.TryGet<GameTicker>(out var ticker) &&
                             ticker.PlayerGameStatuses.TryGetValue(userId, out var status) &&
                             status == PlayerGameStatus.JoinedGame;
@@ -277,6 +288,61 @@ namespace Content.Server.Connection
             return null;
         }
 
+        private async Task<(bool IsInvalid, string Reason)> IsInvalidConnectionDueToBabyJail(NetUserId userId, NetConnectingArgs e)
+        {
+            // If you're whitelisted then bypass this whole thing
+            if (await _db.GetWhitelistStatusAsync(userId))
+                return (false, "");
+
+            // Initial cvar retrieval
+            var showReason = _cfg.GetCVar(CCVars.BabyJailShowReason);
+            var reason = _cfg.GetCVar(CCVars.BabyJailCustomReason);
+            var maxAccountAgeMinutes = _cfg.GetCVar(CCVars.BabyJailMaxAccountAge);
+            var maxPlaytimeMinutes = _cfg.GetCVar(CCVars.BabyJailMaxOverallMinutes);
+
+            // Wait some time to lookup data
+            var record = await _dbManager.GetPlayerRecordByUserId(userId);
+
+            // No player record = new account or the DB is having a skill issue
+            if (record == null)
+                return (false, "");
+
+            var isAccountAgeInvalid = record.FirstSeenTime.CompareTo(DateTimeOffset.Now - TimeSpan.FromMinutes(maxAccountAgeMinutes)) <= 0;
+            if (isAccountAgeInvalid && showReason)
+            {
+                var locAccountReason = reason != string.Empty
+                    ? reason
+                    : Loc.GetString("baby-jail-account-denied-reason",
+                        ("reason",
+                            Loc.GetString(
+                                "baby-jail-account-reason-account",
+                                ("minutes", maxAccountAgeMinutes))));
+
+                return (true, locAccountReason);
+            }
+
+            var overallTime = ( await _db.GetPlayTimes(e.UserId)).Find(p => p.Tracker == PlayTimeTrackingShared.TrackerOverall);
+            var isTotalPlaytimeInvalid = overallTime == null || overallTime.TimeSpent.TotalMinutes >= maxPlaytimeMinutes;
+
+            if (isTotalPlaytimeInvalid && showReason)
+            {
+                var locPlaytimeReason = reason != string.Empty
+                    ? reason
+                    : Loc.GetString("baby-jail-account-denied-reason",
+                        ("reason",
+                            Loc.GetString(
+                                "baby-jail-account-reason-overall",
+                                ("minutes", maxPlaytimeMinutes))));
+
+                return (true, locPlaytimeReason);
+            }
+
+            if (!showReason && isTotalPlaytimeInvalid || isAccountAgeInvalid)
+                return (true, Loc.GetString("baby-jail-account-denied"));
+
+            return (false, "");
+        }
+
         private bool HasTemporaryBypass(NetUserId user)
         {
             return _temporaryBypasses.TryGetValue(user, out var time) && time > _gameTiming.RealTime;
index fcf5b1c25cd7e6f9c4c91a8a12344222b5cccdea..67367b94b7f5abe10bdab6afba86d8e9f3426fe6 100644 (file)
@@ -46,6 +46,12 @@ namespace Content.Server.GameTicking
                 jObject["players"] = _playerManager.PlayerCount;
                 jObject["soft_max_players"] = _cfg.GetCVar(CCVars.SoftMaxPlayers);
                 jObject["panic_bunker"] = _cfg.GetCVar(CCVars.PanicBunkerEnabled);
+
+                /*
+                 * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+                 */
+
+                jObject["baby_jail"] = _cfg.GetCVar(CCVars.BabyJailEnabled);
                 jObject["run_level"] = (int) _runLevel;
                 if (preset != null)
                     jObject["preset"] = Loc.GetString(preset.ModeTitle);
diff --git a/Content.Shared/Administration/Events/BabyJailChangedEvent.cs b/Content.Shared/Administration/Events/BabyJailChangedEvent.cs
new file mode 100644 (file)
index 0000000..56d5ce5
--- /dev/null
@@ -0,0 +1,22 @@
+using Robust.Shared.Serialization;
+
+/*
+ * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+ */
+
+namespace Content.Shared.Administration.Events;
+
+[Serializable, NetSerializable]
+public sealed class BabyJailStatus
+{
+    public bool Enabled;
+    public bool ShowReason;
+    public int MaxAccountAgeMinutes;
+    public int MaxOverallMinutes;
+}
+
+[Serializable, NetSerializable]
+public sealed class BabyJailChangedEvent(BabyJailStatus status) : EntityEventArgs
+{
+    public BabyJailStatus Status = status;
+}
index 8c70631b945c67e0b15c88724902f0e2a9e80299..a0e9157e922d9c1388ed11004ff23a4458ecd88f 100644 (file)
@@ -332,6 +332,48 @@ namespace Content.Shared.CCVar
         public static readonly CVarDef<bool> BypassBunkerWhitelist =
             CVarDef.Create("game.panic_bunker.whitelisted_can_bypass", true, CVar.SERVERONLY);
 
+        /*
+         * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future.
+         */
+
+        /// <summary>
+        /// Whether the baby jail is currently enabled.
+        /// </summary>
+        public static readonly CVarDef<bool> BabyJailEnabled  =
+            CVarDef.Create("game.baby_jail.enabled", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER);
+
+        /// <summary>
+        /// Show reason of disconnect for user or not.
+        /// </summary>
+        public static readonly CVarDef<bool> BabyJailShowReason =
+            CVarDef.Create("game.baby_jail.show_reason", false, CVar.SERVERONLY);
+
+        /// <summary>
+        /// Maximum age of the account (from server's PoV, so from first-seen date) in minutes that can access baby
+        /// jailed servers.
+        /// </summary>
+        public static readonly CVarDef<int> BabyJailMaxAccountAge =
+            CVarDef.Create("game.baby_jail.max_account_age", 1440, CVar.SERVERONLY);
+
+        /// <summary>
+        /// Maximum overall played time allowed to access baby jailed servers.
+        /// </summary>
+        public static readonly CVarDef<int> BabyJailMaxOverallMinutes =
+            CVarDef.Create("game.baby_jail.max_overall_minutes", 120, CVar.SERVERONLY);
+
+        /// <summary>
+        /// A custom message that will be used for connections denied due to the baby jail.
+        /// If not empty, then will overwrite <see cref="BabyJailShowReason"/>
+        /// </summary>
+        public static readonly CVarDef<string> BabyJailCustomReason =
+            CVarDef.Create("game.baby_jail.custom_reason", string.Empty, CVar.SERVERONLY);
+
+        /// <summary>
+        /// Allow bypassing the baby jail if the user is whitelisted.
+        /// </summary>
+        public static readonly CVarDef<bool> BypassBabyJailWhitelist =
+            CVarDef.Create("game.baby_jail.whitelisted_can_bypass", true, CVar.SERVERONLY);
+
         /// <summary>
         /// Make people bonk when trying to climb certain objects like tables.
         /// </summary>
index 787321232609e1cbebb3fa3128c7ace38c34ef3e..b0f955bddec889cdbb1f1ad1501144a14e48a17a 100644 (file)
@@ -11,6 +11,12 @@ panic_bunker.enabled = false
 panic_bunker.disable_with_admins = false
 panic_bunker.enable_without_admins = false
 panic_bunker.custom_reason = ""
+baby_jail.enabled = true
+baby_jail.show_reason = true
+baby_jail.max_account_age = 5256000 # 10 years. Disabling this check specifically isn't currently supported
+baby_jail.max_overall_minutes = 3000 # 50 hours
+baby_jail.custom_reason = "Sorry! Only new players can join the servers, try joining another one instead!"
+baby_jail.whitelisted_can_bypass = true
 
 [hub]
 tags = "lang:en,region:am_n_e,rp:low"
index d1cbfb9c905195bb721a961a84647f2a77ee0b7b..21abbf2e3f0702c636adb9a99eac2365117f676c 100644 (file)
@@ -8,6 +8,10 @@
 soft_max_players = 50
 hostname = "[EN] Wizard's Den Granite Flea [US East]"
 desc = "Official English Space Station 14 servers. Vanilla, roleplay ruleset."
+panic_bunker.enabled = false
+panic_bunker.disable_with_admins = false
+panic_bunker.enable_without_admins = false
+panic_bunker.custom_reason = ""
 
 [hub]
 tags = "lang:en,region:am_n_e,rp:low"
diff --git a/Resources/Locale/en-US/administration/commands/babyjail.ftl b/Resources/Locale/en-US/administration/commands/babyjail.ftl
new file mode 100644 (file)
index 0000000..5a9d949
--- /dev/null
@@ -0,0 +1,19 @@
+cmd-babyjail-desc = Toggles the baby jail, which enables stricter restrictions on who's allowed to join the server.
+cmd-babyjail-help = Usage: babyjail
+babyjail-command-enabled = Baby jail has been enabled.
+babyjail-command-disabled = Baby jail has been disabled.
+
+cmd-babyjail_show_reason-desc = Toggles whether or not to show connecting clients the reason why the baby jail blocked them from joining.
+cmd-babyjail_show_reason-help = Usage: babyjail_show_reason
+babyjail-command-show-reason-enabled = The baby jail will now show a reason to users it blocks from connecting.
+babyjail-command-show-reason-disabled = The baby jail will no longer show a reason to users it blocks from connecting.
+
+cmd-babyjail_max_account_age-desc = Gets or sets the maximum account age in minutes that an account can have to be allowed to connect with the baby jail enabled.
+cmd-babyjail_max_account_age-help = Usage: babyjail_max_account_age <minutes>
+babyjail-command-max-account-age-is = The maximum account age for the baby jail is {$minutes} minutes.
+babyjail-command-max-account-age-set = Set the maximum account age for the baby jail to {$minutes} minutes.
+
+cmd-babyjail_max_overall_minutes-desc = Gets or sets the maximum overall playtime in minutes that an account can have to be allowed to connect with the baby jail enabled.
+cmd-babyjail_max_overall_minutes-help = Usage: babyjail_max_overall_minutes <minutes>
+babyjail-command-max-overall-minutes-is = The maximum overall playtime for the baby jail is {$minutes} minutes.
+babyjail-command-max-overall-minutes-set = Set the maximum overall playtime for the baby jail to {$minutes} minutes.
index c759e4c2cb16f2b3b857f1a4e8eb259e8667886f..03b2046a9e15ba0344d6948d053b204fd146a59b 100644 (file)
@@ -7,5 +7,6 @@ admin-menu-atmos-tab = Atmos
 admin-menu-round-tab = Round
 admin-menu-server-tab = Server
 admin-menu-panic-bunker-tab = Panic Bunker
+admin-menu-baby-jail-tab = Baby Jail
 admin-menu-players-tab = Players
 admin-menu-objects-tab = Objects
diff --git a/Resources/Locale/en-US/administration/ui/tabs/babyjail-tab.ftl b/Resources/Locale/en-US/administration/ui/tabs/babyjail-tab.ftl
new file mode 100644 (file)
index 0000000..46dce54
--- /dev/null
@@ -0,0 +1,16 @@
+admin-ui-baby-jail-window-title = Baby Jail
+
+admin-ui-baby-jail-enabled = Baby Jail Enabled
+admin-ui-baby-jail-disabled = Baby Jail Disabled
+admin-ui-baby-jail-tooltip = The baby jail restricts players from joining if their account is too old or they do have too much overall playtime on this server.
+
+admin-ui-baby-jail-show-reason = Show Reason
+admin-ui-baby-jail-show-reason-tooltip = Show the user why they were blocked from connecting by the baby jail.
+
+admin-ui-baby-jail-max-account-age = Max. Account Age
+admin-ui-baby-jail-max-overall-minutes = Max. Overall Playtime
+
+admin-ui-baby-jail-is-enabled = [font size=20][bold]The baby jail is currently enabled.[/bold][/font]
+
+admin-ui-baby-jail-enabled-admin-alert = The baby jail has been enabled.
+admin-ui-baby-jail-disabled-admin-alert = The baby jail has been disabled.
index 65796b9c795f63eb18f1f28450f74fe7b27eb183..f1596d90152bf465853426cf472190fa4c3b901d 100644 (file)
@@ -40,3 +40,8 @@ panic-bunker-account-denied-reason = This server is in panic bunker mode, often
 panic-bunker-account-reason-account = Your Space Station 14 account is too new. It must be older than {$minutes} minutes
 panic-bunker-account-reason-overall = Your overall playtime on the server must be greater than {$minutes} $minutes
 
+baby-jail-account-denied = This server is a newbie server, intended for new players and those who want to help them. New connections by accounts that are too old or are not on a whitelist are not accepted. Check out some other servers and see everything Space Station 14 has to offer. Have fun!
+baby-jail-account-denied-reason = This server is a newbie server, intended for new players and those who want to help them. New connections by accounts that are too old or are not on a whitelist are not accepted. Check out some other servers and see everything Space Station 14 has to offer. Have fun! Reason: "{$reason}"
+baby-jail-account-reason-account = Your Space Station 14 account is too old. It must be younger than {$minutes} minutes
+baby-jail-account-reason-overall = Your overall playtime on the server must be younger than {$minutes} $minutes
+