using System.Collections.Frozen;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
namespace Content.Shared.Guidebook;
///
/// Used by GuidebookDataSystem to hold data extracted from prototype values,
/// both for storage and for network transmission.
///
[Serializable, NetSerializable]
[DataDefinition]
public sealed partial class GuidebookData
{
///
/// Total number of data values stored.
///
[DataField]
public int Count { get; private set; }
///
/// The data extracted by the system.
///
///
/// Structured as PrototypeName, ComponentName, FieldName, Value
///
[DataField]
public Dictionary>> Data = [];
///
/// The data extracted by the system, converted to a FrozenDictionary for faster lookup.
///
public FrozenDictionary>> FrozenData;
///
/// Has the data been converted to a FrozenDictionary for faster lookup?
/// This should only be done on clients, as FrozenDictionary isn't serializable.
///
public bool IsFrozen;
///
/// Adds a new value using the given identifiers.
///
public void AddData(string prototype, string component, string field, object? value)
{
if (IsFrozen)
throw new InvalidOperationException("Attempted to add data to GuidebookData while it is frozen!");
Data.GetOrNew(prototype).GetOrNew(component).Add(field, value);
Count++;
}
///
/// Attempts to retrieve a value using the given identifiers.
///
/// true if the value was retrieved, otherwise false
public bool TryGetValue(string prototype, string component, string field, out object? value)
{
if (!IsFrozen)
throw new InvalidOperationException("Freeze the GuidebookData before calling TryGetValue!");
// Look in frozen dictionary
if (FrozenData.TryGetValue(prototype, out var p)
&& p.TryGetValue(component, out var c)
&& c.TryGetValue(field, out value))
{
return true;
}
value = null;
return false;
}
///
/// Deletes all data.
///
public void Clear()
{
Data.Clear();
Count = 0;
IsFrozen = false;
}
public void Freeze()
{
var protos = new Dictionary>>();
foreach (var (protoId, protoData) in Data)
{
var comps = new Dictionary>();
foreach (var (compId, compData) in protoData)
{
comps.Add(compId, FrozenDictionary.ToFrozenDictionary(compData));
}
protos.Add(protoId, FrozenDictionary.ToFrozenDictionary(comps));
}
FrozenData = FrozenDictionary.ToFrozenDictionary(protos);
Data.Clear();
IsFrozen = true;
}
}