Antag Rolebans (#35966)

Co-authored-by: beck-thompson <beck314159@hotmail.com>
Co-authored-by: Hannah Giovanna Dawson <karakkaraz@gmail.com>
This commit is contained in:
Errant
2025-09-17 23:59:07 +02:00
committed by GitHub
parent e1ba33814b
commit b692b6e33e
33 changed files with 898 additions and 283 deletions

View File

@@ -1,5 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Content.Client.Lobby;
using Content.Shared.CCVar;
using Content.Shared.Players;
using Content.Shared.Players.JobWhitelist;
@@ -26,7 +25,8 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
[Dependency] private readonly IPrototypeManager _prototypes = default!;
private readonly Dictionary<string, TimeSpan> _roles = new();
private readonly List<string> _roleBans = new();
private readonly List<string> _jobBans = new();
private readonly List<string> _antagBans = new();
private readonly List<string> _jobWhitelists = new();
private ISawmill _sawmill = default!;
@@ -52,16 +52,19 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
// Reset on disconnect, just in case.
_roles.Clear();
_jobWhitelists.Clear();
_roleBans.Clear();
_jobBans.Clear();
_antagBans.Clear();
}
}
private void RxRoleBans(MsgRoleBans message)
{
_sawmill.Debug($"Received roleban info containing {message.Bans.Count} entries.");
_sawmill.Debug($"Received role ban info: {message.JobBans.Count} job ban entries and {message.AntagBans.Count} antag ban entries.");
_roleBans.Clear();
_roleBans.AddRange(message.Bans);
_jobBans.Clear();
_jobBans.AddRange(message.JobBans);
_antagBans.Clear();
_antagBans.AddRange(message.AntagBans);
Updated?.Invoke();
}
@@ -90,33 +93,97 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
Updated?.Invoke();
}
public bool IsAllowed(JobPrototype job, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
/// <summary>
/// Check a list of job- and antag prototypes against the current player, for requirements and bans.
/// </summary>
/// <returns>
/// False if any of the prototypes are banned or have unmet requirements.
/// </returns>>
public bool IsAllowed(
List<ProtoId<JobPrototype>>? jobs,
List<ProtoId<AntagPrototype>>? antags,
HumanoidCharacterProfile? profile,
[NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;
if (_roleBans.Contains($"Job:{job.ID}"))
if (antags is not null)
{
foreach (var proto in antags)
{
if (!IsAllowed(_prototypes.Index(proto), profile, out reason))
return false;
}
}
if (jobs is not null)
{
foreach (var proto in jobs)
{
if (!IsAllowed(_prototypes.Index(proto), profile, out reason))
return false;
}
}
return true;
}
/// <summary>
/// Check the job prototype against the current player, for requirements and bans
/// </summary>
public bool IsAllowed(
JobPrototype job,
HumanoidCharacterProfile? profile,
[NotNullWhen(false)] out FormattedMessage? reason)
{
// Check the player's bans
if (_jobBans.Contains(job.ID))
{
reason = FormattedMessage.FromUnformatted(Loc.GetString("role-ban"));
return false;
}
// Check whitelist requirements
if (!CheckWhitelist(job, out reason))
return false;
var player = _playerManager.LocalSession;
if (player == null)
return true;
// Check other role requirements
var reqs = _entManager.System<SharedRoleSystem>().GetRoleRequirements(job);
if (!CheckRoleRequirements(reqs, profile, out reason))
return false;
return CheckRoleRequirements(job, profile, out reason);
return true;
}
public bool CheckRoleRequirements(JobPrototype job, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
/// <summary>
/// Check the antag prototype against the current player, for requirements and bans
/// </summary>
public bool IsAllowed(
AntagPrototype antag,
HumanoidCharacterProfile? profile,
[NotNullWhen(false)] out FormattedMessage? reason)
{
var reqs = _entManager.System<SharedRoleSystem>().GetJobRequirement(job);
return CheckRoleRequirements(reqs, profile, out reason);
// Check the player's bans
if (_antagBans.Contains(antag.ID))
{
reason = FormattedMessage.FromUnformatted(Loc.GetString("role-ban"));
return false;
}
// Check whitelist requirements
if (!CheckWhitelist(antag, out reason))
return false;
// Check other role requirements
var reqs = _entManager.System<SharedRoleSystem>().GetRoleRequirements(antag);
if (!CheckRoleRequirements(reqs, profile, out reason))
return false;
return true;
}
public bool CheckRoleRequirements(HashSet<JobRequirement>? requirements, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
// This must be private so code paths can't accidentally skip requirement overrides. Call this through IsAllowed()
private bool CheckRoleRequirements(HashSet<JobRequirement>? requirements, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;
@@ -151,6 +218,15 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
return true;
}
public bool CheckWhitelist(AntagPrototype antag, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = default;
// TODO: Implement antag whitelisting.
return true;
}
public TimeSpan FetchOverallPlaytime()
{
return _roles.TryGetValue("Overall", out var overallPlaytime) ? overallPlaytime : TimeSpan.Zero;