-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
job slots console #476
job slots console #476
Changes from all commits
049ed23
3c31cdc
547097a
607e65d
92294b6
5362857
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<BoxContainer xmlns="https://spacestation14.io" | ||
Orientation="Horizontal" | ||
HorizontalExpand="True" | ||
MinHeight="32" | ||
Margin="8 0 8 2"> | ||
<BoxContainer Name="JobTitleContainer" | ||
Orientation="Horizontal" | ||
HorizontalExpand="True" | ||
VerticalAlignment="Center"> | ||
<TextureRect Name="JobIcon" | ||
TextureScale="2 2" | ||
VerticalAlignment="Center" | ||
Margin="0 0 4 0" /> | ||
<Label Name="JobNameLabel" | ||
HorizontalExpand="True" | ||
VerticalAlignment="Center" /> | ||
</BoxContainer> | ||
<Button Name="DecreaseButton" | ||
Text="-" | ||
MinWidth="32" /> | ||
<Label Name="SlotsLabel" | ||
MinWidth="60" | ||
Align="Center" | ||
VerticalAlignment="Center" /> | ||
<Button Name="IncreaseButton" | ||
Text="+" | ||
MinWidth="32" | ||
Margin="0 0 4 0" /> | ||
<Button Name="ToggleInfiniteButton" | ||
Text="∞" | ||
MinWidth="32" | ||
Visible="False" /> | ||
</BoxContainer> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
using Content.Shared._CD.JobSlotsConsole; | ||
using Content.Shared.Roles; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.GameObjects; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client._CD.JobSlotsConsole; | ||
|
||
[GenerateTypedNameReferences] | ||
public sealed partial class JobRow : BoxContainer | ||
{ | ||
[Dependency] private readonly IPrototypeManager _protoManager = default!; | ||
[Dependency] private readonly IEntitySystemManager _entitySystem = default!; | ||
|
||
public event Action<JobSlotAdjustment>? OnAdjustPressed; | ||
public string JobName { get; } | ||
|
||
public JobRow(ProtoId<JobPrototype> job, int? slots, bool blacklisted) | ||
{ | ||
IoCManager.InjectDependencies(this); | ||
RobustXamlLoader.Load(this); | ||
|
||
var spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>(); | ||
|
||
var proto = _protoManager.Index(job); | ||
JobName = Loc.GetString(proto.Name); | ||
JobNameLabel.Text = JobName; | ||
|
||
// Set up job icon | ||
if (_protoManager.TryIndex(proto.Icon, out var jobIcon)) | ||
{ | ||
JobIcon.Texture = spriteSystem.Frame0(jobIcon.Icon); | ||
} | ||
|
||
UpdateSlots(slots, blacklisted); | ||
|
||
DecreaseButton.OnPressed += OnDecrease; | ||
IncreaseButton.OnPressed += OnIncrease; | ||
ToggleInfiniteButton.OnPressed += OnToggleInfinite; | ||
} | ||
|
||
private void OnDecrease(BaseButton.ButtonEventArgs args) | ||
{ | ||
OnAdjustPressed?.Invoke(JobSlotAdjustment.Decrease); | ||
} | ||
|
||
private void OnIncrease(BaseButton.ButtonEventArgs args) | ||
{ | ||
OnAdjustPressed?.Invoke(JobSlotAdjustment.Increase); | ||
} | ||
|
||
private void OnToggleInfinite(BaseButton.ButtonEventArgs args) | ||
{ | ||
var currentInfinite = SlotsLabel.Text == "∞"; | ||
OnAdjustPressed?.Invoke(currentInfinite ? JobSlotAdjustment.SetFinite : JobSlotAdjustment.SetInfinite); | ||
} | ||
|
||
public void ShowDebugControls(bool show) | ||
{ | ||
ToggleInfiniteButton.Visible = show; | ||
} | ||
|
||
private void UpdateSlots(int? slots, bool blacklisted) | ||
{ | ||
SlotsLabel.Text = slots?.ToString() ?? "∞"; | ||
|
||
// Disable buttons if blacklisted or at limits | ||
DecreaseButton.Disabled = blacklisted || slots is 0 or null; | ||
IncreaseButton.Disabled = blacklisted || slots == null; | ||
ToggleInfiniteButton.Disabled = blacklisted; | ||
|
||
if (blacklisted) | ||
{ | ||
DecreaseButton.ToolTip = Loc.GetString("job-slots-console-blacklisted"); | ||
IncreaseButton.ToolTip = Loc.GetString("job-slots-console-blacklisted"); | ||
ToggleInfiniteButton.ToolTip = Loc.GetString("job-slots-console-blacklisted"); | ||
} | ||
else | ||
{ | ||
DecreaseButton.ToolTip = null; | ||
IncreaseButton.ToolTip = null; | ||
ToggleInfiniteButton.ToolTip = null; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using Content.Shared._CD.JobSlotsConsole; | ||
using Content.Shared.Roles; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Client._CD.JobSlotsConsole; | ||
|
||
public sealed class JobSlotsConsoleBoundUserInterface : BoundUserInterface | ||
{ | ||
|
||
private JobSlotsConsoleMenu? _menu; | ||
|
||
public JobSlotsConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) | ||
{ | ||
} | ||
|
||
protected override void Open() | ||
{ | ||
base.Open(); | ||
|
||
_menu = new JobSlotsConsoleMenu(); | ||
_menu.OpenCentered(); | ||
_menu.OnClose += Close; | ||
_menu.OnAdjustPressed += AdjustSlot; | ||
} | ||
|
||
private void AdjustSlot(ProtoId<JobPrototype> jobId, JobSlotAdjustment adjustment) | ||
{ | ||
SendMessage(new JobSlotsConsoleAdjustMessage(jobId, adjustment)); | ||
} | ||
|
||
Comment on lines
+25
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use SendPredictedMessage and make the whole thing predicted? |
||
protected override void UpdateState(BoundUserInterfaceState state) | ||
{ | ||
base.UpdateState(state); | ||
|
||
if (state is not JobSlotsConsoleState cast) | ||
return; | ||
|
||
_menu?.UpdateState(cast); | ||
} | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
base.Dispose(disposing); | ||
if (!disposing) | ||
return; | ||
_menu?.Close(); | ||
_menu = null; | ||
} | ||
Comment on lines
+40
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Obsolete |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<controls:FancyWindow xmlns="https://spacestation14.io" | ||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls" | ||
Title="{Loc 'job-slots-console-title'}" | ||
SetSize="600 400" | ||
MinSize="600 300"> | ||
<BoxContainer Orientation="Vertical" Margin="4"> | ||
<LineEdit Name="SearchBar" | ||
PlaceHolder="{Loc 'job-slots-console-search-placeholder'}" | ||
HorizontalExpand="True" | ||
Margin="0 0 0 4" /> | ||
|
||
<ScrollContainer VerticalExpand="True" HorizontalExpand="True"> | ||
<BoxContainer Name="DepartmentsList" | ||
Orientation="Vertical" | ||
VerticalExpand="True" | ||
HorizontalExpand="True"> | ||
<!-- Populated with departments --> | ||
</BoxContainer> | ||
</ScrollContainer> | ||
</BoxContainer> | ||
</controls:FancyWindow> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
using Content.Client.Administration.UI.CustomControls; | ||
using Content.Client.UserInterface.Controls; | ||
using Content.Shared.Roles; | ||
using Content.Shared._CD.JobSlotsConsole; | ||
using Robust.Client.AutoGenerated; | ||
using Robust.Client.UserInterface.Controls; | ||
using Robust.Client.UserInterface.XAML; | ||
using Robust.Shared.Prototypes; | ||
using System.Linq; | ||
|
||
namespace Content.Client._CD.JobSlotsConsole; | ||
|
||
[GenerateTypedNameReferences] | ||
public sealed partial class JobSlotsConsoleMenu : FancyWindow | ||
{ | ||
[Dependency] private readonly IPrototypeManager _protoManager = default!; | ||
|
||
private readonly Dictionary<ProtoId<DepartmentPrototype>, List<JobRow>> _departmentRows = new(); | ||
private readonly Dictionary<ProtoId<DepartmentPrototype>, Label> _departmentLabels = new(); | ||
private JobSlotsConsoleState? _currentState; | ||
|
||
public event Action<ProtoId<JobPrototype>, JobSlotAdjustment>? OnAdjustPressed; | ||
|
||
public JobSlotsConsoleMenu() | ||
{ | ||
IoCManager.InjectDependencies(this); | ||
RobustXamlLoader.Load(this); | ||
|
||
SearchBar.OnTextChanged += _ => UpdateJobList(); | ||
} | ||
|
||
public void UpdateState(JobSlotsConsoleState state) | ||
{ | ||
_currentState = state; | ||
|
||
DepartmentsList.RemoveAllChildren(); | ||
_departmentRows.Clear(); | ||
_departmentLabels.Clear(); | ||
|
||
var jobsByDepartment = new Dictionary<DepartmentPrototype, List<(JobPrototype proto, int? slots, bool blacklisted)>>(); | ||
|
||
foreach (var (jobId, slots) in state.Jobs) | ||
{ | ||
var proto = _protoManager.Index(jobId); | ||
var department = GetPrimaryDepartmentForJob(proto.ID); | ||
|
||
if (department is not { } dept) | ||
continue; | ||
|
||
if (!jobsByDepartment.TryGetValue(dept, out var jobs)) | ||
{ | ||
jobs = new List<(JobPrototype, int?, bool)>(); | ||
jobsByDepartment[dept] = jobs; | ||
} | ||
|
||
var blacklisted = state.BlacklistedJobs.Contains(jobId); | ||
jobs.Add((proto, slots, blacklisted)); | ||
} | ||
|
||
// Sort and add departments | ||
foreach (var (department, jobs) in jobsByDepartment.OrderBy(x => x.Key, DepartmentUIComparer.Instance)) | ||
{ | ||
var sortedJobs = jobs | ||
.OrderByDescending(x => x.proto.RealDisplayWeight) | ||
.ThenBy(x => x.proto.LocalizedName) | ||
.ToList(); | ||
|
||
AddDepartmentSection(department, sortedJobs); | ||
} | ||
|
||
UpdateJobList(); | ||
} | ||
|
||
private void AddDepartmentSection(DepartmentPrototype department, List<(JobPrototype proto, int? slots, bool blacklisted)> jobs) | ||
{ | ||
var departmentBox = new BoxContainer | ||
{ | ||
Orientation = BoxContainer.LayoutOrientation.Vertical, | ||
HorizontalExpand = true, | ||
Margin = new Thickness(0, 5), | ||
}; | ||
|
||
// Add department header | ||
var label = new Label | ||
{ | ||
Text = Loc.GetString(department.Name), | ||
HorizontalAlignment = HAlignment.Center, | ||
StyleClasses = { "LabelHeading" }, | ||
ModulateSelfOverride = department.Color, | ||
FontColorOverride = department.Color, // css trolling | ||
}; | ||
|
||
_departmentLabels[department.ID] = label; | ||
departmentBox.AddChild(label); | ||
departmentBox.AddChild(new HSeparator { Margin = new Thickness(5, 3, 5, 5) }); | ||
|
||
// Add job rows | ||
var jobRows = new List<JobRow>(); | ||
foreach (var (proto, slots, blacklisted) in jobs) | ||
{ | ||
var row = new JobRow(proto.ID, slots, blacklisted); | ||
row.OnAdjustPressed += adjustment => | ||
OnAdjustPressed?.Invoke(proto.ID, adjustment); | ||
row.ShowDebugControls(_currentState?.Debug ?? false); | ||
jobRows.Add(row); | ||
departmentBox.AddChild(row); | ||
} | ||
|
||
_departmentRows[department.ID] = jobRows; | ||
DepartmentsList.AddChild(departmentBox); | ||
} | ||
|
||
private void UpdateJobList() | ||
{ | ||
var search = SearchBar.Text.Trim().ToLowerInvariant(); | ||
|
||
foreach (var (departmentId, rows) in _departmentRows) | ||
{ | ||
var departmentLabel = _departmentLabels[departmentId]; | ||
var hasVisibleJobs = false; | ||
|
||
foreach (var row in rows) | ||
{ | ||
var visible = string.IsNullOrEmpty(search) || | ||
row.JobName.Contains(search, StringComparison.InvariantCultureIgnoreCase); | ||
row.Visible = visible; | ||
hasVisibleJobs |= visible; | ||
} | ||
|
||
departmentLabel.Parent!.Visible = hasVisibleJobs; | ||
} | ||
} | ||
|
||
private DepartmentPrototype? GetPrimaryDepartmentForJob(ProtoId<JobPrototype> jobId) | ||
{ | ||
return _protoManager.EnumeratePrototypes<DepartmentPrototype>() | ||
.FirstOrDefault(d => d.Roles.Contains(jobId) && d.Primary) | ||
?? _protoManager.EnumeratePrototypes<DepartmentPrototype>() | ||
.FirstOrDefault(d => d.Roles.Contains(jobId)); | ||
} | ||
} | ||
Comment on lines
+133
to
+141
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should really be on jobs or something rather than here. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using Content.Shared.Roles; | ||
using Robust.Shared.Audio; | ||
using Robust.Shared.Prototypes; | ||
|
||
namespace Content.Server._CD.JobSlotsConsole; | ||
|
||
[RegisterComponent] | ||
public sealed partial class JobSlotsConsoleComponent : Component | ||
{ | ||
/// <summary> | ||
/// The station this console is linked to. Set when the station is detected. | ||
/// </summary> | ||
[DataField] | ||
public EntityUid? Station; | ||
|
||
/// <summary> | ||
/// Jobs that cannot have their slots adjusted from this console. | ||
/// </summary> | ||
[DataField] | ||
public HashSet<ProtoId<JobPrototype>> Blacklist = []; | ||
|
||
/// <summary> | ||
/// Whether this console has debug features enabled, like toggling infinite slots. | ||
/// </summary> | ||
[DataField] | ||
public bool Debug; | ||
|
||
/// <summary> | ||
/// The sound to play if the player doesn't have access to change job slots. | ||
/// </summary> | ||
[DataField] | ||
public SoundSpecifier DenySound = new SoundPathSpecifier("/Audio/Effects/Cargo/buzz_sigh.ogg"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.CreateWindow?