1
0

GuideReagentEmbed.xaml.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. using System.Diagnostics.CodeAnalysis;
  2. using System.Linq;
  3. using Content.Client.Chemistry.EntitySystems;
  4. using Content.Client.Guidebook.Richtext;
  5. using Content.Client.Message;
  6. using Content.Client.UserInterface.ControlExtensions;
  7. using Content.Shared.Body.Prototypes;
  8. using Content.Shared.Chemistry.Reaction;
  9. using Content.Shared.Chemistry.Reagent;
  10. using JetBrains.Annotations;
  11. using Robust.Client.AutoGenerated;
  12. using Robust.Client.Graphics;
  13. using Robust.Client.UserInterface;
  14. using Robust.Client.UserInterface.Controls;
  15. using Robust.Client.UserInterface.XAML;
  16. using Robust.Shared.Prototypes;
  17. using Robust.Shared.Utility;
  18. namespace Content.Client.Guidebook.Controls;
  19. /// <summary>
  20. /// Control for embedding a reagent into a guidebook.
  21. /// </summary>
  22. [UsedImplicitly, GenerateTypedNameReferences]
  23. public sealed partial class GuideReagentEmbed : BoxContainer, IDocumentTag, ISearchableControl
  24. {
  25. [Dependency] private readonly IEntitySystemManager _systemManager = default!;
  26. [Dependency] private readonly IPrototypeManager _prototype = default!;
  27. private readonly ChemistryGuideDataSystem _chemistryGuideData;
  28. public GuideReagentEmbed()
  29. {
  30. RobustXamlLoader.Load(this);
  31. IoCManager.InjectDependencies(this);
  32. _chemistryGuideData = _systemManager.GetEntitySystem<ChemistryGuideDataSystem>();
  33. MouseFilter = MouseFilterMode.Stop;
  34. }
  35. public GuideReagentEmbed(string reagent) : this()
  36. {
  37. GenerateControl(_prototype.Index<ReagentPrototype>(reagent));
  38. }
  39. public GuideReagentEmbed(ReagentPrototype reagent) : this()
  40. {
  41. GenerateControl(reagent);
  42. }
  43. public bool CheckMatchesSearch(string query)
  44. {
  45. return this.ChildrenContainText(query);
  46. }
  47. public void SetHiddenState(bool state, string query)
  48. {
  49. Visible = CheckMatchesSearch(query) ? state : !state;
  50. }
  51. public bool TryParseTag(Dictionary<string, string> args, [NotNullWhen(true)] out Control? control)
  52. {
  53. control = null;
  54. if (!args.TryGetValue("Reagent", out var id))
  55. {
  56. Logger.Error("Reagent embed tag is missing reagent prototype argument");
  57. return false;
  58. }
  59. if (!_prototype.TryIndex<ReagentPrototype>(id, out var reagent))
  60. {
  61. Logger.Error($"Specified reagent prototype \"{id}\" is not a valid reagent prototype");
  62. return false;
  63. }
  64. GenerateControl(reagent);
  65. control = this;
  66. return true;
  67. }
  68. private void GenerateControl(ReagentPrototype reagent)
  69. {
  70. NameBackground.PanelOverride = new StyleBoxFlat
  71. {
  72. BackgroundColor = reagent.SubstanceColor
  73. };
  74. var r = reagent.SubstanceColor.R;
  75. var g = reagent.SubstanceColor.G;
  76. var b = reagent.SubstanceColor.B;
  77. var textColor = 0.2126f * r + 0.7152f * g + 0.0722f * b > 0.5
  78. ? Color.Black
  79. : Color.White;
  80. ReagentName.SetMarkup(Loc.GetString("guidebook-reagent-name",
  81. ("color", textColor), ("name", reagent.LocalizedName)));
  82. #region Recipe
  83. var reactions = _prototype.EnumeratePrototypes<ReactionPrototype>()
  84. .Where(p => !p.Source && p.Products.ContainsKey(reagent.ID))
  85. .OrderBy(p => p.Priority)
  86. .ThenBy(p => p.Products.Count)
  87. .ToList();
  88. if (reactions.Any())
  89. {
  90. foreach (var reactionPrototype in reactions)
  91. {
  92. RecipesDescriptionContainer.AddChild(new GuideReagentReaction(reactionPrototype, _prototype, _systemManager));
  93. }
  94. }
  95. else
  96. {
  97. RecipesContainer.Visible = false;
  98. }
  99. #endregion
  100. #region Effects
  101. if (_chemistryGuideData.ReagentGuideRegistry.TryGetValue(reagent.ID, out var guideEntryRegistry) &&
  102. guideEntryRegistry.GuideEntries != null &&
  103. guideEntryRegistry.GuideEntries.Values.Any(pair => pair.EffectDescriptions.Any()))
  104. {
  105. EffectsDescriptionContainer.Children.Clear();
  106. foreach (var (group, effect) in guideEntryRegistry.GuideEntries)
  107. {
  108. if (!effect.EffectDescriptions.Any())
  109. continue;
  110. var groupLabel = new RichTextLabel();
  111. groupLabel.SetMarkup(Loc.GetString("guidebook-reagent-effects-metabolism-group-rate",
  112. ("group", _prototype.Index<MetabolismGroupPrototype>(group).LocalizedName), ("rate", effect.MetabolismRate)));
  113. var descriptionLabel = new RichTextLabel
  114. {
  115. Margin = new Thickness(25, 0, 10, 0)
  116. };
  117. var descMsg = new FormattedMessage();
  118. var descriptionsCount = effect.EffectDescriptions.Length;
  119. var i = 0;
  120. foreach (var effectString in effect.EffectDescriptions)
  121. {
  122. descMsg.AddMarkupOrThrow(effectString);
  123. i++;
  124. if (i < descriptionsCount)
  125. descMsg.PushNewline();
  126. }
  127. descriptionLabel.SetMessage(descMsg);
  128. EffectsDescriptionContainer.AddChild(groupLabel);
  129. EffectsDescriptionContainer.AddChild(descriptionLabel);
  130. }
  131. }
  132. else
  133. {
  134. EffectsContainer.Visible = false;
  135. }
  136. #endregion
  137. #region PlantMetabolisms
  138. if (_chemistryGuideData.ReagentGuideRegistry.TryGetValue(reagent.ID, out var guideEntryRegistryPlant) &&
  139. guideEntryRegistryPlant.PlantMetabolisms != null &&
  140. guideEntryRegistryPlant.PlantMetabolisms.Count > 0)
  141. {
  142. PlantMetabolismsDescriptionContainer.Children.Clear();
  143. var metabolismLabel = new RichTextLabel();
  144. metabolismLabel.SetMarkup(Loc.GetString("guidebook-reagent-plant-metabolisms-rate"));
  145. var descriptionLabel = new RichTextLabel
  146. {
  147. Margin = new Thickness(25, 0, 10, 0)
  148. };
  149. var descMsg = new FormattedMessage();
  150. var descriptionsCount = guideEntryRegistryPlant.PlantMetabolisms.Count;
  151. var i = 0;
  152. foreach (var effectString in guideEntryRegistryPlant.PlantMetabolisms)
  153. {
  154. descMsg.AddMarkupOrThrow(effectString);
  155. i++;
  156. if (i < descriptionsCount)
  157. descMsg.PushNewline();
  158. }
  159. descriptionLabel.SetMessage(descMsg);
  160. PlantMetabolismsDescriptionContainer.AddChild(metabolismLabel);
  161. PlantMetabolismsDescriptionContainer.AddChild(descriptionLabel);
  162. }
  163. else
  164. {
  165. PlantMetabolismsContainer.Visible = false;
  166. }
  167. #endregion
  168. GenerateSources(reagent);
  169. FormattedMessage description = new();
  170. description.AddText(reagent.LocalizedDescription);
  171. description.PushNewline();
  172. description.AddMarkupOrThrow(Loc.GetString("guidebook-reagent-physical-description",
  173. ("description", reagent.LocalizedPhysicalDescription)));
  174. ReagentDescription.SetMessage(description);
  175. }
  176. private void GenerateSources(ReagentPrototype reagent)
  177. {
  178. var sources = _chemistryGuideData.GetReagentSources(reagent.ID);
  179. if (sources.Count == 0)
  180. {
  181. SourcesContainer.Visible = false;
  182. return;
  183. }
  184. SourcesContainer.Visible = true;
  185. var orderedSources = sources
  186. .OrderBy(o => o.OutputCount)
  187. .ThenBy(o => o.IdentifierString);
  188. foreach (var source in orderedSources)
  189. {
  190. if (source is ReagentEntitySourceData entitySourceData)
  191. {
  192. SourcesDescriptionContainer.AddChild(new GuideReagentReaction(
  193. entitySourceData.SourceEntProto,
  194. entitySourceData.Solution,
  195. entitySourceData.MixingType,
  196. _prototype,
  197. _systemManager));
  198. }
  199. else if (source is ReagentReactionSourceData reactionSourceData)
  200. {
  201. SourcesDescriptionContainer.AddChild(new GuideReagentReaction(
  202. reactionSourceData.ReactionPrototype,
  203. _prototype,
  204. _systemManager));
  205. }
  206. else if (source is ReagentGasSourceData gasSourceData)
  207. {
  208. SourcesDescriptionContainer.AddChild(new GuideReagentReaction(
  209. gasSourceData.GasPrototype,
  210. gasSourceData.MixingType,
  211. _prototype,
  212. _systemManager));
  213. }
  214. }
  215. }
  216. }