using System.Linq; using Content.Client._NF.LateJoin.Interfaces; using Content.Client._NF.LateJoin.ListItems; using Content.Client.Lobby; using Content.Client.Players.PlayTimeTracking; using Content.Shared.GameTicking; using Content.Shared.Preferences; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; namespace Content.Client._NF.LateJoin.Controls; [GenerateTypedNameReferences] public sealed partial class StationPickerControl : PickerControl { [Dependency] private readonly ILocalizationManager _loc = default!; [Dependency] private readonly IEntitySystemManager _entitySystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly JobRequirementsManager _jobReqs = default!; [Dependency] private readonly IClientPreferencesManager _preferencesManager = default!; private readonly SpriteSystem _spriteSystem; public StationPickerControl() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _spriteSystem = _entitySystem.GetEntitySystem(); } private Dictionary _lobbyJobs = new(); private StationListItem.ViewState? _lastSelectedStation; public Action? OnJobJoined; public override void UpdateUi(IReadOnlyDictionary obj) { _lobbyJobs = new Dictionary(obj); StationItemList.RemoveAllChildren(); foreach (var stationViewState in BuildStationViewStateList(_lobbyJobs)) { var item = new StationListItem(stationViewState); item.StationButton.OnPressed += _ => OnStationPressed(stationViewState); StationItemList.AddChild(item); } // Build station jobs, the right section of the screen. StationJobItemList.RemoveAllChildren(); if (_lastSelectedStation != null && obj.TryGetValue(_lastSelectedStation.StationEntity, out var stationInfo)) { foreach (var jobViewState in BuildJobViewStateList(stationInfo)) { var item = new JobListItem(jobViewState); item.OnPressed += _ => { OnJobJoined?.Invoke(_lastSelectedStation.StationEntity, jobViewState.JobId); }; StationJobItemList.AddChild(item); } } StationName.Text = _lastSelectedStation?.StationName ?? ""; StationDescription.Text = _lastSelectedStation?.StationDescription ?? ""; } private void OnStationPressed(StationListItem.ViewState stationItemViewState) { _lastSelectedStation = stationItemViewState; UpdateUi(_lobbyJobs); } private List BuildJobViewStateList(StationJobInformation jobInformation) { var viewStateList = new List(); foreach (var (jobPrototype, jobCount) in jobInformation.JobsAvailable) { if (_preferencesManager.Preferences?.SelectedCharacter is not HumanoidCharacterProfile profile) { continue; } var prototype = _prototypeManager.Index(jobPrototype); var jobName = prototype.LocalizedName + jobCount.WrapJobCountInParentheses(); Texture? texture = null; if (_prototypeManager.TryIndex(prototype.Icon, out var jobIcon)) { texture = _spriteSystem.Frame0(jobIcon.Icon); } var buttonTooltip = ""; if (!_jobReqs.IsAllowed(prototype, profile, out var denyReason)) { buttonTooltip = denyReason.ToString(); } var isButtonDisabled = jobCount == 0 || !_jobReqs.IsAllowed(prototype, profile, out _); var viewState = new JobListItem.ViewState( jobId: jobPrototype, jobName: jobName, toolTip: buttonTooltip, disabled: isButtonDisabled, jobIcon: texture ); viewStateList.Add(viewState); } return viewStateList; } /** * Convert some raw dictionary data to a view state model that is more readable. * * @param obj Dictionary of station entities to job prototypes. * @param stationNames Dictionary of station entities to station names. * @return List of view states for each station. */ private List BuildStationViewStateList( IReadOnlyDictionary obj) { var stationList = obj.Where(kvp => kvp.Value.IsLateJoinStation).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); var viewStateList = new List(); foreach (var (stationEntity, stationJobInformation) in stationList) { var viewState = new StationListItem.ViewState( stationEntity, stationJobInformation.GetStationNameWithJobCount(), stationJobInformation.StationDisplayInfo?.StationSubtext != null ? _loc.GetString(stationJobInformation.StationDisplayInfo.StationSubtext) : "", stationJobInformation.StationDisplayInfo?.StationDescription != null ? _loc.GetString(stationJobInformation.StationDisplayInfo.StationDescription) : "", _lastSelectedStation?.StationEntity == stationEntity, stationJobInformation.StationDisplayInfo?.StationIcon?.CanonPath ); // Always select the first station in the list if none is selected yet. // This is because otherwise the right side of the screen would then be a blank space. if (_lastSelectedStation == null) { _lastSelectedStation = viewState; viewState.Selected = true; } viewStateList.Add(viewState); } // Sort 0 to the end of the list in the order it is in the dictionary. // Sort 1 first, 2 second, etc. return viewStateList .OrderBy(viewState => (obj[viewState.StationEntity].StationDisplayInfo?.LobbySortOrder ?? 0) == 0 ? int.MaxValue : obj[viewState.StationEntity].StationDisplayInfo!.LobbySortOrder) .ToList(); } }