base.Shutdown();
ShutdownEmotes();
_configurationManager.UnsubValueChanged(CCVars.LoocEnabled, OnLoocEnabledChanged);
+ _configurationManager.UnsubValueChanged(CCVars.DeadLoocEnabled, OnDeadLoocEnabledChanged);
}
private void OnLoocEnabledChanged(bool val)
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>
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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"));
+ }
+}
--- /dev/null
+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
+}
--- /dev/null
+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"));
+ }
+}
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
*/
--- /dev/null
+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}