diff --git a/Content.Client/Administration/ClientAdminManager.cs b/Content.Client/Administration/ClientAdminManager.cs index 7ef0f31169..0f66a2df98 100644 --- a/Content.Client/Administration/ClientAdminManager.cs +++ b/Content.Client/Administration/ClientAdminManager.cs @@ -21,6 +21,11 @@ namespace Content.Client.Administration public event Action? AdminStatusUpdated; + public bool IsActive() + { + return _adminData?.Active ?? false; + } + public bool HasFlag(AdminFlags flag) { return _adminData?.HasFlag(flag) ?? false; diff --git a/Content.Client/Administration/IClientAdminManager.cs b/Content.Client/Administration/IClientAdminManager.cs index e675e3f378..ed04f1d7e0 100644 --- a/Content.Client/Administration/IClientAdminManager.cs +++ b/Content.Client/Administration/IClientAdminManager.cs @@ -15,6 +15,12 @@ namespace Content.Client.Administration /// event Action AdminStatusUpdated; + /// + /// Checks whether the local player is an admin. + /// + /// true if the local player is an admin, false otherwise even if they are deadminned. + bool IsActive(); + /// /// Checks whether the local player has an admin flag. /// diff --git a/Content.Client/State/GameScreen.cs b/Content.Client/State/GameScreen.cs index eaeaa3fcff..dbbc4a2ab3 100644 --- a/Content.Client/State/GameScreen.cs +++ b/Content.Client/State/GameScreen.cs @@ -1,11 +1,14 @@ +using Content.Client.Administration; using Content.Client.Chat; using Content.Client.Interfaces.Chat; using Content.Client.UserInterface; using Content.Client.Voting; +using Content.Shared; using Content.Shared.Input; using Robust.Client.Input; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; +using Robust.Shared.Configuration; using Robust.Shared.Input.Binding; using Robust.Shared.IoC; using Robust.Shared.Localization; @@ -20,9 +23,14 @@ namespace Content.Client.State [Dependency] private readonly IInputManager _inputManager = default!; [Dependency] private readonly IChatManager _chatManager = default!; [Dependency] private readonly IVoteManager _voteManager = default!; + [Dependency] private readonly IConfigurationManager _configurationManager = default!; + [Dependency] private readonly IClientAdminManager _adminManager = default!; [ViewVariables] private ChatBox _gameChat; + private bool _oocEnabled; + private bool _adminOocEnabled; + public override void Startup() { base.Startup(); @@ -42,13 +50,17 @@ namespace Content.Client.State _gameChat.Input.PlaceHolder = Loc.GetString("Say something! [ for OOC"); _inputManager.SetInputCommand(ContentKeyFunctions.FocusChat, - InputCmdHandler.FromDelegate(s => FocusChat(_gameChat))); + InputCmdHandler.FromDelegate(_ => FocusChat(_gameChat))); _inputManager.SetInputCommand(ContentKeyFunctions.FocusOOC, - InputCmdHandler.FromDelegate(s => FocusOOC(_gameChat))); + InputCmdHandler.FromDelegate(_ => FocusOOC(_gameChat))); _inputManager.SetInputCommand(ContentKeyFunctions.FocusAdminChat, - InputCmdHandler.FromDelegate(s => FocusAdminChat(_gameChat))); + InputCmdHandler.FromDelegate(_ => FocusAdminChat(_gameChat))); + + _configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true); + _configurationManager.OnValueChanged(CCVars.AdminOocEnabled, OnAdminOocEnabledChanged, true); + _adminManager.AdminStatusUpdated += OnAdminStatusUpdated; } public override void Shutdown() @@ -59,6 +71,37 @@ namespace Content.Client.State _gameHud.RootControl.Orphan(); } + private void OnOocEnabledChanged(bool val) + { + _oocEnabled = val; + + if (_adminManager.IsActive()) + { + return; + } + + _gameChat.Input.PlaceHolder = Loc.GetString(_oocEnabled ? "Say something! [ for OOC" : "Say something!"); + } + + private void OnAdminOocEnabledChanged(bool val) + { + _adminOocEnabled = val; + + if (!_adminManager.IsActive()) + { + return; + } + + _gameChat.Input.PlaceHolder = Loc.GetString(_adminOocEnabled ? "Say something! [ for OOC" : "Say something!"); + } + + private void OnAdminStatusUpdated() + { + _gameChat.Input.PlaceHolder = _adminManager.IsActive() + ? Loc.GetString(_adminOocEnabled ? "Say something! [ for OOC" : "Say something!") + : Loc.GetString(_oocEnabled ? "Say something! [ for OOC" : "Say something!"); + } + internal static void FocusChat(ChatBox chat) { if (chat == null || chat.UserInterfaceManager.KeyboardFocused != null) diff --git a/Content.Server/Administration/AdminManager.cs b/Content.Server/Administration/AdminManager.cs index f1d9540017..7085525d2f 100644 --- a/Content.Server/Administration/AdminManager.cs +++ b/Content.Server/Administration/AdminManager.cs @@ -53,6 +53,11 @@ namespace Content.Server.Administration private readonly HashSet _anyCommands = new(); private readonly Dictionary _adminCommands = new(); + public bool IsAdmin(IPlayerSession session, bool includeDeAdmin = false) + { + return GetAdminData(session, includeDeAdmin) != null; + } + public AdminData? GetAdminData(IPlayerSession session, bool includeDeAdmin = false) { if (_admins.TryGetValue(session, out var reg) && (reg.Data.Active || includeDeAdmin)) diff --git a/Content.Server/Administration/IAdminManager.cs b/Content.Server/Administration/IAdminManager.cs index cb7ba4b71d..e6fcd62667 100644 --- a/Content.Server/Administration/IAdminManager.cs +++ b/Content.Server/Administration/IAdminManager.cs @@ -25,12 +25,22 @@ namespace Content.Server.Administration /// IEnumerable ActiveAdmins { get; } + /// + /// Checks if a player is an admin. + /// + /// The player to check. + /// + /// Whether to return admin data for admins that are current de-adminned. + /// + /// true if the player is an admin, false otherwise. + bool IsAdmin(IPlayerSession session, bool includeDeAdmin = false); + /// /// Gets the admin data for a player, if they are an admin. /// /// The player to get admin data for. /// - /// Whether to return admin data for admins that are current de-adminned. + /// Whether to return admin data for admins that are current de-adminned. /// /// if the player is not an admin. AdminData? GetAdminData(IPlayerSession session, bool includeDeAdmin = false); diff --git a/Content.Server/Chat/ChatManager.cs b/Content.Server/Chat/ChatManager.cs index 4a7d558bee..9a107d1568 100644 --- a/Content.Server/Chat/ChatManager.cs +++ b/Content.Server/Chat/ChatManager.cs @@ -8,6 +8,7 @@ using Content.Server.GameObjects.Components.Observer; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces; using Content.Server.Interfaces.Chat; +using Content.Shared; using Content.Shared.Administration; using Content.Shared.Chat; using Content.Shared.GameObjects.Components.Inventory; @@ -15,6 +16,7 @@ using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Robust.Server.GameObjects; using Robust.Server.Player; +using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; @@ -29,10 +31,17 @@ namespace Content.Server.Chat /// internal sealed class ChatManager : IChatManager { + [Dependency] private readonly IServerNetManager _netManager = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IMoMMILink _mommiLink = default!; + [Dependency] private readonly IAdminManager _adminManager = default!; + [Dependency] private readonly IServerPreferencesManager _preferencesManager = default!; + [Dependency] private readonly IConfigurationManager _configurationManager = default!; + /// /// The maximum length a player-sent message can be sent /// - public int MaxMessageLength = 1000; + public const int MaxMessageLength = 1000; private const int VoiceRange = 7; // how far voice goes in world units @@ -43,12 +52,8 @@ namespace Content.Server.Chat //TODO: make prio based? private List _chatTransformHandlers; - - [Dependency] private readonly IServerNetManager _netManager = default!; - [Dependency] private readonly IPlayerManager _playerManager = default!; - [Dependency] private readonly IMoMMILink _mommiLink = default!; - [Dependency] private readonly IAdminManager _adminManager = default!; - [Dependency] private readonly IServerPreferencesManager _preferencesManager = default!; + private bool _oocEnabled = true; + private bool _adminOocEnabled = true; public void Initialize() { @@ -61,6 +66,21 @@ namespace Content.Server.Chat _netManager.ServerSendToAll(msg); _chatTransformHandlers = new List(); + + _configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true); + _configurationManager.OnValueChanged(CCVars.AdminOocEnabled, OnAdminOocEnabledChanged, true); + } + + private void OnOocEnabledChanged(bool val) + { + _oocEnabled = val; + DispatchServerAnnouncement(val ? "OOC chat has been enabled." : "OOC chat has been disabled."); + } + + private void OnAdminOocEnabledChanged(bool val) + { + _adminOocEnabled = val; + DispatchServerAnnouncement(val ? "Admin OOC chat has been enabled." : "Admin OOC chat has been disabled."); } public void DispatchServerAnnouncement(string message) @@ -166,15 +186,17 @@ namespace Content.Server.Chat } // Check if entity is a player - IPlayerSession playerSession = source.GetComponent().playerSession; + if (!source.TryGetComponent(out IActorComponent actor)) + { + return; + } // Check if message exceeds the character limit - if (playerSession != null) - if (action.Length > MaxMessageLength) - { - DispatchServerMessage(playerSession, Loc.GetString(MaxLengthExceededMessage, MaxMessageLength)); - return; - } + if (actor.playerSession != null && action.Length > MaxMessageLength) + { + DispatchServerMessage(actor.playerSession, Loc.GetString(MaxLengthExceededMessage, MaxMessageLength)); + return; + } var pos = source.Transform.Coordinates; var clients = _playerManager.GetPlayersInRange(pos, VoiceRange).Select(p => p.ConnectedClient); @@ -189,6 +211,18 @@ namespace Content.Server.Chat public void SendOOC(IPlayerSession player, string message) { + if (_adminManager.IsAdmin(player)) + { + if (!_adminOocEnabled) + { + return; + } + } + else if (!_oocEnabled) + { + return; + } + // Check if message exceeds the character limit if (message.Length > MaxMessageLength) { @@ -202,7 +236,7 @@ namespace Content.Server.Chat msg.MessageWrap = $"OOC: {player.Name}: {{0}}"; if (_adminManager.HasAdminFlag(player, AdminFlags.Admin)) { - var prefs = _preferencesManager.GetPreferences((player.UserId)); + var prefs = _preferencesManager.GetPreferences(player.UserId); msg.MessageColorOverride = prefs.AdminOOCColor; } //TODO: player.Name color, this will need to change the structure of the MsgChatMessage diff --git a/Content.Shared/CCVars.cs b/Content.Shared/CCVars.cs index c37c01cb99..522b7c791f 100644 --- a/Content.Shared/CCVars.cs +++ b/Content.Shared/CCVars.cs @@ -252,5 +252,14 @@ namespace Content.Shared */ public static readonly CVarDef BrandingSteam = CVarDef.Create("branding.steam", false, CVar.CLIENTONLY); + + /* + * OOC + */ + + public static readonly CVarDef OocEnabled = CVarDef.Create("ooc.enabled", true, CVar.NOTIFY); + + public static readonly CVarDef AdminOocEnabled = + CVarDef.Create("ooc.enabled_admin", true, CVar.NOTIFY); } }