]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Namespace cleanup around Mind Roles (#30965)
authorErrant <35878406+Errant-4@users.noreply.github.com>
Thu, 15 Aug 2024 18:26:57 +0000 (20:26 +0200)
committerGitHub <noreply@github.com>
Thu, 15 Aug 2024 18:26:57 +0000 (20:26 +0200)
* namespaces

* Comment does not need a semicolon

---------

Co-authored-by: Vasilis <vascreeper@yahoo.com>
14 files changed:
Content.Client/Administration/AdminNameOverlay.cs
Content.Client/Administration/UI/Tabs/PlayerTab/PlayerTab.xaml.cs
Content.Client/Chat/Managers/ChatManager.cs
Content.Server/Administration/Systems/AdminSystem.cs
Content.Server/Chat/Managers/ChatManager.cs
Content.Server/Ghost/ObserverRoleComponent.cs
Content.Server/Ghost/Roles/Components/GhostRoleComponent.cs
Content.Server/Ghost/Roles/GhostRoleSystem.cs
Content.Server/Zombies/ZombieSystem.Transform.cs
Content.Shared/Administration/Events/PlayerInfoChangedEvent.cs
Content.Shared/Administration/PlayerInfo.cs
Content.Shared/Ghost/Roles/SharedGhostRoleSystem.cs
Content.Shared/Mind/Components/MindContainerComponent.cs
Content.Shared/Mind/MindComponent.cs

index 27b2a5dedb066bc4492f11c5862938eef860f57e..6a1881a2276073e5006189a12112fee30c26919c 100644 (file)
@@ -7,67 +7,66 @@ using Robust.Shared.GameObjects;
 using Robust.Shared.IoC;
 using Robust.Shared.Maths;
 
-namespace Content.Client.Administration
+namespace Content.Client.Administration;
+
+internal sealed class AdminNameOverlay : Overlay
 {
-    internal sealed class AdminNameOverlay : Overlay
+    private readonly AdminSystem _system;
+    private readonly IEntityManager _entityManager;
+    private readonly IEyeManager _eyeManager;
+    private readonly EntityLookupSystem _entityLookup;
+    private readonly Font _font;
+
+    public AdminNameOverlay(AdminSystem system, IEntityManager entityManager, IEyeManager eyeManager, IResourceCache resourceCache, EntityLookupSystem entityLookup)
     {
-        private readonly AdminSystem _system;
-        private readonly IEntityManager _entityManager;
-        private readonly IEyeManager _eyeManager;
-        private readonly EntityLookupSystem _entityLookup;
-        private readonly Font _font;
+        _system = system;
+        _entityManager = entityManager;
+        _eyeManager = eyeManager;
+        _entityLookup = entityLookup;
+        ZIndex = 200;
+        _font = new VectorFont(resourceCache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
+    }
 
-        public AdminNameOverlay(AdminSystem system, IEntityManager entityManager, IEyeManager eyeManager, IResourceCache resourceCache, EntityLookupSystem entityLookup)
-        {
-            _system = system;
-            _entityManager = entityManager;
-            _eyeManager = eyeManager;
-            _entityLookup = entityLookup;
-            ZIndex = 200;
-            _font = new VectorFont(resourceCache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
-        }
+    public override OverlaySpace Space => OverlaySpace.ScreenSpace;
 
-        public override OverlaySpace Space => OverlaySpace.ScreenSpace;
+    protected override void Draw(in OverlayDrawArgs args)
+    {
+        var viewport = args.WorldAABB;
 
-        protected override void Draw(in OverlayDrawArgs args)
+        foreach (var playerInfo in _system.PlayerList)
         {
-            var viewport = args.WorldAABB;
+            var entity = _entityManager.GetEntity(playerInfo.NetEntity);
 
-            foreach (var playerInfo in _system.PlayerList)
+            // Otherwise the entity can not exist yet
+            if (entity == null || !_entityManager.EntityExists(entity))
             {
-                var entity = _entityManager.GetEntity(playerInfo.NetEntity);
-
-                // Otherwise the entity can not exist yet
-                if (entity == null || !_entityManager.EntityExists(entity))
-                {
-                    continue;
-                }
+                continue;
+            }
 
-                // if not on the same map, continue
-                if (_entityManager.GetComponent<TransformComponent>(entity.Value).MapID != args.MapId)
-                {
-                    continue;
-                }
+            // if not on the same map, continue
+            if (_entityManager.GetComponent<TransformComponent>(entity.Value).MapID != args.MapId)
+            {
+                continue;
+            }
 
-                var aabb = _entityLookup.GetWorldAABB(entity.Value);
+            var aabb = _entityLookup.GetWorldAABB(entity.Value);
 
-                // if not on screen, continue
-                if (!aabb.Intersects(in viewport))
-                {
-                    continue;
-                }
+            // if not on screen, continue
+            if (!aabb.Intersects(in viewport))
+            {
+                continue;
+            }
 
-                var lineoffset = new Vector2(0f, 11f);
-                var screenCoordinates = _eyeManager.WorldToScreen(aabb.Center +
-                                                                  new Angle(-_eyeManager.CurrentEye.Rotation).RotateVec(
-                                                                      aabb.TopRight - aabb.Center)) + new Vector2(1f, 7f);
-                if (playerInfo.Antag)
-                {
-                    args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 2), "ANTAG", Color.OrangeRed);
-                }
-                args.ScreenHandle.DrawString(_font, screenCoordinates+lineoffset, playerInfo.Username, playerInfo.Connected ? Color.Yellow : Color.White);
-                args.ScreenHandle.DrawString(_font, screenCoordinates, playerInfo.CharacterName, playerInfo.Connected ? Color.Aquamarine : Color.White);
+            var lineoffset = new Vector2(0f, 11f);
+            var screenCoordinates = _eyeManager.WorldToScreen(aabb.Center +
+                                                              new Angle(-_eyeManager.CurrentEye.Rotation).RotateVec(
+                                                                  aabb.TopRight - aabb.Center)) + new Vector2(1f, 7f);
+            if (playerInfo.Antag)
+            {
+                args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 2), "ANTAG", Color.OrangeRed);
             }
+            args.ScreenHandle.DrawString(_font, screenCoordinates+lineoffset, playerInfo.Username, playerInfo.Connected ? Color.Yellow : Color.White);
+            args.ScreenHandle.DrawString(_font, screenCoordinates, playerInfo.CharacterName, playerInfo.Connected ? Color.Aquamarine : Color.White);
         }
     }
 }
index 2187c40ce98302d84c028775c2cc213880fb8c27..043bf343ecf26da5fbe4a7f862adc9a7d1ea297c 100644 (file)
@@ -10,220 +10,219 @@ using Robust.Client.UserInterface.XAML;
 using static Content.Client.Administration.UI.Tabs.PlayerTab.PlayerTabHeader;
 using static Robust.Client.UserInterface.Controls.BaseButton;
 
-namespace Content.Client.Administration.UI.Tabs.PlayerTab
+namespace Content.Client.Administration.UI.Tabs.PlayerTab;
+
+[GenerateTypedNameReferences]
+public sealed partial class PlayerTab : Control
 {
-    [GenerateTypedNameReferences]
-    public sealed partial class PlayerTab : Control
-    {
-        [Dependency] private readonly IEntityManager _entManager = default!;
-        [Dependency] private readonly IPlayerManager _playerMan = default!;
+    [Dependency] private readonly IEntityManager _entManager = default!;
+    [Dependency] private readonly IPlayerManager _playerMan = default!;
 
-        private const string ArrowUp = "↑";
-        private const string ArrowDown = "↓";
-        private readonly Color _altColor = Color.FromHex("#292B38");
-        private readonly Color _defaultColor = Color.FromHex("#2F2F3B");
-        private readonly AdminSystem _adminSystem;
-        private IReadOnlyList<PlayerInfo> _players = new List<PlayerInfo>();
+    private const string ArrowUp = "↑";
+    private const string ArrowDown = "↓";
+    private readonly Color _altColor = Color.FromHex("#292B38");
+    private readonly Color _defaultColor = Color.FromHex("#2F2F3B");
+    private readonly AdminSystem _adminSystem;
+    private IReadOnlyList<PlayerInfo> _players = new List<PlayerInfo>();
 
-        private Header _headerClicked = Header.Username;
-        private bool _ascending = true;
-        private bool _showDisconnected;
+    private Header _headerClicked = Header.Username;
+    private bool _ascending = true;
+    private bool _showDisconnected;
 
-        public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
+    public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
 
-        public PlayerTab()
-        {
-            IoCManager.InjectDependencies(this);
-            RobustXamlLoader.Load(this);
+    public PlayerTab()
+    {
+        IoCManager.InjectDependencies(this);
+        RobustXamlLoader.Load(this);
 
-            _adminSystem = _entManager.System<AdminSystem>();
-            _adminSystem.PlayerListChanged += RefreshPlayerList;
-            _adminSystem.OverlayEnabled += OverlayEnabled;
-            _adminSystem.OverlayDisabled += OverlayDisabled;
+        _adminSystem = _entManager.System<AdminSystem>();
+        _adminSystem.PlayerListChanged += RefreshPlayerList;
+        _adminSystem.OverlayEnabled += OverlayEnabled;
+        _adminSystem.OverlayDisabled += OverlayDisabled;
 
-            OverlayButton.OnPressed += OverlayButtonPressed;
-            ShowDisconnectedButton.OnPressed += ShowDisconnectedPressed;
+        OverlayButton.OnPressed += OverlayButtonPressed;
+        ShowDisconnectedButton.OnPressed += ShowDisconnectedPressed;
 
-            ListHeader.BackgroundColorPanel.PanelOverride = new StyleBoxFlat(_altColor);
-            ListHeader.OnHeaderClicked += HeaderClicked;
+        ListHeader.BackgroundColorPanel.PanelOverride = new StyleBoxFlat(_altColor);
+        ListHeader.OnHeaderClicked += HeaderClicked;
 
-            SearchList.SearchBar = SearchLineEdit;
-            SearchList.GenerateItem += GenerateButton;
-            SearchList.DataFilterCondition += DataFilterCondition;
-            SearchList.ItemKeyBindDown += (args, data) => OnEntryKeyBindDown?.Invoke(args, data);
+        SearchList.SearchBar = SearchLineEdit;
+        SearchList.GenerateItem += GenerateButton;
+        SearchList.DataFilterCondition += DataFilterCondition;
+        SearchList.ItemKeyBindDown += (args, data) => OnEntryKeyBindDown?.Invoke(args, data);
 
-            RefreshPlayerList(_adminSystem.PlayerList);
+        RefreshPlayerList(_adminSystem.PlayerList);
 
-        }
+    }
 
-        #region Antag Overlay
+    #region Antag Overlay
 
-        private void OverlayEnabled()
-        {
-            OverlayButton.Pressed = true;
-        }
+    private void OverlayEnabled()
+    {
+        OverlayButton.Pressed = true;
+    }
 
-        private void OverlayDisabled()
+    private void OverlayDisabled()
+    {
+        OverlayButton.Pressed = false;
+    }
+
+    private void OverlayButtonPressed(ButtonEventArgs args)
+    {
+        if (args.Button.Pressed)
         {
-            OverlayButton.Pressed = false;
+            _adminSystem.AdminOverlayOn();
         }
-
-        private void OverlayButtonPressed(ButtonEventArgs args)
+        else
         {
-            if (args.Button.Pressed)
-            {
-                _adminSystem.AdminOverlayOn();
-            }
-            else
-            {
-                _adminSystem.AdminOverlayOff();
-            }
+            _adminSystem.AdminOverlayOff();
         }
+    }
 
-        #endregion
+    #endregion
+
+    private void ShowDisconnectedPressed(ButtonEventArgs args)
+    {
+        _showDisconnected = args.Button.Pressed;
+        RefreshPlayerList(_players);
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
 
-        private void ShowDisconnectedPressed(ButtonEventArgs args)
+        if (disposing)
         {
-            _showDisconnected = args.Button.Pressed;
-            RefreshPlayerList(_players);
+            _adminSystem.PlayerListChanged -= RefreshPlayerList;
+            _adminSystem.OverlayEnabled -= OverlayEnabled;
+            _adminSystem.OverlayDisabled -= OverlayDisabled;
+
+            OverlayButton.OnPressed -= OverlayButtonPressed;
+
+            ListHeader.OnHeaderClicked -= HeaderClicked;
         }
+    }
 
-        protected override void Dispose(bool disposing)
-        {
-            base.Dispose(disposing);
+    #region ListContainer
 
-            if (disposing)
-            {
-                _adminSystem.PlayerListChanged -= RefreshPlayerList;
-                _adminSystem.OverlayEnabled -= OverlayEnabled;
-                _adminSystem.OverlayDisabled -= OverlayDisabled;
+    private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players)
+    {
+        _players = players;
+        PlayerCount.Text = Loc.GetString("player-tab-player-count", ("count", _playerMan.PlayerCount));
 
-                OverlayButton.OnPressed -= OverlayButtonPressed;
+        var filteredPlayers = players.Where(info => _showDisconnected || info.Connected).ToList();
 
-                ListHeader.OnHeaderClicked -= HeaderClicked;
-            }
-        }
+        var sortedPlayers = new List<PlayerInfo>(filteredPlayers);
+        sortedPlayers.Sort(Compare);
 
-        #region ListContainer
+        UpdateHeaderSymbols();
 
-        private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players)
-        {
-            _players = players;
-            PlayerCount.Text = Loc.GetString("player-tab-player-count", ("count", _playerMan.PlayerCount));
+        SearchList.PopulateList(sortedPlayers.Select(info => new PlayerListData(info,
+                $"{info.Username} {info.CharacterName} {info.IdentityName} {info.StartingJob}"))
+            .ToList());
+    }
 
-            var filteredPlayers = players.Where(info => _showDisconnected || info.Connected).ToList();
+    private void GenerateButton(ListData data, ListContainerButton button)
+    {
+        if (data is not PlayerListData { Info: var player})
+            return;
 
-            var sortedPlayers = new List<PlayerInfo>(filteredPlayers);
-            sortedPlayers.Sort(Compare);
+        var entry = new PlayerTabEntry(player, new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor));
+        button.AddChild(entry);
+        button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}";
+    }
 
-            UpdateHeaderSymbols();
+    /// <summary>
+    /// Determines whether <paramref name="filter"/> is contained in <paramref name="listData"/>.FilteringString.
+    /// If all characters are lowercase, the comparison ignores case.
+    /// If there is an uppercase character, the comparison is case sensitive.
+    /// </summary>
+    /// <param name="filter"></param>
+    /// <param name="listData"></param>
+    /// <returns>Whether <paramref name="filter"/> is contained in <paramref name="listData"/>.FilteringString.</returns>
+    private bool DataFilterCondition(string filter, ListData listData)
+    {
+        if (listData is not PlayerListData {Info: var info, FilteringString: var playerString})
+            return false;
 
-            SearchList.PopulateList(sortedPlayers.Select(info => new PlayerListData(info,
-                    $"{info.Username} {info.CharacterName} {info.IdentityName} {info.StartingJob}"))
-                .ToList());
-        }
+        if (!_showDisconnected && !info.Connected)
+            return false;
 
-        private void GenerateButton(ListData data, ListContainerButton button)
+        if (IsAllLower(filter))
         {
-            if (data is not PlayerListData { Info: var player})
-                return;
-
-            var entry = new PlayerTabEntry(player, new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor));
-            button.AddChild(entry);
-            button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}";
+            if (!playerString.Contains(filter, StringComparison.CurrentCultureIgnoreCase))
+                return false;
         }
-
-        /// <summary>
-        /// Determines whether <paramref name="filter"/> is contained in <paramref name="listData"/>.FilteringString.
-        /// If all characters are lowercase, the comparison ignores case.
-        /// If there is an uppercase character, the comparison is case sensitive.
-        /// </summary>
-        /// <param name="filter"></param>
-        /// <param name="listData"></param>
-        /// <returns>Whether <paramref name="filter"/> is contained in <paramref name="listData"/>.FilteringString.</returns>
-        private bool DataFilterCondition(string filter, ListData listData)
+        else
         {
-            if (listData is not PlayerListData {Info: var info, FilteringString: var playerString})
+            if (!playerString.Contains(filter))
                 return false;
+        }
 
-            if (!_showDisconnected && !info.Connected)
-                return false;
+        return true;
+    }
 
-            if (IsAllLower(filter))
-            {
-                if (!playerString.Contains(filter, StringComparison.CurrentCultureIgnoreCase))
-                    return false;
-            }
-            else
-            {
-                if (!playerString.Contains(filter))
-                    return false;
-            }
-
-            return true;
+    private bool IsAllLower(string input)
+    {
+        foreach (var c in input)
+        {
+            if (char.IsLetter(c) && !char.IsLower(c))
+                return false;
         }
 
-        private bool IsAllLower(string input)
-        {
-            foreach (var c in input)
-            {
-                if (char.IsLetter(c) && !char.IsLower(c))
-                    return false;
-            }
+        return true;
+    }
 
-            return true;
-        }
+    #endregion
 
-        #endregion
+    #region Header
 
-        #region Header
+    private void UpdateHeaderSymbols()
+    {
+        ListHeader.ResetHeaderText();
+        ListHeader.GetHeader(_headerClicked).Text += $" {(_ascending ? ArrowUp : ArrowDown)}";
+    }
 
-        private void UpdateHeaderSymbols()
+    private int Compare(PlayerInfo x, PlayerInfo y)
+    {
+        if (!_ascending)
         {
-            ListHeader.ResetHeaderText();
-            ListHeader.GetHeader(_headerClicked).Text += $" {(_ascending ? ArrowUp : ArrowDown)}";
+            (x, y) = (y, x);
         }
 
-        private int Compare(PlayerInfo x, PlayerInfo y)
+        return _headerClicked switch
         {
-            if (!_ascending)
-            {
-                (x, y) = (y, x);
-            }
-
-            return _headerClicked switch
-            {
-                Header.Username => Compare(x.Username, y.Username),
-                Header.Character => Compare(x.CharacterName, y.CharacterName),
-                Header.Job => Compare(x.StartingJob, y.StartingJob),
-                Header.Antagonist => x.Antag.CompareTo(y.Antag),
-                Header.Playtime => TimeSpan.Compare(x.OverallPlaytime ?? default, y.OverallPlaytime ?? default),
-                _ => 1
-            };
-        }
+            Header.Username => Compare(x.Username, y.Username),
+            Header.Character => Compare(x.CharacterName, y.CharacterName),
+            Header.Job => Compare(x.StartingJob, y.StartingJob),
+            Header.Antagonist => x.Antag.CompareTo(y.Antag),
+            Header.Playtime => TimeSpan.Compare(x.OverallPlaytime ?? default, y.OverallPlaytime ?? default),
+            _ => 1
+        };
+    }
+
+    private int Compare(string x, string y)
+    {
+        return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
+    }
 
-        private int Compare(string x, string y)
+    private void HeaderClicked(Header header)
+    {
+        if (_headerClicked == header)
         {
-            return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
+            _ascending = !_ascending;
         }
-
-        private void HeaderClicked(Header header)
+        else
         {
-            if (_headerClicked == header)
-            {
-                _ascending = !_ascending;
-            }
-            else
-            {
-                _headerClicked = header;
-                _ascending = true;
-            }
-
-            RefreshPlayerList(_adminSystem.PlayerList);
+            _headerClicked = header;
+            _ascending = true;
         }
 
-        #endregion
+        RefreshPlayerList(_adminSystem.PlayerList);
     }
 
-    public record PlayerListData(PlayerInfo Info, string FilteringString) : ListData;
+    #endregion
 }
+
+public record PlayerListData(PlayerInfo Info, string FilteringString) : ListData;
index 67b5f5202f9fb80cfdfd9dd7e2ac0936791ab7b4..e428d30f20c702374dba8ea155ccf750baff315f 100644 (file)
@@ -5,71 +5,70 @@ using Content.Shared.Chat;
 using Robust.Client.Console;
 using Robust.Shared.Utility;
 
-namespace Content.Client.Chat.Managers
+namespace Content.Client.Chat.Managers;
+
+internal sealed class ChatManager : IChatManager
 {
-    internal sealed class ChatManager : IChatManager
-    {
-        [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
-        [Dependency] private readonly IClientAdminManager _adminMgr = default!;
-        [Dependency] private readonly IEntitySystemManager _systems = default!;
+    [Dependency] private readonly IClientConsoleHost _consoleHost = default!;
+    [Dependency] private readonly IClientAdminManager _adminMgr = default!;
+    [Dependency] private readonly IEntitySystemManager _systems = default!;
 
-        private ISawmill _sawmill = default!;
+    private ISawmill _sawmill = default!;
 
-        public void Initialize()
-        {
-            _sawmill = Logger.GetSawmill("chat");
-            _sawmill.Level = LogLevel.Info;
-        }
+    public void Initialize()
+    {
+        _sawmill = Logger.GetSawmill("chat");
+        _sawmill.Level = LogLevel.Info;
+    }
 
-        public void SendMessage(string text, ChatSelectChannel channel)
+    public void SendMessage(string text, ChatSelectChannel channel)
+    {
+        var str = text.ToString();
+        switch (channel)
         {
-            var str = text.ToString();
-            switch (channel)
-            {
-                case ChatSelectChannel.Console:
-                    // run locally
-                    _consoleHost.ExecuteCommand(text);
-                    break;
+            case ChatSelectChannel.Console:
+                // run locally
+                _consoleHost.ExecuteCommand(text);
+                break;
 
-                case ChatSelectChannel.LOOC:
-                    _consoleHost.ExecuteCommand($"looc \"{CommandParsing.Escape(str)}\"");
-                    break;
+            case ChatSelectChannel.LOOC:
+                _consoleHost.ExecuteCommand($"looc \"{CommandParsing.Escape(str)}\"");
+                break;
 
-                case ChatSelectChannel.OOC:
-                    _consoleHost.ExecuteCommand($"ooc \"{CommandParsing.Escape(str)}\"");
-                    break;
+            case ChatSelectChannel.OOC:
+                _consoleHost.ExecuteCommand($"ooc \"{CommandParsing.Escape(str)}\"");
+                break;
 
-                case ChatSelectChannel.Admin:
-                    _consoleHost.ExecuteCommand($"asay \"{CommandParsing.Escape(str)}\"");
-                    break;
+            case ChatSelectChannel.Admin:
+                _consoleHost.ExecuteCommand($"asay \"{CommandParsing.Escape(str)}\"");
+                break;
 
-                case ChatSelectChannel.Emotes:
-                    _consoleHost.ExecuteCommand($"me \"{CommandParsing.Escape(str)}\"");
-                    break;
+            case ChatSelectChannel.Emotes:
+                _consoleHost.ExecuteCommand($"me \"{CommandParsing.Escape(str)}\"");
+                break;
 
-                case ChatSelectChannel.Dead:
-                    if (_systems.GetEntitySystemOrNull<GhostSystem>() is {IsGhost: true})
-                        goto case ChatSelectChannel.Local;
+            case ChatSelectChannel.Dead:
+                if (_systems.GetEntitySystemOrNull<GhostSystem>() is {IsGhost: true})
+                    goto case ChatSelectChannel.Local;
 
-                    if (_adminMgr.HasFlag(AdminFlags.Admin))
-                        _consoleHost.ExecuteCommand($"dsay \"{CommandParsing.Escape(str)}\"");
-                    else
-                        _sawmill.Warning("Tried to speak on deadchat without being ghost or admin.");
-                    break;
+                if (_adminMgr.HasFlag(AdminFlags.Admin))
+                    _consoleHost.ExecuteCommand($"dsay \"{CommandParsing.Escape(str)}\"");
+                else
+                    _sawmill.Warning("Tried to speak on deadchat without being ghost or admin.");
+                break;
 
-                // TODO sepearate radio and say into separate commands.
-                case ChatSelectChannel.Radio:
-                case ChatSelectChannel.Local:
-                    _consoleHost.ExecuteCommand($"say \"{CommandParsing.Escape(str)}\"");
-                    break;
+            // TODO sepearate radio and say into separate commands.
+            case ChatSelectChannel.Radio:
+            case ChatSelectChannel.Local:
+                _consoleHost.ExecuteCommand($"say \"{CommandParsing.Escape(str)}\"");
+                break;
 
-                case ChatSelectChannel.Whisper:
-                    _consoleHost.ExecuteCommand($"whisper \"{CommandParsing.Escape(str)}\"");
-                    break;
+            case ChatSelectChannel.Whisper:
+                _consoleHost.ExecuteCommand($"whisper \"{CommandParsing.Escape(str)}\"");
+                break;
 
-                default:
-                    throw new ArgumentOutOfRangeException(nameof(channel), channel, null);
-            }
+            default:
+                throw new ArgumentOutOfRangeException(nameof(channel), channel, null);
         }
     }
 }
index 16c079e4ba1d234927074855ce793d91439b6a81..db22c41520d76ea20b869ca58d616502a35cc790 100644 (file)
@@ -31,426 +31,425 @@ using Robust.Shared.Enums;
 using Robust.Shared.Network;
 using Robust.Shared.Player;
 
-namespace Content.Server.Administration.Systems
+namespace Content.Server.Administration.Systems;
+
+public sealed class AdminSystem : EntitySystem
 {
-    public sealed class AdminSystem : EntitySystem
+    [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 HandsSystem _hands = default!;
+    [Dependency] private readonly SharedJobSystem _jobs = default!;
+    [Dependency] private readonly InventorySystem _inventory = default!;
+    [Dependency] private readonly MindSystem _minds = default!;
+    [Dependency] private readonly PopupSystem _popup = default!;
+    [Dependency] private readonly PhysicsSystem _physics = default!;
+    [Dependency] private readonly PlayTimeTrackingManager _playTime = default!;
+    [Dependency] private readonly SharedRoleSystem _role = default!;
+    [Dependency] private readonly GameTicker _gameTicker = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly StationRecordsSystem _stationRecords = default!;
+    [Dependency] private readonly TransformSystem _transform = default!;
+
+    private readonly Dictionary<NetUserId, PlayerInfo> _playerList = new();
+
+    /// <summary>
+    ///     Set of players that have participated in this round.
+    /// </summary>
+    public IReadOnlySet<NetUserId> RoundActivePlayers => _roundActivePlayers;
+
+    private readonly HashSet<NetUserId> _roundActivePlayers = new();
+    public readonly PanicBunkerStatus PanicBunker = new();
+    public readonly BabyJailStatus BabyJail = new();
+
+    public override void Initialize()
     {
-        [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 HandsSystem _hands = default!;
-        [Dependency] private readonly SharedJobSystem _jobs = default!;
-        [Dependency] private readonly InventorySystem _inventory = default!;
-        [Dependency] private readonly MindSystem _minds = default!;
-        [Dependency] private readonly PopupSystem _popup = default!;
-        [Dependency] private readonly PhysicsSystem _physics = default!;
-        [Dependency] private readonly PlayTimeTrackingManager _playTime = default!;
-        [Dependency] private readonly SharedRoleSystem _role = default!;
-        [Dependency] private readonly GameTicker _gameTicker = default!;
-        [Dependency] private readonly SharedAudioSystem _audio = default!;
-        [Dependency] private readonly StationRecordsSystem _stationRecords = default!;
-        [Dependency] private readonly TransformSystem _transform = default!;
-
-        private readonly Dictionary<NetUserId, PlayerInfo> _playerList = new();
-
-        /// <summary>
-        ///     Set of players that have participated in this round.
-        /// </summary>
-        public IReadOnlySet<NetUserId> RoundActivePlayers => _roundActivePlayers;
-
-        private readonly HashSet<NetUserId> _roundActivePlayers = new();
-        public readonly PanicBunkerStatus PanicBunker = new();
-        public readonly BabyJailStatus BabyJail = new();
-
-        public override void Initialize()
+        base.Initialize();
+
+        _playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
+        _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);
+        Subs.CVar(_config, CCVars.PanicBunkerCountDeadminnedAdmins, OnPanicBunkerCountDeadminnedAdminsChanged, true);
+        Subs.CVar(_config, CCVars.PanicBunkerShowReason, OnPanicBunkerShowReasonChanged, true);
+        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);
+        SubscribeLocalEvent<RoleAddedEvent>(OnRoleEvent);
+        SubscribeLocalEvent<RoleRemovedEvent>(OnRoleEvent);
+        SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestartCleanup);
+    }
+
+    private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev)
+    {
+        _roundActivePlayers.Clear();
+
+        foreach (var (id, data) in _playerList)
         {
-            base.Initialize();
-
-            _playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
-            _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);
-            Subs.CVar(_config, CCVars.PanicBunkerCountDeadminnedAdmins, OnPanicBunkerCountDeadminnedAdminsChanged, true);
-            Subs.CVar(_config, CCVars.PanicBunkerShowReason, OnPanicBunkerShowReasonChanged, true);
-            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);
-            SubscribeLocalEvent<RoleAddedEvent>(OnRoleEvent);
-            SubscribeLocalEvent<RoleRemovedEvent>(OnRoleEvent);
-            SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundRestartCleanup);
+            if (!data.ActiveThisRound)
+                continue;
+
+            if (!_playerManager.TryGetPlayerData(id, out var playerData))
+                return;
+
+            _playerManager.TryGetSessionById(id, out var session);
+            _playerList[id] = GetPlayerInfo(playerData, session);
         }
 
-        private void OnRoundRestartCleanup(RoundRestartCleanupEvent ev)
+        var updateEv = new FullPlayerListEvent() { PlayersInfo = _playerList.Values.ToList() };
+
+        foreach (var admin in _adminManager.ActiveAdmins)
         {
-            _roundActivePlayers.Clear();
+            RaiseNetworkEvent(updateEv, admin.Channel);
+        }
+    }
 
-            foreach (var (id, data) in _playerList)
-            {
-                if (!data.ActiveThisRound)
-                    continue;
+    public void UpdatePlayerList(ICommonSession player)
+    {
+        _playerList[player.UserId] = GetPlayerInfo(player.Data, player);
 
-                if (!_playerManager.TryGetPlayerData(id, out var playerData))
-                    return;
+        var playerInfoChangedEvent = new PlayerInfoChangedEvent
+        {
+            PlayerInfo = _playerList[player.UserId]
+        };
 
-                _playerManager.TryGetSessionById(id, out var session);
-                _playerList[id] = GetPlayerInfo(playerData, session);
-            }
+        foreach (var admin in _adminManager.ActiveAdmins)
+        {
+            RaiseNetworkEvent(playerInfoChangedEvent, admin.Channel);
+        }
+    }
 
-            var updateEv = new FullPlayerListEvent() { PlayersInfo = _playerList.Values.ToList() };
+    public PlayerInfo? GetCachedPlayerInfo(NetUserId? netUserId)
+    {
+        if (netUserId == null)
+            return null;
 
-            foreach (var admin in _adminManager.ActiveAdmins)
-            {
-                RaiseNetworkEvent(updateEv, admin.Channel);
-            }
-        }
+        _playerList.TryGetValue(netUserId.Value, out var value);
+        return value ?? null;
+    }
 
-        public void UpdatePlayerList(ICommonSession player)
-        {
-            _playerList[player.UserId] = GetPlayerInfo(player.Data, player);
+    private void OnIdentityChanged(ref IdentityChangedEvent ev)
+    {
+        if (!TryComp<ActorComponent>(ev.CharacterEntity, out var actor))
+            return;
 
-            var playerInfoChangedEvent = new PlayerInfoChangedEvent
-            {
-                PlayerInfo = _playerList[player.UserId]
-            };
+        UpdatePlayerList(actor.PlayerSession);
+    }
 
-            foreach (var admin in _adminManager.ActiveAdmins)
-            {
-                RaiseNetworkEvent(playerInfoChangedEvent, admin.Channel);
-            }
-        }
+    private void OnRoleEvent(RoleEvent ev)
+    {
+        var session = _minds.GetSession(ev.Mind);
+        if (!ev.Antagonist || session == null)
+            return;
 
-        public PlayerInfo? GetCachedPlayerInfo(NetUserId? netUserId)
-        {
-            if (netUserId == null)
-                return null;
+        UpdatePlayerList(session);
+    }
 
-            _playerList.TryGetValue(netUserId.Value, out var value);
-            return value ?? null;
-        }
+    private void OnAdminPermsChanged(AdminPermsChangedEventArgs obj)
+    {
+        UpdatePanicBunker();
 
-        private void OnIdentityChanged(ref IdentityChangedEvent ev)
+        if (!obj.IsAdmin)
         {
-            if (!TryComp<ActorComponent>(ev.CharacterEntity, out var actor))
-                return;
-
-            UpdatePlayerList(actor.PlayerSession);
+            RaiseNetworkEvent(new FullPlayerListEvent(), obj.Player.Channel);
+            return;
         }
 
-        private void OnRoleEvent(RoleEvent ev)
-        {
-            var session = _minds.GetSession(ev.Mind);
-            if (!ev.Antagonist || session == null)
-                return;
+        SendFullPlayerList(obj.Player);
+    }
 
-            UpdatePlayerList(session);
-        }
+    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;
 
-        private void OnAdminPermsChanged(AdminPermsChangedEventArgs obj)
-        {
-            UpdatePanicBunker();
+        UpdatePlayerList(ev.Player);
+    }
 
-            if (!obj.IsAdmin)
-            {
-                RaiseNetworkEvent(new FullPlayerListEvent(), obj.Player.Channel);
-                return;
-            }
+    private void OnPlayerAttached(PlayerAttachedEvent ev)
+    {
+        if (ev.Player.Status == SessionStatus.Disconnected)
+            return;
 
-            SendFullPlayerList(obj.Player);
-        }
+        _roundActivePlayers.Add(ev.Player.UserId);
+        UpdatePlayerList(ev.Player);
+    }
 
-        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;
+    public override void Shutdown()
+    {
+        base.Shutdown();
+        _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged;
+        _adminManager.OnPermsChanged -= OnAdminPermsChanged;
+        _playTime.SessionPlayTimeUpdated -= OnSessionPlayTimeUpdated;
+    }
 
-            UpdatePlayerList(ev.Player);
-        }
+    private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
+    {
+        UpdatePlayerList(e.Session);
+        UpdatePanicBunker();
+    }
 
-        private void OnPlayerAttached(PlayerAttachedEvent ev)
-        {
-            if (ev.Player.Status == SessionStatus.Disconnected)
-                return;
+    private void SendFullPlayerList(ICommonSession playerSession)
+    {
+        var ev = new FullPlayerListEvent();
 
-            _roundActivePlayers.Add(ev.Player.UserId);
-            UpdatePlayerList(ev.Player);
-        }
+        ev.PlayersInfo = _playerList.Values.ToList();
+
+        RaiseNetworkEvent(ev, playerSession.Channel);
+    }
 
-        public override void Shutdown()
+    private PlayerInfo GetPlayerInfo(SessionData data, ICommonSession? session)
+    {
+        var name = data.UserName;
+        var entityName = string.Empty;
+        var identityName = string.Empty;
+
+        if (session?.AttachedEntity != null)
         {
-            base.Shutdown();
-            _playerManager.PlayerStatusChanged -= OnPlayerStatusChanged;
-            _adminManager.OnPermsChanged -= OnAdminPermsChanged;
-            _playTime.SessionPlayTimeUpdated -= OnSessionPlayTimeUpdated;
+            entityName = EntityManager.GetComponent<MetaDataComponent>(session.AttachedEntity.Value).EntityName;
+            identityName = Identity.Name(session.AttachedEntity.Value, EntityManager);
         }
 
-        private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
+        var antag = false;
+        var startingRole = string.Empty;
+        if (_minds.TryGetMind(session, out var mindId, out _))
         {
-            UpdatePlayerList(e.Session);
-            UpdatePanicBunker();
+            antag = _role.MindIsAntagonist(mindId);
+            startingRole = _jobs.MindTryGetJobName(mindId);
         }
 
-        private void SendFullPlayerList(ICommonSession playerSession)
+        var connected = session != null && session.Status is SessionStatus.Connected or SessionStatus.InGame;
+        TimeSpan? overallPlaytime = null;
+        if (session != null &&
+            _playTime.TryGetTrackerTimes(session, out var playTimes) &&
+            playTimes.TryGetValue(PlayTimeTrackingShared.TrackerOverall, out var playTime))
         {
-            var ev = new FullPlayerListEvent();
-
-            ev.PlayersInfo = _playerList.Values.ToList();
-
-            RaiseNetworkEvent(ev, playerSession.Channel);
+            overallPlaytime = playTime;
         }
 
-        private PlayerInfo GetPlayerInfo(SessionData data, ICommonSession? session)
-        {
-            var name = data.UserName;
-            var entityName = string.Empty;
-            var identityName = string.Empty;
+        return new PlayerInfo(name, entityName, identityName, startingRole, antag, GetNetEntity(session?.AttachedEntity), data.UserId,
+            connected, _roundActivePlayers.Contains(data.UserId), overallPlaytime);
+    }
 
-            if (session?.AttachedEntity != null)
-            {
-                entityName = EntityManager.GetComponent<MetaDataComponent>(session.AttachedEntity.Value).EntityName;
-                identityName = Identity.Name(session.AttachedEntity.Value, EntityManager);
-            }
+    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"
+        ));
 
-            var antag = false;
-            var startingRole = string.Empty;
-            if (_minds.TryGetMind(session, out var mindId, out _))
-            {
-                antag = _role.MindIsAntagonist(mindId);
-                startingRole = _jobs.MindTryGetJobName(mindId);
-            }
+        SendPanicBunkerStatusAll();
+    }
 
-            var connected = session != null && session.Status is SessionStatus.Connected or SessionStatus.InGame;
-            TimeSpan? overallPlaytime = null;
-            if (session != null &&
-                _playTime.TryGetTrackerTimes(session, out var playTimes) &&
-                playTimes.TryGetValue(PlayTimeTrackingShared.TrackerOverall, out var playTime))
-            {
-                overallPlaytime = playTime;
-            }
+    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"
+        ));
 
-            return new PlayerInfo(name, entityName, identityName, startingRole, antag, GetNetEntity(session?.AttachedEntity), data.UserId,
-                connected, _roundActivePlayers.Contains(data.UserId), overallPlaytime);
-        }
+        SendBabyJailStatusAll();
+    }
 
-        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"
-            ));
+    private void OnPanicBunkerDisableWithAdminsChanged(bool enabled)
+    {
+        PanicBunker.DisableWithAdmins = enabled;
+        UpdatePanicBunker();
+    }
 
-            SendPanicBunkerStatusAll();
-        }
+    private void OnPanicBunkerEnableWithoutAdminsChanged(bool enabled)
+    {
+        PanicBunker.EnableWithoutAdmins = enabled;
+        UpdatePanicBunker();
+    }
 
-        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"
-            ));
+    private void OnPanicBunkerCountDeadminnedAdminsChanged(bool enabled)
+    {
+        PanicBunker.CountDeadminnedAdmins = enabled;
+        UpdatePanicBunker();
+    }
 
-            SendBabyJailStatusAll();
-        }
+    private void OnPanicBunkerShowReasonChanged(bool enabled)
+    {
+        PanicBunker.ShowReason = enabled;
+        SendPanicBunkerStatusAll();
+    }
 
-        private void OnPanicBunkerDisableWithAdminsChanged(bool enabled)
-        {
-            PanicBunker.DisableWithAdmins = enabled;
-            UpdatePanicBunker();
-        }
+    private void OnBabyJailShowReasonChanged(bool enabled)
+    {
+        BabyJail.ShowReason = enabled;
+        SendBabyJailStatusAll();
+    }
 
-        private void OnPanicBunkerEnableWithoutAdminsChanged(bool enabled)
-        {
-            PanicBunker.EnableWithoutAdmins = enabled;
-            UpdatePanicBunker();
-        }
+    private void OnPanicBunkerMinAccountAgeChanged(int minutes)
+    {
+        PanicBunker.MinAccountAgeMinutes = minutes;
+        SendPanicBunkerStatusAll();
+    }
 
-        private void OnPanicBunkerCountDeadminnedAdminsChanged(bool enabled)
-        {
-            PanicBunker.CountDeadminnedAdmins = enabled;
-            UpdatePanicBunker();
-        }
+    private void OnBabyJailMaxAccountAgeChanged(int minutes)
+    {
+        BabyJail.MaxAccountAgeMinutes = minutes;
+        SendBabyJailStatusAll();
+    }
 
-        private void OnPanicBunkerShowReasonChanged(bool enabled)
-        {
-            PanicBunker.ShowReason = enabled;
-            SendPanicBunkerStatusAll();
-        }
+    private void OnPanicBunkerMinOverallMinutesChanged(int minutes)
+    {
+        PanicBunker.MinOverallMinutes = minutes;
+        SendPanicBunkerStatusAll();
+    }
 
-        private void OnBabyJailShowReasonChanged(bool enabled)
-        {
-            BabyJail.ShowReason = enabled;
-            SendBabyJailStatusAll();
-        }
+    private void OnBabyJailMaxOverallMinutesChanged(int minutes)
+    {
+        BabyJail.MaxOverallMinutes = minutes;
+        SendBabyJailStatusAll();
+    }
 
-        private void OnPanicBunkerMinAccountAgeChanged(int minutes)
+    private void UpdatePanicBunker()
+    {
+        var admins = PanicBunker.CountDeadminnedAdmins
+            ? _adminManager.AllAdmins
+            : _adminManager.ActiveAdmins;
+        var hasAdmins = admins.Any();
+
+        // TODO Fix order dependent Cvars
+        // Please for the sake of my sanity don't make cvars & order dependent.
+        // Just make a bool field on the system instead of having some cvars automatically modify other cvars.
+        //
+        // I.e., this:
+        //   /sudo cvar game.panic_bunker.enabled true
+        //   /sudo cvar game.panic_bunker.disable_with_admins true
+        // and this:
+        //   /sudo cvar game.panic_bunker.disable_with_admins true
+        //   /sudo cvar game.panic_bunker.enabled true
+        //
+        // should have the same effect, but currently setting the disable_with_admins can modify enabled.
+
+        if (hasAdmins && PanicBunker.DisableWithAdmins)
         {
-            PanicBunker.MinAccountAgeMinutes = minutes;
-            SendPanicBunkerStatusAll();
+            _config.SetCVar(CCVars.PanicBunkerEnabled, false);
         }
-
-        private void OnBabyJailMaxAccountAgeChanged(int minutes)
+        else if (!hasAdmins && PanicBunker.EnableWithoutAdmins)
         {
-            BabyJail.MaxAccountAgeMinutes = minutes;
-            SendBabyJailStatusAll();
+            _config.SetCVar(CCVars.PanicBunkerEnabled, true);
         }
 
-        private void OnPanicBunkerMinOverallMinutesChanged(int minutes)
-        {
-            PanicBunker.MinOverallMinutes = minutes;
-            SendPanicBunkerStatusAll();
-        }
+        SendPanicBunkerStatusAll();
+    }
 
-        private void OnBabyJailMaxOverallMinutesChanged(int minutes)
+    private void SendPanicBunkerStatusAll()
+    {
+        var ev = new PanicBunkerChangedEvent(PanicBunker);
+        foreach (var admin in _adminManager.AllAdmins)
         {
-            BabyJail.MaxOverallMinutes = minutes;
-            SendBabyJailStatusAll();
+            RaiseNetworkEvent(ev, admin);
         }
+    }
 
-        private void UpdatePanicBunker()
+    private void SendBabyJailStatusAll()
+    {
+        var ev = new BabyJailChangedEvent(BabyJail);
+        foreach (var admin in _adminManager.AllAdmins)
         {
-            var admins = PanicBunker.CountDeadminnedAdmins
-                ? _adminManager.AllAdmins
-                : _adminManager.ActiveAdmins;
-            var hasAdmins = admins.Any();
-
-            // TODO Fix order dependent Cvars
-            // Please for the sake of my sanity don't make cvars & order dependent.
-            // Just make a bool field on the system instead of having some cvars automatically modify other cvars.
-            //
-            // I.e., this:
-            //   /sudo cvar game.panic_bunker.enabled true
-            //   /sudo cvar game.panic_bunker.disable_with_admins true
-            // and this:
-            //   /sudo cvar game.panic_bunker.disable_with_admins true
-            //   /sudo cvar game.panic_bunker.enabled true
-            //
-            // should have the same effect, but currently setting the disable_with_admins can modify enabled.
-
-            if (hasAdmins && PanicBunker.DisableWithAdmins)
-            {
-                _config.SetCVar(CCVars.PanicBunkerEnabled, false);
-            }
-            else if (!hasAdmins && PanicBunker.EnableWithoutAdmins)
-            {
-                _config.SetCVar(CCVars.PanicBunkerEnabled, true);
-            }
-
-            SendPanicBunkerStatusAll();
+            RaiseNetworkEvent(ev, admin);
         }
+    }
 
-        private void SendPanicBunkerStatusAll()
-        {
-            var ev = new PanicBunkerChangedEvent(PanicBunker);
-            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
+    ///     chat messages and showing a popup to other players.
+    ///     Their items are dropped on the ground.
+    /// </summary>
+    public void Erase(ICommonSession player)
+    {
+        var entity = player.AttachedEntity;
+        _chat.DeleteMessagesBy(player);
 
-        private void SendBabyJailStatusAll()
+        if (entity != null && !TerminatingOrDeleted(entity.Value))
         {
-            var ev = new BabyJailChangedEvent(BabyJail);
-            foreach (var admin in _adminManager.AllAdmins)
+            if (TryComp(entity.Value, out TransformComponent? transform))
             {
-                RaiseNetworkEvent(ev, admin);
+                var coordinates = _transform.GetMoverCoordinates(entity.Value, transform);
+                var name = Identity.Entity(entity.Value, EntityManager);
+                _popup.PopupCoordinates(Loc.GetString("admin-erase-popup", ("user", name)), coordinates, PopupType.LargeCaution);
+                var filter = Filter.Pvs(coordinates, 1, EntityManager, _playerManager);
+                var audioParams = new AudioParams().WithVolume(3);
+                _audio.PlayStatic("/Audio/Effects/pop_high.ogg", filter, coordinates, true, audioParams);
             }
-        }
-
-        /// <summary>
-        ///     Erases a player from the round.
-        ///     This removes them and any trace of them from the round, deleting their
-        ///     chat messages and showing a popup to other players.
-        ///     Their items are dropped on the ground.
-        /// </summary>
-        public void Erase(ICommonSession player)
-        {
-            var entity = player.AttachedEntity;
-            _chat.DeleteMessagesBy(player);
 
-            if (entity != null && !TerminatingOrDeleted(entity.Value))
+            foreach (var item in _inventory.GetHandOrInventoryEntities(entity.Value))
             {
-                if (TryComp(entity.Value, out TransformComponent? transform))
+                if (TryComp(item, out PdaComponent? pda) &&
+                    TryComp(pda.ContainedId, out StationRecordKeyStorageComponent? keyStorage) &&
+                    keyStorage.Key is { } key &&
+                    _stationRecords.TryGetRecord(key, out GeneralStationRecord? record))
                 {
-                    var coordinates = _transform.GetMoverCoordinates(entity.Value, transform);
-                    var name = Identity.Entity(entity.Value, EntityManager);
-                    _popup.PopupCoordinates(Loc.GetString("admin-erase-popup", ("user", name)), coordinates, PopupType.LargeCaution);
-                    var filter = Filter.Pvs(coordinates, 1, EntityManager, _playerManager);
-                    var audioParams = new AudioParams().WithVolume(3);
-                    _audio.PlayStatic("/Audio/Effects/pop_high.ogg", filter, coordinates, true, audioParams);
-                }
+                    if (TryComp(entity, out DnaComponent? dna) &&
+                        dna.DNA != record.DNA)
+                    {
+                        continue;
+                    }
 
-                foreach (var item in _inventory.GetHandOrInventoryEntities(entity.Value))
-                {
-                    if (TryComp(item, out PdaComponent? pda) &&
-                        TryComp(pda.ContainedId, out StationRecordKeyStorageComponent? keyStorage) &&
-                        keyStorage.Key is { } key &&
-                        _stationRecords.TryGetRecord(key, out GeneralStationRecord? record))
+                    if (TryComp(entity, out FingerprintComponent? fingerPrint) &&
+                        fingerPrint.Fingerprint != record.Fingerprint)
                     {
-                        if (TryComp(entity, out DnaComponent? dna) &&
-                            dna.DNA != record.DNA)
-                        {
-                            continue;
-                        }
-
-                        if (TryComp(entity, out FingerprintComponent? fingerPrint) &&
-                            fingerPrint.Fingerprint != record.Fingerprint)
-                        {
-                            continue;
-                        }
-
-                        _stationRecords.RemoveRecord(key);
-                        Del(item);
+                        continue;
                     }
+
+                    _stationRecords.RemoveRecord(key);
+                    Del(item);
                 }
+            }
 
-                if (_inventory.TryGetContainerSlotEnumerator(entity.Value, out var enumerator))
+            if (_inventory.TryGetContainerSlotEnumerator(entity.Value, out var enumerator))
+            {
+                while (enumerator.NextItem(out var item, out var slot))
                 {
-                    while (enumerator.NextItem(out var item, out var slot))
-                    {
-                        if (_inventory.TryUnequip(entity.Value, entity.Value, slot.Name, true, true))
-                            _physics.ApplyAngularImpulse(item, ThrowingSystem.ThrowAngularImpulse);
-                    }
+                    if (_inventory.TryUnequip(entity.Value, entity.Value, slot.Name, true, true))
+                        _physics.ApplyAngularImpulse(item, ThrowingSystem.ThrowAngularImpulse);
                 }
+            }
 
-                if (TryComp(entity.Value, out HandsComponent? hands))
+            if (TryComp(entity.Value, out HandsComponent? hands))
+            {
+                foreach (var hand in _hands.EnumerateHands(entity.Value, hands))
                 {
-                    foreach (var hand in _hands.EnumerateHands(entity.Value, hands))
-                    {
-                        _hands.TryDrop(entity.Value, hand, checkActionBlocker: false, doDropInteraction: false, handsComp: hands);
-                    }
+                    _hands.TryDrop(entity.Value, hand, checkActionBlocker: false, doDropInteraction: false, handsComp: hands);
                 }
             }
+        }
 
-            _minds.WipeMind(player);
-            QueueDel(entity);
+        _minds.WipeMind(player);
+        QueueDel(entity);
 
-            _gameTicker.SpawnObserver(player);
-        }
+        _gameTicker.SpawnObserver(player);
+    }
 
-        private void OnSessionPlayTimeUpdated(ICommonSession session)
-        {
-            UpdatePlayerList(session);
-        }
+    private void OnSessionPlayTimeUpdated(ICommonSession session)
+    {
+        UpdatePlayerList(session);
     }
 }
index b1b083f86b5a02a3c6de8d5cb6630c4ef7dc0ec0..6fb7bbba8e8debf08da6c4ed59649427c199a069 100644 (file)
@@ -18,385 +18,384 @@ using Robust.Shared.Player;
 using Robust.Shared.Replays;
 using Robust.Shared.Utility;
 
-namespace Content.Server.Chat.Managers
+namespace Content.Server.Chat.Managers;
+
+/// <summary>
+///     Dispatches chat messages to clients.
+/// </summary>
+internal sealed partial class ChatManager : IChatManager
 {
+    private static readonly Dictionary<string, string> PatronOocColors = new()
+    {
+        // I had plans for multiple colors and those went nowhere so...
+        { "nuclear_operative", "#aa00ff" },
+        { "syndicate_agent", "#aa00ff" },
+        { "revolutionary", "#aa00ff" }
+    };
+
+    [Dependency] private readonly IReplayRecordingManager _replay = default!;
+    [Dependency] private readonly IServerNetManager _netManager = default!;
+    [Dependency] private readonly IMoMMILink _mommiLink = default!;
+    [Dependency] private readonly IAdminManager _adminManager = default!;
+    [Dependency] private readonly IAdminLogManager _adminLogger = default!;
+    [Dependency] private readonly IServerPreferencesManager _preferencesManager = default!;
+    [Dependency] private readonly IConfigurationManager _configurationManager = default!;
+    [Dependency] private readonly INetConfigurationManager _netConfigManager = default!;
+    [Dependency] private readonly IEntityManager _entityManager = default!;
+    [Dependency] private readonly PlayerRateLimitManager _rateLimitManager = default!;
+
     /// <summary>
-    ///     Dispatches chat messages to clients.
+    /// The maximum length a player-sent message can be sent
     /// </summary>
-    internal sealed partial class ChatManager : IChatManager
+    public int MaxMessageLength => _configurationManager.GetCVar(CCVars.ChatMaxMessageLength);
+
+    private bool _oocEnabled = true;
+    private bool _adminOocEnabled = true;
+
+    private readonly Dictionary<NetUserId, ChatUser> _players = new();
+
+    public void Initialize()
     {
-        private static readonly Dictionary<string, string> PatronOocColors = new()
-        {
-            // I had plans for multiple colors and those went nowhere so...
-            { "nuclear_operative", "#aa00ff" },
-            { "syndicate_agent", "#aa00ff" },
-            { "revolutionary", "#aa00ff" }
-        };
-
-        [Dependency] private readonly IReplayRecordingManager _replay = default!;
-        [Dependency] private readonly IServerNetManager _netManager = default!;
-        [Dependency] private readonly IMoMMILink _mommiLink = default!;
-        [Dependency] private readonly IAdminManager _adminManager = default!;
-        [Dependency] private readonly IAdminLogManager _adminLogger = default!;
-        [Dependency] private readonly IServerPreferencesManager _preferencesManager = default!;
-        [Dependency] private readonly IConfigurationManager _configurationManager = default!;
-        [Dependency] private readonly INetConfigurationManager _netConfigManager = default!;
-        [Dependency] private readonly IEntityManager _entityManager = default!;
-        [Dependency] private readonly PlayerRateLimitManager _rateLimitManager = default!;
-
-        /// <summary>
-        /// The maximum length a player-sent message can be sent
-        /// </summary>
-        public int MaxMessageLength => _configurationManager.GetCVar(CCVars.ChatMaxMessageLength);
-
-        private bool _oocEnabled = true;
-        private bool _adminOocEnabled = true;
-
-        private readonly Dictionary<NetUserId, ChatUser> _players = new();
-
-        public void Initialize()
-        {
-            _netManager.RegisterNetMessage<MsgChatMessage>();
-            _netManager.RegisterNetMessage<MsgDeleteChatMessagesBy>();
+        _netManager.RegisterNetMessage<MsgChatMessage>();
+        _netManager.RegisterNetMessage<MsgDeleteChatMessagesBy>();
 
-            _configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true);
-            _configurationManager.OnValueChanged(CCVars.AdminOocEnabled, OnAdminOocEnabledChanged, true);
+        _configurationManager.OnValueChanged(CCVars.OocEnabled, OnOocEnabledChanged, true);
+        _configurationManager.OnValueChanged(CCVars.AdminOocEnabled, OnAdminOocEnabledChanged, true);
 
-            RegisterRateLimits();
-        }
+        RegisterRateLimits();
+    }
 
-        private void OnOocEnabledChanged(bool val)
-        {
-            if (_oocEnabled == val) return;
+    private void OnOocEnabledChanged(bool val)
+    {
+        if (_oocEnabled == val) return;
 
-            _oocEnabled = val;
-            DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-ooc-chat-enabled-message" : "chat-manager-ooc-chat-disabled-message"));
-        }
+        _oocEnabled = val;
+        DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-ooc-chat-enabled-message" : "chat-manager-ooc-chat-disabled-message"));
+    }
 
-        private void OnAdminOocEnabledChanged(bool val)
-        {
-            if (_adminOocEnabled == val) return;
+    private void OnAdminOocEnabledChanged(bool val)
+    {
+        if (_adminOocEnabled == val) return;
 
-            _adminOocEnabled = val;
-            DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message"));
-        }
+        _adminOocEnabled = val;
+        DispatchServerAnnouncement(Loc.GetString(val ? "chat-manager-admin-ooc-chat-enabled-message" : "chat-manager-admin-ooc-chat-disabled-message"));
+    }
 
-        public void DeleteMessagesBy(ICommonSession player)
-        {
-            if (!_players.TryGetValue(player.UserId, out var user))
-                return;
+    public void DeleteMessagesBy(ICommonSession player)
+    {
+        if (!_players.TryGetValue(player.UserId, out var user))
+            return;
 
-            var msg = new MsgDeleteChatMessagesBy { Key = user.Key, Entities = user.Entities };
-            _netManager.ServerSendToAll(msg);
-        }
+        var msg = new MsgDeleteChatMessagesBy { Key = user.Key, Entities = user.Entities };
+        _netManager.ServerSendToAll(msg);
+    }
 
-        [return: NotNullIfNotNull(nameof(author))]
-        public ChatUser? EnsurePlayer(NetUserId? author)
-        {
-            if (author == null)
-                return null;
+    [return: NotNullIfNotNull(nameof(author))]
+    public ChatUser? EnsurePlayer(NetUserId? author)
+    {
+        if (author == null)
+            return null;
 
-            ref var user = ref CollectionsMarshal.GetValueRefOrAddDefault(_players, author.Value, out var exists);
-            if (!exists || user == null)
-                user = new ChatUser(_players.Count);
+        ref var user = ref CollectionsMarshal.GetValueRefOrAddDefault(_players, author.Value, out var exists);
+        if (!exists || user == null)
+            user = new ChatUser(_players.Count);
 
-            return user;
-        }
+        return user;
+    }
 
-        #region Server Announcements
+    #region Server Announcements
 
-        public void DispatchServerAnnouncement(string message, Color? colorOverride = null)
-        {
-            var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", FormattedMessage.EscapeText(message)));
-            ChatMessageToAll(ChatChannel.Server, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride);
-            Logger.InfoS("SERVER", message);
+    public void DispatchServerAnnouncement(string message, Color? colorOverride = null)
+    {
+        var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", FormattedMessage.EscapeText(message)));
+        ChatMessageToAll(ChatChannel.Server, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride);
+        Logger.InfoS("SERVER", message);
 
-            _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Server announcement: {message}");
-        }
+        _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Server announcement: {message}");
+    }
 
-        public void DispatchServerMessage(ICommonSession player, string message, bool suppressLog = false)
-        {
-            var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", FormattedMessage.EscapeText(message)));
-            ChatMessageToOne(ChatChannel.Server, message, wrappedMessage, default, false, player.Channel);
+    public void DispatchServerMessage(ICommonSession player, string message, bool suppressLog = false)
+    {
+        var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", FormattedMessage.EscapeText(message)));
+        ChatMessageToOne(ChatChannel.Server, message, wrappedMessage, default, false, player.Channel);
 
-            if (!suppressLog)
-                _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Server message to {player:Player}: {message}");
-        }
+        if (!suppressLog)
+            _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Server message to {player:Player}: {message}");
+    }
 
-        public void SendAdminAnnouncement(string message, AdminFlags? flagBlacklist, AdminFlags? flagWhitelist)
+    public void SendAdminAnnouncement(string message, AdminFlags? flagBlacklist, AdminFlags? flagWhitelist)
+    {
+        var clients = _adminManager.ActiveAdmins.Where(p =>
         {
-            var clients = _adminManager.ActiveAdmins.Where(p =>
-            {
-                var adminData = _adminManager.GetAdminData(p);
+            var adminData = _adminManager.GetAdminData(p);
 
-                DebugTools.AssertNotNull(adminData);
+            DebugTools.AssertNotNull(adminData);
 
-                if (adminData == null)
-                    return false;
+            if (adminData == null)
+                return false;
 
-                if (flagBlacklist != null && adminData.HasFlag(flagBlacklist.Value))
-                    return false;
+            if (flagBlacklist != null && adminData.HasFlag(flagBlacklist.Value))
+                return false;
 
-                return flagWhitelist == null || adminData.HasFlag(flagWhitelist.Value);
+            return flagWhitelist == null || adminData.HasFlag(flagWhitelist.Value);
 
-            }).Select(p => p.Channel);
+        }).Select(p => p.Channel);
 
-            var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
-                ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
+        var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
+            ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
 
-            ChatMessageToMany(ChatChannel.Admin, message, wrappedMessage, default, false, true, clients);
-            _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Admin announcement: {message}");
-        }
+        ChatMessageToMany(ChatChannel.Admin, message, wrappedMessage, default, false, true, clients);
+        _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Admin announcement: {message}");
+    }
 
-        public void SendAdminAnnouncementMessage(ICommonSession player, string message, bool suppressLog = true)
-        {
-            var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
-                ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")),
-                ("message", FormattedMessage.EscapeText(message)));
-            ChatMessageToOne(ChatChannel.Admin, message, wrappedMessage, default, false, player.Channel);
-        }
+    public void SendAdminAnnouncementMessage(ICommonSession player, string message, bool suppressLog = true)
+    {
+        var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
+            ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")),
+            ("message", FormattedMessage.EscapeText(message)));
+        ChatMessageToOne(ChatChannel.Admin, message, wrappedMessage, default, false, player.Channel);
+    }
 
-        public void SendAdminAlert(string message)
-        {
-            var clients = _adminManager.ActiveAdmins.Select(p => p.Channel);
+    public void SendAdminAlert(string message)
+    {
+        var clients = _adminManager.ActiveAdmins.Select(p => p.Channel);
 
-            var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
-                ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
+        var wrappedMessage = Loc.GetString("chat-manager-send-admin-announcement-wrap-message",
+            ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")), ("message", FormattedMessage.EscapeText(message)));
 
-            ChatMessageToMany(ChatChannel.AdminAlert, message, wrappedMessage, default, false, true, clients);
-        }
+        ChatMessageToMany(ChatChannel.AdminAlert, message, wrappedMessage, default, false, true, clients);
+    }
 
-        public void SendAdminAlert(EntityUid player, string message)
+    public void SendAdminAlert(EntityUid player, string message)
+    {
+        var mindSystem = _entityManager.System<SharedMindSystem>();
+        if (!mindSystem.TryGetMind(player, out var mindId, out var mind))
         {
-            var mindSystem = _entityManager.System<SharedMindSystem>();
-            if (!mindSystem.TryGetMind(player, out var mindId, out var mind))
-            {
-                SendAdminAlert(message);
-                return;
-            }
+            SendAdminAlert(message);
+            return;
+        }
 
-            var adminSystem = _entityManager.System<AdminSystem>();
-            var antag = mind.UserId != null && (adminSystem.GetCachedPlayerInfo(mind.UserId.Value)?.Antag ?? false);
+        var adminSystem = _entityManager.System<AdminSystem>();
+        var antag = mind.UserId != null && (adminSystem.GetCachedPlayerInfo(mind.UserId.Value)?.Antag ?? false);
 
-            SendAdminAlert($"{mind.Session?.Name}{(antag ? " (ANTAG)" : "")} {message}");
-        }
+        SendAdminAlert($"{mind.Session?.Name}{(antag ? " (ANTAG)" : "")} {message}");
+    }
 
-        public void SendHookOOC(string sender, string message)
+    public void SendHookOOC(string sender, string message)
+    {
+        if (!_oocEnabled && _configurationManager.GetCVar(CCVars.DisablingOOCDisablesRelay))
         {
-            if (!_oocEnabled && _configurationManager.GetCVar(CCVars.DisablingOOCDisablesRelay))
-            {
-                return;
-            }
-            var wrappedMessage = Loc.GetString("chat-manager-send-hook-ooc-wrap-message", ("senderName", sender), ("message", FormattedMessage.EscapeText(message)));
-            ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, source: EntityUid.Invalid, hideChat: false, recordReplay: true);
-            _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Hook OOC from {sender}: {message}");
+            return;
         }
+        var wrappedMessage = Loc.GetString("chat-manager-send-hook-ooc-wrap-message", ("senderName", sender), ("message", FormattedMessage.EscapeText(message)));
+        ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, source: EntityUid.Invalid, hideChat: false, recordReplay: true);
+        _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Hook OOC from {sender}: {message}");
+    }
 
-        #endregion
+    #endregion
 
-        #region Public OOC Chat API
+    #region Public OOC Chat API
 
-        /// <summary>
-        ///     Called for a player to attempt sending an OOC, out-of-game. message.
-        /// </summary>
-        /// <param name="player">The player sending the message.</param>
-        /// <param name="message">The message.</param>
-        /// <param name="type">The type of message.</param>
-        public void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type)
-        {
-            if (HandleRateLimit(player) != RateLimitStatus.Allowed)
-                return;
+    /// <summary>
+    ///     Called for a player to attempt sending an OOC, out-of-game. message.
+    /// </summary>
+    /// <param name="player">The player sending the message.</param>
+    /// <param name="message">The message.</param>
+    /// <param name="type">The type of message.</param>
+    public void TrySendOOCMessage(ICommonSession player, string message, OOCChatType type)
+    {
+        if (HandleRateLimit(player) != RateLimitStatus.Allowed)
+            return;
 
-            // Check if message exceeds the character limit
-            if (message.Length > MaxMessageLength)
-            {
-                DispatchServerMessage(player, Loc.GetString("chat-manager-max-message-length-exceeded-message", ("limit", MaxMessageLength)));
-                return;
-            }
+        // Check if message exceeds the character limit
+        if (message.Length > MaxMessageLength)
+        {
+            DispatchServerMessage(player, Loc.GetString("chat-manager-max-message-length-exceeded-message", ("limit", MaxMessageLength)));
+            return;
+        }
 
-            switch (type)
-            {
-                case OOCChatType.OOC:
-                    SendOOC(player, message);
-                    break;
-                case OOCChatType.Admin:
-                    SendAdminChat(player, message);
-                    break;
-            }
+        switch (type)
+        {
+            case OOCChatType.OOC:
+                SendOOC(player, message);
+                break;
+            case OOCChatType.Admin:
+                SendAdminChat(player, message);
+                break;
         }
+    }
 
-        #endregion
+    #endregion
 
-        #region Private API
+    #region Private API
 
-        private void SendOOC(ICommonSession player, string message)
+    private void SendOOC(ICommonSession player, string message)
+    {
+        if (_adminManager.IsAdmin(player))
         {
-            if (_adminManager.IsAdmin(player))
-            {
-                if (!_adminOocEnabled)
-                {
-                    return;
-                }
-            }
-            else if (!_oocEnabled)
+            if (!_adminOocEnabled)
             {
                 return;
             }
-
-            Color? colorOverride = null;
-            var wrappedMessage = Loc.GetString("chat-manager-send-ooc-wrap-message", ("playerName",player.Name), ("message", FormattedMessage.EscapeText(message)));
-            if (_adminManager.HasAdminFlag(player, AdminFlags.Admin))
-            {
-                var prefs = _preferencesManager.GetPreferences(player.UserId);
-                colorOverride = prefs.AdminOOCColor;
-            }
-            if (  _netConfigManager.GetClientCVar(player.Channel, CCVars.ShowOocPatronColor) && player.Channel.UserData.PatronTier is { } patron && PatronOocColors.TryGetValue(patron, out var patronColor))
-            {
-                wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
-            }
-
-            //TODO: player.Name color, this will need to change the structure of the MsgChatMessage
-            ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride, author: player.UserId);
-            _mommiLink.SendOOCMessage(player.Name, message.Replace("@", "\\@").Replace("<", "\\<").Replace("/", "\\/")); // @ and < are both problematic for discord due to pinging. / is sanitized solely to kneecap links to murder embeds via blunt force
-            _adminLogger.Add(LogType.Chat, LogImpact.Low, $"OOC from {player:Player}: {message}");
         }
-
-        private void SendAdminChat(ICommonSession player, string message)
+        else if (!_oocEnabled)
         {
-            if (!_adminManager.IsAdmin(player))
-            {
-                _adminLogger.Add(LogType.Chat, LogImpact.Extreme, $"{player:Player} attempted to send admin message but was not admin");
-                return;
-            }
+            return;
+        }
 
-            var clients = _adminManager.ActiveAdmins.Select(p => p.Channel);
-            var wrappedMessage = Loc.GetString("chat-manager-send-admin-chat-wrap-message",
-                                            ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")),
-                                            ("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
+        Color? colorOverride = null;
+        var wrappedMessage = Loc.GetString("chat-manager-send-ooc-wrap-message", ("playerName",player.Name), ("message", FormattedMessage.EscapeText(message)));
+        if (_adminManager.HasAdminFlag(player, AdminFlags.Admin))
+        {
+            var prefs = _preferencesManager.GetPreferences(player.UserId);
+            colorOverride = prefs.AdminOOCColor;
+        }
+        if (  _netConfigManager.GetClientCVar(player.Channel, CCVars.ShowOocPatronColor) && player.Channel.UserData.PatronTier is { } patron && PatronOocColors.TryGetValue(patron, out var patronColor))
+        {
+            wrappedMessage = Loc.GetString("chat-manager-send-ooc-patron-wrap-message", ("patronColor", patronColor),("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
+        }
 
-            foreach (var client in clients)
-            {
-                var isSource = client != player.Channel;
-                ChatMessageToOne(ChatChannel.AdminChat,
-                    message,
-                    wrappedMessage,
-                    default,
-                    false,
-                    client,
-                    audioPath: isSource ? _netConfigManager.GetClientCVar(client, CCVars.AdminChatSoundPath) : default,
-                    audioVolume: isSource ? _netConfigManager.GetClientCVar(client, CCVars.AdminChatSoundVolume) : default,
-                    author: player.UserId);
-            }
+        //TODO: player.Name color, this will need to change the structure of the MsgChatMessage
+        ChatMessageToAll(ChatChannel.OOC, message, wrappedMessage, EntityUid.Invalid, hideChat: false, recordReplay: true, colorOverride: colorOverride, author: player.UserId);
+        _mommiLink.SendOOCMessage(player.Name, message.Replace("@", "\\@").Replace("<", "\\<").Replace("/", "\\/")); // @ and < are both problematic for discord due to pinging. / is sanitized solely to kneecap links to murder embeds via blunt force
+        _adminLogger.Add(LogType.Chat, LogImpact.Low, $"OOC from {player:Player}: {message}");
+    }
 
-            _adminLogger.Add(LogType.Chat, $"Admin chat from {player:Player}: {message}");
+    private void SendAdminChat(ICommonSession player, string message)
+    {
+        if (!_adminManager.IsAdmin(player))
+        {
+            _adminLogger.Add(LogType.Chat, LogImpact.Extreme, $"{player:Player} attempted to send admin message but was not admin");
+            return;
         }
 
-        #endregion
+        var clients = _adminManager.ActiveAdmins.Select(p => p.Channel);
+        var wrappedMessage = Loc.GetString("chat-manager-send-admin-chat-wrap-message",
+                                        ("adminChannelName", Loc.GetString("chat-manager-admin-channel-name")),
+                                        ("playerName", player.Name), ("message", FormattedMessage.EscapeText(message)));
 
-        #region Utility
-
-        public void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, INetChannel client, Color? colorOverride = null, bool recordReplay = false, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
+        foreach (var client in clients)
         {
-            var user = author == null ? null : EnsurePlayer(author);
-            var netSource = _entityManager.GetNetEntity(source);
-            user?.AddEntity(netSource);
+            var isSource = client != player.Channel;
+            ChatMessageToOne(ChatChannel.AdminChat,
+                message,
+                wrappedMessage,
+                default,
+                false,
+                client,
+                audioPath: isSource ? _netConfigManager.GetClientCVar(client, CCVars.AdminChatSoundPath) : default,
+                audioVolume: isSource ? _netConfigManager.GetClientCVar(client, CCVars.AdminChatSoundVolume) : default,
+                author: player.UserId);
+        }
 
-            var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
-            _netManager.ServerSendMessage(new MsgChatMessage() { Message = msg }, client);
+        _adminLogger.Add(LogType.Chat, $"Admin chat from {player:Player}: {message}");
+    }
 
-            if (!recordReplay)
-                return;
+    #endregion
 
-            if ((channel & ChatChannel.AdminRelated) == 0 ||
-                _configurationManager.GetCVar(CCVars.ReplayRecordAdminChat))
-            {
-                _replay.RecordServerMessage(msg);
-            }
-        }
+    #region Utility
+
+    public void ChatMessageToOne(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, INetChannel client, Color? colorOverride = null, bool recordReplay = false, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
+    {
+        var user = author == null ? null : EnsurePlayer(author);
+        var netSource = _entityManager.GetNetEntity(source);
+        user?.AddEntity(netSource);
 
-        public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, IEnumerable<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
-            => ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients.ToList(), colorOverride, audioPath, audioVolume, author);
+        var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
+        _netManager.ServerSendMessage(new MsgChatMessage() { Message = msg }, client);
 
-        public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, List<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
+        if (!recordReplay)
+            return;
+
+        if ((channel & ChatChannel.AdminRelated) == 0 ||
+            _configurationManager.GetCVar(CCVars.ReplayRecordAdminChat))
         {
-            var user = author == null ? null : EnsurePlayer(author);
-            var netSource = _entityManager.GetNetEntity(source);
-            user?.AddEntity(netSource);
+            _replay.RecordServerMessage(msg);
+        }
+    }
 
-            var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
-            _netManager.ServerSendToMany(new MsgChatMessage() { Message = msg }, clients);
+    public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, IEnumerable<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
+        => ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients.ToList(), colorOverride, audioPath, audioVolume, author);
 
-            if (!recordReplay)
-                return;
+    public void ChatMessageToMany(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, List<INetChannel> clients, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
+    {
+        var user = author == null ? null : EnsurePlayer(author);
+        var netSource = _entityManager.GetNetEntity(source);
+        user?.AddEntity(netSource);
 
-            if ((channel & ChatChannel.AdminRelated) == 0 ||
-                _configurationManager.GetCVar(CCVars.ReplayRecordAdminChat))
-            {
-                _replay.RecordServerMessage(msg);
-            }
-        }
+        var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
+        _netManager.ServerSendToMany(new MsgChatMessage() { Message = msg }, clients);
+
+        if (!recordReplay)
+            return;
 
-        public void ChatMessageToManyFiltered(Filter filter, ChatChannel channel, string message, string wrappedMessage, EntityUid source,
-            bool hideChat, bool recordReplay, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0)
+        if ((channel & ChatChannel.AdminRelated) == 0 ||
+            _configurationManager.GetCVar(CCVars.ReplayRecordAdminChat))
         {
-            if (!recordReplay && !filter.Recipients.Any())
-                return;
+            _replay.RecordServerMessage(msg);
+        }
+    }
 
-            var clients = new List<INetChannel>();
-            foreach (var recipient in filter.Recipients)
-            {
-                clients.Add(recipient.Channel);
-            }
+    public void ChatMessageToManyFiltered(Filter filter, ChatChannel channel, string message, string wrappedMessage, EntityUid source,
+        bool hideChat, bool recordReplay, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0)
+    {
+        if (!recordReplay && !filter.Recipients.Any())
+            return;
 
-            ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients, colorOverride, audioPath, audioVolume);
+        var clients = new List<INetChannel>();
+        foreach (var recipient in filter.Recipients)
+        {
+            clients.Add(recipient.Channel);
         }
 
-        public void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
-        {
-            var user = author == null ? null : EnsurePlayer(author);
-            var netSource = _entityManager.GetNetEntity(source);
-            user?.AddEntity(netSource);
+        ChatMessageToMany(channel, message, wrappedMessage, source, hideChat, recordReplay, clients, colorOverride, audioPath, audioVolume);
+    }
 
-            var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
-            _netManager.ServerSendToAll(new MsgChatMessage() { Message = msg });
+    public void ChatMessageToAll(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool recordReplay, Color? colorOverride = null, string? audioPath = null, float audioVolume = 0, NetUserId? author = null)
+    {
+        var user = author == null ? null : EnsurePlayer(author);
+        var netSource = _entityManager.GetNetEntity(source);
+        user?.AddEntity(netSource);
 
-            if (!recordReplay)
-                return;
+        var msg = new ChatMessage(channel, message, wrappedMessage, netSource, user?.Key, hideChat, colorOverride, audioPath, audioVolume);
+        _netManager.ServerSendToAll(new MsgChatMessage() { Message = msg });
 
-            if ((channel & ChatChannel.AdminRelated) == 0 ||
-                _configurationManager.GetCVar(CCVars.ReplayRecordAdminChat))
-            {
-                _replay.RecordServerMessage(msg);
-            }
-        }
+        if (!recordReplay)
+            return;
 
-        public bool MessageCharacterLimit(ICommonSession? player, string message)
+        if ((channel & ChatChannel.AdminRelated) == 0 ||
+            _configurationManager.GetCVar(CCVars.ReplayRecordAdminChat))
         {
-            var isOverLength = false;
+            _replay.RecordServerMessage(msg);
+        }
+    }
 
-            // Non-players don't need to be checked.
-            if (player == null)
-                return false;
+    public bool MessageCharacterLimit(ICommonSession? player, string message)
+    {
+        var isOverLength = false;
 
-            // Check if message exceeds the character limit if the sender is a player
-            if (message.Length > MaxMessageLength)
-            {
-                var feedback = Loc.GetString("chat-manager-max-message-length-exceeded-message", ("limit", MaxMessageLength));
+        // Non-players don't need to be checked.
+        if (player == null)
+            return false;
 
-                DispatchServerMessage(player, feedback);
+        // Check if message exceeds the character limit if the sender is a player
+        if (message.Length > MaxMessageLength)
+        {
+            var feedback = Loc.GetString("chat-manager-max-message-length-exceeded-message", ("limit", MaxMessageLength));
 
-                isOverLength = true;
-            }
+            DispatchServerMessage(player, feedback);
 
-            return isOverLength;
+            isOverLength = true;
         }
 
-        #endregion
+        return isOverLength;
     }
 
-    public enum OOCChatType : byte
-    {
-        OOC,
-        Admin
-    }
+    #endregion
+}
+
+public enum OOCChatType : byte
+{
+    OOC,
+    Admin
 }
index 9952da72a12bc538c5da7f129c00b2412c7e4293..24e592eb946e3751c586c22125c563105a09be10 100644 (file)
@@ -1,11 +1,10 @@
-namespace Content.Server.Ghost
+namespace Content.Server.Ghost;
+
+/// <summary>
+/// This is used to mark Observers properly, as they get Minds
+/// </summary>
+[RegisterComponent]
+public sealed partial class ObserverRoleComponent : Component
 {
-    /// <summary>
-    /// This is used to mark Observers properly, as they get Minds
-    /// </summary>
-    [RegisterComponent]
-    public sealed partial class ObserverRoleComponent : Component
-    {
-        public string Name => Loc.GetString("observer-role-name");
-    }
+    public string Name => Loc.GetString("observer-role-name");
 }
index 14007edcbf9ca0ce3fbdad40d97f3e33b0ae1158..8089941444ff500e725c5774f23038e3931918ab 100644 (file)
 using Content.Server.Mind.Commands;
 using Content.Shared.Roles;
 
-namespace Content.Server.Ghost.Roles.Components
+namespace Content.Server.Ghost.Roles.Components;
+
+[RegisterComponent]
+[Access(typeof(GhostRoleSystem))]
+public sealed partial class GhostRoleComponent : Component
 {
-    [RegisterComponent]
-    [Access(typeof(GhostRoleSystem))]
-    public sealed partial class GhostRoleComponent : Component
-    {
-        [DataField("name")] private string _roleName = "Unknown";
+    [DataField("name")] private string _roleName = "Unknown";
 
-        [DataField("description")] private string _roleDescription = "Unknown";
+    [DataField("description")] private string _roleDescription = "Unknown";
 
-        [DataField("rules")] private string _roleRules = "ghost-role-component-default-rules";
+    [DataField("rules")] private string _roleRules = "ghost-role-component-default-rules";
 
-        // TODO ROLE TIMERS
-        // Actually make use of / enforce this requirement?
-        // Why is this even here.
-        // Move to ghost role prototype & respect CCvars.GameRoleTimerOverride
-        [DataField("requirements")]
-        public HashSet<JobRequirement>? Requirements;
+    // TODO ROLE TIMERS
+    // Actually make use of / enforce this requirement?
+    // Why is this even here.
+    // Move to ghost role prototype & respect CCvars.GameRoleTimerOverride
+    [DataField("requirements")]
+    public HashSet<JobRequirement>? Requirements;
 
-        /// <summary>
-        /// Whether the <see cref="MakeSentientCommand"/> should run on the mob.
-        /// </summary>
-        [ViewVariables(VVAccess.ReadWrite)] [DataField("makeSentient")]
-        public bool MakeSentient = true;
+    /// <summary>
+    /// Whether the <see cref="MakeSentientCommand"/> should run on the mob.
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite)] [DataField("makeSentient")]
+    public bool MakeSentient = true;
 
-        /// <summary>
-        ///     The probability that this ghost role will be available after init.
-        ///     Used mostly for takeover roles that want some probability of being takeover, but not 100%.
-        /// </summary>
-        [DataField("prob")]
-        public float Probability = 1f;
+    /// <summary>
+    ///     The probability that this ghost role will be available after init.
+    ///     Used mostly for takeover roles that want some probability of being takeover, but not 100%.
+    /// </summary>
+    [DataField("prob")]
+    public float Probability = 1f;
 
-        // We do this so updating RoleName and RoleDescription in VV updates the open EUIs.
+    // We do this so updating RoleName and RoleDescription in VV updates the open EUIs.
 
-        [ViewVariables(VVAccess.ReadWrite)]
-        [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
-        public string RoleName
+    [ViewVariables(VVAccess.ReadWrite)]
+    [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
+    public string RoleName
+    {
+        get => Loc.GetString(_roleName);
+        set
         {
-            get => Loc.GetString(_roleName);
-            set
-            {
-                _roleName = value;
-                IoCManager.Resolve<IEntityManager>().System<GhostRoleSystem>().UpdateAllEui();
-            }
+            _roleName = value;
+            IoCManager.Resolve<IEntityManager>().System<GhostRoleSystem>().UpdateAllEui();
         }
+    }
 
-        [ViewVariables(VVAccess.ReadWrite)]
-        [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
-        public string RoleDescription
+    [ViewVariables(VVAccess.ReadWrite)]
+    [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
+    public string RoleDescription
+    {
+        get => Loc.GetString(_roleDescription);
+        set
         {
-            get => Loc.GetString(_roleDescription);
-            set
-            {
-                _roleDescription = value;
-                IoCManager.Resolve<IEntityManager>().System<GhostRoleSystem>().UpdateAllEui();
-            }
+            _roleDescription = value;
+            IoCManager.Resolve<IEntityManager>().System<GhostRoleSystem>().UpdateAllEui();
         }
+    }
 
-        [ViewVariables(VVAccess.ReadWrite)]
-        [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
-        public string RoleRules
+    [ViewVariables(VVAccess.ReadWrite)]
+    [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
+    public string RoleRules
+    {
+        get => Loc.GetString(_roleRules);
+        set
         {
-            get => Loc.GetString(_roleRules);
-            set
-            {
-                _roleRules = value;
-                IoCManager.Resolve<IEntityManager>().System<GhostRoleSystem>().UpdateAllEui();
-            }
+            _roleRules = value;
+            IoCManager.Resolve<IEntityManager>().System<GhostRoleSystem>().UpdateAllEui();
         }
-
-        [DataField("allowSpeech")]
-        [ViewVariables(VVAccess.ReadWrite)]
-        public bool AllowSpeech { get; set; } = true;
-
-        [DataField("allowMovement")]
-        [ViewVariables(VVAccess.ReadWrite)]
-        public bool AllowMovement { get; set; }
-
-        [ViewVariables(VVAccess.ReadOnly)]
-        public bool Taken { get; set; }
-
-        [ViewVariables]
-        public uint Identifier { get; set; }
-
-        /// <summary>
-        /// Reregisters the ghost role when the current player ghosts.
-        /// </summary>
-        [ViewVariables(VVAccess.ReadWrite)]
-        [DataField("reregister")]
-        public bool ReregisterOnGhost { get; set; } = true;
-
-        /// <summary>
-        /// If set, ghost role is raffled, otherwise it is first-come-first-serve.
-        /// </summary>
-        [DataField("raffle")]
-        [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
-        public GhostRoleRaffleConfig? RaffleConfig { get; set; }
     }
+
+    [DataField("allowSpeech")]
+    [ViewVariables(VVAccess.ReadWrite)]
+    public bool AllowSpeech { get; set; } = true;
+
+    [DataField("allowMovement")]
+    [ViewVariables(VVAccess.ReadWrite)]
+    public bool AllowMovement { get; set; }
+
+    [ViewVariables(VVAccess.ReadOnly)]
+    public bool Taken { get; set; }
+
+    [ViewVariables]
+    public uint Identifier { get; set; }
+
+    /// <summary>
+    /// Reregisters the ghost role when the current player ghosts.
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite)]
+    [DataField("reregister")]
+    public bool ReregisterOnGhost { get; set; } = true;
+
+    /// <summary>
+    /// If set, ghost role is raffled, otherwise it is first-come-first-serve.
+    /// </summary>
+    [DataField("raffle")]
+    [Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
+    public GhostRoleRaffleConfig? RaffleConfig { get; set; }
 }
index d95fc922671958143db21b31fbf3b33b1c8d6a0e..4580e2ef36d3f65957fa9e3efdbf647862201db6 100644 (file)
@@ -34,794 +34,793 @@ using Content.Shared.Verbs;
 using Robust.Shared.Collections;
 using Content.Shared.Ghost.Roles.Components;
 
-namespace Content.Server.Ghost.Roles
+namespace Content.Server.Ghost.Roles;
+
+[UsedImplicitly]
+public sealed class GhostRoleSystem : EntitySystem
 {
-    [UsedImplicitly]
-    public sealed class GhostRoleSystem : EntitySystem
-    {
-        [Dependency] private readonly IConfigurationManager _cfg = default!;
-        [Dependency] private readonly EuiManager _euiManager = default!;
-        [Dependency] private readonly IPlayerManager _playerManager = default!;
-        [Dependency] private readonly IAdminLogManager _adminLogger = default!;
-        [Dependency] private readonly IRobustRandom _random = default!;
-        [Dependency] private readonly FollowerSystem _followerSystem = default!;
-        [Dependency] private readonly TransformSystem _transform = default!;
-        [Dependency] private readonly SharedMindSystem _mindSystem = default!;
-        [Dependency] private readonly SharedRoleSystem _roleSystem = default!;
-        [Dependency] private readonly IGameTiming _timing = default!;
-        [Dependency] private readonly PopupSystem _popupSystem = default!;
-        [Dependency] private readonly IPrototypeManager _prototype = default!;
-
-        private uint _nextRoleIdentifier;
-        private bool _needsUpdateGhostRoleCount = true;
-
-        private readonly Dictionary<uint, Entity<GhostRoleComponent>> _ghostRoles = new();
-        private readonly Dictionary<uint, Entity<GhostRoleRaffleComponent>> _ghostRoleRaffles = new();
-
-        private readonly Dictionary<ICommonSession, GhostRolesEui> _openUis = new();
-        private readonly Dictionary<ICommonSession, MakeGhostRoleEui> _openMakeGhostRoleUis = new();
-
-        [ViewVariables]
-        public IReadOnlyCollection<Entity<GhostRoleComponent>> GhostRoles => _ghostRoles.Values;
-
-        public override void Initialize()
-        {
-            base.Initialize();
-
-            SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
-            SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
-            SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindAddedMessage>(OnMindAdded);
-            SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindRemovedMessage>(OnMindRemoved);
-            SubscribeLocalEvent<GhostTakeoverAvailableComponent, MobStateChangedEvent>(OnMobStateChanged);
-            SubscribeLocalEvent<GhostRoleComponent, MapInitEvent>(OnMapInit);
-            SubscribeLocalEvent<GhostRoleComponent, ComponentStartup>(OnRoleStartup);
-            SubscribeLocalEvent<GhostRoleComponent, ComponentShutdown>(OnRoleShutdown);
-            SubscribeLocalEvent<GhostRoleComponent, EntityPausedEvent>(OnPaused);
-            SubscribeLocalEvent<GhostRoleComponent, EntityUnpausedEvent>(OnUnpaused);
-            SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentInit>(OnRaffleInit);
-            SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentShutdown>(OnRaffleShutdown);
-            SubscribeLocalEvent<GhostRoleMobSpawnerComponent, TakeGhostRoleEvent>(OnSpawnerTakeRole);
-            SubscribeLocalEvent<GhostTakeoverAvailableComponent, TakeGhostRoleEvent>(OnTakeoverTakeRole);
-            SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GetVerbsEvent<Verb>>(OnVerb);
-            SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GhostRoleRadioMessage>(OnGhostRoleRadioMessage);
-            _playerManager.PlayerStatusChanged += PlayerStatusChanged;
-        }
+    [Dependency] private readonly IConfigurationManager _cfg = default!;
+    [Dependency] private readonly EuiManager _euiManager = default!;
+    [Dependency] private readonly IPlayerManager _playerManager = default!;
+    [Dependency] private readonly IAdminLogManager _adminLogger = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly FollowerSystem _followerSystem = default!;
+    [Dependency] private readonly TransformSystem _transform = default!;
+    [Dependency] private readonly SharedMindSystem _mindSystem = default!;
+    [Dependency] private readonly SharedRoleSystem _roleSystem = default!;
+    [Dependency] private readonly IGameTiming _timing = default!;
+    [Dependency] private readonly PopupSystem _popupSystem = default!;
+    [Dependency] private readonly IPrototypeManager _prototype = default!;
+
+    private uint _nextRoleIdentifier;
+    private bool _needsUpdateGhostRoleCount = true;
+
+    private readonly Dictionary<uint, Entity<GhostRoleComponent>> _ghostRoles = new();
+    private readonly Dictionary<uint, Entity<GhostRoleRaffleComponent>> _ghostRoleRaffles = new();
+
+    private readonly Dictionary<ICommonSession, GhostRolesEui> _openUis = new();
+    private readonly Dictionary<ICommonSession, MakeGhostRoleEui> _openMakeGhostRoleUis = new();
+
+    [ViewVariables]
+    public IReadOnlyCollection<Entity<GhostRoleComponent>> GhostRoles => _ghostRoles.Values;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
+        SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
+        SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindAddedMessage>(OnMindAdded);
+        SubscribeLocalEvent<GhostTakeoverAvailableComponent, MindRemovedMessage>(OnMindRemoved);
+        SubscribeLocalEvent<GhostTakeoverAvailableComponent, MobStateChangedEvent>(OnMobStateChanged);
+        SubscribeLocalEvent<GhostRoleComponent, MapInitEvent>(OnMapInit);
+        SubscribeLocalEvent<GhostRoleComponent, ComponentStartup>(OnRoleStartup);
+        SubscribeLocalEvent<GhostRoleComponent, ComponentShutdown>(OnRoleShutdown);
+        SubscribeLocalEvent<GhostRoleComponent, EntityPausedEvent>(OnPaused);
+        SubscribeLocalEvent<GhostRoleComponent, EntityUnpausedEvent>(OnUnpaused);
+        SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentInit>(OnRaffleInit);
+        SubscribeLocalEvent<GhostRoleRaffleComponent, ComponentShutdown>(OnRaffleShutdown);
+        SubscribeLocalEvent<GhostRoleMobSpawnerComponent, TakeGhostRoleEvent>(OnSpawnerTakeRole);
+        SubscribeLocalEvent<GhostTakeoverAvailableComponent, TakeGhostRoleEvent>(OnTakeoverTakeRole);
+        SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GetVerbsEvent<Verb>>(OnVerb);
+        SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GhostRoleRadioMessage>(OnGhostRoleRadioMessage);
+        _playerManager.PlayerStatusChanged += PlayerStatusChanged;
+    }
 
-        private void OnMobStateChanged(Entity<GhostTakeoverAvailableComponent> component, ref MobStateChangedEvent args)
-        {
-            if (!TryComp(component, out GhostRoleComponent? ghostRole))
-                return;
+    private void OnMobStateChanged(Entity<GhostTakeoverAvailableComponent> component, ref MobStateChangedEvent args)
+    {
+        if (!TryComp(component, out GhostRoleComponent? ghostRole))
+            return;
 
-            switch (args.NewMobState)
-            {
-                case MobState.Alive:
-                    {
-                        if (!ghostRole.Taken)
-                            RegisterGhostRole((component, ghostRole));
-                        break;
-                    }
-                case MobState.Critical:
-                case MobState.Dead:
-                    UnregisterGhostRole((component, ghostRole));
+        switch (args.NewMobState)
+        {
+            case MobState.Alive:
+                {
+                    if (!ghostRole.Taken)
+                        RegisterGhostRole((component, ghostRole));
                     break;
-            }
+                }
+            case MobState.Critical:
+            case MobState.Dead:
+                UnregisterGhostRole((component, ghostRole));
+                break;
         }
+    }
 
-        public override void Shutdown()
-        {
-            base.Shutdown();
+    public override void Shutdown()
+    {
+        base.Shutdown();
 
-            _playerManager.PlayerStatusChanged -= PlayerStatusChanged;
-        }
+        _playerManager.PlayerStatusChanged -= PlayerStatusChanged;
+    }
 
-        private uint GetNextRoleIdentifier()
-        {
-            return unchecked(_nextRoleIdentifier++);
-        }
+    private uint GetNextRoleIdentifier()
+    {
+        return unchecked(_nextRoleIdentifier++);
+    }
 
-        public void OpenEui(ICommonSession session)
-        {
-            if (session.AttachedEntity is not { Valid: true } attached ||
-                !EntityManager.HasComponent<GhostComponent>(attached))
-                return;
+    public void OpenEui(ICommonSession session)
+    {
+        if (session.AttachedEntity is not { Valid: true } attached ||
+            !EntityManager.HasComponent<GhostComponent>(attached))
+            return;
 
-            if (_openUis.ContainsKey(session))
-                CloseEui(session);
+        if (_openUis.ContainsKey(session))
+            CloseEui(session);
 
-            var eui = _openUis[session] = new GhostRolesEui();
-            _euiManager.OpenEui(eui, session);
-            eui.StateDirty();
-        }
+        var eui = _openUis[session] = new GhostRolesEui();
+        _euiManager.OpenEui(eui, session);
+        eui.StateDirty();
+    }
 
-        public void OpenMakeGhostRoleEui(ICommonSession session, EntityUid uid)
-        {
-            if (session.AttachedEntity == null)
-                return;
+    public void OpenMakeGhostRoleEui(ICommonSession session, EntityUid uid)
+    {
+        if (session.AttachedEntity == null)
+            return;
 
-            if (_openMakeGhostRoleUis.ContainsKey(session))
-                CloseEui(session);
+        if (_openMakeGhostRoleUis.ContainsKey(session))
+            CloseEui(session);
 
-            var eui = _openMakeGhostRoleUis[session] = new MakeGhostRoleEui(EntityManager, GetNetEntity(uid));
-            _euiManager.OpenEui(eui, session);
-            eui.StateDirty();
-        }
+        var eui = _openMakeGhostRoleUis[session] = new MakeGhostRoleEui(EntityManager, GetNetEntity(uid));
+        _euiManager.OpenEui(eui, session);
+        eui.StateDirty();
+    }
 
-        public void CloseEui(ICommonSession session)
-        {
-            if (!_openUis.ContainsKey(session))
-                return;
+    public void CloseEui(ICommonSession session)
+    {
+        if (!_openUis.ContainsKey(session))
+            return;
 
-            _openUis.Remove(session, out var eui);
+        _openUis.Remove(session, out var eui);
 
-            eui?.Close();
-        }
+        eui?.Close();
+    }
 
-        public void CloseMakeGhostRoleEui(ICommonSession session)
+    public void CloseMakeGhostRoleEui(ICommonSession session)
+    {
+        if (_openMakeGhostRoleUis.Remove(session, out var eui))
         {
-            if (_openMakeGhostRoleUis.Remove(session, out var eui))
-            {
-                eui.Close();
-            }
+            eui.Close();
         }
+    }
 
-        public void UpdateAllEui()
+    public void UpdateAllEui()
+    {
+        foreach (var eui in _openUis.Values)
         {
-            foreach (var eui in _openUis.Values)
-            {
-                eui.StateDirty();
-            }
-            // Note that this, like the EUIs, is deferred.
-            // This is for roughly the same reasons, too:
-            // Someone might spawn a ton of ghost roles at once.
-            _needsUpdateGhostRoleCount = true;
+            eui.StateDirty();
         }
+        // Note that this, like the EUIs, is deferred.
+        // This is for roughly the same reasons, too:
+        // Someone might spawn a ton of ghost roles at once.
+        _needsUpdateGhostRoleCount = true;
+    }
 
-        public override void Update(float frameTime)
-        {
-            base.Update(frameTime);
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
 
-            UpdateGhostRoleCount();
-            UpdateRaffles(frameTime);
-        }
+        UpdateGhostRoleCount();
+        UpdateRaffles(frameTime);
+    }
 
-        /// <summary>
-        /// Handles sending count update for the ghost role button in ghost UI, if ghost role count changed.
-        /// </summary>
-        private void UpdateGhostRoleCount()
-        {
-            if (!_needsUpdateGhostRoleCount)
-                return;
+    /// <summary>
+    /// Handles sending count update for the ghost role button in ghost UI, if ghost role count changed.
+    /// </summary>
+    private void UpdateGhostRoleCount()
+    {
+        if (!_needsUpdateGhostRoleCount)
+            return;
 
-            _needsUpdateGhostRoleCount = false;
-            var response = new GhostUpdateGhostRoleCountEvent(GetGhostRoleCount());
-            foreach (var player in _playerManager.Sessions)
-            {
-                RaiseNetworkEvent(response, player.Channel);
-            }
+        _needsUpdateGhostRoleCount = false;
+        var response = new GhostUpdateGhostRoleCountEvent(GetGhostRoleCount());
+        foreach (var player in _playerManager.Sessions)
+        {
+            RaiseNetworkEvent(response, player.Channel);
         }
+    }
 
-        /// <summary>
-        /// Handles ghost role raffle logic.
-        /// </summary>
-        private void UpdateRaffles(float frameTime)
+    /// <summary>
+    /// Handles ghost role raffle logic.
+    /// </summary>
+    private void UpdateRaffles(float frameTime)
+    {
+        var query = EntityQueryEnumerator<GhostRoleRaffleComponent, MetaDataComponent>();
+        while (query.MoveNext(out var entityUid, out var raffle, out var meta))
         {
-            var query = EntityQueryEnumerator<GhostRoleRaffleComponent, MetaDataComponent>();
-            while (query.MoveNext(out var entityUid, out var raffle, out var meta))
+            if (meta.EntityPaused)
+                continue;
+
+            // if all participants leave/were removed from the raffle, the raffle is canceled.
+            if (raffle.CurrentMembers.Count == 0)
             {
-                if (meta.EntityPaused)
-                    continue;
+                RemoveRaffleAndUpdateEui(entityUid, raffle);
+                continue;
+            }
 
-                // if all participants leave/were removed from the raffle, the raffle is canceled.
-                if (raffle.CurrentMembers.Count == 0)
-                {
-                    RemoveRaffleAndUpdateEui(entityUid, raffle);
-                    continue;
-                }
+            raffle.Countdown = raffle.Countdown.Subtract(TimeSpan.FromSeconds(frameTime));
+            if (raffle.Countdown.Ticks > 0)
+                continue;
 
-                raffle.Countdown = raffle.Countdown.Subtract(TimeSpan.FromSeconds(frameTime));
-                if (raffle.Countdown.Ticks > 0)
-                    continue;
+            // the raffle is over! find someone to take over the ghost role
+            if (!TryComp(entityUid, out GhostRoleComponent? ghostRole))
+            {
+                Log.Warning($"Ghost role raffle finished on {entityUid} but {nameof(GhostRoleComponent)} is missing");
+                RemoveRaffleAndUpdateEui(entityUid, raffle);
+                continue;
+            }
 
-                // the raffle is over! find someone to take over the ghost role
-                if (!TryComp(entityUid, out GhostRoleComponent? ghostRole))
-                {
-                    Log.Warning($"Ghost role raffle finished on {entityUid} but {nameof(GhostRoleComponent)} is missing");
-                    RemoveRaffleAndUpdateEui(entityUid, raffle);
-                    continue;
-                }
+            if (ghostRole.RaffleConfig is null)
+            {
+                Log.Warning($"Ghost role raffle finished on {entityUid} but RaffleConfig became null");
+                RemoveRaffleAndUpdateEui(entityUid, raffle);
+                continue;
+            }
 
-                if (ghostRole.RaffleConfig is null)
-                {
-                    Log.Warning($"Ghost role raffle finished on {entityUid} but RaffleConfig became null");
-                    RemoveRaffleAndUpdateEui(entityUid, raffle);
-                    continue;
-                }
+            var foundWinner = false;
+            var deciderPrototype = _prototype.Index(ghostRole.RaffleConfig.Decider);
 
-                var foundWinner = false;
-                var deciderPrototype = _prototype.Index(ghostRole.RaffleConfig.Decider);
-
-                // use the ghost role's chosen winner picker to find a winner
-                deciderPrototype.Decider.PickWinner(
-                    raffle.CurrentMembers.AsEnumerable(),
-                    session =>
-                    {
-                        var success = TryTakeover(session, raffle.Identifier);
-                        foundWinner |= success;
-                        return success;
-                    }
-                );
-
-                if (!foundWinner)
+            // use the ghost role's chosen winner picker to find a winner
+            deciderPrototype.Decider.PickWinner(
+                raffle.CurrentMembers.AsEnumerable(),
+                session =>
                 {
-                    Log.Warning($"Ghost role raffle for {entityUid} ({ghostRole.RoleName}) finished without " +
-                                $"{ghostRole.RaffleConfig?.Decider} finding a winner");
+                    var success = TryTakeover(session, raffle.Identifier);
+                    foundWinner |= success;
+                    return success;
                 }
+            );
 
-                // raffle over
-                RemoveRaffleAndUpdateEui(entityUid, raffle);
+            if (!foundWinner)
+            {
+                Log.Warning($"Ghost role raffle for {entityUid} ({ghostRole.RoleName}) finished without " +
+                            $"{ghostRole.RaffleConfig?.Decider} finding a winner");
             }
+
+            // raffle over
+            RemoveRaffleAndUpdateEui(entityUid, raffle);
         }
+    }
+
+    private bool TryTakeover(ICommonSession player, uint identifier)
+    {
+        // TODO: the following two checks are kind of redundant since they should already be removed
+        //           from the raffle
+        // can't win if you are disconnected (although you shouldn't be a candidate anyway)
+        if (player.Status != SessionStatus.InGame)
+            return false;
+
+        // can't win if you are no longer a ghost (e.g. if you returned to your body)
+        if (player.AttachedEntity == null || !HasComp<GhostComponent>(player.AttachedEntity))
+            return false;
 
-        private bool TryTakeover(ICommonSession player, uint identifier)
+        if (Takeover(player, identifier))
         {
-            // TODO: the following two checks are kind of redundant since they should already be removed
-            //           from the raffle
-            // can't win if you are disconnected (although you shouldn't be a candidate anyway)
-            if (player.Status != SessionStatus.InGame)
-                return false;
+            // takeover successful, we have a winner! remove the winner from other raffles they might be in
+            LeaveAllRaffles(player);
+            return true;
+        }
 
-            // can't win if you are no longer a ghost (e.g. if you returned to your body)
-            if (player.AttachedEntity == null || !HasComp<GhostComponent>(player.AttachedEntity))
-                return false;
+        return false;
+    }
 
-            if (Takeover(player, identifier))
-            {
-                // takeover successful, we have a winner! remove the winner from other raffles they might be in
-                LeaveAllRaffles(player);
-                return true;
-            }
+    private void RemoveRaffleAndUpdateEui(EntityUid entityUid, GhostRoleRaffleComponent raffle)
+    {
+        _ghostRoleRaffles.Remove(raffle.Identifier);
+        RemComp(entityUid, raffle);
+        UpdateAllEui();
+    }
 
-            return false;
+    private void PlayerStatusChanged(object? blah, SessionStatusEventArgs args)
+    {
+        if (args.NewStatus == SessionStatus.InGame)
+        {
+            var response = new GhostUpdateGhostRoleCountEvent(_ghostRoles.Count);
+            RaiseNetworkEvent(response, args.Session.Channel);
         }
-
-        private void RemoveRaffleAndUpdateEui(EntityUid entityUid, GhostRoleRaffleComponent raffle)
+        else
         {
-            _ghostRoleRaffles.Remove(raffle.Identifier);
-            RemComp(entityUid, raffle);
-            UpdateAllEui();
+            // people who disconnect are removed from ghost role raffles
+            LeaveAllRaffles(args.Session);
         }
+    }
 
-        private void PlayerStatusChanged(object? blah, SessionStatusEventArgs args)
+    public void RegisterGhostRole(Entity<GhostRoleComponent> role)
+    {
+        if (_ghostRoles.ContainsValue(role))
+            return;
+
+        _ghostRoles[role.Comp.Identifier = GetNextRoleIdentifier()] = role;
+        UpdateAllEui();
+    }
+
+    public void UnregisterGhostRole(Entity<GhostRoleComponent> role)
+    {
+        var comp = role.Comp;
+        if (!_ghostRoles.ContainsKey(comp.Identifier) || _ghostRoles[comp.Identifier] != role)
+            return;
+
+        _ghostRoles.Remove(comp.Identifier);
+        if (TryComp(role.Owner, out GhostRoleRaffleComponent? raffle))
         {
-            if (args.NewStatus == SessionStatus.InGame)
-            {
-                var response = new GhostUpdateGhostRoleCountEvent(_ghostRoles.Count);
-                RaiseNetworkEvent(response, args.Session.Channel);
-            }
-            else
-            {
-                // people who disconnect are removed from ghost role raffles
-                LeaveAllRaffles(args.Session);
-            }
+            // if a raffle is still running, get rid of it
+            RemoveRaffleAndUpdateEui(role.Owner, raffle);
         }
-
-        public void RegisterGhostRole(Entity<GhostRoleComponent> role)
+        else
         {
-            if (_ghostRoles.ContainsValue(role))
-                return;
-
-            _ghostRoles[role.Comp.Identifier = GetNextRoleIdentifier()] = role;
             UpdateAllEui();
         }
+    }
 
-        public void UnregisterGhostRole(Entity<GhostRoleComponent> role)
+    // probably fine to be init because it's never added during entity initialization, but much later
+    private void OnRaffleInit(Entity<GhostRoleRaffleComponent> ent, ref ComponentInit args)
+    {
+        if (!TryComp(ent, out GhostRoleComponent? ghostRole))
         {
-            var comp = role.Comp;
-            if (!_ghostRoles.ContainsKey(comp.Identifier) || _ghostRoles[comp.Identifier] != role)
-                return;
-
-            _ghostRoles.Remove(comp.Identifier);
-            if (TryComp(role.Owner, out GhostRoleRaffleComponent? raffle))
-            {
-                // if a raffle is still running, get rid of it
-                RemoveRaffleAndUpdateEui(role.Owner, raffle);
-            }
-            else
-            {
-                UpdateAllEui();
-            }
+            // can't have a raffle for a ghost role that doesn't exist
+            RemComp<GhostRoleRaffleComponent>(ent);
+            return;
         }
 
-        // probably fine to be init because it's never added during entity initialization, but much later
-        private void OnRaffleInit(Entity<GhostRoleRaffleComponent> ent, ref ComponentInit args)
+        var config = ghostRole.RaffleConfig;
+        if (config is null)
+            return; // should, realistically, never be reached but you never know
+
+        var settings = config.SettingsOverride
+                       ?? _prototype.Index<GhostRoleRaffleSettingsPrototype>(config.Settings).Settings;
+
+        if (settings.MaxDuration < settings.InitialDuration)
         {
-            if (!TryComp(ent, out GhostRoleComponent? ghostRole))
-            {
-                // can't have a raffle for a ghost role that doesn't exist
-                RemComp<GhostRoleRaffleComponent>(ent);
-                return;
-            }
+            Log.Error($"Ghost role on {ent} has invalid raffle settings (max duration shorter than initial)");
+            ghostRole.RaffleConfig = null; // make it a non-raffle role so stuff isn't entirely broken
+            RemComp<GhostRoleRaffleComponent>(ent);
+            return;
+        }
 
-            var config = ghostRole.RaffleConfig;
-            if (config is null)
-                return; // should, realistically, never be reached but you never know
+        var raffle = ent.Comp;
+        raffle.Identifier = ghostRole.Identifier;
+        var countdown = _cfg.GetCVar(CCVars.GhostQuickLottery)? 1 : settings.InitialDuration;
+        raffle.Countdown = TimeSpan.FromSeconds(countdown);
+        raffle.CumulativeTime = TimeSpan.FromSeconds(settings.InitialDuration);
+        // we copy these settings into the component because they would be cumbersome to access otherwise
+        raffle.JoinExtendsDurationBy = TimeSpan.FromSeconds(settings.JoinExtendsDurationBy);
+        raffle.MaxDuration = TimeSpan.FromSeconds(settings.MaxDuration);
+    }
+
+    private void OnRaffleShutdown(Entity<GhostRoleRaffleComponent> ent, ref ComponentShutdown args)
+    {
+        _ghostRoleRaffles.Remove(ent.Comp.Identifier);
+    }
 
-            var settings = config.SettingsOverride
-                           ?? _prototype.Index<GhostRoleRaffleSettingsPrototype>(config.Settings).Settings;
+    /// <summary>
+    /// Joins the given player onto a ghost role raffle, or creates it if it doesn't exist.
+    /// </summary>
+    /// <param name="player">The player.</param>
+    /// <param name="identifier">The ID that represents the ghost role or ghost role raffle.
+    /// (A raffle will have the same ID as the ghost role it's for.)</param>
+    private void JoinRaffle(ICommonSession player, uint identifier)
+    {
+        if (!_ghostRoles.TryGetValue(identifier, out var roleEnt))
+            return;
 
-            if (settings.MaxDuration < settings.InitialDuration)
-            {
-                Log.Error($"Ghost role on {ent} has invalid raffle settings (max duration shorter than initial)");
-                ghostRole.RaffleConfig = null; // make it a non-raffle role so stuff isn't entirely broken
-                RemComp<GhostRoleRaffleComponent>(ent);
-                return;
-            }
+        // get raffle or create a new one if it doesn't exist
+        var raffle = _ghostRoleRaffles.TryGetValue(identifier, out var raffleEnt)
+            ? raffleEnt.Comp
+            : EnsureComp<GhostRoleRaffleComponent>(roleEnt.Owner);
 
-            var raffle = ent.Comp;
-            raffle.Identifier = ghostRole.Identifier;
-            var countdown = _cfg.GetCVar(CCVars.GhostQuickLottery)? 1 : settings.InitialDuration;
-            raffle.Countdown = TimeSpan.FromSeconds(countdown);
-            raffle.CumulativeTime = TimeSpan.FromSeconds(settings.InitialDuration);
-            // we copy these settings into the component because they would be cumbersome to access otherwise
-            raffle.JoinExtendsDurationBy = TimeSpan.FromSeconds(settings.JoinExtendsDurationBy);
-            raffle.MaxDuration = TimeSpan.FromSeconds(settings.MaxDuration);
-        }
+        _ghostRoleRaffles.TryAdd(identifier, (roleEnt.Owner, raffle));
 
-        private void OnRaffleShutdown(Entity<GhostRoleRaffleComponent> ent, ref ComponentShutdown args)
+        if (!raffle.CurrentMembers.Add(player))
         {
-            _ghostRoleRaffles.Remove(ent.Comp.Identifier);
+            Log.Warning($"{player.Name} tried to join raffle for ghost role {identifier} but they are already in the raffle");
+            return;
         }
 
-        /// <summary>
-        /// Joins the given player onto a ghost role raffle, or creates it if it doesn't exist.
-        /// </summary>
-        /// <param name="player">The player.</param>
-        /// <param name="identifier">The ID that represents the ghost role or ghost role raffle.
-        /// (A raffle will have the same ID as the ghost role it's for.)</param>
-        private void JoinRaffle(ICommonSession player, uint identifier)
+        // if this is the first time the player joins this raffle, and the player wasn't the starter of the raffle:
+        // extend the countdown, but only if doing so will not make the raffle take longer than the maximum
+        // duration
+        if (raffle.AllMembers.Add(player) && raffle.AllMembers.Count > 1
+            && raffle.CumulativeTime.Add(raffle.JoinExtendsDurationBy) <= raffle.MaxDuration)
         {
-            if (!_ghostRoles.TryGetValue(identifier, out var roleEnt))
-                return;
-
-            // get raffle or create a new one if it doesn't exist
-            var raffle = _ghostRoleRaffles.TryGetValue(identifier, out var raffleEnt)
-                ? raffleEnt.Comp
-                : EnsureComp<GhostRoleRaffleComponent>(roleEnt.Owner);
-
-            _ghostRoleRaffles.TryAdd(identifier, (roleEnt.Owner, raffle));
+                raffle.Countdown += raffle.JoinExtendsDurationBy;
+                raffle.CumulativeTime += raffle.JoinExtendsDurationBy;
+        }
 
-            if (!raffle.CurrentMembers.Add(player))
-            {
-                Log.Warning($"{player.Name} tried to join raffle for ghost role {identifier} but they are already in the raffle");
-                return;
-            }
+        UpdateAllEui();
+    }
 
-            // if this is the first time the player joins this raffle, and the player wasn't the starter of the raffle:
-            // extend the countdown, but only if doing so will not make the raffle take longer than the maximum
-            // duration
-            if (raffle.AllMembers.Add(player) && raffle.AllMembers.Count > 1
-                && raffle.CumulativeTime.Add(raffle.JoinExtendsDurationBy) <= raffle.MaxDuration)
-            {
-                    raffle.Countdown += raffle.JoinExtendsDurationBy;
-                    raffle.CumulativeTime += raffle.JoinExtendsDurationBy;
-            }
+    /// <summary>
+    /// Makes the given player leave the raffle corresponding to the given ID.
+    /// </summary>
+    public void LeaveRaffle(ICommonSession player, uint identifier)
+    {
+        if (!_ghostRoleRaffles.TryGetValue(identifier, out var raffleEnt))
+            return;
 
+        if (raffleEnt.Comp.CurrentMembers.Remove(player))
+        {
             UpdateAllEui();
         }
-
-        /// <summary>
-        /// Makes the given player leave the raffle corresponding to the given ID.
-        /// </summary>
-        public void LeaveRaffle(ICommonSession player, uint identifier)
+        else
         {
-            if (!_ghostRoleRaffles.TryGetValue(identifier, out var raffleEnt))
-                return;
+            Log.Warning($"{player.Name} tried to leave raffle for ghost role {identifier} but they are not in the raffle");
+        }
 
-            if (raffleEnt.Comp.CurrentMembers.Remove(player))
-            {
-                UpdateAllEui();
-            }
-            else
-            {
-                Log.Warning($"{player.Name} tried to leave raffle for ghost role {identifier} but they are not in the raffle");
-            }
+        // (raffle ending because all players left is handled in update())
+    }
 
-            // (raffle ending because all players left is handled in update())
-        }
+    /// <summary>
+    /// Makes the given player leave all ghost role raffles.
+    /// </summary>
+    public void LeaveAllRaffles(ICommonSession player)
+    {
+        var shouldUpdateEui = false;
 
-        /// <summary>
-        /// Makes the given player leave all ghost role raffles.
-        /// </summary>
-        public void LeaveAllRaffles(ICommonSession player)
+        foreach (var raffleEnt in _ghostRoleRaffles.Values)
         {
-            var shouldUpdateEui = false;
+            shouldUpdateEui |= raffleEnt.Comp.CurrentMembers.Remove(player);
+        }
 
-            foreach (var raffleEnt in _ghostRoleRaffles.Values)
-            {
-                shouldUpdateEui |= raffleEnt.Comp.CurrentMembers.Remove(player);
-            }
+        if (shouldUpdateEui)
+            UpdateAllEui();
+    }
 
-            if (shouldUpdateEui)
-                UpdateAllEui();
-        }
+    /// <summary>
+    /// Request a ghost role. If it's a raffled role starts or joins a raffle, otherwise the player immediately
+    /// takes over the ghost role if possible.
+    /// </summary>
+    /// <param name="player">The player.</param>
+    /// <param name="identifier">ID of the ghost role.</param>
+    public void Request(ICommonSession player, uint identifier)
+    {
+        if (!_ghostRoles.TryGetValue(identifier, out var roleEnt))
+            return;
 
-        /// <summary>
-        /// Request a ghost role. If it's a raffled role starts or joins a raffle, otherwise the player immediately
-        /// takes over the ghost role if possible.
-        /// </summary>
-        /// <param name="player">The player.</param>
-        /// <param name="identifier">ID of the ghost role.</param>
-        public void Request(ICommonSession player, uint identifier)
+        if (roleEnt.Comp.RaffleConfig is not null)
         {
-            if (!_ghostRoles.TryGetValue(identifier, out var roleEnt))
-                return;
-
-            if (roleEnt.Comp.RaffleConfig is not null)
-            {
-                JoinRaffle(player, identifier);
-            }
-            else
-            {
-                Takeover(player, identifier);
-            }
+            JoinRaffle(player, identifier);
         }
-
-        /// <summary>
-        /// Attempts having the player take over the ghost role with the corresponding ID. Does not start a raffle.
-        /// </summary>
-        /// <returns>True if takeover was successful, otherwise false.</returns>
-        public bool Takeover(ICommonSession player, uint identifier)
+        else
         {
-            if (!_ghostRoles.TryGetValue(identifier, out var role))
-                return false;
+            Takeover(player, identifier);
+        }
+    }
 
-            var ev = new TakeGhostRoleEvent(player);
-            RaiseLocalEvent(role, ref ev);
+    /// <summary>
+    /// Attempts having the player take over the ghost role with the corresponding ID. Does not start a raffle.
+    /// </summary>
+    /// <returns>True if takeover was successful, otherwise false.</returns>
+    public bool Takeover(ICommonSession player, uint identifier)
+    {
+        if (!_ghostRoles.TryGetValue(identifier, out var role))
+            return false;
 
-            if (!ev.TookRole)
-                return false;
+        var ev = new TakeGhostRoleEvent(player);
+        RaiseLocalEvent(role, ref ev);
 
-            if (player.AttachedEntity != null)
-                _adminLogger.Add(LogType.GhostRoleTaken, LogImpact.Low, $"{player:player} took the {role.Comp.RoleName:roleName} ghost role {ToPrettyString(player.AttachedEntity.Value):entity}");
+        if (!ev.TookRole)
+            return false;
 
-            CloseEui(player);
-            return true;
-        }
+        if (player.AttachedEntity != null)
+            _adminLogger.Add(LogType.GhostRoleTaken, LogImpact.Low, $"{player:player} took the {role.Comp.RoleName:roleName} ghost role {ToPrettyString(player.AttachedEntity.Value):entity}");
 
-        public void Follow(ICommonSession player, uint identifier)
-        {
-            if (!_ghostRoles.TryGetValue(identifier, out var role))
-                return;
+        CloseEui(player);
+        return true;
+    }
 
-            if (player.AttachedEntity == null)
-                return;
+    public void Follow(ICommonSession player, uint identifier)
+    {
+        if (!_ghostRoles.TryGetValue(identifier, out var role))
+            return;
 
-            _followerSystem.StartFollowingEntity(player.AttachedEntity.Value, role);
-        }
+        if (player.AttachedEntity == null)
+            return;
 
-        public void GhostRoleInternalCreateMindAndTransfer(ICommonSession player, EntityUid roleUid, EntityUid mob, GhostRoleComponent? role = null)
-        {
-            if (!Resolve(roleUid, ref role))
-                return;
+        _followerSystem.StartFollowingEntity(player.AttachedEntity.Value, role);
+    }
 
-            DebugTools.AssertNotNull(player.ContentData());
+    public void GhostRoleInternalCreateMindAndTransfer(ICommonSession player, EntityUid roleUid, EntityUid mob, GhostRoleComponent? role = null)
+    {
+        if (!Resolve(roleUid, ref role))
+            return;
 
-            var newMind = _mindSystem.CreateMind(player.UserId,
-                EntityManager.GetComponent<MetaDataComponent>(mob).EntityName);
-            _roleSystem.MindAddRole(newMind, new GhostRoleMarkerRoleComponent { Name = role.RoleName });
+        DebugTools.AssertNotNull(player.ContentData());
 
-            _mindSystem.SetUserId(newMind, player.UserId);
-            _mindSystem.TransferTo(newMind, mob);
-        }
+        var newMind = _mindSystem.CreateMind(player.UserId,
+            EntityManager.GetComponent<MetaDataComponent>(mob).EntityName);
+        _roleSystem.MindAddRole(newMind, new GhostRoleMarkerRoleComponent { Name = role.RoleName });
 
-        /// <summary>
-        /// Returns the number of available ghost roles.
-        /// </summary>
-        public int GetGhostRoleCount()
-        {
-            var metaQuery = GetEntityQuery<MetaDataComponent>();
-            return _ghostRoles.Count(pair => metaQuery.GetComponent(pair.Value.Owner).EntityPaused == false);
-        }
+        _mindSystem.SetUserId(newMind, player.UserId);
+        _mindSystem.TransferTo(newMind, mob);
+    }
+
+    /// <summary>
+    /// Returns the number of available ghost roles.
+    /// </summary>
+    public int GetGhostRoleCount()
+    {
+        var metaQuery = GetEntityQuery<MetaDataComponent>();
+        return _ghostRoles.Count(pair => metaQuery.GetComponent(pair.Value.Owner).EntityPaused == false);
+    }
+
+    /// <summary>
+    /// Returns information about all available ghost roles.
+    /// </summary>
+    /// <param name="player">
+    /// If not null, the <see cref="GhostRoleInfo"/>s will show if the given player is in a raffle.
+    /// </param>
+    public GhostRoleInfo[] GetGhostRolesInfo(ICommonSession? player)
+    {
+        var roles = new List<GhostRoleInfo>();
+        var metaQuery = GetEntityQuery<MetaDataComponent>();
 
-        /// <summary>
-        /// Returns information about all available ghost roles.
-        /// </summary>
-        /// <param name="player">
-        /// If not null, the <see cref="GhostRoleInfo"/>s will show if the given player is in a raffle.
-        /// </param>
-        public GhostRoleInfo[] GetGhostRolesInfo(ICommonSession? player)
+        foreach (var (id, (uid, role)) in _ghostRoles)
         {
-            var roles = new List<GhostRoleInfo>();
-            var metaQuery = GetEntityQuery<MetaDataComponent>();
+            if (metaQuery.GetComponent(uid).EntityPaused)
+                continue;
 
-            foreach (var (id, (uid, role)) in _ghostRoles)
-            {
-                if (metaQuery.GetComponent(uid).EntityPaused)
-                    continue;
 
+            var kind = GhostRoleKind.FirstComeFirstServe;
+            GhostRoleRaffleComponent? raffle = null;
 
-                var kind = GhostRoleKind.FirstComeFirstServe;
-                GhostRoleRaffleComponent? raffle = null;
+            if (role.RaffleConfig is not null)
+            {
+                kind = GhostRoleKind.RaffleReady;
 
-                if (role.RaffleConfig is not null)
+                if (_ghostRoleRaffles.TryGetValue(id, out var raffleEnt))
                 {
-                    kind = GhostRoleKind.RaffleReady;
-
-                    if (_ghostRoleRaffles.TryGetValue(id, out var raffleEnt))
-                    {
-                        kind = GhostRoleKind.RaffleInProgress;
-                        raffle = raffleEnt.Comp;
+                    kind = GhostRoleKind.RaffleInProgress;
+                    raffle = raffleEnt.Comp;
 
-                        if (player is not null && raffle.CurrentMembers.Contains(player))
-                            kind = GhostRoleKind.RaffleJoined;
-                    }
+                    if (player is not null && raffle.CurrentMembers.Contains(player))
+                        kind = GhostRoleKind.RaffleJoined;
                 }
-
-                var rafflePlayerCount = (uint?) raffle?.CurrentMembers.Count ?? 0;
-                var raffleEndTime = raffle is not null
-                    ? _timing.CurTime.Add(raffle.Countdown)
-                    : TimeSpan.MinValue;
-
-                roles.Add(new GhostRoleInfo
-                {
-                    Identifier = id,
-                    Name = role.RoleName,
-                    Description = role.RoleDescription,
-                    Rules = role.RoleRules,
-                    Requirements = role.Requirements,
-                    Kind = kind,
-                    RafflePlayerCount = rafflePlayerCount,
-                    RaffleEndTime = raffleEndTime
-                });
             }
 
-            return roles.ToArray();
-        }
+            var rafflePlayerCount = (uint?) raffle?.CurrentMembers.Count ?? 0;
+            var raffleEndTime = raffle is not null
+                ? _timing.CurTime.Add(raffle.Countdown)
+                : TimeSpan.MinValue;
 
-        private void OnPlayerAttached(PlayerAttachedEvent message)
-        {
-            // Close the session of any player that has a ghost roles window open and isn't a ghost anymore.
-            if (!_openUis.ContainsKey(message.Player))
-                return;
+            roles.Add(new GhostRoleInfo
+            {
+                Identifier = id,
+                Name = role.RoleName,
+                Description = role.RoleDescription,
+                Rules = role.RoleRules,
+                Requirements = role.Requirements,
+                Kind = kind,
+                RafflePlayerCount = rafflePlayerCount,
+                RaffleEndTime = raffleEndTime
+            });
+        }
+
+        return roles.ToArray();
+    }
 
-            if (HasComp<GhostComponent>(message.Entity))
-                return;
+    private void OnPlayerAttached(PlayerAttachedEvent message)
+    {
+        // Close the session of any player that has a ghost roles window open and isn't a ghost anymore.
+        if (!_openUis.ContainsKey(message.Player))
+            return;
+
+        if (HasComp<GhostComponent>(message.Entity))
+            return;
+
+        // The player is not a ghost (anymore), so they should not be in any raffles. Remove them.
+        // This ensures player doesn't win a raffle after returning to their (revived) body and ends up being
+        // forced into a ghost role.
+        LeaveAllRaffles(message.Player);
+        CloseEui(message.Player);
+    }
 
-            // The player is not a ghost (anymore), so they should not be in any raffles. Remove them.
-            // This ensures player doesn't win a raffle after returning to their (revived) body and ends up being
-            // forced into a ghost role.
-            LeaveAllRaffles(message.Player);
-            CloseEui(message.Player);
-        }
+    private void OnMindAdded(EntityUid uid, GhostTakeoverAvailableComponent component, MindAddedMessage args)
+    {
+        if (!TryComp(uid, out GhostRoleComponent? ghostRole))
+            return;
 
-        private void OnMindAdded(EntityUid uid, GhostTakeoverAvailableComponent component, MindAddedMessage args)
-        {
-            if (!TryComp(uid, out GhostRoleComponent? ghostRole))
-                return;
+        ghostRole.Taken = true;
+        UnregisterGhostRole((uid, ghostRole));
+    }
 
-            ghostRole.Taken = true;
-            UnregisterGhostRole((uid, ghostRole));
-        }
+    private void OnMindRemoved(EntityUid uid, GhostTakeoverAvailableComponent component, MindRemovedMessage args)
+    {
+        if (!TryComp(uid, out GhostRoleComponent? ghostRole))
+            return;
 
-        private void OnMindRemoved(EntityUid uid, GhostTakeoverAvailableComponent component, MindRemovedMessage args)
-        {
-            if (!TryComp(uid, out GhostRoleComponent? ghostRole))
-                return;
+        // Avoid re-registering it for duplicate entries and potential exceptions.
+        if (!ghostRole.ReregisterOnGhost || component.LifeStage > ComponentLifeStage.Running)
+            return;
 
-            // Avoid re-registering it for duplicate entries and potential exceptions.
-            if (!ghostRole.ReregisterOnGhost || component.LifeStage > ComponentLifeStage.Running)
-                return;
+        ghostRole.Taken = false;
+        RegisterGhostRole((uid, ghostRole));
+    }
 
-            ghostRole.Taken = false;
-            RegisterGhostRole((uid, ghostRole));
+    public void Reset(RoundRestartCleanupEvent ev)
+    {
+        foreach (var session in _openUis.Keys)
+        {
+            CloseEui(session);
         }
 
-        public void Reset(RoundRestartCleanupEvent ev)
-        {
-            foreach (var session in _openUis.Keys)
-            {
-                CloseEui(session);
-            }
+        _openUis.Clear();
+        _ghostRoles.Clear();
+        _ghostRoleRaffles.Clear();
+        _nextRoleIdentifier = 0;
+    }
 
-            _openUis.Clear();
-            _ghostRoles.Clear();
-            _ghostRoleRaffles.Clear();
-            _nextRoleIdentifier = 0;
-        }
+    private void OnPaused(EntityUid uid, GhostRoleComponent component, ref EntityPausedEvent args)
+    {
+        if (HasComp<ActorComponent>(uid))
+            return;
 
-        private void OnPaused(EntityUid uid, GhostRoleComponent component, ref EntityPausedEvent args)
-        {
-            if (HasComp<ActorComponent>(uid))
-                return;
+        UpdateAllEui();
+    }
 
-            UpdateAllEui();
-        }
+    private void OnUnpaused(EntityUid uid, GhostRoleComponent component, ref EntityUnpausedEvent args)
+    {
+        if (HasComp<ActorComponent>(uid))
+            return;
 
-        private void OnUnpaused(EntityUid uid, GhostRoleComponent component, ref EntityUnpausedEvent args)
-        {
-            if (HasComp<ActorComponent>(uid))
-                return;
+        UpdateAllEui();
+    }
 
-            UpdateAllEui();
-        }
+    private void OnMapInit(Entity<GhostRoleComponent> ent, ref MapInitEvent args)
+    {
+        if (ent.Comp.Probability < 1f && !_random.Prob(ent.Comp.Probability))
+            RemCompDeferred<GhostRoleComponent>(ent);
+    }
 
-        private void OnMapInit(Entity<GhostRoleComponent> ent, ref MapInitEvent args)
-        {
-            if (ent.Comp.Probability < 1f && !_random.Prob(ent.Comp.Probability))
-                RemCompDeferred<GhostRoleComponent>(ent);
-        }
+    private void OnRoleStartup(Entity<GhostRoleComponent> ent, ref ComponentStartup args)
+    {
+        RegisterGhostRole(ent);
+    }
 
-        private void OnRoleStartup(Entity<GhostRoleComponent> ent, ref ComponentStartup args)
-        {
-            RegisterGhostRole(ent);
-        }
+    private void OnRoleShutdown(Entity<GhostRoleComponent> role, ref ComponentShutdown args)
+    {
+        UnregisterGhostRole(role);
+    }
 
-        private void OnRoleShutdown(Entity<GhostRoleComponent> role, ref ComponentShutdown args)
+    private void OnSpawnerTakeRole(EntityUid uid, GhostRoleMobSpawnerComponent component, ref TakeGhostRoleEvent args)
+    {
+        if (!TryComp(uid, out GhostRoleComponent? ghostRole) ||
+            !CanTakeGhost(uid, ghostRole))
         {
-            UnregisterGhostRole(role);
+            args.TookRole = false;
+            return;
         }
 
-        private void OnSpawnerTakeRole(EntityUid uid, GhostRoleMobSpawnerComponent component, ref TakeGhostRoleEvent args)
-        {
-            if (!TryComp(uid, out GhostRoleComponent? ghostRole) ||
-                !CanTakeGhost(uid, ghostRole))
-            {
-                args.TookRole = false;
-                return;
-            }
+        if (string.IsNullOrEmpty(component.Prototype))
+            throw new NullReferenceException("Prototype string cannot be null or empty!");
 
-            if (string.IsNullOrEmpty(component.Prototype))
-                throw new NullReferenceException("Prototype string cannot be null or empty!");
+        var mob = Spawn(component.Prototype, Transform(uid).Coordinates);
+        _transform.AttachToGridOrMap(mob);
 
-            var mob = Spawn(component.Prototype, Transform(uid).Coordinates);
-            _transform.AttachToGridOrMap(mob);
+        var spawnedEvent = new GhostRoleSpawnerUsedEvent(uid, mob);
+        RaiseLocalEvent(mob, spawnedEvent);
 
-            var spawnedEvent = new GhostRoleSpawnerUsedEvent(uid, mob);
-            RaiseLocalEvent(mob, spawnedEvent);
+        if (ghostRole.MakeSentient)
+            MakeSentientCommand.MakeSentient(mob, EntityManager, ghostRole.AllowMovement, ghostRole.AllowSpeech);
 
-            if (ghostRole.MakeSentient)
-                MakeSentientCommand.MakeSentient(mob, EntityManager, ghostRole.AllowMovement, ghostRole.AllowSpeech);
+        EnsureComp<MindContainerComponent>(mob);
 
-            EnsureComp<MindContainerComponent>(mob);
+        GhostRoleInternalCreateMindAndTransfer(args.Player, uid, mob, ghostRole);
 
-            GhostRoleInternalCreateMindAndTransfer(args.Player, uid, mob, ghostRole);
+        if (++component.CurrentTakeovers < component.AvailableTakeovers)
+        {
+            args.TookRole = true;
+            return;
+        }
 
-            if (++component.CurrentTakeovers < component.AvailableTakeovers)
-            {
-                args.TookRole = true;
-                return;
-            }
+        ghostRole.Taken = true;
 
-            ghostRole.Taken = true;
+        if (component.DeleteOnSpawn)
+            QueueDel(uid);
 
-            if (component.DeleteOnSpawn)
-                QueueDel(uid);
+        args.TookRole = true;
+    }
 
-            args.TookRole = true;
-        }
+    private bool CanTakeGhost(EntityUid uid, GhostRoleComponent? component = null)
+    {
+        return Resolve(uid, ref component, false) &&
+               !component.Taken &&
+               !MetaData(uid).EntityPaused;
+    }
 
-        private bool CanTakeGhost(EntityUid uid, GhostRoleComponent? component = null)
+    private void OnTakeoverTakeRole(EntityUid uid, GhostTakeoverAvailableComponent component, ref TakeGhostRoleEvent args)
+    {
+        if (!TryComp(uid, out GhostRoleComponent? ghostRole) ||
+            !CanTakeGhost(uid, ghostRole))
         {
-            return Resolve(uid, ref component, false) &&
-                   !component.Taken &&
-                   !MetaData(uid).EntityPaused;
+            args.TookRole = false;
+            return;
         }
 
-        private void OnTakeoverTakeRole(EntityUid uid, GhostTakeoverAvailableComponent component, ref TakeGhostRoleEvent args)
-        {
-            if (!TryComp(uid, out GhostRoleComponent? ghostRole) ||
-                !CanTakeGhost(uid, ghostRole))
-            {
-                args.TookRole = false;
-                return;
-            }
-
-            ghostRole.Taken = true;
+        ghostRole.Taken = true;
 
-            var mind = EnsureComp<MindContainerComponent>(uid);
+        var mind = EnsureComp<MindContainerComponent>(uid);
 
-            if (mind.HasMind)
-            {
-                args.TookRole = false;
-                return;
-            }
+        if (mind.HasMind)
+        {
+            args.TookRole = false;
+            return;
+        }
 
-            if (ghostRole.MakeSentient)
-                MakeSentientCommand.MakeSentient(uid, EntityManager, ghostRole.AllowMovement, ghostRole.AllowSpeech);
+        if (ghostRole.MakeSentient)
+            MakeSentientCommand.MakeSentient(uid, EntityManager, ghostRole.AllowMovement, ghostRole.AllowSpeech);
 
-            GhostRoleInternalCreateMindAndTransfer(args.Player, uid, uid, ghostRole);
-            UnregisterGhostRole((uid, ghostRole));
+        GhostRoleInternalCreateMindAndTransfer(args.Player, uid, uid, ghostRole);
+        UnregisterGhostRole((uid, ghostRole));
 
-            args.TookRole = true;
-        }
+        args.TookRole = true;
+    }
 
-        private void OnVerb(EntityUid uid, GhostRoleMobSpawnerComponent component, GetVerbsEvent<Verb> args)
-        {
-            var prototypes = component.SelectablePrototypes;
-            if (prototypes.Count < 1)
-                return;
+    private void OnVerb(EntityUid uid, GhostRoleMobSpawnerComponent component, GetVerbsEvent<Verb> args)
+    {
+        var prototypes = component.SelectablePrototypes;
+        if (prototypes.Count < 1)
+            return;
 
-            if (!args.CanAccess || !args.CanInteract || args.Hands == null)
-                return;
+        if (!args.CanAccess || !args.CanInteract || args.Hands == null)
+            return;
 
-            var verbs = new ValueList<Verb>();
+        var verbs = new ValueList<Verb>();
 
-            foreach (var prototypeID in prototypes)
+        foreach (var prototypeID in prototypes)
+        {
+            if (_prototype.TryIndex<GhostRolePrototype>(prototypeID, out var prototype))
             {
-                if (_prototype.TryIndex<GhostRolePrototype>(prototypeID, out var prototype))
-                {
-                    var verb = CreateVerb(uid, component, args.User, prototype);
-                    verbs.Add(verb);
-                }
+                var verb = CreateVerb(uid, component, args.User, prototype);
+                verbs.Add(verb);
             }
-
-            args.Verbs.UnionWith(verbs);
         }
 
-        private Verb CreateVerb(EntityUid uid, GhostRoleMobSpawnerComponent component, EntityUid userUid, GhostRolePrototype prototype)
-        {
-            var verbText = Loc.GetString(prototype.Name);
+        args.Verbs.UnionWith(verbs);
+    }
 
-            return new Verb()
-            {
-                Text = verbText,
-                Disabled = component.Prototype == prototype.EntityPrototype,
-                Category = VerbCategory.SelectType,
-                Act = () => SetMode(uid, prototype, verbText, component, userUid)
-            };
-        }
+    private Verb CreateVerb(EntityUid uid, GhostRoleMobSpawnerComponent component, EntityUid userUid, GhostRolePrototype prototype)
+    {
+        var verbText = Loc.GetString(prototype.Name);
 
-        public void SetMode(EntityUid uid, GhostRolePrototype prototype, string verbText, GhostRoleMobSpawnerComponent? component, EntityUid? userUid = null)
+        return new Verb()
         {
-            if (!Resolve(uid, ref component))
-                return;
+            Text = verbText,
+            Disabled = component.Prototype == prototype.EntityPrototype,
+            Category = VerbCategory.SelectType,
+            Act = () => SetMode(uid, prototype, verbText, component, userUid)
+        };
+    }
 
-            var ghostrolecomp = EnsureComp<GhostRoleComponent>(uid);
+    public void SetMode(EntityUid uid, GhostRolePrototype prototype, string verbText, GhostRoleMobSpawnerComponent? component, EntityUid? userUid = null)
+    {
+        if (!Resolve(uid, ref component))
+            return;
 
-            component.Prototype = prototype.EntityPrototype;
-            ghostrolecomp.RoleName = verbText;
-            ghostrolecomp.RoleDescription = prototype.Description;
-            ghostrolecomp.RoleRules = prototype.Rules;
+        var ghostrolecomp = EnsureComp<GhostRoleComponent>(uid);
 
-            // Dirty(ghostrolecomp);
+        component.Prototype = prototype.EntityPrototype;
+        ghostrolecomp.RoleName = verbText;
+        ghostrolecomp.RoleDescription = prototype.Description;
+        ghostrolecomp.RoleRules = prototype.Rules;
 
-            if (userUid != null)
-            {
-                var msg = Loc.GetString("ghostrole-spawner-select", ("mode", verbText));
-                _popupSystem.PopupEntity(msg, uid, userUid.Value);
-            }
-        }
+        // Dirty(ghostrolecomp);
 
-        public void OnGhostRoleRadioMessage(Entity<GhostRoleMobSpawnerComponent> entity, ref GhostRoleRadioMessage args)
+        if (userUid != null)
         {
-            if (!_prototype.TryIndex(args.ProtoId, out var ghostRoleProto))
-                return;
-
-            // if the prototype chosen isn't actually part of the selectable options, ignore it
-            foreach (var selectableProto in entity.Comp.SelectablePrototypes)
-            {
-                if (selectableProto == ghostRoleProto.EntityPrototype.Id)
-                    return;
-            }
-
-            SetMode(entity.Owner, ghostRoleProto, ghostRoleProto.Name, entity.Comp);
+            var msg = Loc.GetString("ghostrole-spawner-select", ("mode", verbText));
+            _popupSystem.PopupEntity(msg, uid, userUid.Value);
         }
     }
 
-    [AnyCommand]
-    public sealed class GhostRoles : IConsoleCommand
+    public void OnGhostRoleRadioMessage(Entity<GhostRoleMobSpawnerComponent> entity, ref GhostRoleRadioMessage args)
     {
-        [Dependency] private readonly IEntityManager _e = default!;
+        if (!_prototype.TryIndex(args.ProtoId, out var ghostRoleProto))
+            return;
 
-        public string Command => "ghostroles";
-        public string Description => "Opens the ghost role request window.";
-        public string Help => $"{Command}";
-        public void Execute(IConsoleShell shell, string argStr, string[] args)
+        // if the prototype chosen isn't actually part of the selectable options, ignore it
+        foreach (var selectableProto in entity.Comp.SelectablePrototypes)
         {
-            if (shell.Player != null)
-                _e.System<GhostRoleSystem>().OpenEui(shell.Player);
-            else
-                shell.WriteLine("You can only open the ghost roles UI on a client.");
+            if (selectableProto == ghostRoleProto.EntityPrototype.Id)
+                return;
         }
+
+        SetMode(entity.Owner, ghostRoleProto, ghostRoleProto.Name, entity.Comp);
+    }
+}
+
+[AnyCommand]
+public sealed class GhostRoles : IConsoleCommand
+{
+    [Dependency] private readonly IEntityManager _e = default!;
+
+    public string Command => "ghostroles";
+    public string Description => "Opens the ghost role request window.";
+    public string Help => $"{Command}";
+    public void Execute(IConsoleShell shell, string argStr, string[] args)
+    {
+        if (shell.Player != null)
+            _e.System<GhostRoleSystem>().OpenEui(shell.Player);
+        else
+            shell.WriteLine("You can only open the ghost roles UI on a client.");
     }
 }
index 74adea6cd6972a15968866e9cbc1918c7108d861..84ab7e2e4a2d9251ebff438ff40aa9d74c5b6467 100644 (file)
@@ -37,245 +37,244 @@ using Content.Shared.Traits.Assorted;
 using Robust.Shared.Audio.Systems;
 using Content.Shared.Ghost.Roles.Components;
 
-namespace Content.Server.Zombies
+namespace Content.Server.Zombies;
+
+/// <summary>
+///     Handles zombie propagation and inherent zombie traits
+/// </summary>
+/// <remarks>
+///     Don't Shitcode Open Inside
+/// </remarks>
+public sealed partial class ZombieSystem
 {
+    [Dependency] private readonly SharedHandsSystem _hands = default!;
+    [Dependency] private readonly ServerInventorySystem _inventory = default!;
+    [Dependency] private readonly NpcFactionSystem _faction = default!;
+    [Dependency] private readonly NPCSystem _npc = default!;
+    [Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!;
+    [Dependency] private readonly IdentitySystem _identity = default!;
+    [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
+    [Dependency] private readonly SharedCombatModeSystem _combat = default!;
+    [Dependency] private readonly IChatManager _chatMan = default!;
+    [Dependency] private readonly MindSystem _mind = default!;
+    [Dependency] private readonly SharedRoleSystem _roles = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+
+    /// <summary>
+    /// Handles an entity turning into a zombie when they die or go into crit
+    /// </summary>
+    private void OnDamageChanged(EntityUid uid, ZombifyOnDeathComponent component, MobStateChangedEvent args)
+    {
+        if (args.NewMobState == MobState.Dead)
+        {
+            ZombifyEntity(uid, args.Component);
+        }
+    }
+
     /// <summary>
-    ///     Handles zombie propagation and inherent zombie traits
+    ///     This is the general purpose function to call if you want to zombify an entity.
+    ///     It handles both humanoid and nonhumanoid transformation and everything should be called through it.
     /// </summary>
+    /// <param name="target">the entity being zombified</param>
+    /// <param name="mobState"></param>
     /// <remarks>
-    ///     Don't Shitcode Open Inside
+    ///     ALRIGHT BIG BOYS, GIRLS AND ANYONE ELSE. YOU'VE COME TO THE LAYER OF THE BEAST. THIS IS YOUR WARNING.
+    ///     This function is the god function for zombie stuff, and it is cursed. I have
+    ///     attempted to label everything thouroughly for your sanity. I have attempted to
+    ///     rewrite this, but this is how it shall lie eternal. Turn back now.
+    ///     -emo
     /// </remarks>
-    public sealed partial class ZombieSystem
+    public void ZombifyEntity(EntityUid target, MobStateComponent? mobState = null)
     {
-        [Dependency] private readonly SharedHandsSystem _hands = default!;
-        [Dependency] private readonly ServerInventorySystem _inventory = default!;
-        [Dependency] private readonly NpcFactionSystem _faction = default!;
-        [Dependency] private readonly NPCSystem _npc = default!;
-        [Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!;
-        [Dependency] private readonly IdentitySystem _identity = default!;
-        [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
-        [Dependency] private readonly SharedCombatModeSystem _combat = default!;
-        [Dependency] private readonly IChatManager _chatMan = default!;
-        [Dependency] private readonly MindSystem _mind = default!;
-        [Dependency] private readonly SharedRoleSystem _roles = default!;
-        [Dependency] private readonly SharedAudioSystem _audio = default!;
-
-        /// <summary>
-        /// Handles an entity turning into a zombie when they die or go into crit
-        /// </summary>
-        private void OnDamageChanged(EntityUid uid, ZombifyOnDeathComponent component, MobStateChangedEvent args)
+        //Don't zombfiy zombies
+        if (HasComp<ZombieComponent>(target) || HasComp<ZombieImmuneComponent>(target))
+            return;
+
+        if (!Resolve(target, ref mobState, logMissing: false))
+            return;
+
+        //you're a real zombie now, son.
+        var zombiecomp = AddComp<ZombieComponent>(target);
+
+        //we need to basically remove all of these because zombies shouldn't
+        //get diseases, breath, be thirst, be hungry, die in space, have offspring or be paraplegic.
+        RemComp<RespiratorComponent>(target);
+        RemComp<BarotraumaComponent>(target);
+        RemComp<HungerComponent>(target);
+        RemComp<ThirstComponent>(target);
+        RemComp<ReproductiveComponent>(target);
+        RemComp<ReproductivePartnerComponent>(target);
+        RemComp<LegsParalyzedComponent>(target);
+        RemComp<ComplexInteractionComponent>(target);
+
+        //funny voice
+        var accentType = "zombie";
+        if (TryComp<ZombieAccentOverrideComponent>(target, out var accent))
+            accentType = accent.Accent;
+
+        EnsureComp<ReplacementAccentComponent>(target).Accent = accentType;
+
+        //This is needed for stupid entities that fuck up combat mode component
+        //in an attempt to make an entity not attack. This is the easiest way to do it.
+        var combat = EnsureComp<CombatModeComponent>(target);
+        RemComp<PacifiedComponent>(target);
+        _combat.SetCanDisarm(target, false, combat);
+        _combat.SetInCombatMode(target, true, combat);
+
+        //This is the actual damage of the zombie. We assign the visual appearance
+        //and range here because of stuff we'll find out later
+        var melee = EnsureComp<MeleeWeaponComponent>(target);
+        melee.Animation = zombiecomp.AttackAnimation;
+        melee.WideAnimation = zombiecomp.AttackAnimation;
+        melee.AltDisarm = false;
+        melee.Range = 1.2f;
+        melee.Angle = 0.0f;
+        melee.HitSound = zombiecomp.BiteSound;
+
+        if (mobState.CurrentState == MobState.Alive)
         {
-            if (args.NewMobState == MobState.Dead)
-            {
-                ZombifyEntity(uid, args.Component);
-            }
+            // Groaning when damaged
+            EnsureComp<EmoteOnDamageComponent>(target);
+            _emoteOnDamage.AddEmote(target, "Scream");
+
+            // Random groaning
+            EnsureComp<AutoEmoteComponent>(target);
+            _autoEmote.AddEmote(target, "ZombieGroan");
         }
 
-        /// <summary>
-        ///     This is the general purpose function to call if you want to zombify an entity.
-        ///     It handles both humanoid and nonhumanoid transformation and everything should be called through it.
-        /// </summary>
-        /// <param name="target">the entity being zombified</param>
-        /// <param name="mobState"></param>
-        /// <remarks>
-        ///     ALRIGHT BIG BOYS, GIRLS AND ANYONE ELSE. YOU'VE COME TO THE LAYER OF THE BEAST. THIS IS YOUR WARNING.
-        ///     This function is the god function for zombie stuff, and it is cursed. I have
-        ///     attempted to label everything thouroughly for your sanity. I have attempted to
-        ///     rewrite this, but this is how it shall lie eternal. Turn back now.
-        ///     -emo
-        /// </remarks>
-        public void ZombifyEntity(EntityUid target, MobStateComponent? mobState = null)
+        //We have specific stuff for humanoid zombies because they matter more
+        if (TryComp<HumanoidAppearanceComponent>(target, out var huApComp)) //huapcomp
         {
-            //Don't zombfiy zombies
-            if (HasComp<ZombieComponent>(target) || HasComp<ZombieImmuneComponent>(target))
-                return;
-
-            if (!Resolve(target, ref mobState, logMissing: false))
-                return;
-
-            //you're a real zombie now, son.
-            var zombiecomp = AddComp<ZombieComponent>(target);
-
-            //we need to basically remove all of these because zombies shouldn't
-            //get diseases, breath, be thirst, be hungry, die in space, have offspring or be paraplegic.
-            RemComp<RespiratorComponent>(target);
-            RemComp<BarotraumaComponent>(target);
-            RemComp<HungerComponent>(target);
-            RemComp<ThirstComponent>(target);
-            RemComp<ReproductiveComponent>(target);
-            RemComp<ReproductivePartnerComponent>(target);
-            RemComp<LegsParalyzedComponent>(target);
-            RemComp<ComplexInteractionComponent>(target);
-
-            //funny voice
-            var accentType = "zombie";
-            if (TryComp<ZombieAccentOverrideComponent>(target, out var accent))
-                accentType = accent.Accent;
-
-            EnsureComp<ReplacementAccentComponent>(target).Accent = accentType;
-
-            //This is needed for stupid entities that fuck up combat mode component
-            //in an attempt to make an entity not attack. This is the easiest way to do it.
-            var combat = EnsureComp<CombatModeComponent>(target);
-            RemComp<PacifiedComponent>(target);
-            _combat.SetCanDisarm(target, false, combat);
-            _combat.SetInCombatMode(target, true, combat);
-
-            //This is the actual damage of the zombie. We assign the visual appearance
-            //and range here because of stuff we'll find out later
-            var melee = EnsureComp<MeleeWeaponComponent>(target);
-            melee.Animation = zombiecomp.AttackAnimation;
-            melee.WideAnimation = zombiecomp.AttackAnimation;
-            melee.AltDisarm = false;
-            melee.Range = 1.2f;
-            melee.Angle = 0.0f;
-            melee.HitSound = zombiecomp.BiteSound;
-
-            if (mobState.CurrentState == MobState.Alive)
+            //store some values before changing them in case the humanoid get cloned later
+            zombiecomp.BeforeZombifiedSkinColor = huApComp.SkinColor;
+            zombiecomp.BeforeZombifiedEyeColor = huApComp.EyeColor;
+            zombiecomp.BeforeZombifiedCustomBaseLayers = new(huApComp.CustomBaseLayers);
+            if (TryComp<BloodstreamComponent>(target, out var stream))
+                zombiecomp.BeforeZombifiedBloodReagent = stream.BloodReagent;
+
+            _humanoidAppearance.SetSkinColor(target, zombiecomp.SkinColor, verify: false, humanoid: huApComp);
+
+            // Messing with the eye layer made it vanish upon cloning, and also it didn't even appear right
+            huApComp.EyeColor = zombiecomp.EyeColor;
+
+            // this might not resync on clone?
+            _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.Tail, zombiecomp.BaseLayerExternal, humanoid: huApComp);
+            _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.HeadSide, zombiecomp.BaseLayerExternal, humanoid: huApComp);
+            _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.HeadTop, zombiecomp.BaseLayerExternal, humanoid: huApComp);
+            _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.Snout, zombiecomp.BaseLayerExternal, humanoid: huApComp);
+
+            //This is done here because non-humanoids shouldn't get baller damage
+            //lord forgive me for the hardcoded damage
+            DamageSpecifier dspec = new()
             {
-                // Groaning when damaged
-                EnsureComp<EmoteOnDamageComponent>(target);
-                _emoteOnDamage.AddEmote(target, "Scream");
+                DamageDict = new()
+                {
+                    { "Slash", 13 },
+                    { "Piercing", 7 },
+                    { "Structural", 10 }
+                }
+            };
+            melee.Damage = dspec;
+
+            // humanoid zombies get to pry open doors and shit
+            var pryComp = EnsureComp<PryingComponent>(target);
+            pryComp.SpeedModifier = 0.75f;
+            pryComp.PryPowered = true;
+            pryComp.Force = true;
+
+            Dirty(target, pryComp);
+        }
 
-                // Random groaning
-                EnsureComp<AutoEmoteComponent>(target);
-                _autoEmote.AddEmote(target, "ZombieGroan");
-            }
+        Dirty(target, melee);
 
-            //We have specific stuff for humanoid zombies because they matter more
-            if (TryComp<HumanoidAppearanceComponent>(target, out var huApComp)) //huapcomp
-            {
-                //store some values before changing them in case the humanoid get cloned later
-                zombiecomp.BeforeZombifiedSkinColor = huApComp.SkinColor;
-                zombiecomp.BeforeZombifiedEyeColor = huApComp.EyeColor;
-                zombiecomp.BeforeZombifiedCustomBaseLayers = new(huApComp.CustomBaseLayers);
-                if (TryComp<BloodstreamComponent>(target, out var stream))
-                    zombiecomp.BeforeZombifiedBloodReagent = stream.BloodReagent;
-
-                _humanoidAppearance.SetSkinColor(target, zombiecomp.SkinColor, verify: false, humanoid: huApComp);
-
-                // Messing with the eye layer made it vanish upon cloning, and also it didn't even appear right
-                huApComp.EyeColor = zombiecomp.EyeColor;
-
-                // this might not resync on clone?
-                _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.Tail, zombiecomp.BaseLayerExternal, humanoid: huApComp);
-                _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.HeadSide, zombiecomp.BaseLayerExternal, humanoid: huApComp);
-                _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.HeadTop, zombiecomp.BaseLayerExternal, humanoid: huApComp);
-                _humanoidAppearance.SetBaseLayerId(target, HumanoidVisualLayers.Snout, zombiecomp.BaseLayerExternal, humanoid: huApComp);
-
-                //This is done here because non-humanoids shouldn't get baller damage
-                //lord forgive me for the hardcoded damage
-                DamageSpecifier dspec = new()
-                {
-                    DamageDict = new()
-                    {
-                        { "Slash", 13 },
-                        { "Piercing", 7 },
-                        { "Structural", 10 }
-                    }
-                };
-                melee.Damage = dspec;
-
-                // humanoid zombies get to pry open doors and shit
-                var pryComp = EnsureComp<PryingComponent>(target);
-                pryComp.SpeedModifier = 0.75f;
-                pryComp.PryPowered = true;
-                pryComp.Force = true;
-
-                Dirty(target, pryComp);
-            }
-
-            Dirty(target, melee);
-
-            //The zombie gets the assigned damage weaknesses and strengths
-            _damageable.SetDamageModifierSetId(target, "Zombie");
-
-            //This makes it so the zombie doesn't take bloodloss damage.
-            //NOTE: they are supposed to bleed, just not take damage
-            _bloodstream.SetBloodLossThreshold(target, 0f);
-            //Give them zombie blood
-            _bloodstream.ChangeBloodReagent(target, zombiecomp.NewBloodReagent);
-
-            //This is specifically here to combat insuls, because frying zombies on grilles is funny as shit.
-            _inventory.TryUnequip(target, "gloves", true, true);
-            //Should prevent instances of zombies using comms for information they shouldnt be able to have.
-            _inventory.TryUnequip(target, "ears", true, true);
-
-            //popup
-            _popup.PopupEntity(Loc.GetString("zombie-transform", ("target", target)), target, PopupType.LargeCaution);
-
-            //Make it sentient if it's an animal or something
-            MakeSentientCommand.MakeSentient(target, EntityManager);
-
-            //Make the zombie not die in the cold. Good for space zombies
-            if (TryComp<TemperatureComponent>(target, out var tempComp))
-                tempComp.ColdDamage.ClampMax(0);
-
-            //Heals the zombie from all the damage it took while human
-            if (TryComp<DamageableComponent>(target, out var damageablecomp))
-                _damageable.SetAllDamage(target, damageablecomp, 0);
-            _mobState.ChangeMobState(target, MobState.Alive);
-
-            _faction.ClearFactions(target, dirty: false);
-            _faction.AddFaction(target, "Zombie");
-
-            //gives it the funny "Zombie ___" name.
-            _nameMod.RefreshNameModifiers(target);
-
-            _identity.QueueIdentityUpdate(target);
-
-            var htn = EnsureComp<HTNComponent>(target);
-            htn.RootTask = new HTNCompoundTask() { Task = "SimpleHostileCompound" };
-            htn.Blackboard.SetValue(NPCBlackboard.Owner, target);
-            _npc.SleepNPC(target, htn);
-
-            //He's gotta have a mind
-            var hasMind = _mind.TryGetMind(target, out var mindId, out _);
-            if (hasMind && _mind.TryGetSession(mindId, out var session))
-            {
-                //Zombie role for player manifest
-                _roles.MindAddRole(mindId, new ZombieRoleComponent { PrototypeId = zombiecomp.ZombieRoleId });
+        //The zombie gets the assigned damage weaknesses and strengths
+        _damageable.SetDamageModifierSetId(target, "Zombie");
 
-                //Greeting message for new bebe zombers
-                _chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
+        //This makes it so the zombie doesn't take bloodloss damage.
+        //NOTE: they are supposed to bleed, just not take damage
+        _bloodstream.SetBloodLossThreshold(target, 0f);
+        //Give them zombie blood
+        _bloodstream.ChangeBloodReagent(target, zombiecomp.NewBloodReagent);
 
-                // Notificate player about new role assignment
-                _audio.PlayGlobal(zombiecomp.GreetSoundNotification, session);
-            }
-            else
-            {
-                _npc.WakeNPC(target, htn);
-            }
+        //This is specifically here to combat insuls, because frying zombies on grilles is funny as shit.
+        _inventory.TryUnequip(target, "gloves", true, true);
+        //Should prevent instances of zombies using comms for information they shouldnt be able to have.
+        _inventory.TryUnequip(target, "ears", true, true);
 
-            if (!HasComp<GhostRoleMobSpawnerComponent>(target) && !hasMind) //this specific component gives build test trouble so pop off, ig
-            {
-                //yet more hardcoding. Visit zombie.ftl for more information.
-                var ghostRole = EnsureComp<GhostRoleComponent>(target);
-                EnsureComp<GhostTakeoverAvailableComponent>(target);
-                ghostRole.RoleName = Loc.GetString("zombie-generic");
-                ghostRole.RoleDescription = Loc.GetString("zombie-role-desc");
-                ghostRole.RoleRules = Loc.GetString("zombie-role-rules");
-            }
-
-            if (TryComp<HandsComponent>(target, out var handsComp))
-            {
-                _hands.RemoveHands(target);
-                RemComp(target, handsComp);
-            }
-
-            // Sloth: What the fuck?
-            // How long until compregistry lmao.
-            RemComp<PullerComponent>(target);
-
-            // No longer waiting to become a zombie:
-            // Requires deferral because this is (probably) the event which called ZombifyEntity in the first place.
-            RemCompDeferred<PendingZombieComponent>(target);
-
-            //zombie gamemode stuff
-            var ev = new EntityZombifiedEvent(target);
-            RaiseLocalEvent(target, ref ev, true);
-            //zombies get slowdown once they convert
-            _movementSpeedModifier.RefreshMovementSpeedModifiers(target);
+        //popup
+        _popup.PopupEntity(Loc.GetString("zombie-transform", ("target", target)), target, PopupType.LargeCaution);
+
+        //Make it sentient if it's an animal or something
+        MakeSentientCommand.MakeSentient(target, EntityManager);
+
+        //Make the zombie not die in the cold. Good for space zombies
+        if (TryComp<TemperatureComponent>(target, out var tempComp))
+            tempComp.ColdDamage.ClampMax(0);
+
+        //Heals the zombie from all the damage it took while human
+        if (TryComp<DamageableComponent>(target, out var damageablecomp))
+            _damageable.SetAllDamage(target, damageablecomp, 0);
+        _mobState.ChangeMobState(target, MobState.Alive);
+
+        _faction.ClearFactions(target, dirty: false);
+        _faction.AddFaction(target, "Zombie");
+
+        //gives it the funny "Zombie ___" name.
+        _nameMod.RefreshNameModifiers(target);
+
+        _identity.QueueIdentityUpdate(target);
+
+        var htn = EnsureComp<HTNComponent>(target);
+        htn.RootTask = new HTNCompoundTask() { Task = "SimpleHostileCompound" };
+        htn.Blackboard.SetValue(NPCBlackboard.Owner, target);
+        _npc.SleepNPC(target, htn);
+
+        //He's gotta have a mind
+        var hasMind = _mind.TryGetMind(target, out var mindId, out _);
+        if (hasMind && _mind.TryGetSession(mindId, out var session))
+        {
+            //Zombie role for player manifest
+            _roles.MindAddRole(mindId, new ZombieRoleComponent { PrototypeId = zombiecomp.ZombieRoleId });
+
+            //Greeting message for new bebe zombers
+            _chatMan.DispatchServerMessage(session, Loc.GetString("zombie-infection-greeting"));
+
+            // Notificate player about new role assignment
+            _audio.PlayGlobal(zombiecomp.GreetSoundNotification, session);
+        }
+        else
+        {
+            _npc.WakeNPC(target, htn);
+        }
+
+        if (!HasComp<GhostRoleMobSpawnerComponent>(target) && !hasMind) //this specific component gives build test trouble so pop off, ig
+        {
+            //yet more hardcoding. Visit zombie.ftl for more information.
+            var ghostRole = EnsureComp<GhostRoleComponent>(target);
+            EnsureComp<GhostTakeoverAvailableComponent>(target);
+            ghostRole.RoleName = Loc.GetString("zombie-generic");
+            ghostRole.RoleDescription = Loc.GetString("zombie-role-desc");
+            ghostRole.RoleRules = Loc.GetString("zombie-role-rules");
+        }
+
+        if (TryComp<HandsComponent>(target, out var handsComp))
+        {
+            _hands.RemoveHands(target);
+            RemComp(target, handsComp);
         }
+
+        // Sloth: What the fuck?
+        // How long until compregistry lmao.
+        RemComp<PullerComponent>(target);
+
+        // No longer waiting to become a zombie:
+        // Requires deferral because this is (probably) the event which called ZombifyEntity in the first place.
+        RemCompDeferred<PendingZombieComponent>(target);
+
+        //zombie gamemode stuff
+        var ev = new EntityZombifiedEvent(target);
+        RaiseLocalEvent(target, ref ev, true);
+        //zombies get slowdown once they convert
+        _movementSpeedModifier.RefreshMovementSpeedModifiers(target);
     }
 }
index f82ca55542abc0fc2df6da101882048c08c118c9..e22ebc0b2802f869640493c1381b076655c92e3e 100644 (file)
@@ -1,10 +1,9 @@
 using Robust.Shared.Serialization;
 
-namespace Content.Shared.Administration.Events
+namespace Content.Shared.Administration.Events;
+
+[NetSerializable, Serializable]
+public sealed class PlayerInfoChangedEvent : EntityEventArgs
 {
-    [NetSerializable, Serializable]
-    public sealed class PlayerInfoChangedEvent : EntityEventArgs
-    {
-        public PlayerInfo? PlayerInfo;
-    }
+    public PlayerInfo? PlayerInfo;
 }
index ed54d57bbef3dbac58fc48e878a7235081710804..89d1477d6b339e6d2309a9e64b7dfdce8e40dae0 100644 (file)
@@ -1,36 +1,35 @@
 using Robust.Shared.Network;
 using Robust.Shared.Serialization;
 
-namespace Content.Shared.Administration
+namespace Content.Shared.Administration;
+
+[Serializable, NetSerializable]
+public sealed record PlayerInfo(
+    string Username,
+    string CharacterName,
+    string IdentityName,
+    string StartingJob,
+    bool Antag,
+    NetEntity? NetEntity,
+    NetUserId SessionId,
+    bool Connected,
+    bool ActiveThisRound,
+    TimeSpan? OverallPlaytime)
 {
-    [Serializable, NetSerializable]
-    public sealed record PlayerInfo(
-        string Username,
-        string CharacterName,
-        string IdentityName,
-        string StartingJob,
-        bool Antag,
-        NetEntity? NetEntity,
-        NetUserId SessionId,
-        bool Connected,
-        bool ActiveThisRound,
-        TimeSpan? OverallPlaytime)
-    {
-        private string? _playtimeString;
+    private string? _playtimeString;
 
-        public bool IsPinned { get; set; }
+    public bool IsPinned { get; set; }
 
-        public string PlaytimeString => _playtimeString ??=
-            OverallPlaytime?.ToString("%d':'hh':'mm") ?? Loc.GetString("generic-unknown-title");
+    public string PlaytimeString => _playtimeString ??=
+        OverallPlaytime?.ToString("%d':'hh':'mm") ?? Loc.GetString("generic-unknown-title");
 
-        public bool Equals(PlayerInfo? other)
-        {
-            return other?.SessionId == SessionId;
-        }
+    public bool Equals(PlayerInfo? other)
+    {
+        return other?.SessionId == SessionId;
+    }
 
-        public override int GetHashCode()
-        {
-            return SessionId.GetHashCode();
-        }
+    public override int GetHashCode()
+    {
+        return SessionId.GetHashCode();
     }
 }
index b64844e9a0623af0b381b17632152875eff68cf4..f8c4e5559eb2f6fda4465e88029d3bb4ecaa3b36 100644 (file)
@@ -1,12 +1,11 @@
 using Robust.Shared.Serialization;
 
-namespace Content.Shared.Ghost.Roles
+namespace Content.Shared.Ghost.Roles;
+
+[Serializable, NetSerializable]
+public sealed class GhostRole
 {
-    [Serializable, NetSerializable]
-    public sealed class GhostRole
-    {
-        public string Name { get; set; } = string.Empty;
-        public string Description { get; set; } = string.Empty;
-        public NetEntity Id;
-    }
+    public string Name { get; set; } = string.Empty;
+    public string Description { get; set; } = string.Empty;
+    public NetEntity Id;
 }
index 62b26cbd35357521239fa4cdcf22d2efeca18793..380d30ca143b63937a03c4bccea002c7c6a1f264 100644 (file)
@@ -1,97 +1,96 @@
 using System.Diagnostics.CodeAnalysis;
 using Robust.Shared.GameStates;
 
-namespace Content.Shared.Mind.Components
+namespace Content.Shared.Mind.Components;
+
+/// <summary>
+/// This component indicates that this entity may have mind, which is simply an entity with a <see cref="MindComponent"/>.
+/// The mind entity is not actually stored in a "container", but is simply stored in nullspace.
+/// </summary>
+[RegisterComponent, Access(typeof(SharedMindSystem)), NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class MindContainerComponent : Component
 {
     /// <summary>
-    /// This component indicates that this entity may have mind, which is simply an entity with a <see cref="MindComponent"/>.
-    /// The mind entity is not actually stored in a "container", but is simply stored in nullspace.
+    ///     The mind controlling this mob. Can be null.
     /// </summary>
-    [RegisterComponent, Access(typeof(SharedMindSystem)), NetworkedComponent, AutoGenerateComponentState]
-    public sealed partial class MindContainerComponent : Component
-    {
-        /// <summary>
-        ///     The mind controlling this mob. Can be null.
-        /// </summary>
-        [DataField, AutoNetworkedField]
-        [Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
-        public EntityUid? Mind { get; set; }
+    [DataField, AutoNetworkedField]
+    [Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
+    public EntityUid? Mind { get; set; }
 
-        /// <summary>
-        ///     True if we have a mind, false otherwise.
-        /// </summary>
-        [MemberNotNullWhen(true, nameof(Mind))]
-        public bool HasMind => Mind != null;
+    /// <summary>
+    ///     True if we have a mind, false otherwise.
+    /// </summary>
+    [MemberNotNullWhen(true, nameof(Mind))]
+    public bool HasMind => Mind != null;
 
-        /// <summary>
-        ///     Whether examining should show information about the mind or not.
-        /// </summary>
-        [ViewVariables(VVAccess.ReadWrite)]
-        [DataField("showExamineInfo"), AutoNetworkedField]
-        public bool ShowExamineInfo { get; set; }
+    /// <summary>
+    ///     Whether examining should show information about the mind or not.
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite)]
+    [DataField("showExamineInfo"), AutoNetworkedField]
+    public bool ShowExamineInfo { get; set; }
 
-        /// <summary>
-        ///     Whether the mind will be put on a ghost after this component is shutdown.
-        /// </summary>
-        [ViewVariables(VVAccess.ReadWrite)]
-        [DataField("ghostOnShutdown")]
-        [Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
-        public bool GhostOnShutdown { get; set; } = true;
-    }
+    /// <summary>
+    ///     Whether the mind will be put on a ghost after this component is shutdown.
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite)]
+    [DataField("ghostOnShutdown")]
+    [Access(typeof(SharedMindSystem), Other = AccessPermissions.ReadWriteExecute)] // FIXME Friends
+    public bool GhostOnShutdown { get; set; } = true;
+}
 
-    public abstract class MindEvent : EntityEventArgs
-    {
-        public readonly Entity<MindComponent> Mind;
-        public readonly Entity<MindContainerComponent> Container;
+public abstract class MindEvent : EntityEventArgs
+{
+    public readonly Entity<MindComponent> Mind;
+    public readonly Entity<MindContainerComponent> Container;
 
-        public MindEvent(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
-        {
-            Mind = mind;
-            Container = container;
-        }
+    public MindEvent(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
+    {
+        Mind = mind;
+        Container = container;
     }
+}
 
-    /// <summary>
-    /// Event raised directed at a mind-container when a mind gets removed.
-    /// </summary>
-    public sealed class MindRemovedMessage : MindEvent
+/// <summary>
+/// Event raised directed at a mind-container when a mind gets removed.
+/// </summary>
+public sealed class MindRemovedMessage : MindEvent
+{
+    public MindRemovedMessage(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
+        : base(mind, container)
     {
-        public MindRemovedMessage(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
-            : base(mind, container)
-        {
-        }
     }
+}
 
-    /// <summary>
-    /// Event raised directed at a mind when it gets removed from a mind-container.
-    /// </summary>
-    public sealed class MindGotRemovedEvent : MindEvent
+/// <summary>
+/// Event raised directed at a mind when it gets removed from a mind-container.
+/// </summary>
+public sealed class MindGotRemovedEvent : MindEvent
+{
+    public MindGotRemovedEvent(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
+        : base(mind, container)
     {
-        public MindGotRemovedEvent(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
-            : base(mind, container)
-        {
-        }
     }
+}
 
-    /// <summary>
-    /// Event raised directed at a mind-container when a mind gets added.
-    /// </summary>
-    public sealed class MindAddedMessage : MindEvent
+/// <summary>
+/// Event raised directed at a mind-container when a mind gets added.
+/// </summary>
+public sealed class MindAddedMessage : MindEvent
+{
+    public MindAddedMessage(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
+        : base(mind, container)
     {
-        public MindAddedMessage(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
-            : base(mind, container)
-        {
-        }
     }
+}
 
-    /// <summary>
-    /// Event raised directed at a mind when it gets added to a mind-container.
-    /// </summary>
-    public sealed class MindGotAddedEvent : MindEvent
+/// <summary>
+/// Event raised directed at a mind when it gets added to a mind-container.
+/// </summary>
+public sealed class MindGotAddedEvent : MindEvent
+{
+    public MindGotAddedEvent(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
+        : base(mind, container)
     {
-        public MindGotAddedEvent(Entity<MindComponent> mind, Entity<MindContainerComponent> container)
-            : base(mind, container)
-        {
-        }
     }
 }
index 51a174c8465c86f70875810f7c7dee20efdd9e3d..d603102682b7fc32f9b85b9eb7dfa486d329b114 100644 (file)
@@ -5,105 +5,104 @@ using Robust.Shared.GameStates;
 using Robust.Shared.Network;
 using Robust.Shared.Player;
 
-namespace Content.Shared.Mind
+namespace Content.Shared.Mind;
+
+/// <summary>
+///     This component stores information about a player/mob mind. The component will be attached to a mind-entity
+///     which is stored in null-space. The entity that is currently "possessed" by the mind will have a
+///     <see cref="MindContainerComponent"/>.
+/// </summary>
+/// <remarks>
+///     Roles are attached as components on the mind-entity entity.
+///     Think of it like this: if a player is supposed to have their memories,
+///     their mind follows along.
+///
+///     Things such as respawning do not follow, because you're a new character.
+///     Getting borged, cloned, turned into a catbeast, etc... will keep it following you.
+///
+///     Minds are stored in null-space, and are thus generally not set to players unless that player is the owner
+///     of the mind. As a result it should be safe to network "secret" information like roles & objectives
+/// </remarks>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
+public sealed partial class MindComponent : Component
 {
+    [DataField, AutoNetworkedField]
+    public List<EntityUid> Objectives = new();
+
     /// <summary>
-    ///     This component stores information about a player/mob mind. The component will be attached to a mind-entity
-    ///     which is stored in null-space. The entity that is currently "possessed" by the mind will have a
-    ///     <see cref="MindContainerComponent"/>.
+    ///     The session ID of the player owning this mind.
     /// </summary>
-    /// <remarks>
-    ///     Roles are attached as components on the mind-entity entity.
-    ///     Think of it like this: if a player is supposed to have their memories,
-    ///     their mind follows along.
-    ///
-    ///     Things such as respawning do not follow, because you're a new character.
-    ///     Getting borged, cloned, turned into a catbeast, etc... will keep it following you.
-    ///
-    ///     Minds are stored in null-space, and are thus generally not set to players unless that player is the owner
-    ///     of the mind. As a result it should be safe to network "secret" information like roles & objectives
-    /// </remarks>
-    [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
-    public sealed partial class MindComponent : Component
-    {
-        [DataField, AutoNetworkedField]
-        public List<EntityUid> Objectives = new();
-
-        /// <summary>
-        ///     The session ID of the player owning this mind.
-        /// </summary>
-        [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
-        public NetUserId? UserId { get; set; }
+    [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
+    public NetUserId? UserId { get; set; }
 
-        /// <summary>
-        ///     The session ID of the original owner, if any.
-        ///     May end up used for round-end information (as the owner may have abandoned Mind since)
-        /// </summary>
-        [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
-        public NetUserId? OriginalOwnerUserId { get; set; }
+    /// <summary>
+    ///     The session ID of the original owner, if any.
+    ///     May end up used for round-end information (as the owner may have abandoned Mind since)
+    /// </summary>
+    [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
+    public NetUserId? OriginalOwnerUserId { get; set; }
 
-        /// <summary>
-        ///     The first entity that this mind controlled. Used for round end information.
-        ///     Might be relevant if the player has ghosted since.
-        /// </summary>
-        [DataField, AutoNetworkedField]
-        public NetEntity? OriginalOwnedEntity;
-        // This is a net entity, because this field currently ddoes not get set to null when this entity is deleted.
-        // This is a lazy way to ensure that people check that the entity still exists.
-        // TODO MIND Fix this properly by adding an OriginalMindContainerComponent or something like that.
+    /// <summary>
+    ///     The first entity that this mind controlled. Used for round end information.
+    ///     Might be relevant if the player has ghosted since.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public NetEntity? OriginalOwnedEntity;
+    // This is a net entity, because this field currently ddoes not get set to null when this entity is deleted.
+    // This is a lazy way to ensure that people check that the entity still exists.
+    // TODO MIND Fix this properly by adding an OriginalMindContainerComponent or something like that.
 
-        [ViewVariables]
-        public bool IsVisitingEntity => VisitingEntity != null;
+    [ViewVariables]
+    public bool IsVisitingEntity => VisitingEntity != null;
 
-        [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
-        public EntityUid? VisitingEntity { get; set; }
+    [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
+    public EntityUid? VisitingEntity { get; set; }
 
-        [ViewVariables]
-        public EntityUid? CurrentEntity => VisitingEntity ?? OwnedEntity;
+    [ViewVariables]
+    public EntityUid? CurrentEntity => VisitingEntity ?? OwnedEntity;
 
-        [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
-        public string? CharacterName { get; set; }
+    [DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
+    public string? CharacterName { get; set; }
 
-        /// <summary>
-        ///     The time of death for this Mind.
-        ///     Can be null - will be null if the Mind is not considered "dead".
-        /// </summary>
-        [DataField]
-        public TimeSpan? TimeOfDeath { get; set; }
+    /// <summary>
+    ///     The time of death for this Mind.
+    ///     Can be null - will be null if the Mind is not considered "dead".
+    /// </summary>
+    [DataField]
+    public TimeSpan? TimeOfDeath { get; set; }
 
-        /// <summary>
-        ///     The entity currently owned by this mind.
-        ///     Can be null.
-        /// </summary>
-        [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
-        public EntityUid? OwnedEntity { get; set; }
+    /// <summary>
+    ///     The entity currently owned by this mind.
+    ///     Can be null.
+    /// </summary>
+    [DataField, AutoNetworkedField, Access(typeof(SharedMindSystem))]
+    public EntityUid? OwnedEntity { get; set; }
 
-        /// <summary>
-        ///     An enumerable over all the objective entities this mind has.
-        /// </summary>
-        [ViewVariables, Obsolete("Use Objectives field")]
-        public IEnumerable<EntityUid> AllObjectives => Objectives;
+    /// <summary>
+    ///     An enumerable over all the objective entities this mind has.
+    /// </summary>
+    [ViewVariables, Obsolete("Use Objectives field")]
+    public IEnumerable<EntityUid> AllObjectives => Objectives;
 
-        /// <summary>
-        ///     Prevents user from ghosting out
-        /// </summary>
-        [ViewVariables(VVAccess.ReadWrite)]
-        [DataField("preventGhosting")]
-        public bool PreventGhosting { get; set; }
+    /// <summary>
+    ///     Prevents user from ghosting out
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite)]
+    [DataField("preventGhosting")]
+    public bool PreventGhosting { get; set; }
 
-        /// <summary>
-        ///     Prevents user from suiciding
-        /// </summary>
-        [ViewVariables(VVAccess.ReadWrite)]
-        [DataField("preventSuicide")]
-        public bool PreventSuicide { get; set; }
+    /// <summary>
+    ///     Prevents user from suiciding
+    /// </summary>
+    [ViewVariables(VVAccess.ReadWrite)]
+    [DataField("preventSuicide")]
+    public bool PreventSuicide { get; set; }
 
-        /// <summary>
-        ///     The session of the player owning this mind.
-        ///     Can be null, in which case the player is currently not logged in.
-        /// </summary>
-        [ViewVariables, Access(typeof(SharedMindSystem), typeof(SharedGameTicker))]
-        // TODO remove this after moving IPlayerManager functions to shared
-        public ICommonSession? Session { get; set; }
-    }
+    /// <summary>
+    ///     The session of the player owning this mind.
+    ///     Can be null, in which case the player is currently not logged in.
+    /// </summary>
+    [ViewVariables, Access(typeof(SharedMindSystem), typeof(SharedGameTicker))]
+    // TODO remove this after moving IPlayerManager functions to shared
+    public ICommonSession? Session { get; set; }
 }