Fix actions not being usable, ordering, and containers (#19964)
This commit is contained in:
@@ -12,12 +12,14 @@ using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared.Actions;
|
||||
|
||||
public abstract class SharedActionsSystem : EntitySystem
|
||||
{
|
||||
private const string ActionContainerId = "ActionContainer";
|
||||
private const string ProvidedActionContainerId = "ProvidedActionContainer";
|
||||
|
||||
[Dependency] protected readonly IGameTiming GameTiming = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
@@ -54,6 +56,10 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
SubscribeLocalEvent<EntityTargetActionComponent, GetActionDataEvent>(OnGetActionData);
|
||||
SubscribeLocalEvent<WorldTargetActionComponent, GetActionDataEvent>(OnGetActionData);
|
||||
|
||||
SubscribeLocalEvent<InstantActionComponent, EntGotRemovedFromContainerMessage>(OnEntGotRemovedFromContainer);
|
||||
SubscribeLocalEvent<EntityTargetActionComponent, EntGotRemovedFromContainerMessage>(OnEntGotRemovedFromContainer);
|
||||
SubscribeLocalEvent<WorldTargetActionComponent, EntGotRemovedFromContainerMessage>(OnEntGotRemovedFromContainer);
|
||||
|
||||
SubscribeAllEvent<RequestPerformActionEvent>(OnActionRequest);
|
||||
}
|
||||
|
||||
@@ -127,6 +133,21 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
args.Action = component;
|
||||
}
|
||||
|
||||
private void OnEntGotRemovedFromContainer<T>(EntityUid uid, T component, EntGotRemovedFromContainerMessage args) where T : BaseActionComponent
|
||||
{
|
||||
if (args.Container.ID != ProvidedActionContainerId)
|
||||
return;
|
||||
|
||||
if (TryComp(component.AttachedEntity, out ActionsComponent? actions))
|
||||
{
|
||||
actions.Actions.Remove(uid);
|
||||
Dirty(component.AttachedEntity.Value, actions);
|
||||
|
||||
if (TryGetActionData(uid, out var action))
|
||||
action.AttachedEntity = null;
|
||||
}
|
||||
}
|
||||
|
||||
public BaseActionComponent? GetActionData(EntityUid? actionId)
|
||||
{
|
||||
if (actionId == null)
|
||||
@@ -147,9 +168,11 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
return actionId != null && (action = GetActionData(actionId)) != null;
|
||||
}
|
||||
|
||||
protected Container EnsureContainer(EntityUid holderId)
|
||||
protected Container EnsureContainer(EntityUid holderId, EntityUid? providerId)
|
||||
{
|
||||
return _containerSystem.EnsureContainer<Container>(holderId, ActionContainerId);
|
||||
return providerId == null
|
||||
? _containerSystem.EnsureContainer<Container>(holderId, ActionContainerId)
|
||||
: _containerSystem.EnsureContainer<Container>(providerId.Value, ProvidedActionContainerId);
|
||||
}
|
||||
|
||||
protected bool TryGetContainer(
|
||||
@@ -160,6 +183,14 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
return _containerSystem.TryGetContainer(holderId, ActionContainerId, out container, containerManager);
|
||||
}
|
||||
|
||||
protected bool TryGetProvidedContainer(
|
||||
EntityUid providerId,
|
||||
[NotNullWhen(true)] out IContainer? container,
|
||||
ContainerManagerComponent? containerManager = null)
|
||||
{
|
||||
return _containerSystem.TryGetContainer(providerId, ProvidedActionContainerId, out container, containerManager);
|
||||
}
|
||||
|
||||
public void SetCooldown(EntityUid? actionId, TimeSpan start, TimeSpan end)
|
||||
{
|
||||
if (actionId == null)
|
||||
@@ -231,16 +262,12 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
|
||||
private void OnActionsMapInit(EntityUid uid, ActionsComponent component, MapInitEvent args)
|
||||
{
|
||||
EnsureContainer(uid);
|
||||
EnsureContainer(uid, null);
|
||||
}
|
||||
|
||||
private void OnActionsGetState(EntityUid uid, ActionsComponent component, ref ComponentGetState args)
|
||||
{
|
||||
var actions = new List<EntityUid>();
|
||||
if (TryGetContainer(uid, out var container))
|
||||
actions.AddRange(container.ContainedEntities);
|
||||
|
||||
args.State = new ActionsComponentState(actions);
|
||||
args.State = new ActionsComponentState(component.Actions);
|
||||
}
|
||||
|
||||
private void OnActionsShutdown(EntityUid uid, ActionsComponent component, ComponentShutdown args)
|
||||
@@ -270,7 +297,7 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
var name = Name(ev.Action, metaData);
|
||||
|
||||
// Does the user actually have the requested action?
|
||||
if (!TryGetContainer(user, out var container) || !container.Contains(ev.Action))
|
||||
if (!component.Actions.Contains(ev.Action))
|
||||
{
|
||||
_adminLogger.Add(LogType.Action,
|
||||
$"{ToPrettyString(user):user} attempted to perform an action that they do not have: {name}.");
|
||||
@@ -538,16 +565,18 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
action.AttachedEntity = holderId;
|
||||
Dirty(actionId, action);
|
||||
|
||||
actionContainer ??= EnsureContainer(holderId);
|
||||
AddActionInternal(actionId, actionContainer);
|
||||
actionContainer ??= EnsureContainer(holderId, provider);
|
||||
AddActionInternal(holderId, actionId, actionContainer, holder);
|
||||
|
||||
if (dirty)
|
||||
Dirty(holderId, holder);
|
||||
}
|
||||
|
||||
protected virtual void AddActionInternal(EntityUid actionId, IContainer container)
|
||||
protected virtual void AddActionInternal(EntityUid holderId, EntityUid actionId, IContainer container, ActionsComponent holder)
|
||||
{
|
||||
container.Insert(actionId);
|
||||
holder.Actions.Add(actionId);
|
||||
Dirty(holderId, holder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -561,7 +590,7 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
comp ??= EnsureComp<ActionsComponent>(holderId);
|
||||
|
||||
var allClientExclusive = true;
|
||||
var container = EnsureContainer(holderId);
|
||||
var container = EnsureContainer(holderId, provider);
|
||||
|
||||
foreach (var actionId in actions)
|
||||
{
|
||||
@@ -577,15 +606,12 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
Dirty(holderId, comp);
|
||||
}
|
||||
|
||||
public IEnumerable<(EntityUid Id, BaseActionComponent Comp)> GetActions(EntityUid holderId, IContainer? container = null)
|
||||
public IEnumerable<(EntityUid Id, BaseActionComponent Comp)> GetActions(EntityUid holderId, ActionsComponent? actions = null)
|
||||
{
|
||||
if (container == null &&
|
||||
!TryGetContainer(holderId, out container))
|
||||
{
|
||||
if (!Resolve(holderId, ref actions, false))
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var actionId in container.ContainedEntities)
|
||||
foreach (var actionId in actions.Actions)
|
||||
{
|
||||
if (!TryGetActionData(actionId, out var action))
|
||||
continue;
|
||||
@@ -597,37 +623,39 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
/// <summary>
|
||||
/// Remove any actions that were enabled by some other entity. Useful when unequiping items that grant actions.
|
||||
/// </summary>
|
||||
public void RemoveProvidedActions(EntityUid holderId, EntityUid provider, ActionsComponent? comp = null, ContainerManagerComponent? actionContainer = null)
|
||||
public void RemoveProvidedActions(EntityUid holderId, EntityUid provider, ActionsComponent? comp = null)
|
||||
{
|
||||
if (!Resolve(holderId, ref comp, ref actionContainer, false))
|
||||
if (!Resolve(holderId, ref comp, false))
|
||||
return;
|
||||
|
||||
if (!TryGetContainer(holderId, out var container, actionContainer))
|
||||
if (!TryGetProvidedContainer(provider, out var container))
|
||||
return;
|
||||
|
||||
foreach (var actionId in container.ContainedEntities.ToArray())
|
||||
{
|
||||
var action = GetActionData(actionId);
|
||||
if (action?.Provider == provider)
|
||||
RemoveAction(holderId, actionId, comp, dirty: false, actionContainer: actionContainer);
|
||||
RemoveAction(holderId, actionId, comp, dirty: false);
|
||||
}
|
||||
|
||||
Dirty(holderId, comp);
|
||||
}
|
||||
|
||||
public virtual void RemoveAction(EntityUid holderId, EntityUid? actionId, ActionsComponent? comp = null, BaseActionComponent? action = null, bool dirty = true, ContainerManagerComponent? actionContainer = null)
|
||||
public virtual void RemoveAction(EntityUid holderId, EntityUid? actionId, ActionsComponent? comp = null, BaseActionComponent? action = null, bool dirty = true)
|
||||
{
|
||||
if (actionId == null ||
|
||||
!Resolve(holderId, ref comp, ref actionContainer, false) ||
|
||||
!TryGetContainer(holderId, out var container, actionContainer) ||
|
||||
!container.Contains(actionId.Value) ||
|
||||
!Resolve(holderId, ref comp, false) ||
|
||||
TerminatingOrDeleted(actionId.Value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
action ??= GetActionData(actionId);
|
||||
container.Remove(actionId.Value);
|
||||
|
||||
if (TryGetContainer(holderId, out var container) && container.Contains(actionId.Value))
|
||||
QueueDel(actionId.Value);
|
||||
|
||||
comp.Actions.Remove(actionId.Value);
|
||||
|
||||
if (action != null)
|
||||
{
|
||||
@@ -637,14 +665,16 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
|
||||
if (dirty)
|
||||
Dirty(holderId, comp);
|
||||
|
||||
DebugTools.Assert(Transform(actionId.Value).ParentUid.IsValid());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all actions with the given prototype id.
|
||||
/// </summary>
|
||||
public void RemoveAction(EntityUid holderId, string actionPrototypeId, ActionsComponent? holderComp = null, ContainerManagerComponent? actionContainer = null)
|
||||
public void RemoveAction(EntityUid holderId, string actionPrototypeId, ActionsComponent? holderComp = null)
|
||||
{
|
||||
if (!Resolve(holderId, ref holderComp, ref actionContainer, false))
|
||||
if (!Resolve(holderId, ref holderComp, false))
|
||||
return;
|
||||
|
||||
var actions = new List<(EntityUid Id, BaseActionComponent Comp)>();
|
||||
@@ -654,9 +684,12 @@ public abstract class SharedActionsSystem : EntitySystem
|
||||
actions.Add((id, comp));
|
||||
}
|
||||
|
||||
if (actions.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (var action in actions)
|
||||
{
|
||||
RemoveAction(holderId, action.Id, holderComp, action.Comp, actionContainer: actionContainer);
|
||||
RemoveAction(holderId, action.Id, holderComp, action.Comp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user