JobRequiremet refactor (#579)

* JobRequirement refactor (#30347)

* refactor JobRequirements

* add profile support

* fix

* Update quartermaster.yml

* sloth fixes

* inport 30208

* Update DepartmentPrototype.cs

* species restriction

* left tweak stick

* stringbuilder is cool!

* Add JobRequirementOverride prototypes (#28607)

* Add JobRequirementOverride prototypes

* a

* invert if

* Add override that takes in prototypes directly

* - fix: Errors.

* - add: Add stuff.

* - fix: Formatted message fix.

* - add: Another requirement.

---------

Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
This commit is contained in:
Aviu00
2024-08-07 17:30:43 +00:00
committed by GitHub
parent 44447d573f
commit 9a9c9598e0
53 changed files with 805 additions and 297 deletions

View File

@@ -42,7 +42,7 @@ public sealed partial class RoleBanWindow : DefaultWindow
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
foreach (var proto in prototypeManager.EnumeratePrototypes<DepartmentPrototype>())
{
CreateRoleGroup(proto.ID, proto.Roles, proto.Color);
CreateRoleGroup(proto.ID, proto.Roles.Select(x => x.Id), proto.Color);
}
CreateRoleGroup("Antagonist", prototypeManager.EnumeratePrototypes<AntagPrototype>().Select(p => p.ID),

View File

@@ -4,7 +4,9 @@ using Content.Client.CrewManifest;
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.Preferences;
using Content.Shared.Roles;
using Content.Shared.StatusIcon;
using Robust.Client.Console;
@@ -26,6 +28,7 @@ namespace Content.Client.LateJoin
[Dependency] private readonly IConfigurationManager _configManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly JobRequirementsManager _jobRequirements = default!;
[Dependency] private readonly IClientPreferencesManager _preferencesManager = default!;
public event Action<(NetEntity, string)> SelectedId;
@@ -254,7 +257,7 @@ namespace Content.Client.LateJoin
jobButton.OnPressed += _ => SelectedId.Invoke((id, jobButton.JobId));
if (!_jobRequirements.IsAllowed(prototype, out var reason))
if (!_jobRequirements.IsAllowed(prototype, (HumanoidCharacterProfile?)_preferencesManager.Preferences?.SelectedCharacter, out var reason))
{
jobButton.Disabled = true;

View File

@@ -1,8 +1,10 @@
using System.Diagnostics.CodeAnalysis;
using Content.Client.Administration.Managers;
using Content.Client.Lobby;
using Content.Shared.CCVar;
using Content.Shared.Players;
using Content.Shared.Players.PlayTimeTracking;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Client;
using Robust.Client.Player;
@@ -22,7 +24,6 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypes = default!;
[Dependency] private readonly IClientAdminManager _adminManager = default!; // WD
private readonly Dictionary<string, TimeSpan> _roles = new();
private readonly List<string> _roleBans = new();
@@ -40,7 +41,6 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
_net.RegisterNetMessage<MsgPlayTime>(RxPlayTime);
_client.RunLevelChanged += ClientOnRunLevelChanged;
_adminManager.AdminStatusUpdated += () => Updated?.Invoke(); // WD
}
private void ClientOnRunLevelChanged(object? sender, RunLevelChangedEventArgs e)
@@ -82,7 +82,8 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
Updated?.Invoke();
}
public bool IsAllowed(JobPrototype job, [NotNullWhen(false)] out FormattedMessage? reason)
public bool IsAllowed(JobPrototype job, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;
@@ -96,11 +97,16 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
if (player == null)
return true;
return _adminManager.IsActive() || // WD
CheckRoleTime(job.Requirements, out reason);
return CheckRoleRequirements(job, profile, out reason);
}
public bool CheckRoleTime(HashSet<JobRequirement>? requirements, [NotNullWhen(false)] out FormattedMessage? reason)
public bool CheckRoleRequirements(JobPrototype job, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
{
var reqs = _entManager.System<SharedRoleSystem>().GetJobRequirement(job);
return CheckRoleRequirements(reqs, profile, out reason);
}
public bool CheckRoleRequirements(HashSet<JobRequirement>? requirements, HumanoidCharacterProfile? profile, [NotNullWhen(false)] out FormattedMessage? reason)
{
reason = null;
@@ -110,7 +116,7 @@ public sealed class JobRequirementsManager : ISharedPlaytimeManager
var reasons = new List<string>();
foreach (var requirement in requirements)
{
if (JobRequirements.TryRequirementMet(requirement, _roles, out var jobReason, _entManager, _prototypes))
if (requirement.Check(_entManager, _prototypes, profile, _roles, out var jobReason))
continue;
reasons.Add(jobReason.ToMarkup());

View File

@@ -1,4 +1,5 @@
using Content.Client.Players.PlayTimeTracking;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Client.UserInterface.Controls;
@@ -15,7 +16,7 @@ public sealed class AntagPreferenceSelector : RequirementsSelector<AntagPrototyp
public event Action<bool>? PreferenceChanged;
public AntagPreferenceSelector(AntagPrototype proto, ButtonGroup btnGroup)
public AntagPreferenceSelector(AntagPrototype proto, ButtonGroup btnGroup, HumanoidCharacterProfile profile)
: base(proto, btnGroup)
{
Options.OnItemSelected += args => PreferenceChanged?.Invoke(Preference);
@@ -28,12 +29,12 @@ public sealed class AntagPreferenceSelector : RequirementsSelector<AntagPrototyp
var title = Loc.GetString(proto.Name);
var description = Loc.GetString(proto.Objective);
// Not supported yet get fucked.
Setup(null, items, title, 250, description);
Setup(null, profile, items, title, 250, description);
// immediately lock requirements if they arent 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))
if (!requirements.CheckRoleRequirements(proto.Requirements, profile, out var reason))
{
LockRequirements(reason);
}

View File

@@ -557,12 +557,16 @@ namespace Content.Client.Preferences.UI
_antagPreferences.Clear();
var btnGroup = new ButtonGroup();
var character = (HumanoidCharacterProfile?) _preferencesManager.Preferences?.SelectedCharacter;
if (character == null)
return;
foreach (var antag in _prototypeManager.EnumeratePrototypes<AntagPrototype>().OrderBy(a => Loc.GetString(a.Name)))
{
if (!antag.SetPreference)
continue;
var selector = new AntagPreferenceSelector(antag, btnGroup)
var selector = new AntagPreferenceSelector(antag, btnGroup, character)
{
Margin = new Thickness(3f, 3f, 3f, 0f),
};
@@ -590,6 +594,10 @@ namespace Content.Client.Preferences.UI
_jobCategories.Clear();
var firstCategory = true;
var character = (HumanoidCharacterProfile?) _preferencesManager.Preferences?.SelectedCharacter;
if (character == null)
return;
var departments = _prototypeManager.EnumeratePrototypes<DepartmentPrototype>().ToArray();
Array.Sort(departments, DepartmentUIComparer.Instance);
@@ -650,12 +658,12 @@ namespace Content.Client.Preferences.UI
// Clone so we don't modify the underlying loadout.
Profile?.Loadouts.TryGetValue(LoadoutSystem.GetJobPrototype(job.ID), out loadout);
loadout = loadout?.Clone();
var selector = new JobPrioritySelector(loadout, job, jobLoadoutGroup, _prototypeManager)
var selector = new JobPrioritySelector(loadout, job, jobLoadoutGroup, _prototypeManager, character)
{
Margin = new Thickness(3f, 3f, 3f, 0f),
};
if (!_requirements.IsAllowed(job, out var reason))
if (!_requirements.IsAllowed(job, (HumanoidCharacterProfile?)_preferencesManager.Preferences?.SelectedCharacter, out var reason))
{
selector.LockRequirements(reason);
}

View File

@@ -20,7 +20,7 @@ public sealed class JobPrioritySelector : RequirementsSelector<JobPrototype>
public event Action<JobPriority>? PriorityChanged;
public JobPrioritySelector(RoleLoadout? loadout, JobPrototype proto, ButtonGroup btnGroup, IPrototypeManager protoMan)
public JobPrioritySelector(RoleLoadout? loadout, JobPrototype proto, ButtonGroup btnGroup, IPrototypeManager protoMan, HumanoidCharacterProfile profile)
: base(proto, btnGroup)
{
Options.OnItemSelected += args => PriorityChanged?.Invoke(Priority);
@@ -41,6 +41,6 @@ public sealed class JobPrioritySelector : RequirementsSelector<JobPrototype>
var jobIcon = protoMan.Index<StatusIconPrototype>(proto.Icon);
icon.Texture = jobIcon.Icon.Frame0();
Setup(loadout, items, proto.LocalizedName, 200, proto.LocalizedDescription, icon);
Setup(loadout, profile, items, proto.LocalizedName, 200, proto.LocalizedDescription, icon);
}
}

View File

@@ -1,5 +1,6 @@
using System.Linq;
using Content.Shared.Clothing;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
@@ -17,18 +18,18 @@ public sealed partial class LoadoutGroupContainer : BoxContainer
public event Action<ProtoId<ItemLoadoutPrototype>>? OnLoadoutPressed;
public event Action<ProtoId<ItemLoadoutPrototype>>? OnLoadoutUnpressed;
public LoadoutGroupContainer(RoleLoadout loadout, LoadoutGroupPrototype groupProto, ICommonSession session, IDependencyCollection collection)
public LoadoutGroupContainer(HumanoidCharacterProfile profile, RoleLoadout loadout, LoadoutGroupPrototype groupProto, ICommonSession session, IDependencyCollection collection)
{
RobustXamlLoader.Load(this);
_groupProto = groupProto;
RefreshLoadouts(loadout, session, collection);
RefreshLoadouts(profile, loadout, session, collection);
}
/// <summary>
/// Updates button availabilities and buttons.
/// </summary>
public void RefreshLoadouts(RoleLoadout loadout, ICommonSession session, IDependencyCollection collection)
public void RefreshLoadouts(HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection)
{
var protoMan = collection.Resolve<IPrototypeManager>();
var loadoutSystem = collection.Resolve<IEntityManager>().System<LoadoutSystem>();
@@ -74,7 +75,7 @@ public sealed partial class LoadoutGroupContainer : BoxContainer
var matchingLoadout = selected.FirstOrDefault(e => e.Prototype == loadoutProto);
var pressed = matchingLoadout != null;
var enabled = loadout.IsValid(session, loadoutProto, collection, out var reason);
var enabled = loadout.IsValid(profile, session, loadoutProto, collection, out var reason);
var loadoutContainer = new LoadoutContainer(loadoutProto, !enabled, reason);
loadoutContainer.Select.Pressed = pressed;
loadoutContainer.Text = loadoutSystem.GetName(loadProto);

View File

@@ -1,5 +1,6 @@
using Content.Client.Lobby;
using Content.Client.UserInterface.Controls;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Preferences.Loadouts.Effects;
using Robust.Client.AutoGenerated;
@@ -17,9 +18,12 @@ public sealed partial class LoadoutWindow : FancyWindow
private List<LoadoutGroupContainer> _groups = new();
public LoadoutWindow(RoleLoadout loadout, RoleLoadoutPrototype proto, ICommonSession session, IDependencyCollection collection)
public HumanoidCharacterProfile Profile;
public LoadoutWindow(HumanoidCharacterProfile profile, RoleLoadout loadout, RoleLoadoutPrototype proto, ICommonSession session, IDependencyCollection collection)
{
RobustXamlLoader.Load(this);
Profile = profile;
var protoManager = collection.Resolve<IPrototypeManager>();
foreach (var group in proto.Groups)
@@ -27,7 +31,7 @@ public sealed partial class LoadoutWindow : FancyWindow
if (!protoManager.TryIndex(group, out var groupProto))
continue;
var container = new LoadoutGroupContainer(loadout, protoManager.Index(group), session, collection);
var container = new LoadoutGroupContainer(profile, loadout, protoManager.Index(group), session, collection);
LoadoutGroupsContainer.AddTab(container, Loc.GetString(groupProto.Name));
_groups.Add(container);
@@ -54,7 +58,7 @@ public sealed partial class LoadoutWindow : FancyWindow
{
foreach (var group in _groups)
{
group.RefreshLoadouts(loadout, session, collection);
group.RefreshLoadouts(Profile, loadout, session, collection);
}
}
}

View File

@@ -3,6 +3,7 @@ using Content.Client.Lobby;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.Clothing;
using Content.Shared.Preferences;
using Content.Shared.Preferences.Loadouts;
using Content.Shared.Preferences.Loadouts.Effects;
using Content.Shared.Roles;
@@ -75,7 +76,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
/// <summary>
/// Actually adds the controls, must be called in the inheriting class' constructor.
/// </summary>
protected void Setup(RoleLoadout? loadout, (string, int)[] items, string title, int titleSize, string? description, TextureRect? icon = null)
protected void Setup(RoleLoadout? loadout, HumanoidCharacterProfile profile, (string, int)[] items, string title, int titleSize, string? description, TextureRect? icon = null)
{
_loadout = loadout;
@@ -131,7 +132,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
_loadout ??= new RoleLoadout(LoadoutSystem.GetJobPrototype(Proto.ID));
_loadout.SetDefault(protoManager);
_loadoutWindow = new LoadoutWindow(_loadout, protoManager.Index(_loadout.Role), session, collection)
_loadoutWindow = new LoadoutWindow(profile, _loadout, protoManager.Index(_loadout.Role), session, collection)
{
Title = Loc.GetString(Proto.ID + "-loadout"),
};
@@ -150,7 +151,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
if (!_loadout.RemoveLoadout(selectedGroup, selectedLoadout, protoManager))
return;
_loadout.EnsureValid(session, collection);
_loadout.EnsureValid(profile, session, collection);
_loadoutWindow.RefreshLoadouts(_loadout, session, collection);
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.ReloadProfile();
@@ -162,7 +163,7 @@ public abstract class RequirementsSelector<T> : BoxContainer where T : IPrototyp
if (!_loadout.AddLoadout(selectedGroup, selectedLoadout, protoManager))
return;
_loadout.EnsureValid(session, collection);
_loadout.EnsureValid(profile, session, collection);
_loadoutWindow.RefreshLoadouts(_loadout, session, collection);
var controller = UserInterfaceManager.GetUIController<LobbyUIController>();
controller.ReloadProfile();

View File

@@ -93,7 +93,7 @@ namespace Content.Client.UserInterface.Systems.Ghost.Controls.Roles
bool hasAccess = true;
FormattedMessage? reason;
if (!requirementsManager.CheckRoleTime(group.Key.Requirements, out reason))
if (!requirementsManager.CheckRoleRequirements(group.Key.Requirements, null, out reason))
{
hasAccess = false;
}