EntityMenuPresenterGrouping.cs 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. using Content.Shared.IdentityManagement;
  2. using Robust.Client.GameObjects;
  3. using System.Linq;
  4. namespace Content.Client.ContextMenu.UI
  5. {
  6. public sealed partial class EntityMenuUIController
  7. {
  8. public const int GroupingTypesCount = 2;
  9. private int GroupingContextMenuType { get; set; }
  10. public void OnGroupingChanged(int obj)
  11. {
  12. _context.Close();
  13. GroupingContextMenuType = obj;
  14. }
  15. private List<List<EntityUid>> GroupEntities(IEnumerable<EntityUid> entities, int depth = 0)
  16. {
  17. if (GroupingContextMenuType == 0)
  18. {
  19. var newEntities = entities.GroupBy(e => Identity.Name(e, _entityManager)).ToList();
  20. return newEntities.Select(grp => grp.ToList()).ToList();
  21. }
  22. else
  23. {
  24. var newEntities = entities.GroupBy(e => e, new PrototypeAndStatesContextMenuComparer(depth, _entityManager)).ToList();
  25. return newEntities.Select(grp => grp.ToList()).ToList();
  26. }
  27. }
  28. private sealed class PrototypeAndStatesContextMenuComparer : IEqualityComparer<EntityUid>
  29. {
  30. private static readonly List<Func<EntityUid, EntityUid, IEntityManager, bool>> EqualsList = new()
  31. {
  32. (a, b, entMan) => entMan.GetComponent<MetaDataComponent>(a).EntityPrototype!.ID == entMan.GetComponent<MetaDataComponent>(b).EntityPrototype!.ID,
  33. (a, b, entMan) =>
  34. {
  35. entMan.TryGetComponent(a, out SpriteComponent? spriteA);
  36. entMan.TryGetComponent(b, out SpriteComponent? spriteB);
  37. if (spriteA == null || spriteB == null)
  38. return spriteA == spriteB;
  39. var xStates = spriteA.AllLayers.Where(e => e.Visible).Select(s => s.RsiState.Name);
  40. var yStates = spriteB.AllLayers.Where(e => e.Visible).Select(s => s.RsiState.Name);
  41. return xStates.OrderBy(t => t).SequenceEqual(yStates.OrderBy(t => t));
  42. },
  43. };
  44. private static readonly List<Func<EntityUid, IEntityManager, int>> GetHashCodeList = new()
  45. {
  46. (e, entMan) => EqualityComparer<string>.Default.GetHashCode(entMan.GetComponent<MetaDataComponent>(e).EntityPrototype!.ID),
  47. (e, entMan) =>
  48. {
  49. var hash = 0;
  50. foreach (var element in entMan.GetComponent<SpriteComponent>(e).AllLayers.Where(obj => obj.Visible).Select(s => s.RsiState.Name))
  51. {
  52. hash ^= EqualityComparer<string>.Default.GetHashCode(element!);
  53. }
  54. return hash;
  55. },
  56. };
  57. private static int Count => EqualsList.Count - 1;
  58. private readonly int _depth;
  59. private readonly IEntityManager _entMan;
  60. public PrototypeAndStatesContextMenuComparer(int step = 0, IEntityManager? entMan = null)
  61. {
  62. IoCManager.Resolve(ref entMan);
  63. _depth = step > Count ? Count : step;
  64. _entMan = entMan;
  65. }
  66. public bool Equals(EntityUid x, EntityUid y)
  67. {
  68. if (x == default)
  69. {
  70. return y == default;
  71. }
  72. return y != default && EqualsList[_depth](x, y, _entMan);
  73. }
  74. public int GetHashCode(EntityUid e)
  75. {
  76. return GetHashCodeList[_depth](e, _entMan);
  77. }
  78. }
  79. }
  80. }