1
0

GuidebookData.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using System.Collections.Frozen;
  2. using Robust.Shared.Serialization;
  3. using Robust.Shared.Utility;
  4. namespace Content.Shared.Guidebook;
  5. /// <summary>
  6. /// Used by GuidebookDataSystem to hold data extracted from prototype values,
  7. /// both for storage and for network transmission.
  8. /// </summary>
  9. [Serializable, NetSerializable]
  10. [DataDefinition]
  11. public sealed partial class GuidebookData
  12. {
  13. /// <summary>
  14. /// Total number of data values stored.
  15. /// </summary>
  16. [DataField]
  17. public int Count { get; private set; }
  18. /// <summary>
  19. /// The data extracted by the system.
  20. /// </summary>
  21. /// <remarks>
  22. /// Structured as PrototypeName, ComponentName, FieldName, Value
  23. /// </remarks>
  24. [DataField]
  25. public Dictionary<string, Dictionary<string, Dictionary<string, object?>>> Data = [];
  26. /// <summary>
  27. /// The data extracted by the system, converted to a FrozenDictionary for faster lookup.
  28. /// </summary>
  29. public FrozenDictionary<string, FrozenDictionary<string, FrozenDictionary<string, object?>>> FrozenData;
  30. /// <summary>
  31. /// Has the data been converted to a FrozenDictionary for faster lookup?
  32. /// This should only be done on clients, as FrozenDictionary isn't serializable.
  33. /// </summary>
  34. public bool IsFrozen;
  35. /// <summary>
  36. /// Adds a new value using the given identifiers.
  37. /// </summary>
  38. public void AddData(string prototype, string component, string field, object? value)
  39. {
  40. if (IsFrozen)
  41. throw new InvalidOperationException("Attempted to add data to GuidebookData while it is frozen!");
  42. Data.GetOrNew(prototype).GetOrNew(component).Add(field, value);
  43. Count++;
  44. }
  45. /// <summary>
  46. /// Attempts to retrieve a value using the given identifiers.
  47. /// </summary>
  48. /// <returns>true if the value was retrieved, otherwise false</returns>
  49. public bool TryGetValue(string prototype, string component, string field, out object? value)
  50. {
  51. if (!IsFrozen)
  52. throw new InvalidOperationException("Freeze the GuidebookData before calling TryGetValue!");
  53. // Look in frozen dictionary
  54. if (FrozenData.TryGetValue(prototype, out var p)
  55. && p.TryGetValue(component, out var c)
  56. && c.TryGetValue(field, out value))
  57. {
  58. return true;
  59. }
  60. value = null;
  61. return false;
  62. }
  63. /// <summary>
  64. /// Deletes all data.
  65. /// </summary>
  66. public void Clear()
  67. {
  68. Data.Clear();
  69. Count = 0;
  70. IsFrozen = false;
  71. }
  72. public void Freeze()
  73. {
  74. var protos = new Dictionary<string, FrozenDictionary<string, FrozenDictionary<string, object?>>>();
  75. foreach (var (protoId, protoData) in Data)
  76. {
  77. var comps = new Dictionary<string, FrozenDictionary<string, object?>>();
  78. foreach (var (compId, compData) in protoData)
  79. {
  80. comps.Add(compId, FrozenDictionary.ToFrozenDictionary(compData));
  81. }
  82. protos.Add(protoId, FrozenDictionary.ToFrozenDictionary(comps));
  83. }
  84. FrozenData = FrozenDictionary.ToFrozenDictionary(protos);
  85. Data.Clear();
  86. IsFrozen = true;
  87. }
  88. }