var ach = AHelpHelper.EnsurePanel(a.SessionId);
var bch = AHelpHelper.EnsurePanel(b.SessionId);
+ // Pinned players first
+ if (a.IsPinned != b.IsPinned)
+ return a.IsPinned ? -1 : 1;
+
// First, sort by unread. Any chat with unread messages appears first. We just sort based on unread
// status, not number of unread messages, so that more recent unread messages take priority.
var aUnread = ach.Unread > 0;
if (a.Connected != b.Connected)
return a.Connected ? -1 : 1;
- // Next, group by whether or not the players have participated in this round.
- // The ahelp window shows all players that have connected since server restart, this groups them all towards the bottom.
- if (a.ActiveThisRound != b.ActiveThisRound)
- return a.ActiveThisRound ? -1 : 1;
+ // Sort connected players by New Player status, then by Antag status
+ if (a.Connected && b.Connected)
+ {
+ var aNewPlayer = a.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold));
+ var bNewPlayer = b.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold));
+
+ if (aNewPlayer != bNewPlayer)
+ return aNewPlayer ? -1 : 1;
+
+ if (a.Antag != b.Antag)
+ return a.Antag ? -1 : 1;
+ }
+
+ // Sort disconnected players by participation in the round
+ if (!a.Connected && !b.Connected)
+ {
+ if (a.ActiveThisRound != b.ActiveThisRound)
+ return a.ActiveThisRound ? -1 : 1;
+ }
// Finally, sort by the most recent message.
return bch.LastMessage.CompareTo(ach.LastMessage);
};
+
Bans.OnPressed += _ =>
{
if (_currentPlayer is not null)
public void PopulateList()
{
+ // Maintain existing pin statuses
+ var pinnedPlayers = ChannelSelector.PlayerInfo.Where(p => p.IsPinned).ToDictionary(p => p.SessionId);
+
ChannelSelector.PopulateList();
+
+ // Restore pin statuses
+ foreach (var player in ChannelSelector.PlayerInfo)
+ {
+ if (pinnedPlayers.TryGetValue(player.SessionId, out var pinnedPlayer))
+ {
+ player.IsPinned = pinnedPlayer.IsPinned;
+ }
+ }
+
UpdateButtons();
}
}
private readonly IEntityManager _entManager;
private readonly IUserInterfaceManager _uiManager;
-
+
private PlayerInfo? _selectedPlayer;
private List<PlayerInfo> _playerList = new();
- private readonly List<PlayerInfo> _sortedPlayerList = new();
+ private List<PlayerInfo> _sortedPlayerList = new();
public Comparison<PlayerInfo>? Comparison;
public Func<PlayerInfo, string, string>? OverrideText;
if (Comparison != null)
_sortedPlayerList.Sort((a, b) => Comparison(a, b));
- // Ensure pinned players are always at the top
- _sortedPlayerList.Sort((a, b) => a.IsPinned != b.IsPinned && a.IsPinned ? -1 : 1);
-
PlayerListContainer.PopulateList(_sortedPlayerList.Select(info => new PlayerListData(info)).ToList());
if (_selectedPlayer != null)
PlayerListContainer.Select(new PlayerListData(_selectedPlayer));
}
+
public void PopulateList(IReadOnlyList<PlayerInfo>? players = null)
{
+ // Maintain existing pin statuses
+ var pinnedPlayers = _playerList.Where(p => p.IsPinned).ToDictionary(p => p.SessionId);
+
players ??= _adminSystem.PlayerList;
_playerList = players.ToList();
+
+ // Restore pin statuses
+ foreach (var player in _playerList)
+ {
+ if (pinnedPlayers.TryGetValue(player.SessionId, out var pinnedPlayer))
+ {
+ player.IsPinned = pinnedPlayer.IsPinned;
+ }
+ }
+
if (_selectedPlayer != null && !_playerList.Contains(_selectedPlayer))
_selectedPlayer = null;