Add tag component and test (#2761)
* Add tag component and test * Remove 0 capacity * Add tag component extensions * Change tags to be prototypes Co-authored-by: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
This commit is contained in:
@@ -228,6 +228,7 @@ namespace Content.Client
|
|||||||
"MachineFrame",
|
"MachineFrame",
|
||||||
"MachineBoard",
|
"MachineBoard",
|
||||||
"ChemicalAmmo",
|
"ChemicalAmmo",
|
||||||
|
"Tag",
|
||||||
"BiologicalSurgeryData",
|
"BiologicalSurgeryData",
|
||||||
"CargoTelepad",
|
"CargoTelepad",
|
||||||
"TraitorDeathMatchRedemption",
|
"TraitorDeathMatchRedemption",
|
||||||
|
|||||||
225
Content.IntegrationTests/Tests/Tag/TagTest.cs
Normal file
225
Content.IntegrationTests/Tests/Tag/TagTest.cs
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Content.Server.GameObjects.Components.Tag;
|
||||||
|
using Content.Shared.Prototypes.Tag;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.Map;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.IntegrationTests.Tests.Tag
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(TagComponent))]
|
||||||
|
public class TagTest : ContentIntegrationTest
|
||||||
|
{
|
||||||
|
private const string TagEntityId = "TagTestDummy";
|
||||||
|
|
||||||
|
// Register these three into the prototype manager
|
||||||
|
private const string StartingTag = "A";
|
||||||
|
private const string AddedTag = "EIOU";
|
||||||
|
private const string UnusedTag = "E";
|
||||||
|
|
||||||
|
// Do not register this one
|
||||||
|
private const string UnregisteredTag = "AAAAAAAAA";
|
||||||
|
|
||||||
|
private static readonly string Prototypes = $@"
|
||||||
|
- type: Tag
|
||||||
|
id: {StartingTag}
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: {AddedTag}
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: {UnusedTag}
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: {TagEntityId}
|
||||||
|
name: {TagEntityId}
|
||||||
|
components:
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- {StartingTag}";
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TagComponentTest()
|
||||||
|
{
|
||||||
|
var options = new ServerContentIntegrationOption {ExtraPrototypes = Prototypes};
|
||||||
|
var server = StartServerDummyTicker(options);
|
||||||
|
|
||||||
|
await server.WaitIdleAsync();
|
||||||
|
|
||||||
|
var sMapManager = server.ResolveDependency<IMapManager>();
|
||||||
|
var sEntityManager = server.ResolveDependency<IEntityManager>();
|
||||||
|
var sPrototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||||
|
|
||||||
|
IEntity sTagDummy = null!;
|
||||||
|
TagComponent sTagComponent = null!;
|
||||||
|
|
||||||
|
await server.WaitPost(() =>
|
||||||
|
{
|
||||||
|
sMapManager.CreateNewMapEntity(MapId.Nullspace);
|
||||||
|
sTagDummy = sEntityManager.SpawnEntity(TagEntityId, MapCoordinates.Nullspace);
|
||||||
|
sTagComponent = sTagDummy.GetComponent<TagComponent>();
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.WaitAssertion(() =>
|
||||||
|
{
|
||||||
|
// Has one tag, the starting tag
|
||||||
|
Assert.That(sTagComponent.Tags.Count, Is.EqualTo(1));
|
||||||
|
|
||||||
|
var startingTagPrototype = sPrototypeManager.Index<TagPrototype>(StartingTag);
|
||||||
|
Assert.That(sTagComponent.Tags, Contains.Item(startingTagPrototype));
|
||||||
|
|
||||||
|
// Single
|
||||||
|
Assert.True(sTagDummy.HasTag(StartingTag));
|
||||||
|
Assert.True(sTagComponent.HasTag(StartingTag));
|
||||||
|
|
||||||
|
// Any
|
||||||
|
Assert.True(sTagDummy.HasAnyTag(StartingTag));
|
||||||
|
Assert.True(sTagComponent.HasAnyTag(StartingTag));
|
||||||
|
|
||||||
|
// All
|
||||||
|
Assert.True(sTagDummy.HasAllTags(StartingTag));
|
||||||
|
Assert.True(sTagComponent.HasAllTags(StartingTag));
|
||||||
|
|
||||||
|
// Does not have the added tag
|
||||||
|
var addedTagPrototype = sPrototypeManager.Index<TagPrototype>(AddedTag);
|
||||||
|
Assert.That(sTagComponent.Tags, Does.Not.Contains(addedTagPrototype));
|
||||||
|
|
||||||
|
// Single
|
||||||
|
Assert.False(sTagDummy.HasTag(AddedTag));
|
||||||
|
Assert.False(sTagComponent.HasTag(AddedTag));
|
||||||
|
|
||||||
|
// Any
|
||||||
|
Assert.False(sTagDummy.HasAnyTag(AddedTag));
|
||||||
|
Assert.False(sTagComponent.HasAnyTag(AddedTag));
|
||||||
|
|
||||||
|
// All
|
||||||
|
Assert.False(sTagDummy.HasAllTags(AddedTag));
|
||||||
|
Assert.False(sTagComponent.HasAllTags(AddedTag));
|
||||||
|
|
||||||
|
// Does not have the unused tag
|
||||||
|
var unusedTagPrototype = sPrototypeManager.Index<TagPrototype>(UnusedTag);
|
||||||
|
Assert.That(sTagComponent.Tags, Does.Not.Contains(unusedTagPrototype));
|
||||||
|
|
||||||
|
// Single
|
||||||
|
Assert.False(sTagDummy.HasTag(UnusedTag));
|
||||||
|
Assert.False(sTagComponent.HasTag(UnusedTag));
|
||||||
|
|
||||||
|
// Any
|
||||||
|
Assert.False(sTagDummy.HasAnyTag(UnusedTag));
|
||||||
|
Assert.False(sTagComponent.HasAnyTag(UnusedTag));
|
||||||
|
|
||||||
|
// All
|
||||||
|
Assert.False(sTagDummy.HasAllTags(UnusedTag));
|
||||||
|
Assert.False(sTagComponent.HasAllTags(UnusedTag));
|
||||||
|
|
||||||
|
// Throws when checking for an unregistered tag
|
||||||
|
Assert.Throws<UnknownPrototypeException>(() =>
|
||||||
|
{
|
||||||
|
sPrototypeManager.Index<TagPrototype>(UnregisteredTag);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Single
|
||||||
|
Assert.Throws<UnknownPrototypeException>(() =>
|
||||||
|
{
|
||||||
|
sTagDummy.HasTag(UnregisteredTag);
|
||||||
|
});
|
||||||
|
Assert.Throws<UnknownPrototypeException>(() =>
|
||||||
|
{
|
||||||
|
sTagComponent.HasTag(UnregisteredTag);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Any
|
||||||
|
Assert.Throws<UnknownPrototypeException>(() =>
|
||||||
|
{
|
||||||
|
sTagDummy.HasAnyTag(UnregisteredTag);
|
||||||
|
});
|
||||||
|
Assert.Throws<UnknownPrototypeException>(() =>
|
||||||
|
{
|
||||||
|
sTagComponent.HasAnyTag(UnregisteredTag);
|
||||||
|
});
|
||||||
|
|
||||||
|
// All
|
||||||
|
Assert.Throws<UnknownPrototypeException>(() =>
|
||||||
|
{
|
||||||
|
sTagDummy.HasAllTags(UnregisteredTag);
|
||||||
|
});
|
||||||
|
Assert.Throws<UnknownPrototypeException>(() =>
|
||||||
|
{
|
||||||
|
sTagComponent.HasAllTags(UnregisteredTag);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cannot add the starting tag again
|
||||||
|
Assert.That(sTagComponent.AddTag(StartingTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.AddTags(StartingTag, StartingTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.AddTags(new List<string> {StartingTag, StartingTag}), Is.False);
|
||||||
|
|
||||||
|
// Has the starting tag
|
||||||
|
Assert.That(sTagComponent.HasTag(StartingTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(StartingTag, StartingTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(new List<string> {StartingTag, StartingTag}), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(StartingTag, StartingTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(new List<string> {StartingTag, StartingTag}), Is.True);
|
||||||
|
|
||||||
|
// Does not have the added tag yet
|
||||||
|
Assert.That(sTagComponent.HasTag(AddedTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(AddedTag, AddedTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(new List<string> {AddedTag, AddedTag}), Is.False);
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(AddedTag, AddedTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(new List<string> {AddedTag, AddedTag}), Is.False);
|
||||||
|
|
||||||
|
// Has a combination of the two tags
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(StartingTag, AddedTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(new List<string> {StartingTag, AddedTag}), Is.True);
|
||||||
|
|
||||||
|
// Does not have both tags
|
||||||
|
Assert.That(sTagComponent.HasAllTags(StartingTag, AddedTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(new List<string> {StartingTag, AddedTag}), Is.False);
|
||||||
|
|
||||||
|
// Cannot remove a tag that does not exist
|
||||||
|
Assert.That(sTagComponent.RemoveTag(AddedTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.RemoveTags(AddedTag, AddedTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.RemoveTags(new List<string> {AddedTag, AddedTag}), Is.False);
|
||||||
|
|
||||||
|
// Can add the new tag
|
||||||
|
Assert.That(sTagComponent.AddTag(AddedTag), Is.True);
|
||||||
|
|
||||||
|
// Cannot add it twice
|
||||||
|
Assert.That(sTagComponent.AddTag(AddedTag), Is.False);
|
||||||
|
|
||||||
|
// Cannot add existing tags
|
||||||
|
Assert.That(sTagComponent.AddTags(StartingTag, AddedTag), Is.False);
|
||||||
|
Assert.That(sTagComponent.AddTags(new List<string> {StartingTag, AddedTag}), Is.False);
|
||||||
|
|
||||||
|
// Now has two tags
|
||||||
|
Assert.That(sTagComponent.Tags.Count, Is.EqualTo(2));
|
||||||
|
|
||||||
|
// Has both tags
|
||||||
|
Assert.That(sTagComponent.HasTag(StartingTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasTag(AddedTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(StartingTag, StartingTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(AddedTag, StartingTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(new List<string> {StartingTag, AddedTag}), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAllTags(new List<string> {AddedTag, StartingTag}), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(StartingTag, AddedTag), Is.True);
|
||||||
|
Assert.That(sTagComponent.HasAnyTag(AddedTag, StartingTag), Is.True);
|
||||||
|
|
||||||
|
// Remove the existing starting tag
|
||||||
|
Assert.That(sTagComponent.RemoveTag(StartingTag), Is.True);
|
||||||
|
|
||||||
|
// Remove the existing added tag
|
||||||
|
Assert.That(sTagComponent.RemoveTags(AddedTag, AddedTag), Is.True);
|
||||||
|
|
||||||
|
// No tags left to remove
|
||||||
|
Assert.That(sTagComponent.RemoveTags(new List<string> {StartingTag, AddedTag}), Is.False);
|
||||||
|
|
||||||
|
// No tags left in the component
|
||||||
|
Assert.That(sTagComponent.Tags, Is.Empty);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
251
Content.Server/GameObjects/Components/Tag/TagComponent.cs
Normal file
251
Content.Server/GameObjects/Components/Tag/TagComponent.cs
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Content.Shared.Prototypes.Tag;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Tag
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public class TagComponent : Component
|
||||||
|
{
|
||||||
|
public override string Name => "Tag";
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private readonly HashSet<TagPrototype> _tags = new();
|
||||||
|
|
||||||
|
public IReadOnlySet<TagPrototype> Tags => _tags;
|
||||||
|
|
||||||
|
public override void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
base.ExposeData(serializer);
|
||||||
|
|
||||||
|
serializer.DataReadWriteFunction(
|
||||||
|
"tags",
|
||||||
|
null!,
|
||||||
|
(ids) =>
|
||||||
|
{
|
||||||
|
_tags.Clear();
|
||||||
|
|
||||||
|
if (ids == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddTags(ids);
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
{
|
||||||
|
var ids = new HashSet<string>();
|
||||||
|
|
||||||
|
foreach (var tag in _tags)
|
||||||
|
{
|
||||||
|
ids.Add(tag.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add a tag if it doesn't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The tag to add.</param>
|
||||||
|
/// <returns>true if it was added, false if it already existed.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if no <see cref="TagPrototype"/> exists with the given id.
|
||||||
|
/// </exception>
|
||||||
|
public bool AddTag(string id)
|
||||||
|
{
|
||||||
|
var tag = IoCManager.Resolve<IPrototypeManager>().Index<TagPrototype>(id);
|
||||||
|
|
||||||
|
return _tags.Add(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add the given tags if they don't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to add.</param>
|
||||||
|
/// <returns>true if any tags were added, false if they all already existed.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool AddTags(params string[] ids)
|
||||||
|
{
|
||||||
|
return AddTags(ids.AsEnumerable());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add the given tags if they don't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to add.</param>
|
||||||
|
/// <returns>true if any tags were added, false if they all already existed.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool AddTags(IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
var count = _tags.Count;
|
||||||
|
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
var tag = prototypeManager.Index<TagPrototype>(id);
|
||||||
|
|
||||||
|
_tags.Add(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _tags.Count > count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a tag has been added.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The tag to check for.</param>
|
||||||
|
/// <returns>true if it exists, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if no <see cref="TagPrototype"/> exists with the given id.
|
||||||
|
/// </exception>
|
||||||
|
public bool HasTag(string id)
|
||||||
|
{
|
||||||
|
var tag = IoCManager.Resolve<IPrototypeManager>().Index<TagPrototype>(id);
|
||||||
|
|
||||||
|
return _tags.Contains(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if all of the given tags have been added.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if they all exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool HasAllTags(params string[] ids)
|
||||||
|
{
|
||||||
|
return HasAllTags(ids.AsEnumerable());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if all of the given tags have been added.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if they all exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool HasAllTags(IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
var tag = prototypeManager.Index<TagPrototype>(id);
|
||||||
|
|
||||||
|
if (!_tags.Contains(tag))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if any of the given tags have been added.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if any of them exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool HasAnyTag(params string[] ids)
|
||||||
|
{
|
||||||
|
return HasAnyTag(ids.AsEnumerable());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if any of the given tags have been added.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if any of them exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool HasAnyTag(IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
var tag = prototypeManager.Index<TagPrototype>(id);
|
||||||
|
|
||||||
|
if (_tags.Contains(tag))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to remove a tag if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The tag to remove.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if it was removed, false otherwise even if it didn't exist.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if no <see cref="TagPrototype"/> exists with the given id.
|
||||||
|
/// </exception>
|
||||||
|
public bool RemoveTag(string id)
|
||||||
|
{
|
||||||
|
var tag = IoCManager.Resolve<IPrototypeManager>().Index<TagPrototype>(id);
|
||||||
|
|
||||||
|
return _tags.Remove(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to remove all of the given tags if they exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to remove.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if it was removed, false otherwise even if they didn't exist.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool RemoveTags(params string[] ids)
|
||||||
|
{
|
||||||
|
return RemoveTags(ids.AsEnumerable());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to remove all of the given tags if they exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids">The tags to remove.</param>
|
||||||
|
/// <returns>true if any tag was removed, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public bool RemoveTags(IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
var count = _tags.Count;
|
||||||
|
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
var tag = prototypeManager.Index<TagPrototype>(id);
|
||||||
|
|
||||||
|
_tags.Remove(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _tags.Count < count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Content.Shared.Prototypes.Tag;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Server.GameObjects.Components.Tag
|
||||||
|
{
|
||||||
|
public static class TagComponentExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add a tag to an entity if the tag doesn't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to add the tag to.</param>
|
||||||
|
/// <param name="id">The tag to add.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if it was added, false otherwise even if it already existed.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if no <see cref="TagPrototype"/> exists with the given id.
|
||||||
|
/// </exception>
|
||||||
|
public static bool AddTag(this IEntity entity, string id)
|
||||||
|
{
|
||||||
|
return entity.EnsureComponent(out TagComponent tagComponent) &&
|
||||||
|
tagComponent.AddTag(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add the given tags to an entity if the tags don't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to add the tag to.</param>
|
||||||
|
/// <param name="ids">The tags to add.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if any tags were added, false otherwise even if they all already existed.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool AddTags(this IEntity entity, params string[] ids)
|
||||||
|
{
|
||||||
|
return entity.EnsureComponent(out TagComponent tagComponent) &&
|
||||||
|
tagComponent.AddTags(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add the given tags to an entity if the tags don't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to add the tag to.</param>
|
||||||
|
/// <param name="ids">The tags to add.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if any tags were added, false otherwise even if they all already existed.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool AddTags(this IEntity entity, IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
return entity.EnsureComponent(out TagComponent tagComponent) &&
|
||||||
|
tagComponent.AddTags(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add a tag to an entity if it has a <see cref="TagComponent"/>
|
||||||
|
/// and the tag doesn't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to add the tag to.</param>
|
||||||
|
/// <param name="id">The tag to add.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if it was added, false otherwise even if it already existed.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if no <see cref="TagPrototype"/> exists with the given id.
|
||||||
|
/// </exception>
|
||||||
|
public static bool TryAddTag(this IEntity entity, string id)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.AddTag(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add the given tags to an entity if it has a
|
||||||
|
/// <see cref="TagComponent"/> and the tags don't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to add the tag to.</param>
|
||||||
|
/// <param name="ids">The tags to add.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if any tags were added, false otherwise even if they all already existed.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool TryAddTags(this IEntity entity, params string[] ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.AddTags(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to add the given tags to an entity if it has a
|
||||||
|
/// <see cref="TagComponent"/> and the tags don't already exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to add the tag to.</param>
|
||||||
|
/// <param name="ids">The tags to add.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if any tags were added, false otherwise even if they all already existed.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool TryAddTags(this IEntity entity, IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.AddTags(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a tag has been added to an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to check.</param>
|
||||||
|
/// <param name="id">The tag to check for.</param>
|
||||||
|
/// <returns>true if it exists, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if no <see cref="TagPrototype"/> exists with the given id.
|
||||||
|
/// </exception>
|
||||||
|
public static bool HasTag(this IEntity entity, string id)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.HasTag(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if all of the given tags have been added to an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to check.</param>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if they all exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool HasAllTags(this IEntity entity, params string[] ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.HasAllTags(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if all of the given tags have been added to an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to check.</param>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if they all exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool HasAllTags(this IEntity entity, IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.HasAllTags(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if all of the given tags have been added to an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to check.</param>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if any of them exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool HasAnyTag(this IEntity entity, params string[] ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.HasAnyTag(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if all of the given tags have been added to an entity.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to check.</param>
|
||||||
|
/// <param name="ids">The tags to check for.</param>
|
||||||
|
/// <returns>true if any of them exist, false otherwise.</returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool HasAnyTag(this IEntity entity, IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.HasAnyTag(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to remove a tag from an entity if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to remove the tag from.</param>
|
||||||
|
/// <param name="id">The tag to remove.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if it was removed, false otherwise even if it didn't exist.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if no <see cref="TagPrototype"/> exists with the given id.
|
||||||
|
/// </exception>
|
||||||
|
public static bool RemoveTag(this IEntity entity, string id)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.RemoveTag(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to remove a tag from an entity if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to remove the tag from.</param>
|
||||||
|
/// <param name="ids">The tag to remove.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if it was removed, false otherwise even if it didn't exist.
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
/// </returns>
|
||||||
|
public static bool RemoveTags(this IEntity entity, params string[] ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.RemoveTags(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to remove a tag from an entity if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entity">The entity to remove the tag from.</param>
|
||||||
|
/// <param name="ids">The tag to remove.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// true if it was removed, false otherwise even if it didn't exist.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="UnknownPrototypeException">
|
||||||
|
/// Thrown if one of the ids represents an unregistered <see cref="TagPrototype"/>.
|
||||||
|
/// </exception>
|
||||||
|
public static bool RemoveTags(this IEntity entity, IEnumerable<string> ids)
|
||||||
|
{
|
||||||
|
return entity.TryGetComponent(out TagComponent? tagComponent) &&
|
||||||
|
tagComponent.RemoveTags(ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
Content.Shared/Prototypes/Tag/TagPrototype.cs
Normal file
31
Content.Shared/Prototypes/Tag/TagPrototype.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#nullable enable
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.Interfaces.Serialization;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using YamlDotNet.RepresentationModel;
|
||||||
|
|
||||||
|
namespace Content.Shared.Prototypes.Tag
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Prototype representing a tag in YAML.
|
||||||
|
/// Meant to only have an ID property, as that is the only thing that
|
||||||
|
/// gets saved in TagComponent.
|
||||||
|
/// </summary>
|
||||||
|
[Prototype("Tag")]
|
||||||
|
public class TagPrototype : IPrototype, IIndexedPrototype, IExposeData
|
||||||
|
{
|
||||||
|
public string ID { get; [UsedImplicitly] private set; } = default!;
|
||||||
|
|
||||||
|
public void ExposeData(ObjectSerializer serializer)
|
||||||
|
{
|
||||||
|
serializer.DataField(this, x => x.ID, "id", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadFrom(YamlMappingNode mapping)
|
||||||
|
{
|
||||||
|
var serializer = YamlObjectSerializer.NewReader(mapping);
|
||||||
|
ExposeData(serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user