1
0

AlertOrderPrototype.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System.Linq;
  2. using Robust.Shared.Prototypes;
  3. using Robust.Shared.Utility;
  4. namespace Content.Shared.Alert
  5. {
  6. /// <summary>
  7. /// Defines the order of alerts so they show up in a consistent order.
  8. /// </summary>
  9. [Prototype]
  10. [DataDefinition]
  11. public sealed partial class AlertOrderPrototype : IPrototype, IComparer<AlertPrototype>
  12. {
  13. [ViewVariables]
  14. [IdDataField]
  15. public string ID { get; private set; } = default!;
  16. [DataField]
  17. private (string type, string alert)[] Order
  18. {
  19. // why would paul do this to me.
  20. get
  21. {
  22. var res = new (string, string)[_typeToIdx.Count + _categoryToIdx.Count];
  23. foreach (var (type, id) in _typeToIdx)
  24. {
  25. res[id] = ("alertType", type.ToString());
  26. }
  27. foreach (var (category, id) in _categoryToIdx)
  28. {
  29. res[id] = ("category", category.ToString());
  30. }
  31. DebugTools.Assert(res.All(x => x != default));
  32. return res;
  33. }
  34. set
  35. {
  36. var i = 0;
  37. foreach (var (type, alert) in value)
  38. {
  39. switch (type)
  40. {
  41. case "alertType":
  42. _typeToIdx[alert] = i++;
  43. break;
  44. case "category":
  45. _categoryToIdx[alert] = i++;
  46. break;
  47. default:
  48. throw new ArgumentException();
  49. }
  50. }
  51. }
  52. }
  53. private readonly Dictionary<ProtoId<AlertPrototype>, int> _typeToIdx = new();
  54. private readonly Dictionary<ProtoId<AlertCategoryPrototype>, int> _categoryToIdx = new();
  55. private int GetOrderIndex(AlertPrototype alert)
  56. {
  57. if (_typeToIdx.TryGetValue(alert.ID, out var idx))
  58. {
  59. return idx;
  60. }
  61. if (alert.Category != null &&
  62. _categoryToIdx.TryGetValue(alert.Category.Value, out idx))
  63. {
  64. return idx;
  65. }
  66. return -1;
  67. }
  68. public int Compare(AlertPrototype? x, AlertPrototype? y)
  69. {
  70. if (x == null && y == null)
  71. return 0;
  72. if (x == null)
  73. return 1;
  74. if (y == null)
  75. return -1;
  76. var idx = GetOrderIndex(x);
  77. var idy = GetOrderIndex(y);
  78. if (idx == -1 && idy == -1)
  79. {
  80. // break ties by type value
  81. // Must cast to int to avoid integer overflow when subtracting (enum's unsigned)
  82. return string.Compare(x.ID, y.ID, StringComparison.InvariantCulture);
  83. }
  84. if (idx == -1)
  85. return 1;
  86. if (idy == -1)
  87. return -1;
  88. var result = idx - idy;
  89. // not strictly necessary (we don't care about ones that go at the same index)
  90. // but it makes the sort stable
  91. if (result == 0)
  92. {
  93. // break ties by type value
  94. // Must cast to int to avoid integer overflow when subtracting (enum's unsigned)
  95. return string.Compare(x.ID, y.ID, StringComparison.InvariantCulture);
  96. }
  97. return result;
  98. }
  99. }
  100. }