using Content.Shared.Roles;
using Robust.Server.Player;
using Robust.Shared.Asynchronous;
+using Robust.Shared.Collections;
using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using Robust.Shared.Timing;
-using Robust.Shared.Utility;
namespace Content.Server.Administration.Managers;
public const string SawmillId = "admin.bans";
public const string JobPrefix = "Job:";
- private readonly Dictionary<NetUserId, HashSet<ServerRoleBanDef>> _cachedRoleBans = new();
+ private readonly Dictionary<ICommonSession, List<ServerRoleBanDef>> _cachedRoleBans = new();
// Cached ban exemption flags are used to handle
private readonly Dictionary<ICommonSession, ServerBanExemptFlags> _cachedBanExemptions = new();
public void Initialize()
{
- _playerManager.PlayerStatusChanged += OnPlayerStatusChanged;
-
_netManager.RegisterNetMessage<MsgRoleBans>();
_db.SubscribeToNotifications(OnDatabaseNotification);
private async Task CachePlayerData(ICommonSession player, CancellationToken cancel)
{
- // Yeah so role ban loading code isn't integrated with exempt flag loading code.
- // Have you seen how garbage role ban code code is? I don't feel like refactoring it right now.
-
var flags = await _db.GetBanExemption(player.UserId, cancel);
+
+ var netChannel = player.Channel;
+ ImmutableArray<byte>? hwId = netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId;
+ var roleBans = await _db.GetServerRoleBansAsync(netChannel.RemoteEndPoint.Address, player.UserId, hwId, false);
+
+ var userRoleBans = new List<ServerRoleBanDef>();
+ foreach (var ban in roleBans)
+ {
+ userRoleBans.Add(ban);
+ }
+
cancel.ThrowIfCancellationRequested();
_cachedBanExemptions[player] = flags;
+ _cachedRoleBans[player] = userRoleBans;
+
+ SendRoleBans(player);
}
private void ClearPlayerData(ICommonSession player)
_cachedBanExemptions.Remove(player);
}
- private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
- {
- if (e.NewStatus != SessionStatus.Connected || _cachedRoleBans.ContainsKey(e.Session.UserId))
- return;
-
- var netChannel = e.Session.Channel;
- ImmutableArray<byte>? hwId = netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId;
- await CacheDbRoleBans(e.Session.UserId, netChannel.RemoteEndPoint.Address, hwId);
-
- SendRoleBans(e.Session);
- }
-
private async Task<bool> AddRoleBan(ServerRoleBanDef banDef)
{
banDef = await _db.AddServerRoleBanAsync(banDef);
- if (banDef.UserId != null)
+ if (banDef.UserId != null
+ && _playerManager.TryGetSessionById(banDef.UserId, out var player)
+ && _cachedRoleBans.TryGetValue(player, out var cachedBans))
{
- _cachedRoleBans.GetOrNew(banDef.UserId.Value).Add(banDef);
+ cachedBans.Add(banDef);
}
return true;
public HashSet<string>? GetRoleBans(NetUserId playerUserId)
{
- return _cachedRoleBans.TryGetValue(playerUserId, out var roleBans)
+ if (!_playerManager.TryGetSessionById(playerUserId, out var session))
+ return null;
+
+ return _cachedRoleBans.TryGetValue(session, out var roleBans)
? roleBans.Select(banDef => banDef.Role).ToHashSet()
: null;
}
- private async Task CacheDbRoleBans(NetUserId userId, IPAddress? address = null, ImmutableArray<byte>? hwId = null)
- {
- var roleBans = await _db.GetServerRoleBansAsync(address, userId, hwId, false);
-
- var userRoleBans = new HashSet<ServerRoleBanDef>();
- foreach (var ban in roleBans)
- {
- userRoleBans.Add(ban);
- }
-
- _cachedRoleBans[userId] = userRoleBans;
- }
-
public void Restart()
{
// Clear out players that have disconnected.
- var toRemove = new List<NetUserId>();
+ var toRemove = new ValueList<ICommonSession>();
foreach (var player in _cachedRoleBans.Keys)
{
- if (!_playerManager.TryGetSessionById(player, out _))
+ if (player.Status == SessionStatus.Disconnected)
toRemove.Add(player);
}
// Check for expired bans
foreach (var roleBans in _cachedRoleBans.Values)
{
- roleBans.RemoveWhere(ban => DateTimeOffset.Now > ban.ExpirationTime);
+ roleBans.RemoveAll(ban => DateTimeOffset.Now > ban.ExpirationTime);
}
}
var length = expires == null ? Loc.GetString("cmd-roleban-inf") : Loc.GetString("cmd-roleban-until", ("expires", expires));
_chat.SendAdminAlert(Loc.GetString("cmd-roleban-success", ("target", targetUsername ?? "null"), ("role", role), ("reason", reason), ("length", length)));
- if (target != null)
+ if (target != null && _playerManager.TryGetSessionById(target.Value, out var session))
{
- SendRoleBans(target.Value);
+ SendRoleBans(session);
}
}
await _db.AddServerRoleUnbanAsync(new ServerRoleUnbanDef(banId, unbanningAdmin, DateTimeOffset.Now));
- if (ban.UserId is { } player && _cachedRoleBans.TryGetValue(player, out var roleBans))
+ if (ban.UserId is { } player
+ && _playerManager.TryGetSessionById(player, out var session)
+ && _cachedRoleBans.TryGetValue(session, out var roleBans))
{
- roleBans.RemoveWhere(roleBan => roleBan.Id == ban.Id);
- SendRoleBans(player);
+ roleBans.RemoveAll(roleBan => roleBan.Id == ban.Id);
+ SendRoleBans(session);
}
return $"Pardoned ban with id {banId}";
public HashSet<ProtoId<JobPrototype>>? GetJobBans(NetUserId playerUserId)
{
- if (!_cachedRoleBans.TryGetValue(playerUserId, out var roleBans))
+ if (!_playerManager.TryGetSessionById(playerUserId, out var session))
+ return null;
+
+ if (!_cachedRoleBans.TryGetValue(session, out var roleBans))
return null;
+
return roleBans
.Where(ban => ban.Role.StartsWith(JobPrefix, StringComparison.Ordinal))
.Select(ban => new ProtoId<JobPrototype>(ban.Role[JobPrefix.Length..]))
}
#endregion
- public void SendRoleBans(NetUserId userId)
- {
- if (!_playerManager.TryGetSessionById(userId, out var player))
- {
- return;
- }
-
- SendRoleBans(player);
- }
-
public void SendRoleBans(ICommonSession pSession)
{
- var roleBans = _cachedRoleBans.GetValueOrDefault(pSession.UserId) ?? new HashSet<ServerRoleBanDef>();
+ var roleBans = _cachedRoleBans.GetValueOrDefault(pSession) ?? new List<ServerRoleBanDef>();
var bans = new MsgRoleBans()
{
Bans = roleBans.Select(o => o.Role).ToList()