Add methods to transfer actions between containers (#20901)
This commit is contained in:
@@ -769,10 +769,9 @@ public sealed class ActionUIController : UIController, IOnStateChanged<GameplayS
|
|||||||
{
|
{
|
||||||
if (_actionsSystem != null && _actionsSystem.TryGetActionData(_menuDragHelper.Dragged?.ActionId, out var action))
|
if (_actionsSystem != null && _actionsSystem.TryGetActionData(_menuDragHelper.Dragged?.ActionId, out var action))
|
||||||
{
|
{
|
||||||
if (action.EntityIcon is {} entIcon)
|
if (EntityManager.TryGetComponent(action.EntityIcon, out SpriteComponent? sprite))
|
||||||
{
|
{
|
||||||
_dragShadow.Texture = EntityManager.GetComponent<SpriteComponent>(entIcon).Icon?
|
_dragShadow.Texture = sprite.Icon?.GetFrame(RsiDirection.South, 0);
|
||||||
.GetFrame(RsiDirection.South, 0);
|
|
||||||
}
|
}
|
||||||
else if (action.Icon != null)
|
else if (action.Icon != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Network;
|
using Robust.Shared.Network;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -15,6 +16,7 @@ public sealed class ActionContainerSystem : EntitySystem
|
|||||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||||
[Dependency] private readonly INetManager _netMan = default!;
|
[Dependency] private readonly INetManager _netMan = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -96,7 +98,61 @@ public sealed class ActionContainerSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a pre-existing action to an action container.
|
/// Transfers an action from one container to another, while keeping the attached entity the same.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// While the attached entity should be the same at the end, this will actually remove and then re-grant the action.
|
||||||
|
/// </remarks>
|
||||||
|
public void TransferAction(
|
||||||
|
EntityUid actionId,
|
||||||
|
EntityUid newContainer,
|
||||||
|
BaseActionComponent? action = null,
|
||||||
|
ActionsContainerComponent? container = null)
|
||||||
|
{
|
||||||
|
if (!_actions.ResolveActionData(actionId, ref action))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (action.Container == newContainer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var attached = action.AttachedEntity;
|
||||||
|
if (!AddAction(newContainer, actionId, action, container))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DebugTools.AssertEqual(action.Container, newContainer);
|
||||||
|
DebugTools.AssertNull(action.AttachedEntity);
|
||||||
|
|
||||||
|
if (attached != null)
|
||||||
|
_actions.AddActionDirect(attached.Value, actionId, action: action);
|
||||||
|
|
||||||
|
DebugTools.AssertEqual(action.AttachedEntity, attached);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Transfers all actions from one container to another, while keeping the attached entity the same.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// While the attached entity should be the same at the end, this will actually remove and then re-grant the action.
|
||||||
|
/// </remarks>
|
||||||
|
public void TransferAllActions(
|
||||||
|
EntityUid from,
|
||||||
|
EntityUid to,
|
||||||
|
ActionsContainerComponent? oldContainer = null,
|
||||||
|
ActionsContainerComponent? newContainer = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(from, ref oldContainer) || !Resolve(to, ref newContainer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var action in oldContainer.Container.ContainedEntities.ToArray())
|
||||||
|
{
|
||||||
|
TransferAction(action, to, container: newContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugTools.AssertEqual(oldContainer.Container.Count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a pre-existing action to an action container. If the action is already in some container it will first remove it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AddAction(EntityUid uid, EntityUid actionId, BaseActionComponent? action = null, ActionsContainerComponent? comp = null)
|
public bool AddAction(EntityUid uid, EntityUid actionId, BaseActionComponent? action = null, ActionsContainerComponent? comp = null)
|
||||||
{
|
{
|
||||||
@@ -104,10 +160,7 @@ public sealed class ActionContainerSystem : EntitySystem
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (action.Container != null)
|
if (action.Container != null)
|
||||||
{
|
RemoveAction(actionId, action);
|
||||||
Log.Error($"Attempted to insert an action {ToPrettyString(actionId)} that was already in a container {ToPrettyString(action.Container.Value)}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugTools.Assert(comp == null || comp.Owner == uid);
|
DebugTools.Assert(comp == null || comp.Owner == uid);
|
||||||
comp ??= EnsureComp<ActionsContainerComponent>(uid);
|
comp ??= EnsureComp<ActionsContainerComponent>(uid);
|
||||||
@@ -124,6 +177,35 @@ public sealed class ActionContainerSystem : EntitySystem
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes an action from its container and any action-performer and moves the action to null-space
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveAction(EntityUid actionId, BaseActionComponent? action = null)
|
||||||
|
{
|
||||||
|
if (!_actions.ResolveActionData(actionId, ref action))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (action.Container == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_transform.DetachParentToNull(actionId, Transform(actionId));
|
||||||
|
|
||||||
|
// Container removal events should have removed the action from the action container.
|
||||||
|
// However, just in case the container was already deleted we will still manually clear the container field
|
||||||
|
if (action.Container != null)
|
||||||
|
{
|
||||||
|
if (Exists(action.Container))
|
||||||
|
Log.Error($"Failed to remove action {ToPrettyString(actionId)} from its container {ToPrettyString(action.Container)}?");
|
||||||
|
action.Container = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the action was granted to some entity, then the removal from the container should have automatically removed it.
|
||||||
|
// However, if the action was granted without ever being placed in an action container, it will not have been removed.
|
||||||
|
// Therefore, to ensure that the behaviour of the method is consistent we will also explicitly remove the action.
|
||||||
|
if (action.AttachedEntity != null)
|
||||||
|
_actions.RemoveAction(action.AttachedEntity.Value, actionId, action: action);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, ActionsContainerComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, ActionsContainerComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
component.Container = _container.EnsureContainer<Container>(uid, ActionsContainerComponent.ContainerId);
|
component.Container = _container.EnsureContainer<Container>(uid, ActionsContainerComponent.ContainerId);
|
||||||
@@ -171,13 +253,7 @@ public sealed class ActionContainerSystem : EntitySystem
|
|||||||
|
|
||||||
var ev = new ActionRemovedEvent(args.Entity, data);
|
var ev = new ActionRemovedEvent(args.Entity, data);
|
||||||
RaiseLocalEvent(uid, ref ev);
|
RaiseLocalEvent(uid, ref ev);
|
||||||
|
data.Container = null;
|
||||||
if (_netMan.IsServer)
|
|
||||||
{
|
|
||||||
// TODO Actions
|
|
||||||
// log an error or warning here once gibbing code is fixed.
|
|
||||||
QueueDel(args.Entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -586,9 +586,16 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
if (!ResolveActionData(actionId, ref action))
|
if (!ResolveActionData(actionId, ref action))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (action.AttachedEntity != performer)
|
||||||
|
{
|
||||||
|
Log.Error($"Attempted to remove an action {ToPrettyString(actionId)} from an entity that it was never attached to: {ToPrettyString(performer)}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!Resolve(performer, ref comp, false))
|
if (!Resolve(performer, ref comp, false))
|
||||||
{
|
{
|
||||||
DebugTools.AssertNull(action.AttachedEntity);
|
DebugTools.Assert(action.AttachedEntity == null || TerminatingOrDeleted(action.AttachedEntity.Value));
|
||||||
|
action.AttachedEntity = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,7 +606,6 @@ public abstract class SharedActionsSystem : EntitySystem
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugTools.Assert(action.AttachedEntity == performer);
|
|
||||||
comp.Actions.Remove(actionId.Value);
|
comp.Actions.Remove(actionId.Value);
|
||||||
action.AttachedEntity = null;
|
action.AttachedEntity = null;
|
||||||
Dirty(actionId.Value, action);
|
Dirty(actionId.Value, action);
|
||||||
|
|||||||
Reference in New Issue
Block a user