1
0

StatValuesCommand.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using System.Globalization;
  2. using System.Linq;
  3. using Content.Server.Administration;
  4. using Content.Server.Cargo.Systems;
  5. using Content.Server.EUI;
  6. using Content.Server.Item;
  7. using Content.Server.Power.Components;
  8. using Content.Shared.Administration;
  9. using Content.Shared.Item;
  10. using Content.Shared.Research.Prototypes;
  11. using Content.Shared.UserInterface;
  12. using Content.Shared.Weapons.Melee;
  13. using Robust.Shared.Console;
  14. using Robust.Shared.Prototypes;
  15. namespace Content.Server.UserInterface;
  16. [AdminCommand(AdminFlags.Debug)]
  17. public sealed class StatValuesCommand : IConsoleCommand
  18. {
  19. [Dependency] private readonly EuiManager _eui = default!;
  20. [Dependency] private readonly IComponentFactory _factory = default!;
  21. [Dependency] private readonly IEntityManager _entManager = default!;
  22. [Dependency] private readonly IPrototypeManager _proto = default!;
  23. public string Command => "showvalues";
  24. public string Description => Loc.GetString("stat-values-desc");
  25. public string Help => $"{Command} <cargosell / lathesell / melee / itemsize>";
  26. public void Execute(IConsoleShell shell, string argStr, string[] args)
  27. {
  28. if (shell.Player is not { } pSession)
  29. {
  30. shell.WriteError(Loc.GetString("stat-values-server"));
  31. return;
  32. }
  33. if (args.Length != 1)
  34. {
  35. shell.WriteError(Loc.GetString("stat-values-args"));
  36. return;
  37. }
  38. StatValuesEuiMessage message;
  39. switch (args[0])
  40. {
  41. case "cargosell":
  42. message = GetCargo();
  43. break;
  44. case "lathesell":
  45. message = GetLatheMessage();
  46. break;
  47. case "melee":
  48. message = GetMelee();
  49. break;
  50. case "itemsize":
  51. message = GetItem();
  52. break;
  53. case "drawrate":
  54. message = GetDrawRateMessage();
  55. break;
  56. default:
  57. shell.WriteError(Loc.GetString("stat-values-invalid", ("arg", args[0])));
  58. return;
  59. }
  60. var eui = new StatValuesEui();
  61. _eui.OpenEui(eui, pSession);
  62. eui.SendMessage(message);
  63. }
  64. public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
  65. {
  66. if (args.Length == 1)
  67. {
  68. return CompletionResult.FromOptions(new[] { "cargosell", "lathesell", "melee", "itemsize", "drawrate" });
  69. }
  70. return CompletionResult.Empty;
  71. }
  72. private StatValuesEuiMessage GetCargo()
  73. {
  74. // Okay so there's no easy way to do this with how pricing works
  75. // So we'll just get the first value for each prototype ID which is probably good enough for the majority.
  76. var values = new List<string[]>();
  77. var priceSystem = _entManager.System<PricingSystem>();
  78. var metaQuery = _entManager.GetEntityQuery<MetaDataComponent>();
  79. var prices = new HashSet<string>(256);
  80. var ents = _entManager.GetEntities().ToArray();
  81. foreach (var entity in ents)
  82. {
  83. if (!metaQuery.TryGetComponent(entity, out var meta))
  84. continue;
  85. var id = meta.EntityPrototype?.ID;
  86. // We'll add it even if we don't have it so we don't have to raise the event again because this is probably faster.
  87. if (id == null || !prices.Add(id))
  88. continue;
  89. var price = priceSystem.GetPrice(entity);
  90. if (price == 0)
  91. continue;
  92. values.Add(new[]
  93. {
  94. id,
  95. $"{price:0}",
  96. });
  97. }
  98. var state = new StatValuesEuiMessage()
  99. {
  100. Title = Loc.GetString("stat-cargo-values"),
  101. Headers = new List<string>()
  102. {
  103. Loc.GetString("stat-cargo-id"),
  104. Loc.GetString("stat-cargo-price"),
  105. },
  106. Values = values,
  107. };
  108. return state;
  109. }
  110. private StatValuesEuiMessage GetItem()
  111. {
  112. var values = new List<string[]>();
  113. var itemSystem = _entManager.System<ItemSystem>();
  114. var metaQuery = _entManager.GetEntityQuery<MetaDataComponent>();
  115. var itemQuery = _entManager.GetEntityQuery<ItemComponent>();
  116. var items = new HashSet<string>(1024);
  117. var ents = _entManager.GetEntities().ToArray();
  118. foreach (var entity in ents)
  119. {
  120. if (!metaQuery.TryGetComponent(entity, out var meta))
  121. continue;
  122. var id = meta.EntityPrototype?.ID;
  123. // We'll add it even if we don't have it so we don't have to raise the event again because this is probably faster.
  124. if (id == null || !items.Add(id))
  125. continue;
  126. if (!itemQuery.TryGetComponent(entity, out var itemComp))
  127. continue;
  128. values.Add(new[]
  129. {
  130. id,
  131. $"{itemSystem.GetItemSizeLocale(itemComp.Size)}",
  132. });
  133. }
  134. var state = new StatValuesEuiMessage
  135. {
  136. Title = Loc.GetString("stat-item-values"),
  137. Headers = new List<string>
  138. {
  139. Loc.GetString("stat-item-id"),
  140. Loc.GetString("stat-item-price"),
  141. },
  142. Values = values,
  143. };
  144. return state;
  145. }
  146. private StatValuesEuiMessage GetMelee()
  147. {
  148. var values = new List<string[]>();
  149. var meleeName = _factory.GetComponentName(typeof(MeleeWeaponComponent));
  150. foreach (var proto in _proto.EnumeratePrototypes<EntityPrototype>())
  151. {
  152. if (proto.Abstract ||
  153. !proto.Components.TryGetValue(meleeName,
  154. out var meleeComp))
  155. {
  156. continue;
  157. }
  158. var comp = (MeleeWeaponComponent) meleeComp.Component;
  159. // TODO: Wielded damage
  160. // TODO: Esword damage
  161. values.Add(new[]
  162. {
  163. proto.ID,
  164. (comp.Damage.GetTotal() * comp.AttackRate).ToString(),
  165. comp.AttackRate.ToString(CultureInfo.CurrentCulture),
  166. comp.Damage.GetTotal().ToString(),
  167. comp.Range.ToString(CultureInfo.CurrentCulture),
  168. });
  169. }
  170. var state = new StatValuesEuiMessage()
  171. {
  172. Title = "Cargo sell prices",
  173. Headers = new List<string>()
  174. {
  175. "ID",
  176. "Price",
  177. },
  178. Values = values,
  179. };
  180. return state;
  181. }
  182. private StatValuesEuiMessage GetLatheMessage()
  183. {
  184. var values = new List<string[]>();
  185. var priceSystem = _entManager.System<PricingSystem>();
  186. foreach (var proto in _proto.EnumeratePrototypes<LatheRecipePrototype>())
  187. {
  188. var cost = 0.0;
  189. foreach (var (material, count) in proto.Materials)
  190. {
  191. var materialPrice = _proto.Index(material).Price;
  192. cost += materialPrice * count;
  193. }
  194. var sell = priceSystem.GetLatheRecipePrice(proto);
  195. values.Add(new[]
  196. {
  197. proto.ID,
  198. $"{cost:0}",
  199. $"{sell:0}",
  200. });
  201. }
  202. var state = new StatValuesEuiMessage()
  203. {
  204. Title = Loc.GetString("stat-lathe-values"),
  205. Headers = new List<string>()
  206. {
  207. Loc.GetString("stat-lathe-id"),
  208. Loc.GetString("stat-lathe-cost"),
  209. Loc.GetString("stat-lathe-sell"),
  210. },
  211. Values = values,
  212. };
  213. return state;
  214. }
  215. private StatValuesEuiMessage GetDrawRateMessage()
  216. {
  217. var values = new List<string[]>();
  218. var powerName = _factory.GetComponentName(typeof(ApcPowerReceiverComponent));
  219. foreach (var proto in _proto.EnumeratePrototypes<EntityPrototype>())
  220. {
  221. if (proto.Abstract ||
  222. !proto.Components.TryGetValue(powerName,
  223. out var powerConsumer))
  224. {
  225. continue;
  226. }
  227. var comp = (ApcPowerReceiverComponent) powerConsumer.Component;
  228. if (comp.Load == 0)
  229. continue;
  230. values.Add(new[]
  231. {
  232. proto.ID,
  233. comp.Load.ToString(CultureInfo.InvariantCulture),
  234. });
  235. }
  236. var state = new StatValuesEuiMessage
  237. {
  238. Title = Loc.GetString("stat-drawrate-values"),
  239. Headers = new List<string>
  240. {
  241. Loc.GetString("stat-drawrate-id"),
  242. Loc.GetString("stat-drawrate-rate"),
  243. },
  244. Values = values,
  245. };
  246. return state;
  247. }
  248. }