Fix actions not being usable, ordering, and containers (#19964)

This commit is contained in:
DrSmugleaf
2023-09-09 16:14:17 -07:00
committed by GitHub
parent 7b41f7451c
commit 09bce85f19
21 changed files with 166 additions and 119 deletions

View File

@@ -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);
}
}