Players with unknown playtimes now are tagged as new players, take 2 (#35648)
* your commit? our commit. * skreee * show joined players before lobby players; comments * comments * playerinfo retains playtime data after disconnect * new connection status symbols
This commit is contained in:
@@ -36,6 +36,9 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
|
var newPlayerThreshold = 0;
|
||||||
|
_cfg.OnValueChanged(CCVars.NewPlayerThreshold, (val) => { newPlayerThreshold = val; }, true);
|
||||||
|
|
||||||
var uiController = _ui.GetUIController<AHelpUIController>();
|
var uiController = _ui.GetUIController<AHelpUIController>();
|
||||||
if (uiController.UIHelper is not AdminAHelpUIHandler helper)
|
if (uiController.UIHelper is not AdminAHelpUIHandler helper)
|
||||||
return;
|
return;
|
||||||
@@ -59,9 +62,9 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
if (info.Connected)
|
if (info.Connected)
|
||||||
sb.Append('●');
|
sb.Append(info.ActiveThisRound ? '⚫' : '◐');
|
||||||
else
|
else
|
||||||
sb.Append(info.ActiveThisRound ? '○' : '·');
|
sb.Append(info.ActiveThisRound ? '⭘' : '·');
|
||||||
|
|
||||||
sb.Append(' ');
|
sb.Append(' ');
|
||||||
if (AHelpHelper.TryGetChannel(info.SessionId, out var panel) && panel.Unread > 0)
|
if (AHelpHelper.TryGetChannel(info.SessionId, out var panel) && panel.Unread > 0)
|
||||||
@@ -73,10 +76,12 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||||||
sb.Append(' ');
|
sb.Append(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark antagonists with symbol
|
||||||
if (info.Antag && info.ActiveThisRound)
|
if (info.Antag && info.ActiveThisRound)
|
||||||
sb.Append(new Rune(0x1F5E1)); // 🗡
|
sb.Append(new Rune(0x1F5E1)); // 🗡
|
||||||
|
|
||||||
if (info.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold)))
|
// Mark new players with symbol
|
||||||
|
if (IsNewPlayer(info))
|
||||||
sb.Append(new Rune(0x23F2)); // ⏲
|
sb.Append(new Rune(0x23F2)); // ⏲
|
||||||
|
|
||||||
sb.AppendFormat("\"{0}\"", text);
|
sb.AppendFormat("\"{0}\"", text);
|
||||||
@@ -84,6 +89,19 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
// Returns true if the player's overall playtime is under the set threshold
|
||||||
|
// </summary>
|
||||||
|
bool IsNewPlayer(PlayerInfo info)
|
||||||
|
{
|
||||||
|
// Don't show every disconnected player as new, don't show 0-minute players as new if threshold is
|
||||||
|
if (newPlayerThreshold <= 0 || info.OverallPlaytime is null && !info.Connected)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (info.OverallPlaytime is null
|
||||||
|
|| info.OverallPlaytime < TimeSpan.FromMinutes(newPlayerThreshold));
|
||||||
|
}
|
||||||
|
|
||||||
ChannelSelector.Comparison = (a, b) =>
|
ChannelSelector.Comparison = (a, b) =>
|
||||||
{
|
{
|
||||||
var ach = AHelpHelper.EnsurePanel(a.SessionId);
|
var ach = AHelpHelper.EnsurePanel(a.SessionId);
|
||||||
@@ -93,31 +111,37 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||||||
if (a.IsPinned != b.IsPinned)
|
if (a.IsPinned != b.IsPinned)
|
||||||
return a.IsPinned ? -1 : 1;
|
return a.IsPinned ? -1 : 1;
|
||||||
|
|
||||||
// First, sort by unread. Any chat with unread messages appears first.
|
// Then, any chat with unread messages.
|
||||||
var aUnread = ach.Unread > 0;
|
var aUnread = ach.Unread > 0;
|
||||||
var bUnread = bch.Unread > 0;
|
var bUnread = bch.Unread > 0;
|
||||||
if (aUnread != bUnread)
|
if (aUnread != bUnread)
|
||||||
return aUnread ? -1 : 1;
|
return aUnread ? -1 : 1;
|
||||||
|
|
||||||
// Sort by recent messages during the current round.
|
// Then, any chat with recent messages from the current round
|
||||||
var aRecent = a.ActiveThisRound && ach.LastMessage != DateTime.MinValue;
|
var aRecent = a.ActiveThisRound && ach.LastMessage != DateTime.MinValue;
|
||||||
var bRecent = b.ActiveThisRound && bch.LastMessage != DateTime.MinValue;
|
var bRecent = b.ActiveThisRound && bch.LastMessage != DateTime.MinValue;
|
||||||
if (aRecent != bRecent)
|
if (aRecent != bRecent)
|
||||||
return aRecent ? -1 : 1;
|
return aRecent ? -1 : 1;
|
||||||
|
|
||||||
// Next, sort by connection status. Any disconnected players are grouped towards the end.
|
// Sort by connection status. Disconnected players will be last.
|
||||||
if (a.Connected != b.Connected)
|
if (a.Connected != b.Connected)
|
||||||
return a.Connected ? -1 : 1;
|
return a.Connected ? -1 : 1;
|
||||||
|
|
||||||
// Sort connected players by New Player status, then by Antag status
|
// Sort connected players by whether they have joined the round, then by New Player status, then by Antag status
|
||||||
if (a.Connected && b.Connected)
|
if (a.Connected && b.Connected)
|
||||||
{
|
{
|
||||||
var aNewPlayer = a.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold));
|
var aNewPlayer = IsNewPlayer(a);
|
||||||
var bNewPlayer = b.OverallPlaytime <= TimeSpan.FromMinutes(_cfg.GetCVar(CCVars.NewPlayerThreshold));
|
var bNewPlayer = IsNewPlayer(b);
|
||||||
|
|
||||||
|
// Players who have joined the round will be listed before players in the lobby
|
||||||
|
if (a.ActiveThisRound != b.ActiveThisRound)
|
||||||
|
return a.ActiveThisRound ? -1 : 1;
|
||||||
|
|
||||||
|
// Within both the joined group and lobby group, new players will be grouped and listed first
|
||||||
if (aNewPlayer != bNewPlayer)
|
if (aNewPlayer != bNewPlayer)
|
||||||
return aNewPlayer ? -1 : 1;
|
return aNewPlayer ? -1 : 1;
|
||||||
|
|
||||||
|
// Within all four previous groups, antagonists will be listed first.
|
||||||
if (a.Antag != b.Antag)
|
if (a.Antag != b.Antag)
|
||||||
return a.Antag ? -1 : 1;
|
return a.Antag ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,9 @@ namespace Content.Client.Administration.UI.Bwoink
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Title = $"{sel.CharacterName} / {sel.Username}";
|
Title = $"{sel.CharacterName} / {sel.Username} | {Loc.GetString("generic-playtime-title")}: ";
|
||||||
|
|
||||||
if (sel.OverallPlaytime != null)
|
Title += sel.OverallPlaytime != null ? sel.PlaytimeString : Loc.GetString("generic-unknown-title");
|
||||||
{
|
|
||||||
Title += $" | {Loc.GetString("generic-playtime-title")}: {sel.PlaytimeString}";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OnOpen += () =>
|
OnOpen += () =>
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ public sealed class AdminSystem : EntitySystem
|
|||||||
var entityName = string.Empty;
|
var entityName = string.Empty;
|
||||||
var identityName = string.Empty;
|
var identityName = string.Empty;
|
||||||
|
|
||||||
|
// Visible (identity) name can be different from real name
|
||||||
if (session?.AttachedEntity != null)
|
if (session?.AttachedEntity != null)
|
||||||
{
|
{
|
||||||
entityName = EntityManager.GetComponent<MetaDataComponent>(session.AttachedEntity.Value).EntityName;
|
entityName = EntityManager.GetComponent<MetaDataComponent>(session.AttachedEntity.Value).EntityName;
|
||||||
@@ -230,6 +231,7 @@ public sealed class AdminSystem : EntitySystem
|
|||||||
|
|
||||||
var antag = false;
|
var antag = false;
|
||||||
|
|
||||||
|
// Starting role, antagonist status and role type
|
||||||
RoleTypePrototype roleType = new();
|
RoleTypePrototype roleType = new();
|
||||||
var startingRole = string.Empty;
|
var startingRole = string.Empty;
|
||||||
if (_minds.TryGetMind(session, out var mindId, out var mindComp))
|
if (_minds.TryGetMind(session, out var mindId, out var mindComp))
|
||||||
@@ -243,8 +245,13 @@ public sealed class AdminSystem : EntitySystem
|
|||||||
startingRole = _jobs.MindTryGetJobName(mindId);
|
startingRole = _jobs.MindTryGetJobName(mindId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connection status and playtime
|
||||||
var connected = session != null && session.Status is SessionStatus.Connected or SessionStatus.InGame;
|
var connected = session != null && session.Status is SessionStatus.Connected or SessionStatus.InGame;
|
||||||
TimeSpan? overallPlaytime = null;
|
|
||||||
|
// Start with the last available playtime data
|
||||||
|
var cachedInfo = GetCachedPlayerInfo(data.UserId);
|
||||||
|
var overallPlaytime = cachedInfo?.OverallPlaytime;
|
||||||
|
// Overwrite with current playtime data, unless it's null (such as if the player just disconnected)
|
||||||
if (session != null &&
|
if (session != null &&
|
||||||
_playTime.TryGetTrackerTimes(session, out var playTimes) &&
|
_playTime.TryGetTrackerTimes(session, out var playTimes) &&
|
||||||
playTimes.TryGetValue(PlayTimeTrackingShared.TrackerOverall, out var playTime))
|
playTimes.TryGetValue(PlayTimeTrackingShared.TrackerOverall, out var playTime))
|
||||||
|
|||||||
Reference in New Issue
Block a user