From b12cb60ff1a1f0cef66d49f3e604cdf51f001540 Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 25 May 2024 17:11:33 +1000 Subject: [PATCH 1/8] Updated tag system --- Content.Client/Verbs/VerbSystem.cs | 3 +- .../Administration/Toolshed/TagCommand.cs | 11 +- .../Mech/Systems/MechAssemblySystem.cs | 3 +- .../Procedural/DungeonJob.PostGen.cs | 5 +- Content.Server/Procedural/DungeonJob.cs | 5 +- Content.Server/Procedural/DungeonSystem.cs | 4 + .../EntitySystems/RevenantSystem.Abilities.cs | 2 +- Content.Server/Spreader/SpreaderSystem.cs | 10 +- .../SharedChameleonClothingSystem.cs | 5 +- .../Conditions/NoWindowsInTile.cs | 3 +- .../EntitySystems/AnchorableSystem.cs | 11 +- .../MultipleTagsConstructionGraphStep.cs | 13 +- .../Pinpointer/SharedNavMapSystem.cs | 5 +- Content.Shared/Tag/TagComponent.cs | 16 +- Content.Shared/Tag/TagComponentState.cs | 15 - Content.Shared/Tag/TagPrototype.cs | 24 +- Content.Shared/Tag/TagSystem.cs | 669 ++++-------------- 17 files changed, 211 insertions(+), 593 deletions(-) delete mode 100644 Content.Shared/Tag/TagComponentState.cs diff --git a/Content.Client/Verbs/VerbSystem.cs b/Content.Client/Verbs/VerbSystem.cs index 2e6c5f58099e..5f1f49e5fd08 100644 --- a/Content.Client/Verbs/VerbSystem.cs +++ b/Content.Client/Verbs/VerbSystem.cs @@ -123,7 +123,6 @@ public bool TryGetEntityMenuEntities(MapCoordinates targetPos, [NotNullWhen(true if ((visibility & MenuVisibility.Invisible) == 0) { var spriteQuery = GetEntityQuery(); - var tagQuery = GetEntityQuery(); for (var i = entities.Count - 1; i >= 0; i--) { @@ -131,7 +130,7 @@ public bool TryGetEntityMenuEntities(MapCoordinates targetPos, [NotNullWhen(true if (!spriteQuery.TryGetComponent(entity, out var spriteComponent) || !spriteComponent.Visible || - _tagSystem.HasTag(entity, "HideContextMenu", tagQuery)) + _tagSystem.HasTag(entity, "HideContextMenu")) { entities.RemoveSwap(i); } diff --git a/Content.Server/Administration/Toolshed/TagCommand.cs b/Content.Server/Administration/Toolshed/TagCommand.cs index 1af27797660d..e1cf53e1b1ab 100644 --- a/Content.Server/Administration/Toolshed/TagCommand.cs +++ b/Content.Server/Administration/Toolshed/TagCommand.cs @@ -1,6 +1,7 @@ using System.Linq; using Content.Shared.Administration; using Content.Shared.Tag; +using Robust.Shared.Prototypes; using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Syntax; using Robust.Shared.Toolshed.TypeParsers; @@ -13,14 +14,14 @@ public sealed class TagCommand : ToolshedCommand private TagSystem? _tag; [CommandImplementation("list")] - public IEnumerable List([PipedArgument] IEnumerable ent) + public IEnumerable> List([PipedArgument] IEnumerable ent) { return ent.SelectMany(x => { if (TryComp(x, out var tags)) // Note: Cast is required for C# to figure out the type signature. - return (IEnumerable)tags.Tags; - return Array.Empty(); + return (IEnumerable>)tags.Tags; + return Array.Empty>(); }); } @@ -72,7 +73,7 @@ [CommandArgument] ValueRef, IEnumerable> @ref ) { _tag ??= GetSys(); - _tag.AddTags(input, @ref.Evaluate(ctx)!); + _tag.AddTags(input, (IEnumerable>)@ref.Evaluate(ctx)!); return input; } @@ -92,7 +93,7 @@ [CommandArgument] ValueRef, IEnumerable> @ref ) { _tag ??= GetSys(); - _tag.RemoveTags(input, @ref.Evaluate(ctx)!); + _tag.RemoveTags(input, (IEnumerable>)@ref.Evaluate(ctx)!); return input; } diff --git a/Content.Server/Mech/Systems/MechAssemblySystem.cs b/Content.Server/Mech/Systems/MechAssemblySystem.cs index e5b7bfaac3c8..c1fff819b4c9 100644 --- a/Content.Server/Mech/Systems/MechAssemblySystem.cs +++ b/Content.Server/Mech/Systems/MechAssemblySystem.cs @@ -14,6 +14,7 @@ namespace Content.Server.Mech.Systems; public sealed class MechAssemblySystem : EntitySystem { [Dependency] private readonly ContainerSystem _container = default!; + [Dependency] private readonly TagSystem _tag = default!; /// public override void Initialize() @@ -44,7 +45,7 @@ private void OnInteractUsing(EntityUid uid, MechAssemblyComponent component, Int foreach (var (tag, val) in component.RequiredParts) { - if (!val && tagComp.Tags.Contains(tag)) + if (!val && _tag.HasTag(tagComp, tag)) { component.RequiredParts[tag] = true; _container.Insert(args.Used, component.PartsContainer); diff --git a/Content.Server/Procedural/DungeonJob.PostGen.cs b/Content.Server/Procedural/DungeonJob.PostGen.cs index b326bcc378f6..cb9e64f04e25 100644 --- a/Content.Server/Procedural/DungeonJob.PostGen.cs +++ b/Content.Server/Procedural/DungeonJob.PostGen.cs @@ -13,6 +13,7 @@ using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; +using Robust.Shared.Prototypes; using Robust.Shared.Random; using Robust.Shared.Utility; @@ -24,13 +25,15 @@ public sealed partial class DungeonJob * Run after the main dungeon generation */ + private static readonly ProtoId WallTag = "Wall"; + private bool HasWall(MapGridComponent grid, Vector2i tile) { var anchored = _maps.GetAnchoredEntitiesEnumerator(_gridUid, _grid, tile); while (anchored.MoveNext(out var uid)) { - if (_tagQuery.TryGetComponent(uid, out var tagComp) && tagComp.Tags.Contains("Wall")) + if (_tag.HasTag(uid.Value, WallTag)) return true; } diff --git a/Content.Server/Procedural/DungeonJob.cs b/Content.Server/Procedural/DungeonJob.cs index 8fecf1c9e8e5..bf2822ff4237 100644 --- a/Content.Server/Procedural/DungeonJob.cs +++ b/Content.Server/Procedural/DungeonJob.cs @@ -28,10 +28,10 @@ public sealed partial class DungeonJob : Job private readonly DecalSystem _decals; private readonly DungeonSystem _dungeon; private readonly EntityLookupSystem _lookup; + private readonly TagSystem _tag; private readonly TileSystem _tile; private readonly SharedMapSystem _maps; private readonly SharedTransformSystem _transform; - private EntityQuery _tagQuery; private readonly DungeonConfigPrototype _gen; private readonly int _seed; @@ -53,6 +53,7 @@ public DungeonJob( DecalSystem decals, DungeonSystem dungeon, EntityLookupSystem lookup, + TagSystem tag, TileSystem tile, SharedTransformSystem transform, DungeonConfigPrototype gen, @@ -72,10 +73,10 @@ public DungeonJob( _decals = decals; _dungeon = dungeon; _lookup = lookup; + _tag = tag; _tile = tile; _maps = _entManager.System(); _transform = transform; - _tagQuery = _entManager.GetEntityQuery(); _gen = gen; _grid = grid; diff --git a/Content.Server/Procedural/DungeonSystem.cs b/Content.Server/Procedural/DungeonSystem.cs index 069508bcbbba..36009896a2cb 100644 --- a/Content.Server/Procedural/DungeonSystem.cs +++ b/Content.Server/Procedural/DungeonSystem.cs @@ -10,6 +10,7 @@ using Content.Shared.Maps; using Content.Shared.Physics; using Content.Shared.Procedural; +using Content.Shared.Tag; using Robust.Server.GameObjects; using Robust.Shared.Configuration; using Robust.Shared.Console; @@ -31,6 +32,7 @@ public sealed partial class DungeonSystem : SharedDungeonSystem [Dependency] private readonly AnchorableSystem _anchorable = default!; [Dependency] private readonly DecalSystem _decals = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly TagSystem _tag = default!; [Dependency] private readonly TileSystem _tile = default!; [Dependency] private readonly MapLoaderSystem _loader = default!; [Dependency] private readonly SharedMapSystem _maps = default!; @@ -199,6 +201,7 @@ public void GenerateDungeon(DungeonConfigPrototype gen, _decals, this, _lookup, + _tag, _tile, _transform, gen, @@ -231,6 +234,7 @@ public async Task GenerateDungeonAsync( _decals, this, _lookup, + _tag, _tile, _transform, gen, diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs index 4106630d526a..0060f3828161 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs @@ -241,7 +241,7 @@ private void OnDefileAction(EntityUid uid, RevenantComponent component, Revenant foreach (var ent in lookup) { //break windows - if (tags.HasComponent(ent) && _tag.HasAnyTag(ent, "Window")) + if (tags.HasComponent(ent) && _tag.HasTag(ent, "Window")) { //hardcoded damage specifiers til i die. var dspec = new DamageSpecifier(); diff --git a/Content.Server/Spreader/SpreaderSystem.cs b/Content.Server/Spreader/SpreaderSystem.cs index fe14d86aa1da..7de8a43d354f 100644 --- a/Content.Server/Spreader/SpreaderSystem.cs +++ b/Content.Server/Spreader/SpreaderSystem.cs @@ -21,6 +21,7 @@ public sealed class SpreaderSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly TagSystem _tag = default!; /// /// Cached maximum number of updates per spreader prototype. This is applied per-grid. @@ -37,8 +38,7 @@ public sealed class SpreaderSystem : EntitySystem public const float SpreadCooldownSeconds = 1; - [ValidatePrototypeId] - private const string IgnoredTag = "SpreaderIgnore"; + private static readonly ProtoId IgnoredTag = "SpreaderIgnore"; /// public override void Initialize() @@ -189,7 +189,6 @@ public void GetNeighbors(EntityUid uid, TransformComponent comp, ProtoId(); var dockQuery = GetEntityQuery(); var xformQuery = GetEntityQuery(); - var tagQuery = GetEntityQuery(); var blockedAtmosDirs = AtmosDirection.Invalid; // Due to docking ports they may not necessarily be opposite directions. @@ -212,7 +211,7 @@ public void GetNeighbors(EntityUid uid, TransformComponent comp, ProtoId(); - var tagQuery = entManager.GetEntityQuery(); var sysMan = entManager.EntitySysManager; var tagSystem = sysMan.GetEntitySystem(); foreach (var entity in location.GetEntitiesInTile(LookupFlags.Static)) { - if (tagSystem.HasTag(entity, "Window", tagQuery)) + if (tagSystem.HasTag(entity, "Window")) return false; } diff --git a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs index c041cf1ba069..e9ef053f629f 100644 --- a/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs +++ b/Content.Shared/Construction/EntitySystems/AnchorableSystem.cs @@ -15,6 +15,7 @@ using Robust.Shared.Map.Components; using Robust.Shared.Physics.Components; using Content.Shared.Tag; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Utility; using SharedToolSystem = Content.Shared.Tools.Systems.SharedToolSystem; @@ -32,16 +33,14 @@ public sealed partial class AnchorableSystem : EntitySystem [Dependency] private readonly TagSystem _tagSystem = default!; private EntityQuery _physicsQuery; - private EntityQuery _tagQuery; - public const string Unstackable = "Unstackable"; + public readonly ProtoId Unstackable = "Unstackable"; public override void Initialize() { base.Initialize(); _physicsQuery = GetEntityQuery(); - _tagQuery = GetEntityQuery(); SubscribeLocalEvent(OnInteractUsing, before: new[] { typeof(ItemSlotsSystem) }, after: new[] { typeof(SharedConstructionSystem) }); @@ -312,7 +311,7 @@ public bool AnyUnstackable(EntityUid uid, EntityCoordinates location) DebugTools.Assert(!Transform(uid).Anchored); // If we are unstackable, iterate through any other entities anchored on the current square - return _tagSystem.HasTag(uid, Unstackable, _tagQuery) && AnyUnstackablesAnchoredAt(location); + return _tagSystem.HasTag(uid, Unstackable) && AnyUnstackablesAnchoredAt(location); } public bool AnyUnstackablesAnchoredAt(EntityCoordinates location) @@ -327,10 +326,8 @@ public bool AnyUnstackablesAnchoredAt(EntityCoordinates location) while (enumerator.MoveNext(out var entity)) { // If we find another unstackable here, return true. - if (_tagSystem.HasTag(entity.Value, Unstackable, _tagQuery)) - { + if (_tagSystem.HasTag(entity.Value, Unstackable)) return true; - } } return false; diff --git a/Content.Shared/Construction/Steps/MultipleTagsConstructionGraphStep.cs b/Content.Shared/Construction/Steps/MultipleTagsConstructionGraphStep.cs index 668952dac23d..07ba46946a61 100644 --- a/Content.Shared/Construction/Steps/MultipleTagsConstructionGraphStep.cs +++ b/Content.Shared/Construction/Steps/MultipleTagsConstructionGraphStep.cs @@ -1,14 +1,15 @@ using Content.Shared.Tag; +using Robust.Shared.Prototypes; namespace Content.Shared.Construction.Steps { public sealed partial class MultipleTagsConstructionGraphStep : ArbitraryInsertConstructionGraphStep { [DataField("allTags")] - private List? _allTags; + private List>? _allTags; [DataField("anyTags")] - private List? _anyTags; + private List>? _anyTags; private static bool IsNullOrEmpty(ICollection? list) { @@ -21,16 +22,12 @@ public override bool EntityValid(EntityUid uid, IEntityManager entityManager, IC if (IsNullOrEmpty(_allTags) && IsNullOrEmpty(_anyTags)) return false; // Step is somehow invalid, we return. - // No tags at all. - if (!entityManager.TryGetComponent(uid, out TagComponent? tags)) - return false; - var tagSystem = entityManager.EntitySysManager.GetEntitySystem(); - if (_allTags != null && !tagSystem.HasAllTags(tags, _allTags)) + if (_allTags != null && !tagSystem.HasAllTags(uid, _allTags)) return false; // We don't have all the tags needed. - if (_anyTags != null && !tagSystem.HasAnyTag(tags, _anyTags)) + if (_anyTags != null && !tagSystem.HasAnyTag(uid, _anyTags)) return false; // We don't have any of the tags needed. // This entity is valid! diff --git a/Content.Shared/Pinpointer/SharedNavMapSystem.cs b/Content.Shared/Pinpointer/SharedNavMapSystem.cs index 7c12321b5db6..3ced5f3c9ed5 100644 --- a/Content.Shared/Pinpointer/SharedNavMapSystem.cs +++ b/Content.Shared/Pinpointer/SharedNavMapSystem.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using Content.Shared.Tag; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -24,7 +25,7 @@ public abstract class SharedNavMapSystem : EntitySystem [Robust.Shared.IoC.Dependency] private readonly TagSystem _tagSystem = default!; - private readonly string[] _wallTags = ["Wall", "Window"]; + private static readonly ProtoId[] WallTags = {"Wall", "Window"}; private EntityQuery _doorQuery; public override void Initialize() @@ -58,7 +59,7 @@ public NavMapChunkType GetEntityType(EntityUid uid) if (_doorQuery.HasComp(uid)) return NavMapChunkType.Airlock; - if (_tagSystem.HasAnyTag(uid, _wallTags)) + if (_tagSystem.HasAnyTag(uid, WallTags)) return NavMapChunkType.Wall; return NavMapChunkType.Invalid; diff --git a/Content.Shared/Tag/TagComponent.cs b/Content.Shared/Tag/TagComponent.cs index b5b8a48a4415..ad4240ba06c7 100644 --- a/Content.Shared/Tag/TagComponent.cs +++ b/Content.Shared/Tag/TagComponent.cs @@ -1,13 +1,11 @@ using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; +using Robust.Shared.Prototypes; -namespace Content.Shared.Tag +namespace Content.Shared.Tag; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, Access(typeof(TagSystem))] +public sealed partial class TagComponent : Component { - [RegisterComponent, NetworkedComponent, Access(typeof(TagSystem))] - public sealed partial class TagComponent : Component - { - [DataField("tags", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] - [Access(typeof(TagSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends - public HashSet Tags = new(); - } + [DataField, ViewVariables, AutoNetworkedField] + public HashSet> Tags = new(); } diff --git a/Content.Shared/Tag/TagComponentState.cs b/Content.Shared/Tag/TagComponentState.cs deleted file mode 100644 index 9919aba108da..000000000000 --- a/Content.Shared/Tag/TagComponentState.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Robust.Shared.Serialization; - -namespace Content.Shared.Tag -{ - [Serializable, NetSerializable] - public sealed class TagComponentState : ComponentState - { - public TagComponentState(string[] tags) - { - Tags = tags; - } - - public string[] Tags { get; } - } -} diff --git a/Content.Shared/Tag/TagPrototype.cs b/Content.Shared/Tag/TagPrototype.cs index 2a06e22cf907..97f8c1af7d44 100644 --- a/Content.Shared/Tag/TagPrototype.cs +++ b/Content.Shared/Tag/TagPrototype.cs @@ -1,17 +1,15 @@ using Robust.Shared.Prototypes; -namespace Content.Shared.Tag +namespace Content.Shared.Tag; + +/// +/// Prototype representing a tag in YAML. +/// Meant to only have an ID property, as that is the only thing that +/// gets saved in TagComponent. +/// +[Prototype("Tag")] +public sealed partial class TagPrototype : IPrototype { - /// - /// Prototype representing a tag in YAML. - /// Meant to only have an ID property, as that is the only thing that - /// gets saved in TagComponent. - /// - [Prototype("Tag")] - public sealed partial class TagPrototype : IPrototype - { - [ViewVariables] - [IdDataField] - public string ID { get; private set; } = default!; - } + [IdDataField, ViewVariables] + public string ID { get; } = string.Empty; } diff --git a/Content.Shared/Tag/TagSystem.cs b/Content.Shared/Tag/TagSystem.cs index 7bcb887a410a..527765540ae3 100644 --- a/Content.Shared/Tag/TagSystem.cs +++ b/Content.Shared/Tag/TagSystem.cs @@ -1,6 +1,3 @@ -using System.Diagnostics; -using System.Linq; -using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -15,685 +12,323 @@ public sealed class TagSystem : EntitySystem public override void Initialize() { base.Initialize(); + _tagQuery = GetEntityQuery(); - SubscribeLocalEvent(OnTagGetState); - SubscribeLocalEvent(OnTagHandleState); #if DEBUG SubscribeLocalEvent(OnTagInit); +#endif } +#if DEBUG private void OnTagInit(EntityUid uid, TagComponent component, ComponentInit args) { foreach (var tag in component.Tags) { AssertValidTag(tag); } -#endif - } - - - private void OnTagHandleState(EntityUid uid, TagComponent component, ref ComponentHandleState args) - { - if (args.Current is not TagComponentState state) - return; - - component.Tags.Clear(); - - foreach (var tag in state.Tags) - { - AssertValidTag(tag); - component.Tags.Add(tag); - } - } - - private static void OnTagGetState(EntityUid uid, TagComponent component, ref ComponentGetState args) - { - var tags = new string[component.Tags.Count]; - var i = 0; - - foreach (var tag in component.Tags) - { - tags[i] = tag; - i++; - } - - args.State = new TagComponentState(tags); - } - - private void AssertValidTag(string id) - { - DebugTools.Assert(_proto.HasIndex(id), $"Unknown tag: {id}"); } +#endif /// - /// Tries to add a tag to an entity if the tag doesn't already exist. + /// Tries to add a tag to an entity if the tag doesn't already exist. /// - /// The entity to add the tag to. - /// The tag to add. /// - /// true if it was added, false otherwise even if it already existed. + /// true if it was added, false otherwise even if it already existed. /// /// - /// Thrown if no exists with the given id. + /// Thrown if no exists with the given id. /// - public bool AddTag(EntityUid entity, string id) + public bool AddTag(EntityUid entityUid, ProtoId tag) { - return AddTag(entity, EnsureComp(entity), id); + return AddTag((entityUid, EnsureComp(entityUid)), tag); } /// - /// Tries to add the given tags to an entity if the tags don't already exist. + /// Tries to add the given tags to an entity if the tags don't already exist. /// - /// The entity to add the tag to. - /// The tags to add. /// - /// true if any tags were added, false otherwise even if they all already existed. + /// true if any tags were added, false otherwise even if they all already existed. /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if one of the ids represents an unregistered . /// - public bool AddTags(EntityUid entity, params string[] ids) + public bool AddTags(EntityUid entityUid, IEnumerable> tags) { - return AddTags(entity, EnsureComp(entity), ids); + return AddTags((entityUid, EnsureComp(entityUid)), tags); } /// - /// Tries to add the given tags to an entity if the tags don't already exist. + /// Tries to add a tag to an entity if it has a + /// and the tag doesn't already exist. /// - /// The entity to add the tag to. - /// The tags to add. /// - /// true if any tags were added, false otherwise even if they all already existed. + /// true if it was added, false otherwise even if it already existed. /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if no exists with the given id. /// - public bool AddTags(EntityUid entity, IEnumerable ids) + public bool TryAddTag(EntityUid entityUid, ProtoId tag) { - return AddTags(entity, EnsureComp(entity), ids); + return _tagQuery.TryComp(entityUid, out var component) && + AddTag((entityUid, component), tag); } /// - /// Tries to add a tag to an entity if it has a - /// and the tag doesn't already exist. + /// Tries to add the given tags to an entity if it has a + /// and the tags don't already exist. /// - /// The entity to add the tag to. - /// The tag to add. /// - /// true if it was added, false otherwise even if it already existed. + /// true if any tags were added, false otherwise even if they all already existed. /// /// - /// Thrown if no exists with the given id. + /// Thrown if one of the ids represents an unregistered . /// - public bool TryAddTag(EntityUid entity, string id) + public bool TryAddTags(EntityUid entityUid, IEnumerable> tags) { - return _tagQuery.TryComp(entity, out var component) && - AddTag(entity, component, id); + return _tagQuery.TryComp(entityUid, out var component) && + AddTags((entityUid, component), tags); } /// - /// Tries to add the given tags to an entity if it has a - /// and the tags don't already exist. + /// Checks if a tag has been added to an entity. /// - /// The entity to add the tag to. - /// The tags to add. /// - /// true if any tags were added, false otherwise even if they all already existed. + /// true if it exists, false otherwise. /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if no exists with the given id. /// - public bool TryAddTags(EntityUid entity, params string[] ids) + public bool HasTag(EntityUid entityUid, ProtoId tag) { - return _tagQuery.TryComp(entity, out var component) && - AddTags(entity, component, ids); + return _tagQuery.TryComp(entityUid, out var component) && + HasTag(component, tag); } /// - /// Tries to add the given tags to an entity if it has a - /// and the tags don't already exist. + /// Checks if all of the given tags have been added to an entity. /// - /// The entity to add the tag to. - /// The tags to add. /// - /// true if any tags were added, false otherwise even if they all already existed. + /// true if they all exist, false otherwise. /// /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool TryAddTags(EntityUid entity, IEnumerable ids) - { - return _tagQuery.TryComp(entity, out var component) && - AddTags(entity, component, ids); - } - - /// - /// Checks if a tag has been added to an entity. - /// - /// The entity to check. - /// The tag to check for. - /// true if it exists, false otherwise. - /// - /// Thrown if no exists with the given id. - /// - public bool HasTag(EntityUid entity, string id) - { - return _tagQuery.TryComp(entity, out var component) && - HasTag(component, id); - } - - /// - /// Checks if a tag has been added to an entity. - /// - [Obsolete] - public bool HasTag(EntityUid entity, string id, EntityQuery tagQuery) - { - return tagQuery.TryGetComponent(entity, out var component) && - HasTag(component, id); - } - - /// - /// Checks if all of the given tags have been added to an entity. - /// - /// The entity to check. - /// The tags to check for. - /// true if they all exist, false otherwise. - /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool HasAllTags(EntityUid entity, string id) => HasTag(entity, id); - - /// - /// Checks if all of the given tags have been added to an entity. - /// - /// The entity to check. - /// The tags to check for. - /// true if they all exist, false otherwise. - /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool HasAllTags(EntityUid entity, List ids) - { - return _tagQuery.TryComp(entity, out var component) && - HasAllTags(component, ids); - } - - /// - /// Checks if all of the given tags have been added to an entity. - /// - /// The entity to check. - /// The tags to check for. - /// true if they all exist, false otherwise. - /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool HasAllTags(EntityUid entity, IEnumerable ids) - { - return _tagQuery.TryComp(entity, out var component) && - HasAllTags(component, ids); - } - - /// - /// Checks if all of the given tags have been added to an entity. - /// - /// The entity to check. - /// The tags to check for. - /// true if they all exist, false otherwise. - /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool HasAllTags(EntityUid entity, List> ids) - { - return _tagQuery.TryComp(entity, out var component) && - HasAllTags(component, ids); - } - - /// - /// Checks if any of the given tags have been added to an entity. - /// - /// The entity to check. - /// 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(EntityUid entity, params string[] ids) - { - return _tagQuery.TryComp(entity, out var component) && - HasAnyTag(component, ids); - } - - /// - /// Checks if any of the given tags have been added to an entity. - /// - /// The entity to check. - /// The tag to check for. - /// true if any of them exist, false otherwise. - /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if one of the ids represents an unregistered . /// - public bool HasAnyTag(EntityUid entity, string id) => HasTag(entity, id); - - /// - /// Checks if any of the given tags have been added to an entity. - /// - /// The entity to check. - /// 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(EntityUid entity, List ids) - { - return _tagQuery.TryComp(entity, out var component) && - HasAnyTag(component, ids); - } - - /// - /// Checks if any of the given tags have been added to an entity. - /// - /// The entity to check. - /// 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(EntityUid entity, List> ids) + public bool HasAllTags(EntityUid entityUid, IEnumerable> tags) { - return TryComp(entity, out var component) && - HasAnyTag(component, ids); + return _tagQuery.TryComp(entityUid, out var component) && + HasAllTags(component, tags); } /// - /// Checks if any of the given tags have been added to an entity. + /// Checks if any of the given tags have been added to an entity. /// - /// The entity to check. - /// 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(EntityUid entity, IEnumerable ids) - { - return _tagQuery.TryComp(entity, out var component) && - HasAnyTag(component, ids); - } - - /// - /// Tries to remove a tag from an entity if it exists. - /// - /// The entity to remove the tag from. - /// The tag to remove. /// - /// true if it was removed, false otherwise even if it didn't exist. + /// true if any of them exist, false otherwise. /// /// - /// Thrown if no exists with the given id. + /// Thrown if one of the ids represents an unregistered . /// - public bool RemoveTag(EntityUid entity, string id) + public bool HasAnyTag(EntityUid entityUid, IEnumerable> tags) { - return _tagQuery.TryComp(entity, out var component) && - RemoveTag(entity, component, id); + return _tagQuery.TryComp(entityUid, out var component) && + HasAnyTag(component, tags); } /// - /// Tries to remove a tag from an entity if it exists. + /// Checks if a tag has been added to an component. /// - /// The entity to remove the tag from. - /// The tag to remove. /// - /// true if it was removed, false otherwise even if it didn't exist. + /// true if it exists, false otherwise. + /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if no exists with the given id. /// - /// - public bool RemoveTags(EntityUid entity, params string[] ids) + public bool HasTag(TagComponent component, ProtoId tag) { - return _tagQuery.TryComp(entity, out var component) && - RemoveTags(entity, component, ids); +#if DEBUG + AssertValidTag(tag); +#endif + return component.Tags.Contains(tag); } /// - /// Tries to remove a tag from an entity if it exists. + /// Checks if all of the given tags have been added to an component. /// - /// The entity to remove the tag from. - /// The tag to remove. /// - /// true if it was removed, false otherwise even if it didn't exist. + /// true if they all exist, false otherwise. /// /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool RemoveTags(EntityUid entity, IEnumerable ids) - { - return _tagQuery.TryComp(entity, out var component) && - RemoveTags(entity, component, ids); - } - - /// - /// 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. + /// Thrown if one of the ids represents an unregistered . /// - public bool AddTag(EntityUid uid, TagComponent component, string id) + public bool HasAllTags(TagComponent component, IEnumerable> tags) { - AssertValidTag(id); - var added = component.Tags.Add(id); - - if (added) + foreach (var tag in tags) { - Dirty(uid, component); - return true; +#if DEBUG + AssertValidTag(tag); +#endif + if (!component.Tags.Contains(tag)) + return false; } - 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(EntityUid uid, TagComponent component, params string[] ids) - { - return AddTags(uid, component, ids.AsEnumerable()); + return true; } /// - /// Tries to add the given tags if they don't already exist. + /// Checks if any of the given tags have been added to an component. /// - /// The tags to add. - /// true if any tags were added, false if they all already existed. + /// + /// true if any of them exist, false otherwise. + /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if one of the ids represents an unregistered . /// - public bool AddTags(EntityUid uid, TagComponent component, IEnumerable ids) + public bool HasAnyTag(TagComponent component, IEnumerable> tags) { - var count = component.Tags.Count; - - foreach (var id in ids) + foreach (var tag in tags) { - AssertValidTag(id); - component.Tags.Add(id); - } - - if (component.Tags.Count > count) - { - Dirty(uid, component); - return true; +#if DEBUG + AssertValidTag(tag); +#endif + if (component.Tags.Contains(tag)) + return true; } return false; } /// - /// Checks if a tag has been added. + /// Tries to remove a tag from an entity if it exists. /// - /// The tag to check for. - /// true if it exists, false otherwise. + /// + /// true if it was removed, false otherwise even if it didn't exist. + /// /// - /// Thrown if no exists with the given id. + /// Thrown if no exists with the given id. /// - public bool HasTag(TagComponent component, string id) + public bool RemoveTag(EntityUid entityUid, ProtoId tag) { - AssertValidTag(id); - return component.Tags.Contains(id); + return _tagQuery.TryComp(entityUid, out var component) && + RemoveTag((entityUid, component), tag); } /// - /// Checks if all of the given tags have been added. + /// Tries to remove a tag from an entity if it exists. /// - /// The tags to check for. - /// true if they all exist, false otherwise. + /// + /// true if it was removed, false otherwise even if it didn't exist. + /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if one of the ids represents an unregistered . /// - public bool HasAllTags(TagComponent component, params string[] ids) + public bool RemoveTags(EntityUid entityUid, IEnumerable> tags) { - return HasAllTags(component, ids.AsEnumerable()); + return _tagQuery.TryComp(entityUid, out var component) && + RemoveTags((entityUid, component), tags); } /// - /// Checks if all of the given tags have been added. - /// - /// The tag to check for. - /// true if they all exist, false otherwise. - /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool HasAllTags(TagComponent component, string id) => HasTag(component, id); - - /// - /// Checks if all of the given tags have been added. + /// Tries to add a tag if it doesn't already exist. /// - /// The tags to check for. - /// true if they all exist, false otherwise. + /// + /// true if it was added, false if it already existed. + /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if no exists with the given id. /// - public bool HasAllTags(TagComponent component, List ids) + public bool AddTag(Entity entity, ProtoId tag) { - foreach (var id in ids) - { - AssertValidTag(id); - - if (!component.Tags.Contains(id)) - return false; - } +#if DEBUG + AssertValidTag(tag); +#endif + if (!entity.Comp.Tags.Add(tag)) + return false; + Dirty(entity); return true; } /// - /// Checks if all of the given tags have been added. + /// Tries to add the given tags if they don't already exist. /// - /// The tags to check for. - /// true if they all exist, false otherwise. + /// + /// true if any tags were added, false if they all already existed. + /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if one of the ids represents an unregistered . /// - public bool HasAllTags(TagComponent component, IEnumerable ids) + public bool AddTags(Entity entity, IEnumerable> tags) { - foreach (var id in ids) + var update = false; + foreach (var tag in tags) { - AssertValidTag(id); - - if (!component.Tags.Contains(id)) - return false; - +#if DEBUG + AssertValidTag(tag); +#endif + if (entity.Comp.Tags.Add(tag) && !update) + update = true; } - return true; - } - - /// - /// 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(TagComponent component, List> ids) - { - foreach (var id in ids) - { - AssertValidTag(id); - - if (!component.Tags.Contains(id)) - return false; - - } + if (!update) + return false; + Dirty(entity); 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(TagComponent component, params string[] ids) - { - foreach (var id in ids) - { - AssertValidTag(id); - - if (component.Tags.Contains(id)) - return true; - } - - return false; - } - - /// - /// Checks if any of the given tags have been added. - /// - /// The tag to check for. - /// true if any of them exist, false otherwise. - /// - /// Thrown if one of the ids represents an unregistered . - /// - public bool HasAnyTag(TagComponent component, string id) => HasTag(component, id); - - /// - /// 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(TagComponent component, List ids) - { - foreach (var id in ids) - { - AssertValidTag(id); - - if (component.Tags.Contains(id)) - { - return true; - } - } - - return false; - } - - /// - /// Checks if any of the given tags have been added. + /// Tries to remove a tag if it exists. /// - /// The tags to check for. - /// true if any of them exist, false otherwise. + /// + /// true if it was removed, false otherwise even if it didn't exist. + /// /// - /// Thrown if one of the ids represents an unregistered . + /// Thrown if no exists with the given id. /// - public bool HasAnyTag(TagComponent component, IEnumerable ids) + public bool RemoveTag(Entity entity, ProtoId tag) { - foreach (var id in ids) - { - AssertValidTag(id); - - if (component.Tags.Contains(id)) - { - return true; - } - } - - return false; - } +#if DEBUG + AssertValidTag(tag); +#endif - /// - /// 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(TagComponent comp, List> ids) - { - foreach (var id in ids) - { - AssertValidTag(id); + if (!entity.Comp.Tags.Remove(tag)) + return false; - if (comp.Tags.Contains(id)) - return true; - } - - return false; + Dirty(entity); + return true; } /// - /// Tries to remove a tag if it exists. + /// Tries to remove all of the given tags if they exist. /// /// - /// true if it was removed, false otherwise even if it didn't exist. + /// true if any tag was removed, false otherwise. /// /// - /// Thrown if no exists with the given id. + /// Thrown if one of the ids represents an unregistered . /// - public bool RemoveTag(EntityUid uid, TagComponent component, string id) + public bool RemoveTags(Entity entity, IEnumerable> tags) { - AssertValidTag(id); - - if (component.Tags.Remove(id)) + var update = false; + foreach (var tag in tags) { - Dirty(uid, component); - return true; +#if DEBUG + AssertValidTag(tag); +#endif + if (entity.Comp.Tags.Remove(tag) && !update) + update = true; } - return false; - } + if (!update) + 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(EntityUid uid, TagComponent component, params string[] ids) - { - return RemoveTags(uid, component, ids.AsEnumerable()); + Dirty(entity); + return true; } - /// - /// 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(EntityUid uid, TagComponent component, IEnumerable ids) + private void AssertValidTag(string id) { - var count = component.Tags.Count; - - foreach (var id in ids) - { - AssertValidTag(id); - component.Tags.Remove(id); - } - - if (component.Tags.Count < count) - { - Dirty(uid, component); - return true; - } - - return false; + DebugTools.Assert(_proto.HasIndex(id), $"Unknown tag: {id}"); } } From 9e1d1f9362e428eea4d0fa7c46531e985112f0d3 Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 25 May 2024 17:31:19 +1000 Subject: [PATCH 2/8] Added params methods --- Content.Shared/Tag/TagSystem.cs | 127 ++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/Content.Shared/Tag/TagSystem.cs b/Content.Shared/Tag/TagSystem.cs index 527765540ae3..c7d2e021ecbc 100644 --- a/Content.Shared/Tag/TagSystem.cs +++ b/Content.Shared/Tag/TagSystem.cs @@ -44,6 +44,20 @@ public bool AddTag(EntityUid entityUid, ProtoId tag) return AddTag((entityUid, EnsureComp(entityUid)), tag); } + /// + /// Tries to add the given tags to an entity if the tags don't already exist. + /// + /// + /// true if any tags were added, false otherwise even if they all already existed. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool AddTags(EntityUid entityUid, params ProtoId[] tags) + { + return AddTags(entityUid, tags); + } + /// /// Tries to add the given tags to an entity if the tags don't already exist. /// @@ -74,6 +88,21 @@ public bool TryAddTag(EntityUid entityUid, ProtoId tag) AddTag((entityUid, component), tag); } + /// + /// Tries to add the given tags to an entity if it has a + /// and the tags don't already exist. + /// + /// + /// true if any tags were added, false otherwise even if they all already existed. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool TryAddTags(EntityUid entityUid, params ProtoId[] tags) + { + return TryAddTags(entityUid, tags); + } + /// /// Tries to add the given tags to an entity if it has a /// and the tags don't already exist. @@ -105,6 +134,20 @@ public bool HasTag(EntityUid entityUid, ProtoId tag) HasTag(component, tag); } + /// + /// Checks if all of the given tags have been added to an entity. + /// + /// + /// true if they all exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(EntityUid entityUid, params ProtoId[] tags) + { + return HasAllTags(entityUid, tags); + } + /// /// Checks if all of the given tags have been added to an entity. /// @@ -120,6 +163,20 @@ public bool HasAllTags(EntityUid entityUid, IEnumerable> t HasAllTags(component, tags); } + /// + /// Checks if any of the given tags have been added to an entity. + /// + /// + /// true if any of them exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(EntityUid entityUid, params ProtoId[] tags) + { + return HasAnyTag(entityUid, tags); + } + /// /// Checks if any of the given tags have been added to an entity. /// @@ -152,6 +209,20 @@ public bool HasTag(TagComponent component, ProtoId tag) return component.Tags.Contains(tag); } + /// + /// Checks if all of the given tags have been added to an component. + /// + /// + /// true if they all exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(TagComponent component, params ProtoId[] tags) + { + return HasAllTags(component, tags); + } + /// /// Checks if all of the given tags have been added to an component. /// @@ -175,6 +246,20 @@ public bool HasAllTags(TagComponent component, IEnumerable return true; } + /// + /// Checks if any of the given tags have been added to an component. + /// + /// + /// true if any of them exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(TagComponent component, params ProtoId[] tags) + { + return HasAnyTag(component, tags); + } + /// /// Checks if any of the given tags have been added to an component. /// @@ -213,6 +298,20 @@ public bool RemoveTag(EntityUid entityUid, ProtoId tag) RemoveTag((entityUid, component), tag); } + /// + /// Tries to remove a tag from an entity if it exists. + /// + /// + /// true if it was removed, false otherwise even if it didn't exist. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool RemoveTags(EntityUid entityUid, params ProtoId[] tags) + { + return RemoveTags(entityUid, tags); + } + /// /// Tries to remove a tag from an entity if it exists. /// @@ -249,6 +348,20 @@ public bool AddTag(Entity entity, ProtoId tag) return true; } + /// + /// Tries to add the given tags if they don't already exist. + /// + /// + /// true if any tags were added, false if they all already existed. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool AddTags(Entity entity, params ProtoId[] tags) + { + return AddTags(entity, tags); + } + /// /// Tries to add the given tags if they don't already exist. /// @@ -299,6 +412,20 @@ public bool RemoveTag(Entity entity, ProtoId tag) return true; } + /// + /// Tries to remove all of the given tags if they exist. + /// + /// + /// true if any tag was removed, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool RemoveTags(Entity entity, params ProtoId[] tags) + { + return RemoveTags(entity, tags); + } + /// /// Tries to remove all of the given tags if they exist. /// From 81cc4a5f7dee797aa355725810bcd3ac1975ab8e Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 25 May 2024 17:31:39 +1000 Subject: [PATCH 3/8] Fixed tag integration tests --- Content.IntegrationTests/Tests/Tag/TagTest.cs | 74 ++++++------------- 1 file changed, 21 insertions(+), 53 deletions(-) diff --git a/Content.IntegrationTests/Tests/Tag/TagTest.cs b/Content.IntegrationTests/Tests/Tag/TagTest.cs index cbcdd1c6c623..fb4adcaaefbe 100644 --- a/Content.IntegrationTests/Tests/Tag/TagTest.cs +++ b/Content.IntegrationTests/Tests/Tag/TagTest.cs @@ -73,14 +73,6 @@ await server.WaitAssertion(() => // Single Assert.That(tagSystem.HasTag(sTagDummy, StartingTag)); Assert.That(tagSystem.HasTag(sTagComponent, StartingTag)); - - // Any - Assert.That(tagSystem.HasAnyTag(sTagDummy, StartingTag)); - Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag)); - - // All - Assert.That(tagSystem.HasAllTags(sTagDummy, StartingTag)); - Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag)); }); // Does not have the added tag @@ -92,14 +84,6 @@ await server.WaitAssertion(() => // Single Assert.That(tagSystem.HasTag(sTagDummy, AddedTag), Is.False); Assert.That(tagSystem.HasTag(sTagComponent, AddedTag), Is.False); - - // Any - Assert.That(tagSystem.HasAnyTag(sTagDummy, AddedTag), Is.False); - Assert.That(tagSystem.HasAnyTag(sTagComponent, AddedTag), Is.False); - - // All - Assert.That(tagSystem.HasAllTags(sTagDummy, AddedTag), Is.False); - Assert.That(tagSystem.HasAllTags(sTagComponent, AddedTag), Is.False); }); // Does not have the unused tag @@ -111,14 +95,6 @@ await server.WaitAssertion(() => // Single Assert.That(tagSystem.HasTag(sTagDummy, UnusedTag), Is.False); Assert.That(tagSystem.HasTag(sTagComponent, UnusedTag), Is.False); - - // Any - Assert.That(tagSystem.HasAnyTag(sTagDummy, UnusedTag), Is.False); - Assert.That(tagSystem.HasAnyTag(sTagComponent, UnusedTag), Is.False); - - // All - Assert.That(tagSystem.HasAllTags(sTagDummy, UnusedTag), Is.False); - Assert.That(tagSystem.HasAllTags(sTagComponent, UnusedTag), Is.False); }); // Throws when checking for an unregistered tag @@ -130,49 +106,49 @@ await server.WaitAssertion(() => Assert.Multiple(() => { // Cannot add the starting tag again - Assert.That(tagSystem.AddTag(sTagDummy, sTagComponent, StartingTag), Is.False); - Assert.That(tagSystem.AddTags(sTagDummy, sTagComponent, StartingTag, StartingTag), Is.False); - Assert.That(tagSystem.AddTags(sTagDummy, sTagComponent, new List { StartingTag, StartingTag }), Is.False); + Assert.That(tagSystem.AddTag((sTagDummy, sTagComponent), StartingTag), Is.False); + Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), StartingTag, StartingTag), Is.False); + Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), new List> { StartingTag, StartingTag }), Is.False); // Has the starting tag Assert.That(tagSystem.HasTag(sTagComponent, StartingTag), Is.True); Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag, StartingTag), Is.True); - Assert.That(tagSystem.HasAllTags(sTagComponent, new List { StartingTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { StartingTag, StartingTag }), Is.True); Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag, StartingTag), Is.True); - Assert.That(tagSystem.HasAnyTag(sTagComponent, new List { StartingTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { StartingTag, StartingTag }), Is.True); // Does not have the added tag yet Assert.That(tagSystem.HasTag(sTagComponent, AddedTag), Is.False); Assert.That(tagSystem.HasAllTags(sTagComponent, AddedTag, AddedTag), Is.False); - Assert.That(tagSystem.HasAllTags(sTagComponent, new List { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { AddedTag, AddedTag }), Is.False); Assert.That(tagSystem.HasAnyTag(sTagComponent, AddedTag, AddedTag), Is.False); - Assert.That(tagSystem.HasAnyTag(sTagComponent, new List { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { AddedTag, AddedTag }), Is.False); // Has a combination of the two tags Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag, AddedTag), Is.True); - Assert.That(tagSystem.HasAnyTag(sTagComponent, new List { StartingTag, AddedTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { StartingTag, AddedTag }), Is.True); // Does not have both tags Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag, AddedTag), Is.False); - Assert.That(tagSystem.HasAllTags(sTagComponent, new List { StartingTag, AddedTag }), Is.False); + Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { StartingTag, AddedTag }), Is.False); // Cannot remove a tag that does not exist - Assert.That(tagSystem.RemoveTag(sTagDummy, sTagComponent, AddedTag), Is.False); - Assert.That(tagSystem.RemoveTags(sTagDummy, sTagComponent, AddedTag, AddedTag), Is.False); - Assert.That(tagSystem.RemoveTags(sTagDummy, sTagComponent, new List { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.RemoveTag((sTagDummy, sTagComponent), AddedTag), Is.False); + Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), AddedTag, AddedTag), Is.False); + Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), new List> { AddedTag, AddedTag }), Is.False); }); // Can add the new tag - Assert.That(tagSystem.AddTag(sTagDummy, sTagComponent, AddedTag), Is.True); + Assert.That(tagSystem.AddTag((sTagDummy, sTagComponent), AddedTag), Is.True); Assert.Multiple(() => { // Cannot add it twice - Assert.That(tagSystem.AddTag(sTagDummy, sTagComponent, AddedTag), Is.False); + Assert.That(tagSystem.AddTag((sTagDummy, sTagComponent), AddedTag), Is.False); // Cannot add existing tags - Assert.That(tagSystem.AddTags(sTagDummy, sTagComponent, StartingTag, AddedTag), Is.False); - Assert.That(tagSystem.AddTags(sTagDummy, sTagComponent, new List { StartingTag, AddedTag }), Is.False); + Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), StartingTag, AddedTag), Is.False); + Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), new List> { StartingTag, AddedTag }), Is.False); // Now has two tags Assert.That(sTagComponent.Tags, Has.Count.EqualTo(2)); @@ -182,8 +158,8 @@ await server.WaitAssertion(() => Assert.That(tagSystem.HasTag(sTagComponent, AddedTag), Is.True); Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag, StartingTag), Is.True); Assert.That(tagSystem.HasAllTags(sTagComponent, AddedTag, StartingTag), Is.True); - Assert.That(tagSystem.HasAllTags(sTagComponent, new List { StartingTag, AddedTag }), Is.True); - Assert.That(tagSystem.HasAllTags(sTagComponent, new List { AddedTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { StartingTag, AddedTag }), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { AddedTag, StartingTag }), Is.True); Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag, AddedTag), Is.True); Assert.That(tagSystem.HasAnyTag(sTagComponent, AddedTag, StartingTag), Is.True); }); @@ -191,16 +167,16 @@ await server.WaitAssertion(() => Assert.Multiple(() => { // Remove the existing starting tag - Assert.That(tagSystem.RemoveTag(sTagDummy, sTagComponent, StartingTag), Is.True); + Assert.That(tagSystem.RemoveTag((sTagDummy, sTagComponent), StartingTag), Is.True); // Remove the existing added tag - Assert.That(tagSystem.RemoveTags(sTagDummy, sTagComponent, AddedTag, AddedTag), Is.True); + Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), AddedTag, AddedTag), Is.True); }); Assert.Multiple(() => { // No tags left to remove - Assert.That(tagSystem.RemoveTags(sTagDummy, sTagComponent, new List { StartingTag, AddedTag }), Is.False); + Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), new List> { StartingTag, AddedTag }), Is.False); // No tags left in the component Assert.That(sTagComponent.Tags, Is.Empty); @@ -222,20 +198,12 @@ await server.WaitAssertion(() => // Any Assert.Throws(() => - { - tagSystem.HasAnyTag(sTagDummy, UnregisteredTag); - }); - Assert.Throws(() => { tagSystem.HasAnyTag(sTagComponent, UnregisteredTag); }); // All Assert.Throws(() => - { - tagSystem.HasAllTags(sTagDummy, UnregisteredTag); - }); - Assert.Throws(() => { tagSystem.HasAllTags(sTagComponent, UnregisteredTag); }); From d75a4cfd5b686507db1d96be994050c42881679d Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 25 May 2024 17:49:26 +1000 Subject: [PATCH 4/8] Fixed params methods recursion --- Content.Shared/Tag/TagSystem.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Content.Shared/Tag/TagSystem.cs b/Content.Shared/Tag/TagSystem.cs index c7d2e021ecbc..41a0b8f0abbf 100644 --- a/Content.Shared/Tag/TagSystem.cs +++ b/Content.Shared/Tag/TagSystem.cs @@ -55,7 +55,7 @@ public bool AddTag(EntityUid entityUid, ProtoId tag) /// public bool AddTags(EntityUid entityUid, params ProtoId[] tags) { - return AddTags(entityUid, tags); + return AddTags(entityUid, (IEnumerable>)tags); } /// @@ -100,7 +100,7 @@ public bool TryAddTag(EntityUid entityUid, ProtoId tag) /// public bool TryAddTags(EntityUid entityUid, params ProtoId[] tags) { - return TryAddTags(entityUid, tags); + return TryAddTags(entityUid, (IEnumerable>)tags); } /// @@ -145,7 +145,7 @@ public bool HasTag(EntityUid entityUid, ProtoId tag) /// public bool HasAllTags(EntityUid entityUid, params ProtoId[] tags) { - return HasAllTags(entityUid, tags); + return HasAllTags(entityUid, (IEnumerable>)tags); } /// @@ -174,7 +174,7 @@ public bool HasAllTags(EntityUid entityUid, IEnumerable> t /// public bool HasAnyTag(EntityUid entityUid, params ProtoId[] tags) { - return HasAnyTag(entityUid, tags); + return HasAnyTag(entityUid, (IEnumerable>)tags); } /// @@ -220,7 +220,7 @@ public bool HasTag(TagComponent component, ProtoId tag) /// public bool HasAllTags(TagComponent component, params ProtoId[] tags) { - return HasAllTags(component, tags); + return HasAllTags(component, (IEnumerable>)tags); } /// @@ -257,7 +257,7 @@ public bool HasAllTags(TagComponent component, IEnumerable /// public bool HasAnyTag(TagComponent component, params ProtoId[] tags) { - return HasAnyTag(component, tags); + return HasAnyTag(component, (IEnumerable>) tags); } /// @@ -309,7 +309,7 @@ public bool RemoveTag(EntityUid entityUid, ProtoId tag) /// public bool RemoveTags(EntityUid entityUid, params ProtoId[] tags) { - return RemoveTags(entityUid, tags); + return RemoveTags(entityUid, (IEnumerable>)tags); } /// @@ -359,7 +359,7 @@ public bool AddTag(Entity entity, ProtoId tag) /// public bool AddTags(Entity entity, params ProtoId[] tags) { - return AddTags(entity, tags); + return AddTags(entity, (IEnumerable>)tags); } /// @@ -423,7 +423,7 @@ public bool RemoveTag(Entity entity, ProtoId tag) /// public bool RemoveTags(Entity entity, params ProtoId[] tags) { - return RemoveTags(entity, tags); + return RemoveTags(entity, (IEnumerable>)tags); } /// From 68462b6c32ec461a02830acec41a4fb4e12fbec9 Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:12:33 +1000 Subject: [PATCH 5/8] Revert has All/Any tag one argument realisation --- Content.Shared/Tag/TagSystem.cs | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/Content.Shared/Tag/TagSystem.cs b/Content.Shared/Tag/TagSystem.cs index 41a0b8f0abbf..8a6832d1a398 100644 --- a/Content.Shared/Tag/TagSystem.cs +++ b/Content.Shared/Tag/TagSystem.cs @@ -134,6 +134,18 @@ public bool HasTag(EntityUid entityUid, ProtoId tag) HasTag(component, tag); } + /// + /// Checks if a tag has been added to an entity. + /// + /// + /// true if it exists, false otherwise. + /// + /// + /// Thrown if no exists with the given id. + /// + public bool HasAllTags(EntityUid entityUid, ProtoId tag) => + HasTag(entityUid, tag); + /// /// Checks if all of the given tags have been added to an entity. /// @@ -163,6 +175,18 @@ public bool HasAllTags(EntityUid entityUid, IEnumerable> t HasAllTags(component, tags); } + /// + /// Checks if a tag has been added to an entity. + /// + /// + /// true if it exists, false otherwise. + /// + /// + /// Thrown if no exists with the given id. + /// + public bool HasAnyTag(EntityUid entityUid, ProtoId tag) => + HasTag(entityUid, tag); + /// /// Checks if any of the given tags have been added to an entity. /// @@ -209,6 +233,18 @@ public bool HasTag(TagComponent component, ProtoId tag) return component.Tags.Contains(tag); } + /// + /// Checks if a tag has been added to an component. + /// + /// + /// true if it exists, false otherwise. + /// + /// + /// Thrown if no exists with the given id. + /// + public bool HasAllTags(TagComponent component, ProtoId tag) => + HasTag(component, tag); + /// /// Checks if all of the given tags have been added to an component. /// @@ -246,6 +282,18 @@ public bool HasAllTags(TagComponent component, IEnumerable return true; } + /// + /// Checks if a tag has been added to an component. + /// + /// + /// true if it exists, false otherwise. + /// + /// + /// Thrown if no exists with the given id. + /// + public bool HasAnyTag(TagComponent component, ProtoId tag) => + HasTag(component, tag); + /// /// Checks if any of the given tags have been added to an component. /// From f517d66dae6f7ae7b1de6a14324b849032bf56f6 Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:20:16 +1000 Subject: [PATCH 6/8] Updated tag integration tests --- Content.IntegrationTests/Tests/Tag/TagTest.cs | 60 +++++++++++++++---- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/Content.IntegrationTests/Tests/Tag/TagTest.cs b/Content.IntegrationTests/Tests/Tag/TagTest.cs index fb4adcaaefbe..075fa3148852 100644 --- a/Content.IntegrationTests/Tests/Tag/TagTest.cs +++ b/Content.IntegrationTests/Tests/Tag/TagTest.cs @@ -53,11 +53,13 @@ public async Task TagComponentTest() EntityUid sTagDummy = default; TagComponent sTagComponent = null!; + Entity sTagEntity = default; await server.WaitPost(() => { sTagDummy = sEntityManager.SpawnEntity(TagEntityId, MapCoordinates.Nullspace); sTagComponent = sEntityManager.GetComponent(sTagDummy); + sTagEntity = new Entity(sTagDummy, sTagEntity); }); await server.WaitAssertion(() => @@ -73,6 +75,14 @@ await server.WaitAssertion(() => // Single Assert.That(tagSystem.HasTag(sTagDummy, StartingTag)); Assert.That(tagSystem.HasTag(sTagComponent, StartingTag)); + + // Any + Assert.That(tagSystem.HasAnyTag(sTagDummy, StartingTag)); + Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag)); + + // All + Assert.That(tagSystem.HasAllTags(sTagDummy, StartingTag)); + Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag)); }); // Does not have the added tag @@ -84,6 +94,14 @@ await server.WaitAssertion(() => // Single Assert.That(tagSystem.HasTag(sTagDummy, AddedTag), Is.False); Assert.That(tagSystem.HasTag(sTagComponent, AddedTag), Is.False); + + // Any + Assert.That(tagSystem.HasAnyTag(sTagDummy, AddedTag), Is.False); + Assert.That(tagSystem.HasAnyTag(sTagComponent, AddedTag), Is.False); + + // All + Assert.That(tagSystem.HasAllTags(sTagDummy, AddedTag), Is.False); + Assert.That(tagSystem.HasAllTags(sTagComponent, AddedTag), Is.False); }); // Does not have the unused tag @@ -95,6 +113,14 @@ await server.WaitAssertion(() => // Single Assert.That(tagSystem.HasTag(sTagDummy, UnusedTag), Is.False); Assert.That(tagSystem.HasTag(sTagComponent, UnusedTag), Is.False); + + // Any + Assert.That(tagSystem.HasAnyTag(sTagDummy, UnusedTag), Is.False); + Assert.That(tagSystem.HasAnyTag(sTagComponent, UnusedTag), Is.False); + + // All + Assert.That(tagSystem.HasAllTags(sTagDummy, UnusedTag), Is.False); + Assert.That(tagSystem.HasAllTags(sTagComponent, UnusedTag), Is.False); }); // Throws when checking for an unregistered tag @@ -106,9 +132,9 @@ await server.WaitAssertion(() => Assert.Multiple(() => { // Cannot add the starting tag again - Assert.That(tagSystem.AddTag((sTagDummy, sTagComponent), StartingTag), Is.False); - Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), StartingTag, StartingTag), Is.False); - Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), new List> { StartingTag, StartingTag }), Is.False); + Assert.That(tagSystem.AddTag(sTagEntity, StartingTag), Is.False); + Assert.That(tagSystem.AddTags(sTagEntity, StartingTag, StartingTag), Is.False); + Assert.That(tagSystem.AddTags(sTagEntity, new List> { StartingTag, StartingTag }), Is.False); // Has the starting tag Assert.That(tagSystem.HasTag(sTagComponent, StartingTag), Is.True); @@ -133,22 +159,22 @@ await server.WaitAssertion(() => Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { StartingTag, AddedTag }), Is.False); // Cannot remove a tag that does not exist - Assert.That(tagSystem.RemoveTag((sTagDummy, sTagComponent), AddedTag), Is.False); - Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), AddedTag, AddedTag), Is.False); - Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), new List> { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.RemoveTag(sTagEntity, AddedTag), Is.False); + Assert.That(tagSystem.RemoveTags(sTagEntity, AddedTag, AddedTag), Is.False); + Assert.That(tagSystem.RemoveTags(sTagEntity, new List> { AddedTag, AddedTag }), Is.False); }); // Can add the new tag - Assert.That(tagSystem.AddTag((sTagDummy, sTagComponent), AddedTag), Is.True); + Assert.That(tagSystem.AddTag(sTagEntity, AddedTag), Is.True); Assert.Multiple(() => { // Cannot add it twice - Assert.That(tagSystem.AddTag((sTagDummy, sTagComponent), AddedTag), Is.False); + Assert.That(tagSystem.AddTag(sTagEntity, AddedTag), Is.False); // Cannot add existing tags - Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), StartingTag, AddedTag), Is.False); - Assert.That(tagSystem.AddTags((sTagDummy, sTagComponent), new List> { StartingTag, AddedTag }), Is.False); + Assert.That(tagSystem.AddTags(sTagEntity, StartingTag, AddedTag), Is.False); + Assert.That(tagSystem.AddTags(sTagEntity, new List> { StartingTag, AddedTag }), Is.False); // Now has two tags Assert.That(sTagComponent.Tags, Has.Count.EqualTo(2)); @@ -167,16 +193,16 @@ await server.WaitAssertion(() => Assert.Multiple(() => { // Remove the existing starting tag - Assert.That(tagSystem.RemoveTag((sTagDummy, sTagComponent), StartingTag), Is.True); + Assert.That(tagSystem.RemoveTag(sTagEntity, StartingTag), Is.True); // Remove the existing added tag - Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), AddedTag, AddedTag), Is.True); + Assert.That(tagSystem.RemoveTags(sTagEntity, AddedTag, AddedTag), Is.True); }); Assert.Multiple(() => { // No tags left to remove - Assert.That(tagSystem.RemoveTags((sTagDummy, sTagComponent), new List> { StartingTag, AddedTag }), Is.False); + Assert.That(tagSystem.RemoveTags(sTagEntity, new List> { StartingTag, AddedTag }), Is.False); // No tags left in the component Assert.That(sTagComponent.Tags, Is.Empty); @@ -198,12 +224,20 @@ await server.WaitAssertion(() => // Any Assert.Throws(() => + { + tagSystem.HasAnyTag(sTagDummy, UnregisteredTag); + }); + Assert.Throws(() => { tagSystem.HasAnyTag(sTagComponent, UnregisteredTag); }); // All Assert.Throws(() => + { + tagSystem.HasAllTags(sTagDummy, UnregisteredTag); + }); + Assert.Throws(() => { tagSystem.HasAllTags(sTagComponent, UnregisteredTag); }); From a9eacb1e118d33d41d16840bb75ce887e6baa1c8 Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:40:45 +1000 Subject: [PATCH 7/8] Shit happens --- Content.IntegrationTests/Tests/Tag/TagTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.IntegrationTests/Tests/Tag/TagTest.cs b/Content.IntegrationTests/Tests/Tag/TagTest.cs index 075fa3148852..70c42ad6e09b 100644 --- a/Content.IntegrationTests/Tests/Tag/TagTest.cs +++ b/Content.IntegrationTests/Tests/Tag/TagTest.cs @@ -59,7 +59,7 @@ await server.WaitPost(() => { sTagDummy = sEntityManager.SpawnEntity(TagEntityId, MapCoordinates.Nullspace); sTagComponent = sEntityManager.GetComponent(sTagDummy); - sTagEntity = new Entity(sTagDummy, sTagEntity); + sTagEntity = new Entity(sTagDummy, sTagComponent); }); await server.WaitAssertion(() => From 6dc1608fa05a2c2c215549d16c36d6e9f28ae77f Mon Sep 17 00:00:00 2001 From: Tornado Tech <54727692+Tornado-Technology@users.noreply.github.com> Date: Sat, 1 Jun 2024 20:00:33 +1000 Subject: [PATCH 8/8] Added individual List/HashSet methods, docs, tests --- Content.IntegrationTests/Tests/Tag/TagTest.cs | 117 +++++++--- Content.Shared/Tag/TagSystem.cs | 214 +++++++++++++++++- 2 files changed, 295 insertions(+), 36 deletions(-) diff --git a/Content.IntegrationTests/Tests/Tag/TagTest.cs b/Content.IntegrationTests/Tests/Tag/TagTest.cs index 70c42ad6e09b..e6cd2accaf56 100644 --- a/Content.IntegrationTests/Tests/Tag/TagTest.cs +++ b/Content.IntegrationTests/Tests/Tag/TagTest.cs @@ -133,35 +133,49 @@ await server.WaitAssertion(() => { // Cannot add the starting tag again Assert.That(tagSystem.AddTag(sTagEntity, StartingTag), Is.False); + Assert.That(tagSystem.AddTags(sTagEntity, StartingTag, StartingTag), Is.False); Assert.That(tagSystem.AddTags(sTagEntity, new List> { StartingTag, StartingTag }), Is.False); + Assert.That(tagSystem.AddTags(sTagEntity, new HashSet> { StartingTag, StartingTag }), Is.False); // Has the starting tag Assert.That(tagSystem.HasTag(sTagComponent, StartingTag), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag, StartingTag), Is.True); Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { StartingTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, new HashSet> { StartingTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag, StartingTag), Is.True); Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { StartingTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new HashSet> { StartingTag, StartingTag }), Is.True); // Does not have the added tag yet Assert.That(tagSystem.HasTag(sTagComponent, AddedTag), Is.False); + Assert.That(tagSystem.HasAllTags(sTagComponent, AddedTag, AddedTag), Is.False); Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.HasAllTags(sTagComponent, new HashSet> { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.HasAnyTag(sTagComponent, AddedTag, AddedTag), Is.False); Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new HashSet> { AddedTag, AddedTag }), Is.False); // Has a combination of the two tags Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag, AddedTag), Is.True); Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { StartingTag, AddedTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new HashSet> { StartingTag, AddedTag }), Is.True); // Does not have both tags Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag, AddedTag), Is.False); Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { StartingTag, AddedTag }), Is.False); + Assert.That(tagSystem.HasAllTags(sTagComponent, new HashSet> { StartingTag, AddedTag }), Is.False); // Cannot remove a tag that does not exist Assert.That(tagSystem.RemoveTag(sTagEntity, AddedTag), Is.False); + Assert.That(tagSystem.RemoveTags(sTagEntity, AddedTag, AddedTag), Is.False); Assert.That(tagSystem.RemoveTags(sTagEntity, new List> { AddedTag, AddedTag }), Is.False); + Assert.That(tagSystem.RemoveTags(sTagEntity, new HashSet> { AddedTag, AddedTag }), Is.False); }); // Can add the new tag @@ -175,6 +189,7 @@ await server.WaitAssertion(() => // Cannot add existing tags Assert.That(tagSystem.AddTags(sTagEntity, StartingTag, AddedTag), Is.False); Assert.That(tagSystem.AddTags(sTagEntity, new List> { StartingTag, AddedTag }), Is.False); + Assert.That(tagSystem.AddTags(sTagEntity, new HashSet> { StartingTag, AddedTag }), Is.False); // Now has two tags Assert.That(sTagComponent.Tags, Has.Count.EqualTo(2)); @@ -182,12 +197,20 @@ await server.WaitAssertion(() => // Has both tags Assert.That(tagSystem.HasTag(sTagComponent, StartingTag), Is.True); Assert.That(tagSystem.HasTag(sTagComponent, AddedTag), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, StartingTag, StartingTag), Is.True); Assert.That(tagSystem.HasAllTags(sTagComponent, AddedTag, StartingTag), Is.True); Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { StartingTag, AddedTag }), Is.True); Assert.That(tagSystem.HasAllTags(sTagComponent, new List> { AddedTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, new HashSet> { StartingTag, AddedTag }), Is.True); + Assert.That(tagSystem.HasAllTags(sTagComponent, new HashSet> { AddedTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, StartingTag, AddedTag), Is.True); Assert.That(tagSystem.HasAnyTag(sTagComponent, AddedTag, StartingTag), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { StartingTag, AddedTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new List> { AddedTag, StartingTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new HashSet> { StartingTag, AddedTag }), Is.True); + Assert.That(tagSystem.HasAnyTag(sTagComponent, new HashSet> { AddedTag, StartingTag }), Is.True); }); Assert.Multiple(() => @@ -208,39 +231,69 @@ await server.WaitAssertion(() => Assert.That(sTagComponent.Tags, Is.Empty); }); -#if !DEBUG - return; + // It is run only in DEBUG build, + // as the checks are performed only in DEBUG build. +#if DEBUG + // Has single + Assert.Throws(() => { tagSystem.HasTag(sTagDummy, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasTag(sTagComponent, UnregisteredTag); }); + + // HasAny entityUid methods + Assert.Throws(() => { tagSystem.HasAnyTag(sTagDummy, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAnyTag(sTagDummy, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAnyTag(sTagDummy, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.HasAnyTag(sTagDummy, new HashSet> { UnregisteredTag }); }); + + // HasAny component methods + Assert.Throws(() => { tagSystem.HasAnyTag(sTagComponent, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAnyTag(sTagComponent, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAnyTag(sTagComponent, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.HasAnyTag(sTagComponent, new HashSet> { UnregisteredTag }); }); + + // HasAll entityUid methods + Assert.Throws(() => { tagSystem.HasAllTags(sTagDummy, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAllTags(sTagDummy, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAllTags(sTagDummy, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.HasAllTags(sTagDummy, new HashSet> { UnregisteredTag }); }); + + // HasAll component methods + Assert.Throws(() => { tagSystem.HasAllTags(sTagComponent, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAllTags(sTagComponent, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.HasAllTags(sTagComponent, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.HasAllTags(sTagComponent, new HashSet> { UnregisteredTag }); }); + + // RemoveTag single + Assert.Throws(() => { tagSystem.RemoveTag(sTagDummy, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.RemoveTag(sTagEntity, UnregisteredTag); }); + + // RemoveTags entityUid methods + Assert.Throws(() => { tagSystem.RemoveTags(sTagDummy, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.RemoveTags(sTagDummy, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.RemoveTags(sTagDummy, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.RemoveTags(sTagDummy, new HashSet> { UnregisteredTag }); }); + + // RemoveTags entity methods + Assert.Throws(() => { tagSystem.RemoveTags(sTagEntity, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.RemoveTags(sTagEntity, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.RemoveTags(sTagEntity, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.RemoveTags(sTagEntity, new HashSet> { UnregisteredTag }); }); + + // AddTag single + Assert.Throws(() => { tagSystem.AddTag(sTagDummy, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.AddTag(sTagEntity, UnregisteredTag); }); + + // AddTags entityUid methods + Assert.Throws(() => { tagSystem.AddTags(sTagDummy, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.AddTags(sTagDummy, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.AddTags(sTagDummy, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.AddTags(sTagDummy, new HashSet> { UnregisteredTag }); }); + + // AddTags entity methods + Assert.Throws(() => { tagSystem.AddTags(sTagEntity, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.AddTags(sTagEntity, UnregisteredTag, UnregisteredTag); }); + Assert.Throws(() => { tagSystem.AddTags(sTagEntity, new List> { UnregisteredTag }); }); + Assert.Throws(() => { tagSystem.AddTags(sTagEntity, new HashSet> { UnregisteredTag }); }); #endif - - // Single - Assert.Throws(() => - { - tagSystem.HasTag(sTagDummy, UnregisteredTag); - }); - Assert.Throws(() => - { - tagSystem.HasTag(sTagComponent, UnregisteredTag); - }); - - // Any - Assert.Throws(() => - { - tagSystem.HasAnyTag(sTagDummy, UnregisteredTag); - }); - Assert.Throws(() => - { - tagSystem.HasAnyTag(sTagComponent, UnregisteredTag); - }); - - // All - Assert.Throws(() => - { - tagSystem.HasAllTags(sTagDummy, UnregisteredTag); - }); - Assert.Throws(() => - { - tagSystem.HasAllTags(sTagComponent, UnregisteredTag); - }); }); await pair.CleanReturnAsync(); } diff --git a/Content.Shared/Tag/TagSystem.cs b/Content.Shared/Tag/TagSystem.cs index 8a6832d1a398..f1f620a69494 100644 --- a/Content.Shared/Tag/TagSystem.cs +++ b/Content.Shared/Tag/TagSystem.cs @@ -3,6 +3,17 @@ namespace Content.Shared.Tag; +/// +/// The system that is responsible for working with tags. +/// Checking the existence of the only happens in DEBUG builds, +/// to improve performance, so don't forget to check it. +/// +/// +/// The methods to add or remove a list of tags have only an implementation with the type, +/// it's not much, but it takes away performance, +/// if you need to use them often, it's better to make a proper implementation, +/// you can read more HERE. +/// public sealed class TagSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _proto = default!; @@ -157,7 +168,38 @@ public bool HasAllTags(EntityUid entityUid, ProtoId tag) => /// public bool HasAllTags(EntityUid entityUid, params ProtoId[] tags) { - return HasAllTags(entityUid, (IEnumerable>)tags); + return _tagQuery.TryComp(entityUid, out var component) && + HasAllTags(component, tags); + } + + /// + /// Checks if all of the given tags have been added to an entity. + /// + /// + /// true if they all exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(EntityUid entityUid, HashSet> tags) + { + return _tagQuery.TryComp(entityUid, out var component) && + HasAllTags(component, tags); + } + + /// + /// Checks if all of the given tags have been added to an entity. + /// + /// + /// true if they all exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(EntityUid entityUid, List> tags) + { + return _tagQuery.TryComp(entityUid, out var component) && + HasAllTags(component, tags); } /// @@ -198,7 +240,38 @@ public bool HasAnyTag(EntityUid entityUid, ProtoId tag) => /// public bool HasAnyTag(EntityUid entityUid, params ProtoId[] tags) { - return HasAnyTag(entityUid, (IEnumerable>)tags); + return _tagQuery.TryComp(entityUid, out var component) && + HasAnyTag(component, tags); + } + + /// + /// Checks if any of the given tags have been added to an entity. + /// + /// + /// true if any of them exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(EntityUid entityUid, HashSet> tags) + { + return _tagQuery.TryComp(entityUid, out var component) && + HasAnyTag(component, tags); + } + + /// + /// Checks if any of the given tags have been added to an entity. + /// + /// + /// true if any of them exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(EntityUid entityUid, List> tags) + { + return _tagQuery.TryComp(entityUid, out var component) && + HasAnyTag(component, tags); } /// @@ -256,7 +329,85 @@ public bool HasAllTags(TagComponent component, ProtoId tag) => /// public bool HasAllTags(TagComponent component, params ProtoId[] tags) { - return HasAllTags(component, (IEnumerable>)tags); + foreach (var tag in tags) + { +#if DEBUG + AssertValidTag(tag); +#endif + if (!component.Tags.Contains(tag)) + return false; + } + + return true; + } + + /// + /// Checks if all of the given tags have been added to an component. + /// + /// + /// true if they all exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTagsArray(TagComponent component, ProtoId[] tags) + { + foreach (var tag in tags) + { +#if DEBUG + AssertValidTag(tag); +#endif + if (!component.Tags.Contains(tag)) + return false; + } + + return true; + } + + /// + /// Checks if all of the given tags have been added to an component. + /// + /// + /// true if they all exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(TagComponent component, List> tags) + { + foreach (var tag in tags) + { +#if DEBUG + AssertValidTag(tag); +#endif + if (!component.Tags.Contains(tag)) + return false; + } + + return true; + } + + /// + /// Checks if all of the given tags have been added to an component. + /// + /// + /// true if they all exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAllTags(TagComponent component, HashSet> tags) + { + foreach (var tag in tags) + { +#if DEBUG + AssertValidTag(tag); +#endif + if (!component.Tags.Contains(tag)) + return false; + } + + return true; } /// @@ -305,7 +456,62 @@ public bool HasAnyTag(TagComponent component, ProtoId tag) => /// public bool HasAnyTag(TagComponent component, params ProtoId[] tags) { - return HasAnyTag(component, (IEnumerable>) tags); + foreach (var tag in tags) + { +#if DEBUG + AssertValidTag(tag); +#endif + if (component.Tags.Contains(tag)) + return true; + } + + return false; + } + + /// + /// Checks if any of the given tags have been added to an component. + /// + /// + /// true if any of them exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(TagComponent component, HashSet> tags) + { + foreach (var tag in tags) + { +#if DEBUG + AssertValidTag(tag); +#endif + if (component.Tags.Contains(tag)) + return true; + } + + return false; + } + + /// + /// Checks if any of the given tags have been added to an component. + /// + /// + /// true if any of them exist, false otherwise. + /// + /// + /// Thrown if one of the ids represents an unregistered . + /// + public bool HasAnyTag(TagComponent component, List> tags) + { + foreach (var tag in tags) + { +#if DEBUG + AssertValidTag(tag); +#endif + if (component.Tags.Contains(tag)) + return true; + } + + return false; } ///