using System.Linq; using Content.Client.Lathe; using Content.Client.Research; using Content.Client.Research.UI; using Content.Shared._NF.Research; using Content.Shared.Research.Prototypes; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.UserInterface; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; using Robust.Shared.Utility; // Added for SpriteSpecifier namespace Content.Client._NF.Research.UI; [GenerateTypedNameReferences] public sealed partial class FancyTechnologyInfoPanel : Control { [Dependency] private readonly IEntityManager _ent = default!; [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly ILogManager _logManager = default!; private ISawmill _sawmill = default!; public TechnologyPrototype Prototype; public Action? BuyAction; public FancyTechnologyInfoPanel(TechnologyPrototype proto, bool hasAccess, ResearchAvailability availability, SpriteSystem sprite) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _sawmill = _logManager.GetSawmill("research"); var lathe = _ent.System(); var research = _ent.System(); Prototype = proto; TechnologyNameLabel.Text = Loc.GetString(proto.Name); DisciplineTexture.Texture = sprite.Frame0(_proto.Index(proto.Discipline).Icon); // Handle technology icon - use EntityIcon if available, otherwise fall back to Icon if (proto.EntityIcon.HasValue) { TechnologyTexture.SetPrototype(proto.EntityIcon); } else if (proto.Icon != null) { // For backward compatibility, we need to handle SpriteSpecifier icons //_sawmill.Warning($"Technology {proto.ID} uses legacy Icon field instead of EntityIcon. Consider migrating to EntityIcon for better performance."); // For now, we'll need to handle this differently since EntityPrototypeView doesn't directly support SpriteSpecifier // We can try to extract the entity from SpriteSpecifier if it's an EntityPrototype type if (proto.Icon is SpriteSpecifier.EntityPrototype entityProtoSpec) { TechnologyTexture.SetPrototype(entityProtoSpec.EntityPrototypeId); } else { // For other SpriteSpecifier types, we'll need a different approach // Since this is a complex conversion, we'll log this case for now //_sawmill.Error($"Technology {proto.ID} uses unsupported Icon type. Please use EntityIcon field instead."); } } else { //_sawmill.Warning($"Technology {proto.ID} has no icon specified. Consider adding an EntityIcon field."); } InitializePrerequisites(proto, research, sprite); InitializeRecipeUnlocks(proto, lathe, sprite); ResearchButton.ToolTip = !hasAccess ? Loc.GetString("research-console-no-access-popup") : null; ResearchButton.Text = availability == ResearchAvailability.Researched ? Loc.GetString("research-console-menu-server-researched-button") : ResearchButton.Text; Color? color = ResearchColorScheme.GetInfoPanelColor(availability); TechnologyCostLabel.SetMessage( Loc.GetString("research-console-tech-cost-label", ("cost", proto.Cost)), defaultColor: color ); ResearchButton.Disabled = !hasAccess || availability != ResearchAvailability.Available; // Replace the event handling method to use a simpler approach ResearchButton.OnPressed += args => { _sawmill.Debug($"Research button pressed for {proto.ID}"); if (BuyAction != null) { _sawmill.Debug($"Triggering BuyAction for {proto.ID}"); BuyAction.Invoke(proto); } else { _sawmill.Error($"BuyAction is null for {proto.ID}"); } }; _sawmill.Debug($"Created tech panel: {proto.ID}, availability: {availability}, button disabled: {ResearchButton.Disabled}"); } private void InitializePrerequisites(TechnologyPrototype proto, ResearchSystem research, SpriteSystem sprite) { // required techs always visible, label in required techs foreach (var child in RequiredTechContainer.Children.ToList()) { if (child != NoPrereqLabel) RequiredTechContainer.RemoveChild(child); } NoPrereqLabel.Visible = proto.TechnologyPrerequisites.Count == 0; foreach (var techId in proto.TechnologyPrerequisites) { var tech = _proto.Index(techId); var description = research.GetTechnologyDescription(tech, true, false, true); RequiredTechContainer.AddChild(new MiniTechnologyCardControl(tech, _proto, sprite, description)); } } private void InitializeRecipeUnlocks(TechnologyPrototype proto, LatheSystem lathe, SpriteSystem sprite) { UnlocksContainer.RemoveAllChildren(); foreach (var recipeId in proto.RecipeUnlocks) { var recipe = _proto.Index(recipeId); UnlocksContainer.AddChild(new MiniRecipeCardControl(proto, recipe, _proto, sprite, lathe)); } } protected override void ExitedTree() { base.ExitedTree(); // No need to explicitly remove handlers as the control is being destroyed } }