ECS tags (#6504)
This commit is contained in:
@@ -9,6 +9,7 @@ using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Broadphase;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Construction.Conditions
|
||||
{
|
||||
@@ -39,18 +40,23 @@ namespace Content.Shared.Construction.Conditions
|
||||
var physics = EntitySystem.Get<SharedPhysicsSystem>();
|
||||
var rUserToObj = new CollisionRay(userWorldPosition, userToObject.Normalized, (int) CollisionGroup.Impassable);
|
||||
var length = userToObject.Length;
|
||||
|
||||
var tagSystem = EntitySystem.Get<TagSystem>();
|
||||
|
||||
var userToObjRaycastResults = physics.IntersectRayWithPredicate(entManager.GetComponent<TransformComponent>(user).MapID, rUserToObj, maxLength: length,
|
||||
predicate: (e) => !e.HasTag("Wall"));
|
||||
if (!userToObjRaycastResults.Any())
|
||||
predicate: (e) => !tagSystem.HasTag(e, "Wall"));
|
||||
|
||||
var targetWall = userToObjRaycastResults.FirstOrNull();
|
||||
|
||||
if (targetWall == null)
|
||||
return false;
|
||||
|
||||
// get this wall entity
|
||||
var targetWall = userToObjRaycastResults.First().HitEntity;
|
||||
|
||||
// check that we didn't try to build wallmount that facing another adjacent wall
|
||||
var rAdjWall = new CollisionRay(objWorldPosition, directionWithOffset.Normalized, (int) CollisionGroup.Impassable);
|
||||
var adjWallRaycastResults = physics.IntersectRayWithPredicate(entManager.GetComponent<TransformComponent>(user).MapID, rAdjWall, maxLength: 0.5f,
|
||||
predicate: (e) => e == targetWall || !e.HasTag("Wall"));
|
||||
predicate: (e) => e == targetWall.Value.HitEntity || !tagSystem.HasTag(e, "Wall"));
|
||||
|
||||
return !adjWallRaycastResults.Any();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,12 @@ namespace Content.Shared.Construction.Steps
|
||||
if (!entityManager.TryGetComponent(uid, out TagComponent? tags))
|
||||
return false;
|
||||
|
||||
if (_allTags != null && !tags.HasAllTags(_allTags))
|
||||
var tagSystem = EntitySystem.Get<TagSystem>();
|
||||
|
||||
if (_allTags != null && !tagSystem.HasAllTags(tags, _allTags))
|
||||
return false; // We don't have all the tags needed.
|
||||
|
||||
if (_anyTags != null && !tags.HasAnyTag(_anyTags))
|
||||
if (_anyTags != null && !tagSystem.HasAnyTag(tags, _anyTags))
|
||||
return false; // We don't have any of the tags needed.
|
||||
|
||||
// This entity is valid!
|
||||
|
||||
@@ -12,7 +12,8 @@ namespace Content.Shared.Construction.Steps
|
||||
|
||||
public override bool EntityValid(EntityUid uid, IEntityManager entityManager)
|
||||
{
|
||||
return !string.IsNullOrEmpty(_tag) && entityManager.TryGetComponent(uid, out TagComponent? tags) && tags.HasTag(_tag);
|
||||
var tagSystem = EntitySystem.Get<TagSystem>();
|
||||
return !string.IsNullOrEmpty(_tag) && tagSystem.HasTag(uid, _tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,289 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.Tag
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class TagComponent : Component, ISerializationHooks
|
||||
[RegisterComponent, Friend(typeof(TagSystem))]
|
||||
public sealed class TagComponent : Component, ISerializationHooks
|
||||
{
|
||||
[ViewVariables]
|
||||
[DataField("tags", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<TagPrototype>))]
|
||||
private readonly HashSet<string> _tags = new();
|
||||
|
||||
public IReadOnlySet<string> Tags => _tags;
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
foreach (var tag in _tags)
|
||||
{
|
||||
GetTagOrThrow(tag);
|
||||
}
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
var tags = new string[_tags.Count];
|
||||
var i = 0;
|
||||
|
||||
foreach (var tag in _tags)
|
||||
{
|
||||
tags[i] = tag;
|
||||
}
|
||||
|
||||
return new TagComponentState(tags);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
if (curState is not TagComponentState state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_tags.Clear();
|
||||
|
||||
var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
|
||||
|
||||
foreach (var tag in state.Tags)
|
||||
{
|
||||
GetTagOrThrow(tag, prototypeManager);
|
||||
_tags.Add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
private TagPrototype GetTagOrThrow(string id, IPrototypeManager? manager = null)
|
||||
{
|
||||
manager ??= IoCManager.Resolve<IPrototypeManager>();
|
||||
return manager.Index<TagPrototype>(id);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
var added = _tags.Add(id);
|
||||
|
||||
if (added)
|
||||
{
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
GetTagOrThrow(id, prototypeManager);
|
||||
_tags.Add(id);
|
||||
}
|
||||
|
||||
if (_tags.Count > count)
|
||||
{
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
return _tags.Contains(id);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
GetTagOrThrow(id, prototypeManager);
|
||||
|
||||
if (!_tags.Contains(id))
|
||||
{
|
||||
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)
|
||||
{
|
||||
GetTagOrThrow(id, prototypeManager);
|
||||
|
||||
if (_tags.Contains(id))
|
||||
{
|
||||
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)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
|
||||
if (_tags.Remove(id))
|
||||
{
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
GetTagOrThrow(id, prototypeManager);
|
||||
_tags.Remove(id);
|
||||
}
|
||||
|
||||
if (_tags.Count < count)
|
||||
{
|
||||
Dirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public readonly HashSet<string> Tags = new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.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 EntityUid 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 EntityUid 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 EntityUid 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 EntityUid entity, string id)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, params string[] ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, string id)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, params string[] ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, params string[] ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, string id)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, params string[] ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, 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 EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return IoCManager.Resolve<IEntityManager>().TryGetComponent(entity, out TagComponent? tagComponent) &&
|
||||
tagComponent.RemoveTags(ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
501
Content.Shared/Tag/TagSystem.cs
Normal file
501
Content.Shared/Tag/TagSystem.cs
Normal file
@@ -0,0 +1,501 @@
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Tag;
|
||||
|
||||
public sealed class TagSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<TagComponent, ComponentInit>(OnTagInit);
|
||||
SubscribeLocalEvent<TagComponent, ComponentGetState>(OnTagGetState);
|
||||
SubscribeLocalEvent<TagComponent, ComponentHandleState>(OnTagHandleState);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GetTagOrThrow(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 OnTagInit(EntityUid uid, TagComponent component, ComponentInit args)
|
||||
{
|
||||
foreach (var tag in component.Tags)
|
||||
{
|
||||
GetTagOrThrow(tag);
|
||||
}
|
||||
}
|
||||
|
||||
private TagPrototype GetTagOrThrow(string id)
|
||||
{
|
||||
return _proto.Index<TagPrototype>(id);
|
||||
}
|
||||
|
||||
/// <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 bool AddTag(EntityUid entity, string id)
|
||||
{
|
||||
return EntityManager.EnsureComponent<TagComponent>(entity, out var component) &&
|
||||
AddTag(component, 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 bool AddTags(EntityUid entity, params string[] ids)
|
||||
{
|
||||
return EntityManager.EnsureComponent<TagComponent>(entity, out var component) &&
|
||||
AddTags(component, 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 bool AddTags(EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return EntityManager.EnsureComponent<TagComponent>(entity, out var component) &&
|
||||
AddTags(component, 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 bool TryAddTag(EntityUid entity, string id)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
AddTag(component, 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 bool TryAddTags(EntityUid entity, params string[] ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
AddTags(component, 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 bool TryAddTags(EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
AddTags(component, 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 bool HasTag(EntityUid entity, string id)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
HasTag(component, 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 bool HasAllTags(EntityUid entity, params string[] ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
HasAllTags(component, 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 bool HasAllTags(EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
HasAllTags(component, 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 bool HasAnyTag(EntityUid entity, params string[] ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
HasAnyTag(component, 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 bool HasAnyTag(EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
HasAnyTag(component, 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 bool RemoveTag(EntityUid entity, string id)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
RemoveTag(component, 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 bool RemoveTags(EntityUid entity, params string[] ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
RemoveTags(component, 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 bool RemoveTags(EntityUid entity, IEnumerable<string> ids)
|
||||
{
|
||||
return TryComp<TagComponent>(entity, out var component) &&
|
||||
RemoveTags(component, 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(TagComponent component, string id)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
var added = component.Tags.Add(id);
|
||||
|
||||
if (added)
|
||||
{
|
||||
Dirty(component);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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(TagComponent component, params string[] ids)
|
||||
{
|
||||
return AddTags(component, 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(TagComponent component, IEnumerable<string> ids)
|
||||
{
|
||||
var count = component.Tags.Count;
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
component.Tags.Add(id);
|
||||
}
|
||||
|
||||
if (component.Tags.Count > count)
|
||||
{
|
||||
Dirty(component);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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(TagComponent component, string id)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
return component.Tags.Contains(id);
|
||||
}
|
||||
|
||||
/// <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(TagComponent component, params string[] ids)
|
||||
{
|
||||
return HasAllTags(component, 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(TagComponent component, IEnumerable<string> ids)
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
|
||||
if (!component.Tags.Contains(id))
|
||||
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(TagComponent component, params string[] ids)
|
||||
{
|
||||
return HasAnyTag(component, 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(TagComponent component, IEnumerable<string> ids)
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
|
||||
if (component.Tags.Contains(id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to remove a tag if it exists.
|
||||
/// </summary>
|
||||
/// <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(TagComponent component, string id)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
|
||||
if (component.Tags.Remove(id))
|
||||
{
|
||||
Dirty(component);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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(TagComponent component, params string[] ids)
|
||||
{
|
||||
return RemoveTags(component, 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(TagComponent component, IEnumerable<string> ids)
|
||||
{
|
||||
var count = component.Tags.Count;
|
||||
|
||||
foreach (var id in ids)
|
||||
{
|
||||
GetTagOrThrow(id);
|
||||
component.Tags.Remove(id);
|
||||
}
|
||||
|
||||
if (component.Tags.Count < count)
|
||||
{
|
||||
Dirty(component);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -72,10 +72,11 @@ namespace Content.Shared.Whitelist
|
||||
public bool IsValid(EntityUid uid, IEntityManager? entityManager = null)
|
||||
{
|
||||
entityManager ??= IoCManager.Resolve<IEntityManager>();
|
||||
var tagSystem = EntitySystem.Get<TagSystem>();
|
||||
|
||||
if (Tags != null && entityManager.TryGetComponent(uid, out TagComponent? tags))
|
||||
{
|
||||
if (tags.HasAnyTag(Tags))
|
||||
if (tagSystem.HasAnyTag(tags, Tags))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user