]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
MotD (#13655)
authorTemporalOroboros <TemporalOroboros@gmail.com>
Tue, 28 Feb 2023 16:15:48 +0000 (08:15 -0800)
committerGitHub <noreply@github.com>
Tue, 28 Feb 2023 16:15:48 +0000 (08:15 -0800)
* MOTD

* Message of the Day

* Pretty sure the tests aren't me. Let's check.

* Update Content.Shared/CCVar/CCVars.cs

Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
* command dependencies and moving MOTD to its own system

* Some doc comments

* Let's try those tests again

* More doc comments, most of the github reviews, and aliases for get-motd and set-motd

* Clear test MOTD

* Localized motd commands and completion hints

* Makes set-motd only show up in the alias command if the player has access to it.

---------

Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com>
Content.Server/Chat/Systems/ChatSystem.cs
Content.Server/Motd/GetMOTDCommand.cs [new file with mode: 0644]
Content.Server/Motd/MOTDCommand.cs [new file with mode: 0644]
Content.Server/Motd/MOTDSystem.cs [new file with mode: 0644]
Content.Server/Motd/SetMOTDCommand.cs [new file with mode: 0644]
Content.Shared/CCVar/CCVars.cs
Resources/Locale/en-US/motd/motd.ftl [new file with mode: 0644]

index f180cf045a47743ee0ad87d264a98ebce271d528..fd3182e65c4360025f3dbbcb2bf7a0e961fddcd4 100644 (file)
@@ -77,6 +77,7 @@ public sealed partial class ChatSystem : SharedChatSystem
         base.Shutdown();
         ShutdownEmotes();
         _configurationManager.UnsubValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged);
+        _configurationManager.UnsubValueChanged(CCVars.DeadLoocEnabled, OnDeadLoocEnabledChanged);
     }
 
     private void OnLoocEnabledChanged(bool val)
@@ -99,13 +100,17 @@ public sealed partial class ChatSystem : SharedChatSystem
 
     private void OnGameChange(GameRunLevelChangedEvent ev)
     {
-        if (_configurationManager.GetCVar(CCVars.OocEnableDuringRound))
-            return;
-
-        if (ev.New == GameRunLevel.InRound)
-            _configurationManager.SetCVar(CCVars.OocEnabled, false);
-        else if (ev.New == GameRunLevel.PostRound)
-            _configurationManager.SetCVar(CCVars.OocEnabled, true);
+        switch(ev.New)
+        {
+            case GameRunLevel.InRound:
+                if(!_configurationManager.GetCVar(CCVars.OocEnableDuringRound))
+                    _configurationManager.SetCVar(CCVars.OocEnabled, false);
+                break;
+            case GameRunLevel.PostRound:
+                if(!_configurationManager.GetCVar(CCVars.OocEnableDuringRound))
+                    _configurationManager.SetCVar(CCVars.OocEnabled, true);
+                break;
+        }
     }
 
     /// <summary>
diff --git a/Content.Server/Motd/GetMOTDCommand.cs b/Content.Server/Motd/GetMOTDCommand.cs
new file mode 100644 (file)
index 0000000..dc310e9
--- /dev/null
@@ -0,0 +1,20 @@
+using Content.Shared.Administration;
+using Robust.Shared.Console;
+
+namespace Content.Server.Motd;
+
+/// <summary>
+/// A command that can be used by any player to print the Message of the Day.
+/// </summary>
+[AnyCommand]
+public sealed class GetMotdCommand : LocalizedCommands
+{
+    [Dependency] private readonly IEntityManager _entityManager = default!;
+
+    public override string Command => "get-motd";
+    
+    public override void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        _entityManager.EntitySysManager.GetEntitySystem<MOTDSystem>().TrySendMOTD(shell);
+    }
+}
diff --git a/Content.Server/Motd/MOTDCommand.cs b/Content.Server/Motd/MOTDCommand.cs
new file mode 100644 (file)
index 0000000..a1aa4d2
--- /dev/null
@@ -0,0 +1,36 @@
+using Content.Server.Administration.Managers;
+using Content.Shared.Administration;
+using Robust.Server.Player;
+using Robust.Shared.Console;
+
+namespace Content.Server.Motd;
+
+/// <summary>
+/// A console command which acts as an alias for <see cref="GetMotdCommand"/> or <see cref="SetMotdCommand"/> depending on the number of arguments given.
+/// </summary>
+[AnyCommand]
+internal sealed class MOTDCommand : LocalizedCommands
+{
+    [Dependency] private readonly IAdminManager _adminManager = default!;
+
+    public override string Command => "motd";
+    
+    public override void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        var player = (IPlayerSession?)shell.Player;
+        if (args.Length < 1 || (player != null && _adminManager is AdminManager aMan && !aMan.CanCommand(player, "set-motd")))
+            shell.ConsoleHost.ExecuteCommand(shell.Player, "get-motd");
+        else
+            shell.ConsoleHost.ExecuteCommand(shell.Player, $"set-motd {string.Join(" ", args)}");
+    }
+
+    public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
+    {
+        var player = (IPlayerSession?)shell.Player;
+        if (player != null && _adminManager is AdminManager aMan && !aMan.CanCommand(player, "set-motd"))
+            return CompletionResult.Empty;
+        if (args.Length == 1)
+            return CompletionResult.FromHint(Loc.GetString("cmd-set-motd-hint-head"));
+        return CompletionResult.FromHint(Loc.GetString("cmd-set-motd-hint-cont"));
+    }
+}
diff --git a/Content.Server/Motd/MOTDSystem.cs b/Content.Server/Motd/MOTDSystem.cs
new file mode 100644 (file)
index 0000000..e749fe4
--- /dev/null
@@ -0,0 +1,101 @@
+using Content.Server.Chat.Managers;
+using Content.Server.GameTicking;
+using Content.Shared.CCVar;
+using Content.Shared.Chat;
+using Robust.Server.Player;
+using Robust.Shared.Console;
+using Robust.Shared.Configuration;
+
+namespace Content.Server.Motd;
+
+/// <summary>
+/// The system that handles broadcasting the Message Of The Day to players when they join the lobby/the MOTD changes/they ask for it to be printed.
+/// </summary>
+public sealed class MOTDSystem : EntitySystem
+{
+    [Dependency] private readonly IChatManager _chatManager = default!;
+    [Dependency] private readonly IConfigurationManager _configurationManager = default!;
+
+    /// <summary>
+    /// The cached value of the Message of the Day. Used for fast access.
+    /// </summary>
+    private string _messageOfTheDay = "";
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        _configurationManager.OnValueChanged(CCVars.MOTD, OnMOTDChanged, invokeImmediately: true);
+        SubscribeLocalEvent<PlayerJoinedLobbyEvent>(OnPlayerJoinedLobby);
+    }
+
+    public override void Shutdown()
+    {
+        _configurationManager.UnsubValueChanged(CCVars.MOTD, OnMOTDChanged);
+        base.Shutdown();
+    }
+
+    /// <summary>
+    /// Sends the Message Of The Day, if any, to all connected players.
+    /// </summary>
+    public void TrySendMOTD()
+    {
+        if (string.IsNullOrEmpty(_messageOfTheDay))
+            return;
+        
+        var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay));
+        _chatManager.ChatMessageToAll(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, recordReplay: true);
+    }
+
+    /// <summary>
+    /// Sends the Message Of The Day, if any, to a specific player.
+    /// </summary>
+    public void TrySendMOTD(IPlayerSession player)
+    {
+        if (string.IsNullOrEmpty(_messageOfTheDay))
+            return;
+        
+        var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay));
+        _chatManager.ChatMessageToOne(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, client: player.ConnectedClient);
+    }
+
+    /// <summary>
+    /// Sends the Message Of The Day, if any, to a specific player's console and chat.
+    /// </summary>
+    /// <remarks>
+    /// This is used by the MOTD console command because we can't tell whether the player is using `console or /console so we send the message to both.
+    /// </remarks>
+    public void TrySendMOTD(IConsoleShell shell)
+    {
+        if (string.IsNullOrEmpty(_messageOfTheDay))
+            return;
+        
+        var wrappedMessage = Loc.GetString("motd-wrap-message", ("motd", _messageOfTheDay));
+        shell.WriteLine(wrappedMessage);
+        if (shell.Player is IPlayerSession player)
+            _chatManager.ChatMessageToOne(ChatChannel.Server, _messageOfTheDay, wrappedMessage, source: EntityUid.Invalid, hideChat: false, client: player.ConnectedClient);
+    }
+
+    #region Event Handlers
+
+    /// <summary>
+    /// Posts the Message Of The Day to any players who join the lobby.
+    /// </summary>
+    private void OnPlayerJoinedLobby(PlayerJoinedLobbyEvent ev)
+    {
+        TrySendMOTD(ev.PlayerSession);
+    }
+
+    /// <summary>
+    /// Broadcasts changes to the Message Of The Day to all players.
+    /// </summary>
+    private void OnMOTDChanged(string val)
+    {
+        if (val == _messageOfTheDay)
+            return;
+        
+        _messageOfTheDay = val;
+        TrySendMOTD();
+    }
+
+    #endregion Event Handlers
+}
diff --git a/Content.Server/Motd/SetMOTDCommand.cs b/Content.Server/Motd/SetMOTDCommand.cs
new file mode 100644 (file)
index 0000000..f3f52b0
--- /dev/null
@@ -0,0 +1,55 @@
+using Content.Server.Administration;
+using Content.Server.Administration.Logs;
+using Content.Shared.Administration;
+using Content.Shared.Database;
+using Content.Shared.CCVar;
+using Content.Server.Chat.Managers;
+using Robust.Server.Player;
+using Robust.Shared.Configuration;
+using Robust.Shared.Console;
+
+namespace Content.Server.Motd;
+
+/// <summary>
+/// A console command usable by any user which prints or sets the Message of the Day.
+/// </summary>
+[AdminCommand(AdminFlags.Admin)]
+public sealed class SetMotdCommand : LocalizedCommands
+{
+    [Dependency] private readonly IAdminLogManager _adminLogManager = default!;
+    [Dependency] private readonly IChatManager _chatManager = default!;
+    [Dependency] private readonly IConfigurationManager _configurationManager = default!;
+
+    public override string Command => "set-motd";
+    
+    public override void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        string motd = "";
+        var player = (IPlayerSession?)shell.Player;
+        if (args.Length > 0)
+        {
+            motd = string.Join(" ", args).Trim();
+            if (player != null && _chatManager.MessageCharacterLimit(player, motd))
+                return; // check function prints its own error response
+        }
+        
+        _configurationManager.SetCVar(CCVars.MOTD, motd); // A hook in MOTDSystem broadcasts changes to the MOTD to everyone so we don't need to do it here.
+        if (string.IsNullOrEmpty(motd))
+        {
+            shell.WriteLine(Loc.GetString("cmd-set-motd-cleared-motd-message"));
+            _adminLogManager.Add(LogType.Chat, LogImpact.Low, $"{(player == null ? "LOCALHOST" : player.ConnectedClient.UserName):Player} cleared the MOTD for the server.");
+        }
+        else
+        {
+            shell.WriteLine(Loc.GetString("cmd-set-motd-set-motd-message", ("motd", motd)));
+            _adminLogManager.Add(LogType.Chat, LogImpact.Low, $"{(player == null ? "LOCALHOST" : player.ConnectedClient.UserName):Player} set the MOTD for the server to \"{motd:motd}\"");
+        }
+    }
+
+    public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
+    {
+        if (args.Length == 1)
+            return CompletionResult.FromHint(Loc.GetString("cmd-set-motd-hint-head"));
+        return CompletionResult.FromHint(Loc.GetString("cmd-set-motd-hint-cont"));
+    }
+}
index 44cfb1d92965f48f3c826389d8300be49faece12..9bcaccc48d606f6f35fbb2ed70f3862ace46bb6c 100644 (file)
@@ -1214,6 +1214,15 @@ namespace Content.Shared.CCVar
         public static readonly CVarDef<bool> ChatShowTypingIndicator =
             CVarDef.Create("chat.show_typing_indicator", true, CVar.CLIENTONLY);
 
+        /// <summary>
+        /// A message broadcast to each player that joins the lobby.
+        /// May be changed by admins ingame through use of the "set-motd" command.
+        /// In this case the new value, if not empty, is broadcast to all connected players and saved between rounds.
+        /// May be requested by any player through use of the "get-motd" command.
+        /// </summary>
+        public static readonly CVarDef<string> MOTD =
+            CVarDef.Create("chat.motd", "", CVar.SERVER | CVar.SERVERONLY | CVar.ARCHIVE, "A message broadcast to each player that joins the lobby.");
+
         /*
          * AFK
          */
diff --git a/Resources/Locale/en-US/motd/motd.ftl b/Resources/Locale/en-US/motd/motd.ftl
new file mode 100644 (file)
index 0000000..4e982e7
--- /dev/null
@@ -0,0 +1,11 @@
+cmd-motd-desc = Prints or sets the Message Of The Day.
+cmd-motd-help = motd [ message... ]
+cmd-get-motd-desc = Prints the Message Of The Day.
+cmd-get-motd-help = get-motd
+cmd-set-motd-desc = Sets or clears the Message Of The Day.
+cmd-set-motd-help = set-motd [ message... ]
+cmd-set-motd-hint-head = [ message... ]
+cmd-set-motd-hint-cont = [ ...message... ]
+cmd-set-motd-cleared-motd-message = Cleared the Message of the Day.
+cmd-set-motd-set-motd-message = Set the Message Of The Day to "{$motd}".
+motd-wrap-message = Message of the Day: {$motd}