using System.Collections.Generic; using System.Linq; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Players; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; using Robust.Shared.ViewVariables; namespace Content.Shared.Tag { [RegisterComponent] public class TagComponent : Component, ISerializationHooks { [ViewVariables] [DataField("tags", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] private readonly HashSet _tags = new(); public IReadOnlySet Tags => _tags; protected override void Initialize() { base.Initialize(); foreach (var tag in _tags) { GetTagOrThrow(tag); } } public override ComponentState GetComponentState() { var tags = new string[_tags.Count]; var i = 0; foreach (var tag in _tags) { tags[i] = tag; } return new TagComponentState(tags); } public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { if (curState is not TagComponentState state) { return; } _tags.Clear(); var prototypeManager = IoCManager.Resolve(); foreach (var tag in state.Tags) { GetTagOrThrow(tag, prototypeManager); _tags.Add(tag); } } private TagPrototype GetTagOrThrow(string id, IPrototypeManager? manager = null) { manager ??= IoCManager.Resolve(); return manager.Index(id); } /// /// Tries to add a tag if it doesn't already exist. /// /// The tag to add. /// true if it was added, false if it already existed. /// /// Thrown if no exists with the given id. /// public bool AddTag(string id) { GetTagOrThrow(id); var added = _tags.Add(id); if (added) { Dirty(); return true; } return false; } /// /// Tries to add the given tags if they don't already exist. /// /// The tags to add. /// true if any tags were added, false if they all already existed. /// /// Thrown if one of the ids represents an unregistered . /// public bool AddTags(params string[] ids) { return AddTags(ids.AsEnumerable()); } /// /// Tries to add the given tags if they don't already exist. /// /// The tags to add. /// true if any tags were added, false if they all already existed. /// /// Thrown if one of the ids represents an unregistered . /// public bool AddTags(IEnumerable ids) { var count = _tags.Count; var prototypeManager = IoCManager.Resolve(); foreach (var id in ids) { GetTagOrThrow(id, prototypeManager); _tags.Add(id); } if (_tags.Count > count) { Dirty(); return true; } return false; } /// /// Checks if a tag has been added. /// /// The tag to check for. /// true if it exists, false otherwise. /// /// Thrown if no exists with the given id. /// public bool HasTag(string id) { GetTagOrThrow(id); return _tags.Contains(id); } /// /// Checks if all of the given tags have been added. /// /// The tags to check for. /// true if they all exist, false otherwise. /// /// Thrown if one of the ids represents an unregistered . /// public bool HasAllTags(params string[] ids) { return HasAllTags(ids.AsEnumerable()); } /// /// Checks if all of the given tags have been added. /// /// The tags to check for. /// true if they all exist, false otherwise. /// /// Thrown if one of the ids represents an unregistered . /// public bool HasAllTags(IEnumerable ids) { var prototypeManager = IoCManager.Resolve(); foreach (var id in ids) { GetTagOrThrow(id, prototypeManager); if (!_tags.Contains(id)) { return false; } } return true; } /// /// Checks if any of the given tags have been added. /// /// The tags to check for. /// true if any of them exist, false otherwise. /// /// Thrown if one of the ids represents an unregistered . /// public bool HasAnyTag(params string[] ids) { return HasAnyTag(ids.AsEnumerable()); } /// /// Checks if any of the given tags have been added. /// /// The tags to check for. /// true if any of them exist, false otherwise. /// /// Thrown if one of the ids represents an unregistered . /// public bool HasAnyTag(IEnumerable ids) { var prototypeManager = IoCManager.Resolve(); foreach (var id in ids) { GetTagOrThrow(id, prototypeManager); if (_tags.Contains(id)) { return true; } } return false; } /// /// Tries to remove a tag if it exists. /// /// The tag to remove. /// /// true if it was removed, false otherwise even if it didn't exist. /// /// /// Thrown if no exists with the given id. /// public bool RemoveTag(string id) { GetTagOrThrow(id); if (_tags.Remove(id)) { Dirty(); return true; } return false; } /// /// Tries to remove all of the given tags if they exist. /// /// The tags to remove. /// /// true if it was removed, false otherwise even if they didn't exist. /// /// /// Thrown if one of the ids represents an unregistered . /// public bool RemoveTags(params string[] ids) { return RemoveTags(ids.AsEnumerable()); } /// /// Tries to remove all of the given tags if they exist. /// /// The tags to remove. /// true if any tag was removed, false otherwise. /// /// Thrown if one of the ids represents an unregistered . /// public bool RemoveTags(IEnumerable ids) { var count = _tags.Count; var prototypeManager = IoCManager.Resolve(); foreach (var id in ids) { GetTagOrThrow(id, prototypeManager); _tags.Remove(id); } if (_tags.Count < count) { Dirty(); return true; } return false; } } }