mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Remove IContainer and move some functions to the system (#4351)
This commit is contained in:
@@ -11,7 +11,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using static Robust.Shared.Containers.ContainerManagerComponent;
|
||||
|
||||
namespace Robust.Client.GameObjects
|
||||
@@ -25,7 +24,7 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
private readonly HashSet<EntityUid> _updateQueue = new();
|
||||
|
||||
public readonly Dictionary<EntityUid, IContainer> ExpectedEntities = new();
|
||||
public readonly Dictionary<EntityUid, BaseContainer> ExpectedEntities = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -43,7 +42,7 @@ namespace Robust.Client.GameObjects
|
||||
base.Shutdown();
|
||||
}
|
||||
|
||||
protected override void ValidateMissingEntity(EntityUid uid, IContainer cont, EntityUid missing)
|
||||
protected override void ValidateMissingEntity(EntityUid uid, BaseContainer cont, EntityUid missing)
|
||||
{
|
||||
DebugTools.Assert(ExpectedEntities.TryGetValue(missing, out var expectedContainer) && expectedContainer == cont && cont.ExpectedEntities.Contains(missing));
|
||||
}
|
||||
@@ -53,9 +52,6 @@ namespace Robust.Client.GameObjects
|
||||
if (!RemoveExpectedEntity(uid, out var container))
|
||||
return;
|
||||
|
||||
if (container.Deleted)
|
||||
return;
|
||||
|
||||
container.Insert(uid);
|
||||
}
|
||||
|
||||
@@ -72,8 +68,11 @@ namespace Robust.Client.GameObjects
|
||||
var toDelete = new ValueList<string>();
|
||||
foreach (var (id, container) in component.Containers)
|
||||
{
|
||||
if (cast.Containers.ContainsKey(id))
|
||||
if (cast.Containers.TryGetValue(id, out var stateContainer)
|
||||
&& stateContainer.GetType() == container.GetType())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var entity in container.ContainedEntities.ToArray())
|
||||
{
|
||||
@@ -98,26 +97,26 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
// Add new containers and update existing contents.
|
||||
|
||||
foreach (var (containerType, id, showEnts, occludesLight, entityUids) in cast.Containers.Values)
|
||||
foreach (var (id, stateContainer) in cast.Containers)
|
||||
{
|
||||
DebugTools.AssertNotNull(stateContainer.ContainedEntities);
|
||||
if (!component.Containers.TryGetValue(id, out var container))
|
||||
{
|
||||
container = ContainerFactory(component, containerType, id);
|
||||
container = _dynFactory.CreateInstanceUnchecked<BaseContainer>(stateContainer.GetType(), inject: false);
|
||||
container.Init(id, uid, component);
|
||||
component.Containers.Add(id, container);
|
||||
}
|
||||
|
||||
// sync show flag
|
||||
container.ShowContents = showEnts;
|
||||
container.OccludesLight = occludesLight;
|
||||
DebugTools.Assert(container.ID == id);
|
||||
container.ShowContents = stateContainer.ShowContents;
|
||||
container.OccludesLight = stateContainer.OccludesLight;
|
||||
|
||||
// Remove gone entities.
|
||||
var toRemove = new ValueList<EntityUid>();
|
||||
foreach (var entity in container.ContainedEntities)
|
||||
{
|
||||
if (!entityUids.Contains(entity))
|
||||
{
|
||||
if (!stateContainer.Contains(entity))
|
||||
toRemove.Add(entity);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var entity in toRemove)
|
||||
@@ -137,10 +136,8 @@ namespace Robust.Client.GameObjects
|
||||
var removedExpected = new ValueList<EntityUid>();
|
||||
foreach (var entityUid in container.ExpectedEntities)
|
||||
{
|
||||
if (!entityUids.Contains(entityUid))
|
||||
{
|
||||
if (!stateContainer.Contains(entityUid))
|
||||
removedExpected.Add(entityUid);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var entityUid in removedExpected)
|
||||
@@ -149,7 +146,7 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
|
||||
// Add new entities.
|
||||
foreach (var entity in entityUids)
|
||||
foreach (var entity in stateContainer.ContainedEntities)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(entity, out MetaDataComponent? meta))
|
||||
{
|
||||
@@ -208,24 +205,10 @@ namespace Robust.Client.GameObjects
|
||||
return;
|
||||
}
|
||||
|
||||
if (container.Deleted)
|
||||
return;
|
||||
|
||||
container.Insert(message.Entity, EntityManager);
|
||||
}
|
||||
|
||||
private IContainer ContainerFactory(ContainerManagerComponent component, string containerType, string id)
|
||||
{
|
||||
var type = _serializer.FindSerializedType(typeof(IContainer), containerType);
|
||||
if (type is null) throw new ArgumentException($"Container of type {containerType} for id {id} cannot be found.");
|
||||
|
||||
var newContainer = _dynFactory.CreateInstanceUnchecked<BaseContainer>(type);
|
||||
newContainer.ID = id;
|
||||
newContainer.Manager = component;
|
||||
return newContainer;
|
||||
}
|
||||
|
||||
public void AddExpectedEntity(EntityUid uid, IContainer container)
|
||||
public void AddExpectedEntity(EntityUid uid, BaseContainer container)
|
||||
{
|
||||
DebugTools.Assert(!TryComp(uid, out MetaDataComponent? meta) ||
|
||||
(meta.Flags & ( MetaDataFlags.Detached | MetaDataFlags.InContainer) ) == MetaDataFlags.Detached,
|
||||
@@ -247,7 +230,7 @@ namespace Robust.Client.GameObjects
|
||||
container.ExpectedEntities.Add(uid);
|
||||
}
|
||||
|
||||
public bool RemoveExpectedEntity(EntityUid uid, [NotNullWhen(true)] out IContainer? container)
|
||||
public bool RemoveExpectedEntity(EntityUid uid, [NotNullWhen(true)] out BaseContainer? container)
|
||||
{
|
||||
if (!ExpectedEntities.Remove(uid, out container))
|
||||
return false;
|
||||
|
||||
@@ -1000,7 +1000,7 @@ namespace Robust.Client.GameStates
|
||||
|
||||
// In some cursed scenarios an entity inside of a container can leave PVS without the container itself leaving PVS.
|
||||
// In those situations, we need to add the entity back to the list of expected entities after detaching.
|
||||
IContainer? container = null;
|
||||
BaseContainer? container = null;
|
||||
if ((meta.Flags & MetaDataFlags.InContainer) != 0 &&
|
||||
metas.TryGetComponent(xform.ParentUid, out var containerMeta) &&
|
||||
(containerMeta.Flags & MetaDataFlags.Detached) == 0 &&
|
||||
@@ -1238,7 +1238,7 @@ namespace Robust.Client.GameStates
|
||||
var xform = _entities.GetComponent<TransformComponent>(uid);
|
||||
if (xform.ParentUid.IsValid())
|
||||
{
|
||||
IContainer? container = null;
|
||||
BaseContainer? container = null;
|
||||
if ((meta.Flags & MetaDataFlags.InContainer) != 0 &&
|
||||
_entities.TryGetComponent(xform.ParentUid, out MetaDataComponent? containerMeta) &&
|
||||
(containerMeta.Flags & MetaDataFlags.Detached) == 0)
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Robust.Server.Containers
|
||||
{
|
||||
public sealed class ContainerSystem : SharedContainerSystem
|
||||
{
|
||||
protected override void ValidateMissingEntity(EntityUid uid, IContainer cont, EntityUid missing)
|
||||
protected override void ValidateMissingEntity(EntityUid uid, BaseContainer cont, EntityUid missing)
|
||||
{
|
||||
Log.Error($"Missing entity for container {ToPrettyString(uid)}. Missing uid: {missing}");
|
||||
//cont.InternalRemove(ent);
|
||||
|
||||
@@ -12,57 +12,81 @@ using Robust.Shared.ViewVariables;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.Shared.Containers
|
||||
{
|
||||
/// <summary>
|
||||
/// Base container class that all container inherit from.
|
||||
/// </summary>
|
||||
public abstract partial class BaseContainer : IContainer
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[Serializable, NetSerializable]
|
||||
public abstract partial class BaseContainer
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Readonly collection of all the entities contained within this specific container
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public abstract IReadOnlyList<EntityUid> ContainedEntities { get; }
|
||||
|
||||
[ViewVariables]
|
||||
public abstract List<EntityUid> ExpectedEntities { get; }
|
||||
[ViewVariables, NonSerialized]
|
||||
public List<EntityUid> ExpectedEntities = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract string ContainerType { get; }
|
||||
/// <summary>
|
||||
/// The ID of this container.
|
||||
/// </summary>
|
||||
[ViewVariables, NonSerialized, Access(typeof(SharedContainerSystem), typeof(ContainerManagerComponent))]
|
||||
public string ID = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
public bool Deleted { get; private set; }
|
||||
[NonSerialized]
|
||||
internal ContainerManagerComponent Manager = default!;
|
||||
|
||||
/// <inheritdoc />
|
||||
[ViewVariables]
|
||||
public string ID { get; internal set; } = default!; // Make sure you set me in init
|
||||
|
||||
/// <inheritdoc />
|
||||
public ContainerManagerComponent Manager { get; internal set; } = default!; // Make sure you set me in init
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Prevents light from escaping the container, from ex. a flashlight.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("occludes")]
|
||||
public bool OccludesLight { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// The entity that owns this container.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public EntityUid Owner => Manager.Owner;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Should the contents of this container be shown? False for closed containers like lockers, true for
|
||||
/// things like glass display cases.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("showEnts")]
|
||||
public bool ShowContents { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DO NOT CALL THIS METHOD DIRECTLY!
|
||||
/// You want <see cref="IContainerManager.MakeContainer{T}(string)" /> instead.
|
||||
/// </summary>
|
||||
protected BaseContainer() { }
|
||||
internal void Init(string id, EntityUid owner, ContainerManagerComponent component)
|
||||
{
|
||||
DebugTools.AssertNull(ID);
|
||||
ID = id;
|
||||
Manager = component;
|
||||
|
||||
/// <inheritdoc />
|
||||
// TODO fix container init.
|
||||
// Eventually, we want an owner field, but currently it needs to use component.Owner
|
||||
// Owner = owner;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to insert the entity into this container.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the insertion is successful, the inserted entity will end up parented to the
|
||||
/// container entity, and the inserted entity's local position will be set to the zero vector.
|
||||
/// </remarks>
|
||||
/// <param name="toinsert">The entity to insert.</param>
|
||||
/// <param name="entMan"></param>
|
||||
/// <returns>False if the entity could not be inserted.</returns>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown if this container is a child of the entity,
|
||||
/// which would cause infinite loops.
|
||||
/// </exception>
|
||||
public bool Insert(
|
||||
EntityUid toinsert,
|
||||
IEntityManager? entMan = null,
|
||||
@@ -72,7 +96,6 @@ namespace Robust.Shared.Containers
|
||||
PhysicsComponent? physics = null,
|
||||
bool force = false)
|
||||
{
|
||||
DebugTools.Assert(!Deleted);
|
||||
DebugTools.Assert(transform == null || transform.Owner == toinsert);
|
||||
DebugTools.Assert(ownerTransform == null || ownerTransform.Owner == Owner);
|
||||
DebugTools.Assert(ownerTransform == null || ownerTransform.Owner == Owner);
|
||||
@@ -80,10 +103,6 @@ namespace Robust.Shared.Containers
|
||||
DebugTools.Assert(!ExpectedEntities.Contains(toinsert));
|
||||
IoCManager.Resolve(ref entMan);
|
||||
|
||||
//Verify we can insert into this container
|
||||
if (!force && !CanInsert(toinsert, entMan))
|
||||
return false;
|
||||
|
||||
var physicsQuery = entMan.GetEntityQuery<PhysicsComponent>();
|
||||
var transformQuery = entMan.GetEntityQuery<TransformComponent>();
|
||||
var jointQuery = entMan.GetEntityQuery<JointComponent>();
|
||||
@@ -91,6 +110,11 @@ namespace Robust.Shared.Containers
|
||||
// ECS containers when
|
||||
var physicsSys = entMan.EntitySysManager.GetEntitySystem<SharedPhysicsSystem>();
|
||||
var jointSys = entMan.EntitySysManager.GetEntitySystem<SharedJointSystem>();
|
||||
var containerSys = entMan.EntitySysManager.GetEntitySystem<SharedContainerSystem>();
|
||||
|
||||
//Verify we can insert into this container
|
||||
if (!force && !containerSys.CanInsert(toinsert, this))
|
||||
return false;
|
||||
|
||||
// Please somebody ecs containers
|
||||
var lookupSys = entMan.EntitySysManager.GetEntitySystem<EntityLookupSystem>();
|
||||
@@ -214,45 +238,22 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool CanInsert(EntityUid toinsert, IEntityManager? entMan = null)
|
||||
{
|
||||
DebugTools.Assert(!Deleted);
|
||||
/// <summary>
|
||||
/// Whether the given entity can be inserted into this container.
|
||||
/// </summary>
|
||||
/// <param name="assumeEmpty">Whether to assume that the container is currently empty.</param>
|
||||
protected internal virtual bool CanInsert(EntityUid toInsert, bool assumeEmpty, IEntityManager entMan) => true;
|
||||
|
||||
// cannot insert into itself.
|
||||
if (Owner == toinsert)
|
||||
return false;
|
||||
|
||||
IoCManager.Resolve(ref entMan);
|
||||
|
||||
// no, you can't put maps or grids into containers
|
||||
if (entMan.HasComponent<MapComponent>(toinsert) || entMan.HasComponent<MapGridComponent>(toinsert))
|
||||
return false;
|
||||
|
||||
var xformSystem = entMan.EntitySysManager.GetEntitySystem<SharedTransformSystem>();
|
||||
var xformQuery = entMan.GetEntityQuery<TransformComponent>();
|
||||
|
||||
// Crucial, prevent circular insertion.
|
||||
if (xformSystem.ContainsEntity(xformQuery.GetComponent(toinsert), Owner, xformQuery))
|
||||
return false;
|
||||
|
||||
//Improvement: Traverse the entire tree to make sure we are not creating a loop.
|
||||
|
||||
//raise events
|
||||
var insertAttemptEvent = new ContainerIsInsertingAttemptEvent(this, toinsert);
|
||||
entMan.EventBus.RaiseLocalEvent(Owner, insertAttemptEvent, true);
|
||||
if (insertAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
var gettingInsertedAttemptEvent = new ContainerGettingInsertedAttemptEvent(this, toinsert);
|
||||
entMan.EventBus.RaiseLocalEvent(toinsert, gettingInsertedAttemptEvent, true);
|
||||
if (gettingInsertedAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Attempts to remove the entity from this container.
|
||||
/// </summary>
|
||||
/// <param name="reparent">If false, this operation will not rigger a move or parent change event. Ignored if
|
||||
/// destination is not null</param>
|
||||
/// <param name="force">If true, this will not perform can-remove checks.</param>
|
||||
/// <param name="destination">Where to place the entity after removing. Avoids unnecessary broadphase updates.
|
||||
/// If not specified, and reparent option is true, then the entity will either be inserted into a parent
|
||||
/// container, the grid, or the map.</param>
|
||||
/// <param name="localRotation">Optional final local rotation after removal. Avoids redundant move events.</param>
|
||||
public bool Remove(
|
||||
EntityUid toRemove,
|
||||
IEntityManager? entMan = null,
|
||||
@@ -264,7 +265,6 @@ namespace Robust.Shared.Containers
|
||||
Angle? localRotation = null)
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
DebugTools.Assert(!Deleted);
|
||||
DebugTools.AssertNotNull(Manager);
|
||||
DebugTools.Assert(entMan.EntityExists(toRemove));
|
||||
DebugTools.Assert(xform == null || xform.Owner == toRemove);
|
||||
@@ -273,7 +273,8 @@ namespace Robust.Shared.Containers
|
||||
xform ??= entMan.GetComponent<TransformComponent>(toRemove);
|
||||
meta ??= entMan.GetComponent<MetaDataComponent>(toRemove);
|
||||
|
||||
if (!force && !CanRemove(toRemove, entMan))
|
||||
var sys = entMan.EntitySysManager.GetEntitySystem<SharedContainerSystem>();
|
||||
if (!force && !sys.CanRemove(toRemove, this))
|
||||
return false;
|
||||
|
||||
if (force && !Contains(toRemove))
|
||||
@@ -305,7 +306,7 @@ namespace Robust.Shared.Containers
|
||||
else if (reparent)
|
||||
{
|
||||
// Container ECS when.
|
||||
entMan.EntitySysManager.GetEntitySystem<SharedContainerSystem>().AttachParentToContainerOrGrid(xform);
|
||||
sys.AttachParentToContainerOrGrid(xform);
|
||||
if (localRotation != null)
|
||||
entMan.EntitySysManager.GetEntitySystem<SharedTransformSystem>().SetLocalRotation(xform, localRotation.Value);
|
||||
}
|
||||
@@ -336,40 +337,22 @@ namespace Robust.Shared.Containers
|
||||
public void ForceRemove(EntityUid toRemove, IEntityManager? entMan = null, MetaDataComponent? meta = null)
|
||||
=> Remove(toRemove, entMan, meta: meta, reparent: false, force: true);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool CanRemove(EntityUid toRemove, IEntityManager? entMan = null)
|
||||
{
|
||||
DebugTools.Assert(!Deleted);
|
||||
|
||||
if (!Contains(toRemove))
|
||||
return false;
|
||||
|
||||
IoCManager.Resolve(ref entMan);
|
||||
|
||||
//raise events
|
||||
var removeAttemptEvent = new ContainerIsRemovingAttemptEvent(this, toRemove);
|
||||
entMan.EventBus.RaiseLocalEvent(Owner, removeAttemptEvent, true);
|
||||
if (removeAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
var gettingRemovedAttemptEvent = new ContainerGettingRemovedAttemptEvent(this, toRemove);
|
||||
entMan.EventBus.RaiseLocalEvent(toRemove, gettingRemovedAttemptEvent, true);
|
||||
if (gettingRemovedAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Checks if the entity is contained in this container.
|
||||
/// This is not recursive, so containers of children are not checked.
|
||||
/// </summary>
|
||||
/// <param name="contained">The entity to check.</param>
|
||||
/// <returns>True if the entity is immediately contained in this container, false otherwise.</returns>
|
||||
public abstract bool Contains(EntityUid contained);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Clears the container and marks it as deleted.
|
||||
/// </summary>
|
||||
public void Shutdown(IEntityManager? entMan = null, INetManager? netMan = null)
|
||||
{
|
||||
IoCManager.Resolve(ref entMan, ref netMan);
|
||||
InternalShutdown(entMan, netMan.IsClient);
|
||||
Manager.Containers.Remove(ID);
|
||||
Deleted = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Containers
|
||||
@@ -15,27 +17,18 @@ namespace Robust.Shared.Containers
|
||||
/// For example, inventory containers should be modified only through an inventory component.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
[SerializedType(ClassName)]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class Container : BaseContainer
|
||||
{
|
||||
private const string ClassName = "Container";
|
||||
|
||||
/// <summary>
|
||||
/// The generic container class uses a list of entities
|
||||
/// </summary>
|
||||
[DataField("ents")]
|
||||
private List<EntityUid> _containerList = new();
|
||||
|
||||
private readonly List<EntityUid> _expectedEntities = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IReadOnlyList<EntityUid> ContainedEntities => _containerList;
|
||||
|
||||
public override List<EntityUid> ExpectedEntities => _expectedEntities;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ContainerType => ClassName;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void InternalInsert(EntityUid toInsert, IEntityManager entMan)
|
||||
{
|
||||
@@ -56,6 +49,9 @@ namespace Robust.Shared.Containers
|
||||
return false;
|
||||
|
||||
#if DEBUG
|
||||
if (IoCManager.Resolve<IGameTiming>().ApplyingState)
|
||||
return true;
|
||||
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
var flags = entMan.GetComponent<MetaDataComponent>(contained).Flags;
|
||||
DebugTools.Assert((flags & MetaDataFlags.InContainer) != 0, $"Entity has bad container flags. Ent: {entMan.ToPrettyString(contained)}. Container: {ID}, Owner: {entMan.ToPrettyString(Owner)}");
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Robust.Shared.Containers
|
||||
/// <param name="container">The container that this entity is inside of.</param>
|
||||
/// <returns>If a container was found.</returns>
|
||||
[Obsolete("Use ContainerSystem.TryGetContainingContainer() instead")]
|
||||
public static bool TryGetContainer(this EntityUid entity, [NotNullWhen(true)] out IContainer? container, IEntityManager? entMan = null)
|
||||
public static bool TryGetContainer(this EntityUid entity, [NotNullWhen(true)] out BaseContainer? container, IEntityManager? entMan = null)
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
DebugTools.Assert(entMan.EntityExists(entity));
|
||||
@@ -100,7 +100,7 @@ namespace Robust.Shared.Containers
|
||||
/// <see cref="SharedContainerSystem.EmptyContainer"/>
|
||||
/// </summary>
|
||||
[Obsolete("Use SharedContainerSystem.EmptyContainer() instead")]
|
||||
public static void EmptyContainer(this IContainer container, bool force = false, EntityCoordinates? moveTo = null,
|
||||
public static void EmptyContainer(this BaseContainer container, bool force = false, EntityCoordinates? moveTo = null,
|
||||
bool attachToGridOrMap = false, IEntityManager? entMan = null)
|
||||
{
|
||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<SharedContainerSystem>()
|
||||
@@ -112,7 +112,7 @@ namespace Robust.Shared.Containers
|
||||
/// <see cref="SharedContainerSystem.CleanContainer"/>
|
||||
/// </summary>
|
||||
[Obsolete("Use SharedContainerSystem.CleanContainer() instead")]
|
||||
public static void CleanContainer(this IContainer container, IEntityManager? entMan = null)
|
||||
public static void CleanContainer(this BaseContainer container, IEntityManager? entMan = null)
|
||||
{
|
||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<SharedContainerSystem>()
|
||||
.CleanContainer(container);
|
||||
@@ -147,10 +147,10 @@ namespace Robust.Shared.Containers
|
||||
/// <param name="containerId"></param>
|
||||
/// <returns>The new container.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if there already is a container with the specified ID.</exception>
|
||||
/// <seealso cref="IContainerManager.MakeContainer{T}(string)" />
|
||||
/// <seealso cref="BaseContainerManager.MakeContainer{T}(string)" />
|
||||
[Obsolete("Use ContainerSystem.MakeContainer() instead")]
|
||||
public static T CreateContainer<T>(this EntityUid entity, string containerId, IEntityManager? entMan = null)
|
||||
where T : IContainer
|
||||
where T : BaseContainer
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
var containermanager = entMan.EnsureComponent<ContainerManagerComponent>(entity);
|
||||
@@ -159,7 +159,7 @@ namespace Robust.Shared.Containers
|
||||
|
||||
[Obsolete("Use ContainerSystem.EnsureContainer() instead")]
|
||||
public static T EnsureContainer<T>(this EntityUid entity, string containerId, IEntityManager? entMan = null)
|
||||
where T : IContainer
|
||||
where T : BaseContainer
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
return EnsureContainer<T>(entity, containerId, out _, entMan);
|
||||
@@ -167,7 +167,7 @@ namespace Robust.Shared.Containers
|
||||
|
||||
[Obsolete("Use ContainerSystem.EnsureContainer() instead")]
|
||||
public static T EnsureContainer<T>(this EntityUid entity, string containerId, out bool alreadyExisted, IEntityManager? entMan = null)
|
||||
where T : IContainer
|
||||
where T : BaseContainer
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
var containerManager = entMan.EnsureComponent<ContainerManagerComponent>(entity);
|
||||
|
||||
@@ -25,18 +25,16 @@ namespace Robust.Shared.Containers
|
||||
[Dependency] private readonly INetManager _netMan = default!;
|
||||
|
||||
[DataField("containers")]
|
||||
public Dictionary<string, IContainer> Containers = new();
|
||||
public Dictionary<string, BaseContainer> Containers = new();
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
// TODO remove ISerializationHooks I guess the IDs can be set by a custom serializer for the dictionary? But
|
||||
// the component??? Maybe other systems need to stop assuming that containers have been initialized during
|
||||
// their own init.
|
||||
// TODO custom type serializer
|
||||
// TODO set owner uid on init.
|
||||
foreach (var (id, container) in Containers)
|
||||
{
|
||||
var baseContainer = (BaseContainer) container;
|
||||
baseContainer.Manager = this;
|
||||
baseContainer.ID = id;
|
||||
container.Manager = this;
|
||||
container.ID = id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,13 +53,20 @@ namespace Robust.Shared.Containers
|
||||
|
||||
/// <inheritdoc />
|
||||
public T MakeContainer<T>(string id)
|
||||
where T : IContainer
|
||||
where T : BaseContainer
|
||||
{
|
||||
return (T) MakeContainer(id, typeof(T));
|
||||
if (HasContainer(id))
|
||||
throw new ArgumentException($"Container with specified ID already exists: '{id}'");
|
||||
|
||||
var container = _dynFactory.CreateInstanceUnchecked<T>(typeof(T), inject: false);
|
||||
container.Init(id, Owner, this);
|
||||
Containers[id] = container;
|
||||
_entMan.Dirty(this);
|
||||
return container;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IContainer GetContainer(string id)
|
||||
public BaseContainer GetContainer(string id)
|
||||
{
|
||||
return Containers[id];
|
||||
}
|
||||
@@ -73,7 +78,7 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetContainer(string id, [NotNullWhen(true)] out IContainer? container)
|
||||
public bool TryGetContainer(string id, [NotNullWhen(true)] out BaseContainer? container)
|
||||
{
|
||||
var ret = Containers.TryGetValue(id, out var cont);
|
||||
container = cont!;
|
||||
@@ -81,11 +86,11 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool TryGetContainer(EntityUid entity, [NotNullWhen(true)] out IContainer? container)
|
||||
public bool TryGetContainer(EntityUid entity, [NotNullWhen(true)] out BaseContainer? container)
|
||||
{
|
||||
foreach (var contain in Containers.Values)
|
||||
{
|
||||
if (!contain.Deleted && contain.Contains(entity))
|
||||
if (contain.Contains(entity))
|
||||
{
|
||||
container = contain;
|
||||
return true;
|
||||
@@ -101,7 +106,7 @@ namespace Robust.Shared.Containers
|
||||
{
|
||||
foreach (var container in Containers.Values)
|
||||
{
|
||||
if (!container.Deleted && container.Contains(entity)) return true;
|
||||
if (container.Contains(entity)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -125,19 +130,6 @@ namespace Robust.Shared.Containers
|
||||
return true; // If we don't contain the entity, it will always be removed
|
||||
}
|
||||
|
||||
private IContainer MakeContainer(string id, Type type)
|
||||
{
|
||||
if (HasContainer(id)) throw new ArgumentException($"Container with specified ID already exists: '{id}'");
|
||||
|
||||
var container = _dynFactory.CreateInstanceUnchecked<BaseContainer>(type);
|
||||
container.ID = id;
|
||||
container.Manager = this;
|
||||
|
||||
Containers[id] = container;
|
||||
_entMan.Dirty(this);
|
||||
return container;
|
||||
}
|
||||
|
||||
public AllContainersEnumerable GetAllContainers()
|
||||
{
|
||||
return new(this);
|
||||
@@ -146,60 +138,15 @@ namespace Robust.Shared.Containers
|
||||
[Serializable, NetSerializable]
|
||||
internal sealed class ContainerManagerComponentState : ComponentState
|
||||
{
|
||||
public Dictionary<string, ContainerData> Containers;
|
||||
public Dictionary<string, BaseContainer> Containers;
|
||||
|
||||
public ContainerManagerComponentState(Dictionary<string, ContainerData> containers)
|
||||
public ContainerManagerComponentState(Dictionary<string, BaseContainer> containers)
|
||||
{
|
||||
Containers = containers;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public readonly struct ContainerData
|
||||
{
|
||||
public readonly string ContainerType;
|
||||
public readonly string Id;
|
||||
public readonly bool ShowContents;
|
||||
public readonly bool OccludesLight;
|
||||
public readonly EntityUid[] ContainedEntities;
|
||||
|
||||
public ContainerData(string containerType, string id, bool showContents, bool occludesLight, EntityUid[] containedEntities)
|
||||
{
|
||||
ContainerType = containerType;
|
||||
Id = id;
|
||||
ShowContents = showContents;
|
||||
OccludesLight = occludesLight;
|
||||
ContainedEntities = containedEntities;
|
||||
}
|
||||
|
||||
public void Deconstruct(out string type, out string id, out bool showEnts, out bool occludesLight, out EntityUid[] ents)
|
||||
{
|
||||
type = ContainerType;
|
||||
id = Id;
|
||||
showEnts = ShowContents;
|
||||
occludesLight = OccludesLight;
|
||||
ents = ContainedEntities;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
private partial struct ContainerPrototypeData
|
||||
{
|
||||
[DataField("entities")] public List<EntityUid> Entities = new ();
|
||||
|
||||
[DataField("type")] public string? Type = null;
|
||||
|
||||
// explicit parameterless constructor is required.
|
||||
public ContainerPrototypeData() { }
|
||||
|
||||
public ContainerPrototypeData(List<EntityUid> entities, string type)
|
||||
{
|
||||
Entities = entities;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct AllContainersEnumerable : IEnumerable<IContainer>
|
||||
public readonly struct AllContainersEnumerable : IEnumerable<BaseContainer>
|
||||
{
|
||||
private readonly ContainerManagerComponent? _manager;
|
||||
|
||||
@@ -213,7 +160,7 @@ namespace Robust.Shared.Containers
|
||||
return new(_manager);
|
||||
}
|
||||
|
||||
IEnumerator<IContainer> IEnumerable<IContainer>.GetEnumerator()
|
||||
IEnumerator<BaseContainer> IEnumerable<BaseContainer>.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
@@ -224,9 +171,9 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
}
|
||||
|
||||
public struct AllContainersEnumerator : IEnumerator<IContainer>
|
||||
public struct AllContainersEnumerator : IEnumerator<BaseContainer>
|
||||
{
|
||||
private Dictionary<string, IContainer>.ValueCollection.Enumerator _enumerator;
|
||||
private Dictionary<string, BaseContainer>.ValueCollection.Enumerator _enumerator;
|
||||
|
||||
public AllContainersEnumerator(ContainerManagerComponent? manager)
|
||||
{
|
||||
@@ -238,11 +185,8 @@ namespace Robust.Shared.Containers
|
||||
{
|
||||
while (_enumerator.MoveNext())
|
||||
{
|
||||
if (!_enumerator.Current.Deleted)
|
||||
{
|
||||
Current = _enumerator.Current;
|
||||
return true;
|
||||
}
|
||||
Current = _enumerator.Current;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -250,11 +194,11 @@ namespace Robust.Shared.Containers
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
((IEnumerator<IContainer>) _enumerator).Reset();
|
||||
((IEnumerator<BaseContainer>) _enumerator).Reset();
|
||||
}
|
||||
|
||||
[AllowNull]
|
||||
public IContainer Current { get; private set; }
|
||||
public BaseContainer Current { get; private set; }
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
|
||||
@@ -6,24 +6,25 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Containers
|
||||
{
|
||||
[UsedImplicitly]
|
||||
[SerializedType(ClassName)]
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class ContainerSlot : BaseContainer
|
||||
{
|
||||
private const string ClassName = "ContainerSlot";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IReadOnlyList<EntityUid> ContainedEntities
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ContainedEntity == null)
|
||||
if (_containedEntity == null)
|
||||
return Array.Empty<EntityUid>();
|
||||
|
||||
_containedEntityArray ??= new[] { _containedEntity.Value };
|
||||
DebugTools.Assert(_containedEntityArray[0] == _containedEntity);
|
||||
return _containedEntityArray;
|
||||
}
|
||||
}
|
||||
@@ -36,39 +37,18 @@ namespace Robust.Shared.Containers
|
||||
{
|
||||
_containedEntity = value;
|
||||
if (value != null)
|
||||
_containedEntityArray[0] = value!.Value;
|
||||
{
|
||||
_containedEntityArray ??= new EntityUid[1];
|
||||
_containedEntityArray[0] = value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override List<EntityUid> ExpectedEntities => _expectedEntities;
|
||||
|
||||
private EntityUid? _containedEntity;
|
||||
private readonly List<EntityUid> _expectedEntities = new();
|
||||
|
||||
// Used by ContainedEntities to avoid allocating.
|
||||
private readonly EntityUid[] _containedEntityArray = new EntityUid[1];
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ContainerType => ClassName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanInsert(EntityUid toinsert, IEntityManager? entMan = null)
|
||||
{
|
||||
return (ContainedEntity == null) && CanInsertIfEmpty(toinsert, entMan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity can be inserted into this container, assuming that the container slot is empty.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Useful if you need to know whether an item could be inserted into a slot, without having to actually eject
|
||||
/// the currently contained entity first.
|
||||
/// </remarks>
|
||||
/// <param name="toinsert">The entity to attempt to insert.</param>
|
||||
/// <returns>True if the entity could be inserted into an empty slot, false otherwise.</returns>
|
||||
public bool CanInsertIfEmpty(EntityUid toinsert, IEntityManager? entMan = null)
|
||||
{
|
||||
return base.CanInsert(toinsert, entMan);
|
||||
}
|
||||
[NonSerialized]
|
||||
private EntityUid[]? _containedEntityArray;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Contains(EntityUid contained)
|
||||
@@ -77,6 +57,9 @@ namespace Robust.Shared.Containers
|
||||
return false;
|
||||
|
||||
#if DEBUG
|
||||
if (IoCManager.Resolve<IGameTiming>().ApplyingState)
|
||||
return true;
|
||||
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
var flags = entMan.GetComponent<MetaDataComponent>(contained).Flags;
|
||||
DebugTools.Assert((flags & MetaDataFlags.InContainer) != 0, $"Entity has bad container flags. Ent: {entMan.ToPrettyString(contained)}. Container: {ID}, Owner: {entMan.ToPrettyString(Owner)}");
|
||||
|
||||
@@ -6,10 +6,10 @@ namespace Robust.Shared.Containers;
|
||||
|
||||
public abstract class ContainerAttemptEventBase : CancellableEntityEventArgs
|
||||
{
|
||||
public readonly IContainer Container;
|
||||
public readonly BaseContainer Container;
|
||||
public readonly EntityUid EntityUid;
|
||||
|
||||
public ContainerAttemptEventBase(IContainer container, EntityUid entityUid)
|
||||
public ContainerAttemptEventBase(BaseContainer container, EntityUid entityUid)
|
||||
{
|
||||
Container = container;
|
||||
EntityUid = entityUid;
|
||||
@@ -18,28 +18,44 @@ public abstract class ContainerAttemptEventBase : CancellableEntityEventArgs
|
||||
|
||||
public sealed class ContainerIsInsertingAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
public ContainerIsInsertingAttemptEvent(IContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
/// <summary>
|
||||
/// If true, this check should assume that the container is currently empty.
|
||||
/// I.e., could the entity be inserted if the container doesn't contain anything else?
|
||||
/// </summary>
|
||||
public bool AssumeEmpty { get; set; }
|
||||
|
||||
public ContainerIsInsertingAttemptEvent(BaseContainer container, EntityUid entityUid, bool assumeEmpty)
|
||||
: base(container, entityUid)
|
||||
{
|
||||
AssumeEmpty = assumeEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ContainerGettingInsertedAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
public ContainerGettingInsertedAttemptEvent(IContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
/// <summary>
|
||||
/// If true, this check should assume that the container is currently empty.
|
||||
/// I.e., could the entity be inserted if the container doesn't contain anything else?
|
||||
/// </summary>
|
||||
public bool AssumeEmpty { get; set; }
|
||||
|
||||
public ContainerGettingInsertedAttemptEvent(BaseContainer container, EntityUid entityUid, bool assumeEmpty)
|
||||
: base(container, entityUid)
|
||||
{
|
||||
AssumeEmpty = assumeEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ContainerIsRemovingAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
public ContainerIsRemovingAttemptEvent(IContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
public ContainerIsRemovingAttemptEvent(BaseContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ContainerGettingRemovedAttemptEvent : ContainerAttemptEventBase
|
||||
{
|
||||
public ContainerGettingRemovedAttemptEvent(IContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
public ContainerGettingRemovedAttemptEvent(BaseContainer container, EntityUid entityUid) : base(container, entityUid)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@ namespace Robust.Shared.Containers
|
||||
/// <summary>
|
||||
/// The container being acted upon.
|
||||
/// </summary>
|
||||
public IContainer Container { get; }
|
||||
public BaseContainer Container { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The entity that was removed or inserted from/into the container.
|
||||
/// </summary>
|
||||
public EntityUid Entity { get; }
|
||||
|
||||
protected ContainerModifiedMessage(EntityUid entity, IContainer container)
|
||||
protected ContainerModifiedMessage(EntityUid entity, BaseContainer container)
|
||||
{
|
||||
Entity = entity;
|
||||
Container = container;
|
||||
|
||||
@@ -9,5 +9,5 @@ namespace Robust.Shared.Containers;
|
||||
[PublicAPI]
|
||||
public sealed class EntGotInsertedIntoContainerMessage : ContainerModifiedMessage
|
||||
{
|
||||
public EntGotInsertedIntoContainerMessage(EntityUid entity, IContainer container) : base(entity, container) { }
|
||||
public EntGotInsertedIntoContainerMessage(EntityUid entity, BaseContainer container) : base(entity, container) { }
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Robust.Shared.Containers
|
||||
{
|
||||
public readonly EntityUid OldParent;
|
||||
|
||||
public EntInsertedIntoContainerMessage(EntityUid entity, EntityUid oldParent, IContainer container) : base(entity, container)
|
||||
public EntInsertedIntoContainerMessage(EntityUid entity, EntityUid oldParent, BaseContainer container) : base(entity, container)
|
||||
{
|
||||
OldParent = oldParent;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Robust.Shared.Containers
|
||||
[PublicAPI]
|
||||
public sealed class EntRemovedFromContainerMessage : ContainerModifiedMessage
|
||||
{
|
||||
public EntRemovedFromContainerMessage(EntityUid entity, IContainer container) : base(entity, container) { }
|
||||
public EntRemovedFromContainerMessage(EntityUid entity, BaseContainer container) : base(entity, container) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -18,6 +18,6 @@ namespace Robust.Shared.Containers
|
||||
[PublicAPI]
|
||||
public sealed class EntGotRemovedFromContainerMessage : ContainerModifiedMessage
|
||||
{
|
||||
public EntGotRemovedFromContainerMessage(EntityUid entity, IContainer container) : base(entity, container) { }
|
||||
public EntGotRemovedFromContainerMessage(EntityUid entity, BaseContainer container) : base(entity, container) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Robust.Shared.Containers
|
||||
{
|
||||
/// <summary>
|
||||
/// A container is a way to "contain" entities inside other entities, in a logical way.
|
||||
/// This is alike BYOND's <c>contents</c> system, except more advanced.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Containers are logical separations of entities contained inside another entity.
|
||||
/// for example, a crate with two separated compartments would have two separate containers.
|
||||
/// If an entity inside compartment A drops something,
|
||||
/// the dropped entity would be placed in compartment A too,
|
||||
/// and compartment B would be completely untouched.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Containers are managed by an entity's <see cref="IContainerManager" />,
|
||||
/// and have an ID to be referenced by.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <seealso cref="IContainerManager" />
|
||||
[PublicAPI]
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public partial interface IContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Readonly collection of all the entities contained within this specific container
|
||||
/// </summary>
|
||||
IReadOnlyList<EntityUid> ContainedEntities { get; }
|
||||
|
||||
List<EntityUid> ExpectedEntities { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of this container.
|
||||
/// </summary>
|
||||
string ContainerType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the container has been shut down via <see cref="Shutdown" />
|
||||
/// </summary>
|
||||
bool Deleted { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The ID of this container.
|
||||
/// </summary>
|
||||
string ID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Prevents light from escaping the container, from ex. a flashlight.
|
||||
/// </summary>
|
||||
bool OccludesLight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The entity owning this container.
|
||||
/// </summary>
|
||||
EntityUid Owner { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Should the contents of this container be shown? False for closed containers like lockers, true for
|
||||
/// things like glass display cases.
|
||||
/// </summary>
|
||||
bool ShowContents { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity can be inserted into this container.
|
||||
/// </summary>
|
||||
/// <param name="toinsert">The entity to attempt to insert.</param>
|
||||
/// <param name="entMan"></param>
|
||||
/// <returns>True if the entity can be inserted, false otherwise.</returns>
|
||||
bool CanInsert(EntityUid toinsert, IEntityManager? entMan = null);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to insert the entity into this container.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the insertion is successful, the inserted entity will end up parented to the
|
||||
/// container entity, and the inserted entity's local position will be set to the zero vector.
|
||||
/// </remarks>
|
||||
/// <param name="toinsert">The entity to insert.</param>
|
||||
/// <param name="entMan"></param>
|
||||
/// <returns>False if the entity could not be inserted.</returns>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown if this container is a child of the entity,
|
||||
/// which would cause infinite loops.
|
||||
/// </exception>
|
||||
bool Insert(EntityUid toinsert,
|
||||
IEntityManager? entMan = null,
|
||||
TransformComponent? transform = null,
|
||||
TransformComponent? ownerTransform = null,
|
||||
MetaDataComponent? meta = null,
|
||||
PhysicsComponent? physics = null,
|
||||
bool force = false);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity can be removed from this container.
|
||||
/// </summary>
|
||||
/// <param name="toremove">The entity to check.</param>
|
||||
/// <param name="entMan"></param>
|
||||
/// <returns>True if the entity can be removed, false otherwise.</returns>
|
||||
bool CanRemove(EntityUid toremove, IEntityManager? entMan = null);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to remove the entity from this container.
|
||||
/// </summary>
|
||||
/// <param name="reparent">If false, this operation will not rigger a move or parent change event. Ignored if
|
||||
/// destination is not null</param>
|
||||
/// <param name="force">If true, this will not perform can-remove checks.</param>
|
||||
/// <param name="destination">Where to place the entity after removing. Avoids unnecessary broadphase updates.
|
||||
/// If not specified, and reparent option is true, then the entity will either be inserted into a parent
|
||||
/// container, the grid, or the map.</param>
|
||||
/// <param name="localRotation">Optional final local rotation after removal. Avoids redundant move events.</param>
|
||||
bool Remove(
|
||||
EntityUid toremove,
|
||||
IEntityManager? entMan = null,
|
||||
TransformComponent? xform = null,
|
||||
MetaDataComponent? meta = null,
|
||||
bool reparent = true,
|
||||
bool force = false,
|
||||
EntityCoordinates? destination = null,
|
||||
Angle? localRotation = null);
|
||||
|
||||
[Obsolete("use force option in Remove()")]
|
||||
void ForceRemove(EntityUid toRemove, IEntityManager? entMan = null, MetaDataComponent? meta = null);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entity is contained in this container.
|
||||
/// This is not recursive, so containers of children are not checked.
|
||||
/// </summary>
|
||||
/// <param name="contained">The entity to check.</param>
|
||||
/// <returns>True if the entity is immediately contained in this container, false otherwise.</returns>
|
||||
bool Contains(EntityUid contained);
|
||||
|
||||
/// <summary>
|
||||
/// Clears the container and marks it as deleted.
|
||||
/// </summary>
|
||||
void Shutdown(IEntityManager? entMan = null, INetManager? netMan = null);
|
||||
}
|
||||
}
|
||||
49
Robust.Shared/Containers/SharedContainerSystem.Insert.cs
Normal file
49
Robust.Shared/Containers/SharedContainerSystem.Insert.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Robust.Shared.Containers;
|
||||
|
||||
public abstract partial class SharedContainerSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the entity can be inserted into the given container.
|
||||
/// </summary>
|
||||
/// <param name="assumeEmpty">If true, this will check whether the entity could be inserted if the container were
|
||||
/// empty.</param>
|
||||
public bool CanInsert(
|
||||
EntityUid toInsert,
|
||||
BaseContainer container,
|
||||
TransformComponent? toInsertXform = null,
|
||||
bool assumeEmpty = false)
|
||||
{
|
||||
if (container.Owner == toInsert)
|
||||
return false;
|
||||
|
||||
if (!assumeEmpty && container.Contains(toInsert))
|
||||
return false;
|
||||
|
||||
if (!container.CanInsert(toInsert, assumeEmpty, EntityManager))
|
||||
return false;
|
||||
|
||||
if (!_xforms.Resolve(toInsert, ref toInsertXform))
|
||||
return false;
|
||||
|
||||
// no, you can't put maps or grids into containers
|
||||
if (_mapQuery.HasComponent(toInsert) || _gridQuery.HasComponent(toInsert))
|
||||
return false;
|
||||
|
||||
// Prevent circular insertion.
|
||||
if (_transform.ContainsEntity(toInsertXform, container.Owner))
|
||||
return false;
|
||||
|
||||
var insertAttemptEvent = new ContainerIsInsertingAttemptEvent(container, toInsert, assumeEmpty);
|
||||
RaiseLocalEvent(container.Owner, insertAttemptEvent, true);
|
||||
if (insertAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
var gettingInsertedAttemptEvent = new ContainerGettingInsertedAttemptEvent(container, toInsert, assumeEmpty);
|
||||
RaiseLocalEvent(toInsert, gettingInsertedAttemptEvent, true);
|
||||
|
||||
return !gettingInsertedAttemptEvent.Cancelled;
|
||||
}
|
||||
}
|
||||
26
Robust.Shared/Containers/SharedContainerSystem.Remove.cs
Normal file
26
Robust.Shared/Containers/SharedContainerSystem.Remove.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Robust.Shared.Containers;
|
||||
|
||||
public abstract partial class SharedContainerSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the entity can be removed from this container.
|
||||
/// </summary>
|
||||
/// <returns>True if the entity can be removed, false otherwise.</returns>
|
||||
public bool CanRemove(EntityUid toRemove, BaseContainer container)
|
||||
{
|
||||
if (!container.Contains(toRemove))
|
||||
return false;
|
||||
|
||||
//raise events
|
||||
var removeAttemptEvent = new ContainerIsRemovingAttemptEvent(container, toRemove);
|
||||
RaiseLocalEvent(container.Owner, removeAttemptEvent, true);
|
||||
if (removeAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
var gettingRemovedAttemptEvent = new ContainerGettingRemovedAttemptEvent(container, toRemove);
|
||||
RaiseLocalEvent(toRemove, gettingRemovedAttemptEvent, true);
|
||||
return !gettingRemovedAttemptEvent.Cancelled;
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public abstract partial class SharedContainerSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void ValidateMissingEntity(EntityUid uid, IContainer cont, EntityUid missing);
|
||||
protected abstract void ValidateMissingEntity(EntityUid uid, BaseContainer cont, EntityUid missing);
|
||||
|
||||
private void ValidateChildren(TransformComponent xform, EntityQuery<TransformComponent> xformQuery, EntityQuery<PhysicsComponent> physicsQuery)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -16,6 +17,10 @@ namespace Robust.Shared.Containers
|
||||
{
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
private EntityQuery<MapGridComponent> _gridQuery;
|
||||
private EntityQuery<MapComponent> _mapQuery;
|
||||
|
||||
private EntityQuery<MetaDataComponent> _metas;
|
||||
private EntityQuery<TransformComponent> _xforms;
|
||||
@@ -29,29 +34,15 @@ namespace Robust.Shared.Containers
|
||||
SubscribeLocalEvent<ContainerManagerComponent, ComponentStartup>(OnStartupValidation);
|
||||
SubscribeLocalEvent<ContainerManagerComponent, ComponentGetState>(OnContainerGetState);
|
||||
|
||||
_gridQuery = GetEntityQuery<MapGridComponent>();
|
||||
_mapQuery = GetEntityQuery<MapComponent>();
|
||||
_metas = EntityManager.GetEntityQuery<MetaDataComponent>();
|
||||
_xforms = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
}
|
||||
|
||||
private void OnContainerGetState(EntityUid uid, ContainerManagerComponent component, ref ComponentGetState args)
|
||||
{
|
||||
// naive implementation that just sends the full state of the component
|
||||
Dictionary<string, ContainerManagerComponent.ContainerManagerComponentState.ContainerData> containerSet = new(component.Containers.Count);
|
||||
|
||||
foreach (var container in component.Containers.Values)
|
||||
{
|
||||
var uidArr = new EntityUid[container.ContainedEntities.Count];
|
||||
|
||||
for (var index = 0; index < container.ContainedEntities.Count; index++)
|
||||
{
|
||||
uidArr[index] = container.ContainedEntities[index];
|
||||
}
|
||||
|
||||
var sContainer = new ContainerManagerComponent.ContainerManagerComponentState.ContainerData(container.ContainerType, container.ID, container.ShowContents, container.OccludesLight, uidArr);
|
||||
containerSet.Add(container.ID, sContainer);
|
||||
}
|
||||
|
||||
args.State = new ContainerManagerComponent.ContainerManagerComponentState(containerSet);
|
||||
args.State = new ContainerManagerComponent.ContainerManagerComponentState(component.Containers);
|
||||
}
|
||||
|
||||
// TODO: Make ContainerManagerComponent ECS and make these proxy methods the real deal.
|
||||
@@ -59,7 +50,7 @@ namespace Robust.Shared.Containers
|
||||
#region Proxy Methods
|
||||
|
||||
public T MakeContainer<T>(EntityUid uid, string id, ContainerManagerComponent? containerManager = null)
|
||||
where T : IContainer
|
||||
where T : BaseContainer
|
||||
{
|
||||
if (!Resolve(uid, ref containerManager, false))
|
||||
containerManager = EntityManager.AddComponent<ContainerManagerComponent>(uid); // Happy Vera.
|
||||
@@ -68,7 +59,7 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
|
||||
public T EnsureContainer<T>(EntityUid uid, string id, out bool alreadyExisted, ContainerManagerComponent? containerManager = null)
|
||||
where T : IContainer
|
||||
where T : BaseContainer
|
||||
{
|
||||
if (!Resolve(uid, ref containerManager, false))
|
||||
containerManager = EntityManager.AddComponent<ContainerManagerComponent>(uid);
|
||||
@@ -88,12 +79,12 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
|
||||
public T EnsureContainer<T>(EntityUid uid, string id, ContainerManagerComponent? containerManager = null)
|
||||
where T : IContainer
|
||||
where T : BaseContainer
|
||||
{
|
||||
return EnsureContainer<T>(uid, id, out _, containerManager);
|
||||
}
|
||||
|
||||
public IContainer GetContainer(EntityUid uid, string id, ContainerManagerComponent? containerManager = null)
|
||||
public BaseContainer GetContainer(EntityUid uid, string id, ContainerManagerComponent? containerManager = null)
|
||||
{
|
||||
if (!Resolve(uid, ref containerManager))
|
||||
throw new ArgumentException("Entity does not have a ContainerManagerComponent!", nameof(uid));
|
||||
@@ -109,7 +100,7 @@ namespace Robust.Shared.Containers
|
||||
return containerManager.HasContainer(id);
|
||||
}
|
||||
|
||||
public bool TryGetContainer(EntityUid uid, string id, [NotNullWhen(true)] out IContainer? container, ContainerManagerComponent? containerManager = null)
|
||||
public bool TryGetContainer(EntityUid uid, string id, [NotNullWhen(true)] out BaseContainer? container, ContainerManagerComponent? containerManager = null)
|
||||
{
|
||||
if (Resolve(uid, ref containerManager, false))
|
||||
return containerManager.TryGetContainer(id, out container);
|
||||
@@ -118,7 +109,7 @@ namespace Robust.Shared.Containers
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetContainingContainer(EntityUid uid, EntityUid containedUid, [NotNullWhen(true)] out IContainer? container, ContainerManagerComponent? containerManager = null, bool skipExistCheck = false)
|
||||
public bool TryGetContainingContainer(EntityUid uid, EntityUid containedUid, [NotNullWhen(true)] out BaseContainer? container, ContainerManagerComponent? containerManager = null, bool skipExistCheck = false)
|
||||
{
|
||||
if (Resolve(uid, ref containerManager, false) && (skipExistCheck || EntityManager.EntityExists(containedUid)))
|
||||
return containerManager.TryGetContainer(containedUid, out container);
|
||||
@@ -164,7 +155,7 @@ namespace Robust.Shared.Containers
|
||||
|
||||
#region Container Helpers
|
||||
|
||||
public bool TryGetContainingContainer(EntityUid uid, [NotNullWhen(true)] out IContainer? container, MetaDataComponent? meta = null, TransformComponent? transform = null)
|
||||
public bool TryGetContainingContainer(EntityUid uid, [NotNullWhen(true)] out BaseContainer? container, MetaDataComponent? meta = null, TransformComponent? transform = null)
|
||||
{
|
||||
container = null;
|
||||
|
||||
@@ -227,7 +218,7 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the first instance of a component on the recursive parented containers that hold an entity
|
||||
/// Finds the first instance of a component on the recursive parented containers that hold an entity
|
||||
/// </summary>
|
||||
public bool TryFindComponentOnEntityContainerOrParent<T>(
|
||||
EntityUid uid,
|
||||
@@ -255,7 +246,7 @@ namespace Robust.Shared.Containers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all instances of a component on the recursive parented containers that hold an entity
|
||||
/// Finds all instances of a component on the recursive parented containers that hold an entity
|
||||
/// </summary>
|
||||
public bool TryFindComponentsOnEntityContainerOrParent<T>(
|
||||
EntityUid uid,
|
||||
@@ -335,8 +326,8 @@ namespace Robust.Shared.Containers
|
||||
public bool IsInSameOrTransparentContainer(
|
||||
EntityUid user,
|
||||
EntityUid other,
|
||||
IContainer? userContainer = null,
|
||||
IContainer? otherContainer = null,
|
||||
BaseContainer? userContainer = null,
|
||||
BaseContainer? otherContainer = null,
|
||||
bool userSeeInsideSelf = false)
|
||||
{
|
||||
if (userContainer == null)
|
||||
@@ -371,14 +362,14 @@ namespace Robust.Shared.Containers
|
||||
/// <summary>
|
||||
/// Gets the top-most container in the hierarchy for this entity, if it exists.
|
||||
/// </summary>
|
||||
public bool TryGetOuterContainer(EntityUid uid, TransformComponent xform, [NotNullWhen(true)] out IContainer? container)
|
||||
public bool TryGetOuterContainer(EntityUid uid, TransformComponent xform, [NotNullWhen(true)] out BaseContainer? container)
|
||||
{
|
||||
var xformQuery = EntityManager.GetEntityQuery<TransformComponent>();
|
||||
return TryGetOuterContainer(uid, xform, out container, xformQuery);
|
||||
}
|
||||
|
||||
public bool TryGetOuterContainer(EntityUid uid, TransformComponent xform,
|
||||
[NotNullWhen(true)] out IContainer? container, EntityQuery<TransformComponent> xformQuery)
|
||||
[NotNullWhen(true)] out BaseContainer? container, EntityQuery<TransformComponent> xformQuery)
|
||||
{
|
||||
container = null;
|
||||
|
||||
@@ -448,7 +439,7 @@ namespace Robust.Shared.Containers
|
||||
/// Attempts to remove all entities in a container. Returns removed entities.
|
||||
/// </summary>
|
||||
public List<EntityUid> EmptyContainer(
|
||||
IContainer container,
|
||||
BaseContainer container,
|
||||
bool force = false,
|
||||
EntityCoordinates? destination = null,
|
||||
bool reparent = true)
|
||||
@@ -470,7 +461,7 @@ namespace Robust.Shared.Containers
|
||||
/// <summary>
|
||||
/// Attempts to remove and delete all entities in a container.
|
||||
/// </summary>
|
||||
public void CleanContainer(IContainer container)
|
||||
public void CleanContainer(BaseContainer container)
|
||||
{
|
||||
foreach (var ent in container.ContainedEntities.ToArray())
|
||||
{
|
||||
@@ -491,7 +482,7 @@ namespace Robust.Shared.Containers
|
||||
transform.AttachToGridOrMap();
|
||||
}
|
||||
|
||||
private bool TryInsertIntoContainer(TransformComponent transform, IContainer container)
|
||||
private bool TryInsertIntoContainer(TransformComponent transform, BaseContainer container)
|
||||
{
|
||||
if (container.Insert(transform.Owner)) return true;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
@@ -8,6 +9,8 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
// ReSharper disable AccessToStaticMemberViaDerivedType
|
||||
@@ -64,10 +67,6 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
Assert.That(() => manager.GetContainer("dummy3"), Throws.TypeOf<KeyNotFoundException>());
|
||||
|
||||
entManager.DeleteEntity(entity);
|
||||
|
||||
Assert.That(manager.Deleted, Is.True);
|
||||
Assert.That(container.Deleted, Is.True);
|
||||
Assert.That(container2.Deleted, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -172,7 +171,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
var container = containerSys.MakeContainer<Container>(entity, "dummy");
|
||||
|
||||
Assert.That(container.Insert(entity), Is.False);
|
||||
Assert.That(container.CanInsert(entity), Is.False);
|
||||
Assert.That(containerSys.CanInsert(entity, container), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -186,7 +185,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
var container = containerSys.MakeContainer<Container>(entity, "dummy");
|
||||
|
||||
Assert.That(container.Insert(mapEnt), Is.False);
|
||||
Assert.That(container.CanInsert(mapEnt), Is.False);
|
||||
Assert.That(containerSys.CanInsert(mapEnt, container), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -200,7 +199,7 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
var container = containerSys.MakeContainer<Container>(entity, "dummy");
|
||||
|
||||
Assert.That(container.Insert(grid), Is.False);
|
||||
Assert.That(container.CanInsert(grid), Is.False);
|
||||
Assert.That(containerSys.CanInsert(grid, container), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -284,13 +283,14 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
|
||||
Assert.That(state.Containers, Has.Count.EqualTo(1));
|
||||
var cont = state.Containers.Values.First();
|
||||
Assert.That(cont.Id, Is.EqualTo("dummy"));
|
||||
Assert.That(cont.ID, Is.EqualTo("dummy"));
|
||||
Assert.That(cont.OccludesLight, Is.True);
|
||||
Assert.That(cont.ShowContents, Is.True);
|
||||
Assert.That(cont.ContainedEntities.Length, Is.EqualTo(1));
|
||||
Assert.That(cont.ContainedEntities.Count, Is.EqualTo(1));
|
||||
Assert.That(cont.ContainedEntities[0], Is.EqualTo(childEnt));
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
private sealed partial class ContainerOnlyContainer : BaseContainer
|
||||
{
|
||||
/// <summary>
|
||||
@@ -299,13 +299,9 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
private readonly List<EntityUid> _containerList = new();
|
||||
private readonly List<EntityUid> _expectedEntities = new();
|
||||
|
||||
public override string ContainerType => nameof(ContainerOnlyContainer);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IReadOnlyList<EntityUid> ContainedEntities => _containerList;
|
||||
|
||||
public override List<EntityUid> ExpectedEntities => _expectedEntities;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void InternalInsert(EntityUid toInsert, IEntityManager entMan)
|
||||
{
|
||||
@@ -324,6 +320,9 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
if (!_containerList.Contains(contained))
|
||||
return false;
|
||||
|
||||
if (IoCManager.Resolve<IGameTiming>().ApplyingState)
|
||||
return true;
|
||||
|
||||
var flags = IoCManager.Resolve<IEntityManager>().GetComponent<MetaDataComponent>(contained).Flags;
|
||||
DebugTools.Assert((flags & MetaDataFlags.InContainer) != 0);
|
||||
return true;
|
||||
@@ -341,10 +340,9 @@ namespace Robust.UnitTesting.Server.GameObjects.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanInsert(EntityUid toinsert, IEntityManager? entMan = null)
|
||||
protected internal override bool CanInsert(EntityUid toinsert, bool assumeEmpty, IEntityManager entMan)
|
||||
{
|
||||
IoCManager.Resolve(ref entMan);
|
||||
return entMan.TryGetComponent(toinsert, out ContainerManagerComponent? _);
|
||||
return entMan.HasComponent<ContainerManagerComponent>(toinsert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,10 +346,10 @@ namespace Robust.UnitTesting.Shared.GameObjects
|
||||
|
||||
Assert.That(containerComp.Containers.ContainsKey("testContainer"));
|
||||
|
||||
var iContainer = containerComp.GetContainer("testContainer");
|
||||
Assert.That(iContainer.ContainedEntities.Count, Is.EqualTo(1));
|
||||
var BaseContainer = containerComp.GetContainer("testContainer");
|
||||
Assert.That(BaseContainer.ContainedEntities.Count, Is.EqualTo(1));
|
||||
|
||||
var containeeEnt = iContainer.ContainedEntities[0];
|
||||
var containeeEnt = BaseContainer.ContainedEntities[0];
|
||||
Assert.That(entMan.GetComponent<MetaDataComponent>(containeeEnt).EntityName, Is.EqualTo("ContaineeEnt"));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
@@ -5,6 +6,7 @@ using NUnit.Framework;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Robust.UnitTesting.Shared.Spawning;
|
||||
|
||||
@@ -100,18 +102,16 @@ public abstract partial class EntitySpawnHelpersTest : RobustIntegrationTest
|
||||
/// <summary>
|
||||
/// Simple container that can store up to 2 entities.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
private sealed partial class TestContainer : BaseContainer
|
||||
{
|
||||
private readonly List<EntityUid> _ents = new();
|
||||
private readonly List<EntityUid> _expected = new();
|
||||
public override string ContainerType => nameof(TestContainer);
|
||||
public override IReadOnlyList<EntityUid> ContainedEntities => _ents;
|
||||
public override List<EntityUid> ExpectedEntities => _expected;
|
||||
protected override void InternalInsert(EntityUid toInsert, IEntityManager entMan) => _ents.Add(toInsert);
|
||||
protected override void InternalRemove(EntityUid toRemove, IEntityManager entMan) => _ents.Remove(toRemove);
|
||||
public override bool Contains(EntityUid contained) => _ents.Contains(contained);
|
||||
protected override void InternalShutdown(IEntityManager entMan, bool isClient) { }
|
||||
public override bool CanInsert(EntityUid toinsert, IEntityManager? entMan = null)
|
||||
protected internal override bool CanInsert(EntityUid toinsert, bool assumeEmpty, IEntityManager entMan)
|
||||
=> _ents.Count < 2 && !_ents.Contains(toinsert);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user