Skip to content

Commit

Permalink
Make Jobs & Antags Use CharacterRequirements (Simple-Station#596)
Browse files Browse the repository at this point in the history
# Description

- Makes jobs use CharacterRequirements
- Makes antags use CharReqs
- Splits CharReqs into multiple files
- Adds a Whitelist CharReq
- Prays the tests pass

---

---------

Signed-off-by: DEATHB4DEFEAT <[email protected]>
Co-authored-by: VMSolidus <[email protected]>
  • Loading branch information
DEATHB4DEFEAT and VMSolidus authored Jul 29, 2024
1 parent 7c5625b commit 54c119e
Show file tree
Hide file tree
Showing 78 changed files with 925 additions and 1,013 deletions.
23 changes: 20 additions & 3 deletions Content.Client/LateJoin/LateJoinGui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
using Content.Client.GameTicking.Managers;
using Content.Client.UserInterface.Controls;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Preferences;
using Content.Shared.CCVar;
using Content.Shared.Customization.Systems;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Microsoft.Win32.SafeHandles;
using Robust.Client.Console;
using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
Expand All @@ -26,6 +30,9 @@ public sealed class LateJoinGui : DefaultWindow
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
[Dependency] private readonly CharacterRequirementsSystem _characterRequirements = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IClientPreferencesManager _prefs = default!;

public event Action<(NetEntity, string)> SelectedId;

Expand Down Expand Up @@ -254,14 +261,24 @@ private void RebuildUI()

jobButton.OnPressed += _ => SelectedId.Invoke((id, jobButton.JobId));

if (!_jobRequirements.IsAllowed(prototype, out var reason))
if (!_characterRequirements.CheckRequirementsValid(
prototype.Requirements ?? new(),
prototype,
(HumanoidCharacterProfile) (_prefs.Preferences?.SelectedCharacter
?? HumanoidCharacterProfile.DefaultWithSpecies()),
_jobRequirements.GetPlayTimes(),
_jobRequirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configManager,
out var reasons))
{
jobButton.Disabled = true;

if (!reason.IsEmpty)
if (reasons.Count > 0)
{
var tooltip = new Tooltip();
tooltip.SetMessage(reason);
tooltip.SetMessage(_characterRequirements.GetRequirementsText(reasons));
jobButton.TooltipSupplier = _ => tooltip;
}

Expand Down
12 changes: 5 additions & 7 deletions Content.Client/Lobby/LobbyUIController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Content.Client.Humanoid;
using Content.Client.Inventory;
using Content.Client.Lobby.UI;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Preferences;
using Content.Client.Preferences.UI;
using Content.Shared.Clothing.Loadouts.Systems;
Expand All @@ -23,6 +24,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
[UISystemDependency] private readonly HumanoidAppearanceSystem _humanoid = default!;
[UISystemDependency] private readonly ClientInventorySystem _inventory = default!;
[UISystemDependency] private readonly LoadoutSystem _loadouts = default!;
Expand Down Expand Up @@ -123,7 +125,8 @@ public void UpdateCharacterUI()
if (ShowClothes)
GiveDummyJobClothes(_previewDummy.Value, GetPreferredJob(maybeProfile), maybeProfile);
if (ShowLoadouts)
GiveDummyLoadouts(_previewDummy.Value, GetPreferredJob(maybeProfile), maybeProfile);
_loadouts.ApplyCharacterLoadout(_previewDummy.Value, GetPreferredJob(maybeProfile), maybeProfile,
_jobRequirements.GetPlayTimes(), _jobRequirements.IsWhitelisted());
UpdateClothes = false;
}

Expand Down Expand Up @@ -170,12 +173,7 @@ public void GiveDummyJobClothesLoadout(EntityUid dummy, HumanoidCharacterProfile
{
var job = GetPreferredJob(profile);
GiveDummyJobClothes(dummy, job, profile);
GiveDummyLoadouts(dummy, job, profile);
}

public void GiveDummyLoadouts(EntityUid dummy, JobPrototype job, HumanoidCharacterProfile profile)
{
_loadouts.ApplyCharacterLoadout(dummy, job, profile);
_loadouts.ApplyCharacterLoadout(dummy, job, profile, _jobRequirements.GetPlayTimes(), _jobRequirements.IsWhitelisted());
}

/// <summary>
Expand Down
47 changes: 2 additions & 45 deletions Content.Client/Players/PlayTimeTracking/JobRequirementsManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using Content.Shared.CCVar;
using Content.Shared.Customization.Systems;
using Content.Shared.Players;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Roles;
Expand All @@ -17,9 +18,6 @@ public sealed partial class JobRequirementsManager : ISharedPlaytimeManager
{
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly IClientNetManager _net = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypes = default!;

private readonly Dictionary<string, TimeSpan> _roles = new();
Expand Down Expand Up @@ -80,43 +78,6 @@ private void RxPlayTime(MsgPlayTime message)
Updated?.Invoke();
}

public bool IsAllowed(JobPrototype job, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;

if (_roleBans.Contains($"Job:{job.ID}"))
{
reason = FormattedMessage.FromUnformatted(Loc.GetString("role-ban"));
return false;
}

var player = _playerManager.LocalSession;
if (player == null)
return true;

return CheckRoleTime(job.Requirements, out reason);
}

public bool CheckRoleTime(HashSet<JobRequirement>? requirements, [NotNullWhen(false)] out FormattedMessage? reason, string? localePrefix = "role-timer-")
{
reason = null;

if (requirements == null || !_cfg.GetCVar(CCVars.GameRoleTimers))
return true;

var reasons = new List<string>();
foreach (var requirement in requirements)
{
if (JobRequirements.TryRequirementMet(requirement, _roles, out var jobReason, _entManager, _prototypes, _whitelisted, localePrefix))
continue;

reasons.Add(jobReason.ToMarkup());
}

reason = reasons.Count == 0 ? null : FormattedMessage.FromMarkup(string.Join('\n', reasons));
return reason == null;
}

public TimeSpan FetchOverallPlaytime()
{
return _roles.TryGetValue("Overall", out var overallPlaytime) ? overallPlaytime : TimeSpan.Zero;
Expand All @@ -137,12 +98,8 @@ public Dictionary<string, TimeSpan> FetchPlaytimeByRoles()

public Dictionary<string, TimeSpan> GetPlayTimes()
{
var dict = new Dictionary<string, TimeSpan>();

var dict = FetchPlaytimeByRoles();
dict.Add(PlayTimeTrackingShared.TrackerOverall, FetchOverallPlaytime());
foreach (var role in FetchPlaytimeByRoles())
dict.Add(role.Key, role.Value);

return dict;
}
}
26 changes: 23 additions & 3 deletions Content.Client/Preferences/UI/AntagPreferenceSelector.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using Content.Client.Players.PlayTimeTracking;
using Content.Shared.Customization.Systems;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;

namespace Content.Client.Preferences.UI;

Expand All @@ -14,7 +18,7 @@ public bool Preference

public event Action<bool>? PreferenceChanged;

public AntagPreferenceSelector(AntagPrototype proto) : base(proto)
public AntagPreferenceSelector(AntagPrototype proto, JobPrototype highJob) : base(proto, highJob)
{
Options.OnItemSelected += _ => PreferenceChanged?.Invoke(Preference);

Expand All @@ -30,7 +34,23 @@ public AntagPreferenceSelector(AntagPrototype proto) : base(proto)
// Immediately lock requirements if they aren't met.
// Another function checks Disabled after creating the selector so this has to be done now
var requirements = IoCManager.Resolve<JobRequirementsManager>();
if (proto.Requirements != null && !requirements.CheckRoleTime(proto.Requirements, out var reason))
LockRequirements(reason);
var prefs = IoCManager.Resolve<IClientPreferencesManager>();
var entMan = IoCManager.Resolve<IEntityManager>();
var characterReqs = entMan.System<CharacterRequirementsSystem>();
var protoMan = IoCManager.Resolve<IPrototypeManager>();
var configMan = IoCManager.Resolve<IConfigurationManager>();

if (proto.Requirements != null
&& !characterReqs.CheckRequirementsValid(
proto.Requirements,
highJob,
(HumanoidCharacterProfile) (prefs.Preferences?.SelectedCharacter ?? HumanoidCharacterProfile.DefaultWithSpecies()),
requirements.GetPlayTimes(),
requirements.IsWhitelisted(),
entMan,
protoMan,
configMan,
out var reasons))
LockRequirements(characterReqs.GetRequirementsText(reasons));
}
}
53 changes: 38 additions & 15 deletions Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt
_preferencesManager = preferencesManager;
_configurationManager = configurationManager;
_markingManager = IoCManager.Resolve<MarkingManager>();
_characterRequirementsSystem = EntitySystem.Get<CharacterRequirementsSystem>();
_characterRequirementsSystem = _entityManager.System<CharacterRequirementsSystem>();
_controller = UserInterfaceManager.GetUIController<LobbyUIController>();

_controller.SetProfileEditor(this);
Expand Down Expand Up @@ -642,7 +642,9 @@ private void UpdateAntagRequirements()
if (!antag.SetPreference)
continue;

var selector = new AntagPreferenceSelector(antag)
var selector = new AntagPreferenceSelector(antag,
_jobPriorities.FirstOrDefault(j => j.Priority == JobPriority.High)?.HighJob
?? new())
{ Margin = new Thickness(3f, 3f, 3f, 0f) };
_antagList.AddChild(selector);
_antagPreferences.Add(selector);
Expand Down Expand Up @@ -723,10 +725,17 @@ private void UpdateRoleRequirements()
{
var selector = new JobPrioritySelector(job, _prototypeManager);

if (!_requirements.IsAllowed(job, out var reason))
{
selector.LockRequirements(reason);
}
if (!_characterRequirementsSystem.CheckRequirementsValid(
job.Requirements ?? new(),
job,
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
_requirements.GetPlayTimes(),
_requirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configurationManager,
out var reasons))
selector.LockRequirements(_characterRequirementsSystem.GetRequirementsText(reasons));

category.AddChild(selector);
_jobPriorities.Add(selector);
Expand Down Expand Up @@ -770,7 +779,17 @@ private void EnsureJobRequirementsValid()
var changed = false;
foreach (var selector in _jobPriorities)
{
if (_requirements.IsAllowed(selector.Proto, out var _) || selector.Priority == JobPriority.Never)
if (selector.Priority == JobPriority.Never
|| _characterRequirementsSystem.CheckRequirementsValid(
selector.Proto.Requirements ?? new(),
selector.Proto,
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
_requirements.GetPlayTimes(),
_requirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configurationManager,
out _))
continue;

selector.Priority = JobPriority.Never;
Expand Down Expand Up @@ -1412,11 +1431,11 @@ private void UpdateTraits(bool showUnusable)
var traits = enumeratedTraits.Where(trait =>
showUnusable || // Ignore everything if this is true
_characterRequirementsSystem.CheckRequirementsValid(
trait,
trait.Requirements,
highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
_requirements.GetPlayTimes(),
_requirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configurationManager,
Expand All @@ -1427,11 +1446,11 @@ out _
// Traits to highlight red when showUnusable is true
var traitsUnusable = enumeratedTraits.Where(trait =>
_characterRequirementsSystem.CheckRequirementsValid(
trait,
trait.Requirements,
highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
_requirements.GetPlayTimes(),
_requirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configurationManager,
Expand Down Expand Up @@ -1538,7 +1557,8 @@ out _
var selector = new TraitPreferenceSelector(trait, highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
traitsUnusable.Contains(trait) ? "" : "ButtonColorRed",
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem);
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem,
_requirements);

// Look for an existing trait category
BoxContainer? match = null;
Expand Down Expand Up @@ -1570,7 +1590,8 @@ out _
{
var selector = new TraitPreferenceSelector(trait, highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), "",
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem);
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem,
_requirements);


AddSelector(selector, trait.Points, trait.ID);
Expand Down Expand Up @@ -1671,11 +1692,11 @@ private void UpdateLoadouts(bool showUnusable)
var loadouts = enumeratedLoadouts.Where(loadout =>
showUnusable || // Ignore everything if this is true
_characterRequirementsSystem.CheckRequirementsValid(
loadout,
loadout.Requirements,
highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
_requirements.GetPlayTimes(),
_requirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configurationManager,
Expand All @@ -1686,11 +1707,11 @@ out _
// Loadouts to highlight red when showUnusable is true
var loadoutsUnusable = enumeratedLoadouts.Where(loadout =>
_characterRequirementsSystem.CheckRequirementsValid(
loadout,
loadout.Requirements,
highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
_requirements.GetPlayTimes(),
_requirements.IsWhitelisted(),
_entityManager,
_prototypeManager,
_configurationManager,
Expand Down Expand Up @@ -1800,7 +1821,8 @@ out _
var selector = new LoadoutPreferenceSelector(loadout, highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(),
loadoutsUnusable.Contains(loadout) ? "" : "ButtonColorRed",
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem);
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem,
_requirements);

// Look for an existing loadout category
BoxContainer? match = null;
Expand Down Expand Up @@ -1829,7 +1851,8 @@ out _
{
var selector = new LoadoutPreferenceSelector(loadout, highJob?.Proto ?? new JobPrototype(),
Profile ?? HumanoidCharacterProfile.DefaultWithSpecies(), "",
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem);
_entityManager, _prototypeManager, _configurationManager, _characterRequirementsSystem,
_requirements);


AddSelector(selector, loadout.Cost, loadout.ID);
Expand Down
3 changes: 2 additions & 1 deletion Content.Client/Preferences/UI/JobPrioritySelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Content.Shared.StatusIcon;
using Robust.Client.UserInterface.Controls;
using Robust.Client.Utility;
using Robust.Shared.CPUJob.JobQueues;
using Robust.Shared.Prototypes;

namespace Content.Client.Preferences.UI;
Expand All @@ -18,7 +19,7 @@ public JobPriority Priority

public event Action<JobPriority>? PriorityChanged;

public JobPrioritySelector(JobPrototype proto, IPrototypeManager protoMan) : base(proto)
public JobPrioritySelector(JobPrototype proto, IPrototypeManager protoMan) : base(proto, proto)
{
Options.OnItemSelected += _ => PriorityChanged?.Invoke(Priority);

Expand Down
Loading

0 comments on commit 54c119e

Please sign in to comment.