using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Shared.StationRecords; using Robust.Shared.Utility; namespace Content.Server.StationRecords; /// /// Set of station records. StationRecordsComponent stores these. /// Keyed by StationRecordKey, which should be obtained from /// an entity that stores a reference to it. /// [DataDefinition] public sealed partial class StationRecordSet { [DataField("currentRecordId")] private uint _currentRecordId; // TODO add custom type serializer so that keys don't have to be written twice. [DataField("keys")] public HashSet Keys = new(); [DataField("recentlyAccessed")] private HashSet _recentlyAccessed = new(); [DataField("tables")] // TODO ensure all of this data is serializable. private Dictionary> _tables = new(); /// /// Gets all records of a specific type stored in the record set. /// /// The type of record to fetch. /// An enumerable object that contains a pair of both a station key, and the record associated with it. public IEnumerable<(StationRecordKey, T)> GetRecordsOfType() { if (!_tables.ContainsKey(typeof(T))) { yield break; } foreach (var (key, entry) in _tables[typeof(T)]) { if (entry is not T cast) { continue; } _recentlyAccessed.Add(key); yield return (key, cast); } } /// /// Add an entry into a record. /// /// Entry to add. /// Type of the entry that's being added. public StationRecordKey AddRecordEntry(EntityUid station, T entry) { if (entry == null) return StationRecordKey.Invalid; var key = new StationRecordKey(_currentRecordId++, station); AddRecordEntry(key, entry); return key; } /// /// Add an entry into a record. /// /// Key for the record. /// Entry to add. /// Type of the entry that's being added. public void AddRecordEntry(StationRecordKey key, T entry) { if (entry == null) return; if (Keys.Add(key)) _tables.GetOrNew(typeof(T))[key] = entry; } /// /// Try to get an record entry by type, from this record key. /// /// The StationRecordKey to get the entries from. /// The entry that is retrieved from the record set. /// The type of entry to search for. /// True if the record exists and was retrieved, false otherwise. public bool TryGetRecordEntry(StationRecordKey key, [NotNullWhen(true)] out T? entry) { entry = default; if (!Keys.Contains(key) || !_tables.TryGetValue(typeof(T), out var table) || !table.TryGetValue(key, out var entryObject)) { return false; } entry = (T) entryObject; _recentlyAccessed.Add(key); return true; } /// /// Checks if the record associated with this key has an entry of a certain type. /// /// The record key. /// Type to check. /// True if the entry exists, false otherwise. public bool HasRecordEntry(StationRecordKey key) { return Keys.Contains(key) && _tables.TryGetValue(typeof(T), out var table) && table.ContainsKey(key); } /// /// Get the recently accessed keys from this record set. /// /// All recently accessed keys from this record set. public IEnumerable GetRecentlyAccessed() { return _recentlyAccessed.ToArray(); } /// /// Clears the recently accessed keys from the set. /// public void ClearRecentlyAccessed() { _recentlyAccessed.Clear(); } /// /// Removes all record entries related to this key from this set. /// /// The key to remove. /// True if successful, false otherwise. public bool RemoveAllRecords(StationRecordKey key) { if (!Keys.Remove(key)) { return false; } foreach (var table in _tables.Values) { table.Remove(key); } return true; } }