1
0

LatheMenu.xaml.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. using System.Linq;
  2. using System.Text;
  3. using Content.Client.Materials;
  4. using Content.Shared.Lathe;
  5. using Content.Shared.Lathe.Prototypes;
  6. using Content.Shared.Research.Prototypes;
  7. using Robust.Client.AutoGenerated;
  8. using Robust.Client.GameObjects;
  9. using Robust.Client.UserInterface;
  10. using Robust.Client.UserInterface.Controls;
  11. using Robust.Client.UserInterface.CustomControls;
  12. using Robust.Client.UserInterface.XAML;
  13. using Robust.Shared.Prototypes;
  14. namespace Content.Client.Lathe.UI;
  15. [GenerateTypedNameReferences]
  16. public sealed partial class LatheMenu : DefaultWindow
  17. {
  18. [Dependency] private readonly IEntityManager _entityManager = default!;
  19. [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
  20. private readonly SpriteSystem _spriteSystem;
  21. private readonly LatheSystem _lathe;
  22. private readonly MaterialStorageSystem _materialStorage;
  23. public event Action<BaseButton.ButtonEventArgs>? OnServerListButtonPressed;
  24. public event Action<string, int>? RecipeQueueAction;
  25. public List<ProtoId<LatheRecipePrototype>> Recipes = new();
  26. public List<ProtoId<LatheCategoryPrototype>>? Categories;
  27. public ProtoId<LatheCategoryPrototype>? CurrentCategory;
  28. public EntityUid Entity;
  29. public LatheMenu()
  30. {
  31. RobustXamlLoader.Load(this);
  32. IoCManager.InjectDependencies(this);
  33. _spriteSystem = _entityManager.System<SpriteSystem>();
  34. _lathe = _entityManager.System<LatheSystem>();
  35. _materialStorage = _entityManager.System<MaterialStorageSystem>();
  36. SearchBar.OnTextChanged += _ =>
  37. {
  38. PopulateRecipes();
  39. };
  40. AmountLineEdit.OnTextChanged += _ =>
  41. {
  42. PopulateRecipes();
  43. };
  44. FilterOption.OnItemSelected += OnItemSelected;
  45. ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a);
  46. }
  47. public void SetEntity(EntityUid uid)
  48. {
  49. Entity = uid;
  50. if (_entityManager.TryGetComponent<LatheComponent>(Entity, out var latheComponent))
  51. {
  52. if (!latheComponent.DynamicPacks.Any())
  53. {
  54. ServerListButton.Visible = false;
  55. }
  56. }
  57. MaterialsList.SetOwner(Entity);
  58. }
  59. protected override void Opened()
  60. {
  61. base.Opened();
  62. if (_entityManager.TryGetComponent<LatheComponent>(Entity, out var latheComp))
  63. {
  64. AmountLineEdit.SetText(latheComp.DefaultProductionAmount.ToString());
  65. }
  66. }
  67. /// <summary>
  68. /// Populates the list of all the recipes
  69. /// </summary>
  70. public void PopulateRecipes()
  71. {
  72. var recipesToShow = new List<LatheRecipePrototype>();
  73. foreach (var recipe in Recipes)
  74. {
  75. if (!_prototypeManager.TryIndex(recipe, out var proto))
  76. continue;
  77. // Category filtering
  78. if (CurrentCategory != null)
  79. {
  80. if (proto.Categories.Count <= 0)
  81. continue;
  82. var validRecipe = proto.Categories.Any(category => category == CurrentCategory);
  83. if (!validRecipe)
  84. continue;
  85. }
  86. if (SearchBar.Text.Trim().Length != 0)
  87. {
  88. if (_lathe.GetRecipeName(recipe).ToLowerInvariant().Contains(SearchBar.Text.Trim().ToLowerInvariant()))
  89. recipesToShow.Add(proto);
  90. }
  91. else
  92. {
  93. recipesToShow.Add(proto);
  94. }
  95. }
  96. if (!int.TryParse(AmountLineEdit.Text, out var quantity) || quantity <= 0)
  97. quantity = 1;
  98. RecipeCount.Text = Loc.GetString("lathe-menu-recipe-count", ("count", recipesToShow.Count));
  99. var sortedRecipesToShow = recipesToShow.OrderBy(_lathe.GetRecipeName);
  100. RecipeList.Children.Clear();
  101. _entityManager.TryGetComponent(Entity, out LatheComponent? lathe);
  102. foreach (var prototype in sortedRecipesToShow)
  103. {
  104. var canProduce = _lathe.CanProduce(Entity, prototype, quantity, component: lathe);
  105. var control = new RecipeControl(_lathe, prototype, () => GenerateTooltipText(prototype), canProduce, GetRecipeDisplayControl(prototype));
  106. control.OnButtonPressed += s =>
  107. {
  108. if (!int.TryParse(AmountLineEdit.Text, out var amount) || amount <= 0)
  109. amount = 1;
  110. RecipeQueueAction?.Invoke(s, amount);
  111. };
  112. RecipeList.AddChild(control);
  113. }
  114. }
  115. private string GenerateTooltipText(LatheRecipePrototype prototype)
  116. {
  117. StringBuilder sb = new();
  118. var multiplier = _entityManager.GetComponent<LatheComponent>(Entity).MaterialUseMultiplier;
  119. foreach (var (id, amount) in prototype.Materials)
  120. {
  121. if (!_prototypeManager.TryIndex(id, out var proto))
  122. continue;
  123. var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, multiplier);
  124. var sheetVolume = _materialStorage.GetSheetVolume(proto);
  125. var unit = Loc.GetString(proto.Unit);
  126. var sheets = adjustedAmount / (float) sheetVolume;
  127. var availableAmount = _materialStorage.GetMaterialAmount(Entity, id);
  128. var missingAmount = Math.Max(0, adjustedAmount - availableAmount);
  129. var missingSheets = missingAmount / (float) sheetVolume;
  130. var name = Loc.GetString(proto.Name);
  131. string tooltipText;
  132. if (missingSheets > 0)
  133. {
  134. tooltipText = Loc.GetString("lathe-menu-material-amount-missing", ("amount", sheets), ("missingAmount", missingSheets), ("unit", unit), ("material", name));
  135. }
  136. else
  137. {
  138. var amountText = Loc.GetString("lathe-menu-material-amount", ("amount", sheets), ("unit", unit));
  139. tooltipText = Loc.GetString("lathe-menu-tooltip-display", ("material", name), ("amount", amountText));
  140. }
  141. sb.AppendLine(tooltipText);
  142. }
  143. var desc = _lathe.GetRecipeDescription(prototype);
  144. if (!string.IsNullOrWhiteSpace(desc))
  145. sb.AppendLine(Loc.GetString("lathe-menu-description-display", ("description", desc)));
  146. // Remove last newline
  147. if (sb.Length > 0)
  148. sb.Remove(sb.Length - 1, 1);
  149. return sb.ToString();
  150. }
  151. public void UpdateCategories()
  152. {
  153. // Get categories from recipes
  154. var currentCategories = new List<ProtoId<LatheCategoryPrototype>>();
  155. foreach (var recipeId in Recipes)
  156. {
  157. var recipe = _prototypeManager.Index(recipeId);
  158. if (recipe.Categories.Count <= 0)
  159. continue;
  160. foreach (var category in recipe.Categories)
  161. {
  162. if (currentCategories.Contains(category))
  163. continue;
  164. currentCategories.Add(category);
  165. }
  166. }
  167. if (Categories != null && (Categories.Count == currentCategories.Count || !Categories.All(currentCategories.Contains)))
  168. return;
  169. Categories = currentCategories;
  170. var sortedCategories = currentCategories
  171. .Select(p => _prototypeManager.Index(p))
  172. .OrderBy(p => Loc.GetString(p.Name))
  173. .ToList();
  174. FilterOption.Clear();
  175. FilterOption.AddItem(Loc.GetString("lathe-menu-category-all"), -1);
  176. foreach (var category in sortedCategories)
  177. {
  178. FilterOption.AddItem(Loc.GetString(category.Name), Categories.IndexOf(category.ID));
  179. }
  180. FilterOption.SelectId(-1);
  181. }
  182. /// <summary>
  183. /// Populates the build queue list with all queued items
  184. /// </summary>
  185. /// <param name="queue"></param>
  186. public void PopulateQueueList(List<LatheRecipePrototype> queue)
  187. {
  188. QueueList.DisposeAllChildren();
  189. var idx = 1;
  190. foreach (var recipe in queue)
  191. {
  192. var queuedRecipeBox = new BoxContainer();
  193. queuedRecipeBox.Orientation = BoxContainer.LayoutOrientation.Horizontal;
  194. queuedRecipeBox.AddChild(GetRecipeDisplayControl(recipe));
  195. var queuedRecipeLabel = new Label();
  196. queuedRecipeLabel.Text = $"{idx}. {_lathe.GetRecipeName(recipe)}";
  197. queuedRecipeBox.AddChild(queuedRecipeLabel);
  198. QueueList.AddChild(queuedRecipeBox);
  199. idx++;
  200. }
  201. }
  202. public void SetQueueInfo(LatheRecipePrototype? recipe)
  203. {
  204. FabricatingContainer.Visible = recipe != null;
  205. if (recipe == null)
  206. return;
  207. FabricatingDisplayContainer.Children.Clear();
  208. FabricatingDisplayContainer.AddChild(GetRecipeDisplayControl(recipe));
  209. NameLabel.Text = _lathe.GetRecipeName(recipe);
  210. }
  211. public Control GetRecipeDisplayControl(LatheRecipePrototype recipe)
  212. {
  213. if (recipe.Icon != null)
  214. {
  215. var textRect = new TextureRect();
  216. textRect.Texture = _spriteSystem.Frame0(recipe.Icon);
  217. return textRect;
  218. }
  219. if (recipe.Result is { } result)
  220. {
  221. var entProtoView = new EntityPrototypeView();
  222. entProtoView.SetPrototype(result);
  223. return entProtoView;
  224. }
  225. return new Control();
  226. }
  227. private void OnItemSelected(OptionButton.ItemSelectedEventArgs obj)
  228. {
  229. FilterOption.SelectId(obj.Id);
  230. if (obj.Id == -1)
  231. {
  232. CurrentCategory = null;
  233. }
  234. else
  235. {
  236. CurrentCategory = Categories?[obj.Id];
  237. }
  238. PopulateRecipes();
  239. }
  240. }