Fix actions not being usable, ordering, and containers (#19964)
This commit is contained in:
@@ -63,13 +63,16 @@ namespace Content.Client.Actions
|
||||
|
||||
private void HandleComponentState(EntityUid uid, ActionsComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not ActionsComponentState)
|
||||
if (args.Current is not ActionsComponentState state)
|
||||
return;
|
||||
|
||||
component.Actions.Clear();
|
||||
component.Actions.UnionWith(state.Actions);
|
||||
|
||||
_actionHoldersQueue.Enqueue(uid);
|
||||
}
|
||||
|
||||
protected override void AddActionInternal(EntityUid actionId, IContainer container)
|
||||
protected override void AddActionInternal(EntityUid holderId, EntityUid actionId, IContainer container, ActionsComponent holder)
|
||||
{
|
||||
// Sometimes the client receives actions from the server, before predicting that newly added components will add
|
||||
// their own shared actions. Just in case those systems ever decided to directly access action properties (e.g.,
|
||||
@@ -80,7 +83,7 @@ namespace Content.Client.Actions
|
||||
}
|
||||
else
|
||||
{
|
||||
container.Insert(actionId);
|
||||
base.AddActionInternal(holderId, actionId, container, holder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +106,7 @@ namespace Content.Client.Actions
|
||||
ActionAdded?.Invoke(actionId);
|
||||
}
|
||||
|
||||
public override void RemoveAction(EntityUid holderId, EntityUid? actionId, ActionsComponent? comp = null, BaseActionComponent? action = null, bool dirty = true, ContainerManagerComponent? actionContainer = null)
|
||||
public override void RemoveAction(EntityUid holderId, EntityUid? actionId, ActionsComponent? comp = null, BaseActionComponent? action = null, bool dirty = true)
|
||||
{
|
||||
if (GameTiming.ApplyingState)
|
||||
return;
|
||||
@@ -120,7 +123,7 @@ namespace Content.Client.Actions
|
||||
return;
|
||||
|
||||
dirty &= !action?.ClientExclusive ?? true;
|
||||
base.RemoveAction(holderId, actionId, comp, action, dirty, actionContainer);
|
||||
base.RemoveAction(holderId, actionId, comp, action, dirty);
|
||||
|
||||
if (_playerManager.LocalPlayer?.ControlledEntity != holderId)
|
||||
return;
|
||||
@@ -281,7 +284,7 @@ namespace Content.Client.Actions
|
||||
return;
|
||||
|
||||
var removed = new List<EntityUid>();
|
||||
var added = new List<EntityUid>();
|
||||
var added = new List<(EntityUid Id, BaseActionComponent Comp)>();
|
||||
var query = GetEntityQuery<ActionsComponent>();
|
||||
var queue = new Queue<EntityUid>(_actionHoldersQueue);
|
||||
_actionHoldersQueue.Clear();
|
||||
@@ -305,7 +308,7 @@ namespace Content.Client.Actions
|
||||
if (data.ClientExclusive)
|
||||
continue;
|
||||
|
||||
if (!container.Contains(act))
|
||||
if (!holder.Actions.Contains(act))
|
||||
{
|
||||
holder.OldClientActions.Remove(act);
|
||||
if (data.AutoRemove)
|
||||
@@ -314,13 +317,15 @@ namespace Content.Client.Actions
|
||||
}
|
||||
|
||||
// Anything that remains is a new action
|
||||
foreach (var newAct in container.ContainedEntities)
|
||||
foreach (var newAct in holder.Actions)
|
||||
{
|
||||
if (!holder.OldClientActions.ContainsKey(newAct))
|
||||
added.Add(newAct);
|
||||
if (!TryGetActionData(newAct, out var serverData))
|
||||
continue;
|
||||
|
||||
if (TryGetActionData(newAct, out var serverData))
|
||||
holder.OldClientActions[newAct] = new ActionMetaData(serverData.ClientExclusive, serverData.AutoRemove);
|
||||
if (!holder.OldClientActions.ContainsKey(newAct))
|
||||
added.Add((newAct, serverData));
|
||||
|
||||
holder.OldClientActions[newAct] = new ActionMetaData(serverData.ClientExclusive, serverData.AutoRemove);
|
||||
}
|
||||
|
||||
if (_playerManager.LocalPlayer?.ControlledEntity != holderId)
|
||||
@@ -331,9 +336,29 @@ namespace Content.Client.Actions
|
||||
ActionRemoved?.Invoke(action);
|
||||
}
|
||||
|
||||
added.Sort(static (a, b) =>
|
||||
{
|
||||
if (a.Comp.Priority != b.Comp.Priority)
|
||||
return a.Comp.Priority - b.Comp.Priority;
|
||||
|
||||
if (a.Comp.Provider != b.Comp.Provider)
|
||||
{
|
||||
if (a.Comp.Provider == null)
|
||||
return -1;
|
||||
|
||||
if (b.Comp.Provider == null)
|
||||
return 1;
|
||||
|
||||
// uid to int casting... it says "Do NOT use this in content". You can't tell me what to do.
|
||||
return (int) a.Comp.Provider - (int) b.Comp.Provider;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
foreach (var action in added)
|
||||
{
|
||||
ActionAdded?.Invoke(action);
|
||||
ActionAdded?.Invoke(action.Item1);
|
||||
}
|
||||
|
||||
ActionsUpdated?.Invoke();
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using Content.Client.Hands.Systems;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.CombatMode;
|
||||
using Content.Shared.Targeting;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Client.CombatMode;
|
||||
|
||||
@@ -20,10 +20,10 @@ namespace Content.Server.Abilities.Mime
|
||||
/// The wall prototype to use.
|
||||
/// </summary>
|
||||
[DataField("wallPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string WallPrototype = "ActionMimeInvisibleWall";
|
||||
public string WallPrototype = "WallInvisible";
|
||||
|
||||
[DataField("invisibleWallAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? InvisibleWallAction;
|
||||
public string? InvisibleWallAction = "ActionMimeInvisibleWall";
|
||||
|
||||
[DataField("invisibleWallActionEntity")] public EntityUid? InvisibleWallActionEntity;
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace Content.Server.Abilities.Mime
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<MimePowersComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<MimePowersComponent, MapInitEvent>(OnComponentMapInit);
|
||||
SubscribeLocalEvent<MimePowersComponent, InvisibleWallActionEvent>(OnInvisibleWall);
|
||||
}
|
||||
|
||||
@@ -55,10 +54,6 @@ namespace Content.Server.Abilities.Mime
|
||||
{
|
||||
EnsureComp<MutedComponent>(uid);
|
||||
_alertsSystem.ShowAlert(uid, AlertType.VowOfSilence);
|
||||
}
|
||||
|
||||
private void OnComponentMapInit(EntityUid uid, MimePowersComponent component, MapInitEvent args)
|
||||
{
|
||||
_actionsSystem.AddAction(uid, ref component.InvisibleWallActionEntity, component.InvisibleWallAction, uid);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ public sealed partial class DragonSystem : EntitySystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DragonComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<DragonComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<DragonComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<DragonComponent, DragonSpawnRiftActionEvent>(OnDragonRift);
|
||||
SubscribeLocalEvent<DragonComponent, RefreshMovementSpeedModifiersEvent>(OnDragonMove);
|
||||
@@ -296,10 +295,6 @@ public sealed partial class DragonSystem : EntitySystem
|
||||
private void OnStartup(EntityUid uid, DragonComponent component, ComponentStartup args)
|
||||
{
|
||||
Roar(component);
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, DragonComponent component, MapInitEvent args)
|
||||
{
|
||||
_actionsSystem.AddAction(uid, ref component.SpawnRiftActionEntity, component.SpawnRiftAction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ namespace Content.Server.Ghost
|
||||
|
||||
SubscribeLocalEvent<GhostComponent, ComponentStartup>(OnGhostStartup);
|
||||
SubscribeLocalEvent<GhostComponent, ComponentShutdown>(OnGhostShutdown);
|
||||
SubscribeLocalEvent<GhostComponent, MapInitEvent>(OnGhostMapInit);
|
||||
|
||||
SubscribeLocalEvent<GhostComponent, ExaminedEvent>(OnGhostExamine);
|
||||
|
||||
@@ -121,7 +120,20 @@ namespace Content.Server.Ghost
|
||||
eye.VisibilityMask |= (uint) VisibilityFlags.Ghost;
|
||||
}
|
||||
|
||||
component.TimeOfDeath = _gameTiming.CurTime;
|
||||
var time = _gameTiming.CurTime;
|
||||
component.TimeOfDeath = time;
|
||||
|
||||
// TODO ghost: remove once ghosts are persistent and aren't deleted when returning to body
|
||||
var action = _actions.AddAction(uid, ref component.ActionEntity, component.Action);
|
||||
if (action?.UseDelay != null)
|
||||
{
|
||||
action.Cooldown = (time, time + action.UseDelay.Value);
|
||||
Dirty(component.ActionEntity!.Value, action);
|
||||
}
|
||||
|
||||
_actions.AddAction(uid, ref component.ToggleLightingActionEntity, component.ToggleLightingAction);
|
||||
_actions.AddAction(uid, ref component.ToggleFoVActionEntity, component.ToggleFoVAction);
|
||||
_actions.AddAction(uid, ref component.ToggleGhostsActionEntity, component.ToggleGhostsAction);
|
||||
}
|
||||
|
||||
private void OnGhostShutdown(EntityUid uid, GhostComponent component, ComponentShutdown args)
|
||||
@@ -147,22 +159,6 @@ namespace Content.Server.Ghost
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGhostMapInit(EntityUid uid, GhostComponent component, MapInitEvent args)
|
||||
{
|
||||
// TODO ghost: remove once ghosts are persistent and aren't deleted when returning to body
|
||||
var time = _gameTiming.CurTime;
|
||||
var action = _actions.AddAction(uid, ref component.ActionEntity, component.Action);
|
||||
if (action?.UseDelay != null)
|
||||
{
|
||||
action.Cooldown = (time, time + action.UseDelay.Value);
|
||||
Dirty(component.ActionEntity!.Value, action);
|
||||
}
|
||||
|
||||
_actions.AddAction(uid, ref component.ToggleLightingActionEntity, component.ToggleLightingAction);
|
||||
_actions.AddAction(uid, ref component.ToggleFoVActionEntity, component.ToggleFoVAction);
|
||||
_actions.AddAction(uid, ref component.ToggleGhostsActionEntity, component.ToggleGhostsAction);
|
||||
}
|
||||
|
||||
private void OnGhostExamine(EntityUid uid, GhostComponent component, ExaminedEvent args)
|
||||
{
|
||||
var timeSinceDeath = _gameTiming.RealTime.Subtract(component.TimeOfDeath);
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace Content.Server.Guardian
|
||||
SubscribeLocalEvent<GuardianComponent, PlayerDetachedEvent>(OnGuardianUnplayer);
|
||||
|
||||
SubscribeLocalEvent<GuardianHostComponent, ComponentInit>(OnHostInit);
|
||||
SubscribeLocalEvent<GuardianHostComponent, MapInitEvent>(OnHostMapInit);
|
||||
SubscribeLocalEvent<GuardianHostComponent, MoveEvent>(OnHostMove);
|
||||
SubscribeLocalEvent<GuardianHostComponent, MobStateChangedEvent>(OnHostStateChange);
|
||||
SubscribeLocalEvent<GuardianHostComponent, ComponentShutdown>(OnHostShutdown);
|
||||
@@ -90,10 +89,6 @@ namespace Content.Server.Guardian
|
||||
private void OnHostInit(EntityUid uid, GuardianHostComponent component, ComponentInit args)
|
||||
{
|
||||
component.GuardianContainer = uid.EnsureContainer<ContainerSlot>("GuardianContainer");
|
||||
}
|
||||
|
||||
private void OnHostMapInit(EntityUid uid, GuardianHostComponent component, MapInitEvent args)
|
||||
{
|
||||
_actionSystem.AddAction(uid, ref component.ActionEntity, component.Action);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ public sealed partial class ArtifactComponent : Component
|
||||
Volume = 3f
|
||||
}
|
||||
};
|
||||
|
||||
[DataField("activateActionEntity")] public EntityUid? ActivateActionEntity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,21 +18,21 @@ public partial class ArtifactSystem
|
||||
/// </summary>
|
||||
public void InitializeActions()
|
||||
{
|
||||
SubscribeLocalEvent<ArtifactComponent, MapInitEvent>(OnStartup);
|
||||
SubscribeLocalEvent<ArtifactComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<ArtifactComponent, ComponentRemove>(OnRemove);
|
||||
|
||||
SubscribeLocalEvent<ArtifactComponent, ArtifactSelfActivateEvent>(OnSelfActivate);
|
||||
}
|
||||
|
||||
private void OnStartup(EntityUid uid, ArtifactComponent component, MapInitEvent args)
|
||||
private void OnMapInit(EntityUid uid, ArtifactComponent component, MapInitEvent args)
|
||||
{
|
||||
RandomizeArtifact(uid, component);
|
||||
_actions.AddAction(uid, Spawn(ArtifactActivateActionId), null);
|
||||
_actions.AddAction(uid, ref component.ActivateActionEntity, ArtifactActivateActionId);
|
||||
}
|
||||
|
||||
private void OnRemove(EntityUid uid, ArtifactComponent component, ComponentRemove args)
|
||||
{
|
||||
_actions.RemoveAction(uid, ArtifactActivateActionId);
|
||||
_actions.RemoveAction(uid, component.ActivateActionEntity);
|
||||
}
|
||||
|
||||
private void OnSelfActivate(EntityUid uid, ArtifactComponent component, ArtifactSelfActivateEvent args)
|
||||
|
||||
@@ -105,8 +105,8 @@ namespace Content.Server.Zombies
|
||||
|
||||
//This is needed for stupid entities that fuck up combat mode component
|
||||
//in an attempt to make an entity not attack. This is the easiest way to do it.
|
||||
RemComp<CombatModeComponent>(target);
|
||||
var combat = AddComp<CombatModeComponent>(target);
|
||||
var combat = EnsureComp<CombatModeComponent>(target);
|
||||
_combat.SetCanDisarm(target, false, combat);
|
||||
_combat.SetInCombatMode(target, true, combat);
|
||||
|
||||
//This is the actual damage of the zombie. We assign the visual appearance
|
||||
|
||||
@@ -13,15 +13,17 @@ public sealed partial class ActionsComponent : Component
|
||||
/// </summary>
|
||||
[ViewVariables] public readonly Dictionary<EntityUid, ActionMetaData> OldClientActions = new();
|
||||
|
||||
[ViewVariables] public readonly HashSet<EntityUid> Actions = new();
|
||||
|
||||
public override bool SendOnlyToOwner => true;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ActionsComponentState : ComponentState
|
||||
{
|
||||
public readonly List<EntityUid> Actions;
|
||||
public readonly HashSet<EntityUid> Actions;
|
||||
|
||||
public ActionsComponentState(List<EntityUid> actions)
|
||||
public ActionsComponentState(HashSet<EntityUid> actions)
|
||||
{
|
||||
Actions = actions;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Shared.Actions;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Eye.Blinding.Systems;
|
||||
using Content.Shared.Speech;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
@@ -10,6 +11,7 @@ namespace Content.Server.Bed.Sleep
|
||||
public abstract class SharedSleepingSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private readonly BlindableSystem _blindableSystem = default!;
|
||||
|
||||
@@ -19,7 +21,6 @@ namespace Content.Server.Bed.Sleep
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<SleepingComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<SleepingComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<SleepingComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<SleepingComponent, SpeakAttemptEvent>(OnSpeakAttempt);
|
||||
SubscribeLocalEvent<SleepingComponent, CanSeeAttemptEvent>(OnSeeAttempt);
|
||||
@@ -37,10 +38,10 @@ namespace Content.Server.Bed.Sleep
|
||||
var ev = new SleepStateChangedEvent(true);
|
||||
RaiseLocalEvent(uid, ev);
|
||||
_blindableSystem.UpdateIsBlind(uid);
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, SleepingComponent component, MapInitEvent args)
|
||||
{
|
||||
if (_net.IsClient)
|
||||
return;
|
||||
|
||||
component.WakeAction = Spawn(WakeActionId);
|
||||
_actionsSystem.SetCooldown(component.WakeAction, _gameTiming.CurTime, _gameTiming.CurTime + TimeSpan.FromSeconds(15));
|
||||
_actionsSystem.AddAction(uid, component.WakeAction.Value, null);
|
||||
|
||||
@@ -9,7 +9,6 @@ using Content.Shared.Popups;
|
||||
using Content.Shared.Strip;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -23,7 +22,6 @@ public sealed class ToggleableClothingSystem : EntitySystem
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly SharedStrippableSystem _strippable = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
private Queue<EntityUid> _toInsert = new();
|
||||
|
||||
@@ -283,8 +281,6 @@ public sealed class ToggleableClothingSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
component.ActionEntity ??= Spawn(component.Action);
|
||||
|
||||
if (component.ClothingUid != null && component.ActionEntity != null)
|
||||
{
|
||||
DebugTools.Assert(Exists(component.ClothingUid), "Toggleable clothing is missing expected entity.");
|
||||
|
||||
@@ -17,12 +17,12 @@ public abstract class SharedCombatModeSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CombatModeComponent, MapInitEvent>(OnStartup);
|
||||
SubscribeLocalEvent<CombatModeComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<CombatModeComponent, ComponentShutdown>(OnShutdown);
|
||||
SubscribeLocalEvent<CombatModeComponent, ToggleCombatActionEvent>(OnActionPerform);
|
||||
}
|
||||
|
||||
private void OnStartup(EntityUid uid, CombatModeComponent component, MapInitEvent args)
|
||||
private void OnMapInit(EntityUid uid, CombatModeComponent component, MapInitEvent args)
|
||||
{
|
||||
_actionsSystem.AddAction(uid, ref component.CombatToggleActionEntity, component.CombatToggleAction);
|
||||
}
|
||||
|
||||
@@ -21,11 +21,11 @@ public abstract class SharedDevourSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DevourerComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<DevourerComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<DevourerComponent, DevourActionEvent>(OnDevourAction);
|
||||
}
|
||||
|
||||
protected void OnMapInit(EntityUid uid, DevourerComponent component, MapInitEvent args)
|
||||
protected void OnStartup(EntityUid uid, DevourerComponent component, ComponentStartup args)
|
||||
{
|
||||
//Devourer doesn't actually chew, since he sends targets right into his stomach.
|
||||
//I did it mom, I added ERP content into upstream. Legally!
|
||||
|
||||
@@ -6,13 +6,13 @@ using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.Implants;
|
||||
|
||||
public abstract class SharedSubdermalImplantSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actionsSystem = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly TagSystem _tag = default!;
|
||||
@@ -32,7 +32,7 @@ public abstract class SharedSubdermalImplantSystem : EntitySystem
|
||||
|
||||
private void OnInsert(EntityUid uid, SubdermalImplantComponent component, EntGotInsertedIntoContainerMessage args)
|
||||
{
|
||||
if (component.ImplantedEntity == null)
|
||||
if (component.ImplantedEntity == null || _net.IsClient)
|
||||
return;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(component.ImplantAction))
|
||||
|
||||
@@ -17,7 +17,7 @@ using Content.Shared.Popups;
|
||||
using Content.Shared.Weapons.Melee;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Content.Shared.Mech.EntitySystems;
|
||||
public abstract class SharedMechSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
||||
[Dependency] private readonly AccessReaderSystem _access = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||
@@ -176,6 +176,9 @@ public abstract class SharedMechSystem : EntitySystem
|
||||
rider.Mech = mech;
|
||||
Dirty(pilot, rider);
|
||||
|
||||
if (_net.IsClient)
|
||||
return;
|
||||
|
||||
_actions.AddAction(pilot, Spawn(component.MechCycleAction), mech);
|
||||
_actions.AddAction(pilot, Spawn(component.MechUiAction),
|
||||
mech);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.Mobs.Systems;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Content.Shared.Mobs.Systems;
|
||||
/// </summary>
|
||||
public sealed class MobStateActionsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -20,6 +20,9 @@ public sealed class MobStateActionsSystem : EntitySystem
|
||||
|
||||
private void OnMobStateChanged(EntityUid uid, MobStateActionsComponent component, MobStateChangedEvent args)
|
||||
{
|
||||
if (_net.IsClient)
|
||||
return;
|
||||
|
||||
if (!TryComp<ActionsComponent>(uid, out var action))
|
||||
return;
|
||||
|
||||
@@ -30,10 +33,6 @@ public sealed class MobStateActionsSystem : EntitySystem
|
||||
|
||||
foreach (var item in acts)
|
||||
{
|
||||
if (!_proto.TryIndex<EntityPrototype>(item, out var proto))
|
||||
continue;
|
||||
|
||||
var instance = Spawn(item);
|
||||
if (state == args.OldMobState)
|
||||
{
|
||||
// Don't remove actions that would be getting readded anyway
|
||||
@@ -41,11 +40,11 @@ public sealed class MobStateActionsSystem : EntitySystem
|
||||
&& value.Contains(item))
|
||||
continue;
|
||||
|
||||
_actions.RemoveAction(uid, instance, action);
|
||||
_actions.RemoveAction(uid, item, action);
|
||||
}
|
||||
else if (state == args.NewMobState)
|
||||
{
|
||||
_actions.AddAction(uid, instance, null, action);
|
||||
_actions.AddAction(uid, Spawn(item), null, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared.Spider;
|
||||
@@ -6,6 +7,7 @@ namespace Content.Shared.Spider;
|
||||
public abstract class SharedSpiderSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedActionsSystem _action = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
@@ -13,12 +15,15 @@ public abstract class SharedSpiderSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SpiderComponent, MapInitEvent>(OnSpiderMapInit);
|
||||
SubscribeLocalEvent<SpiderComponent, ComponentStartup>(OnSpiderStartup);
|
||||
SubscribeLocalEvent<SpiderWebObjectComponent, ComponentStartup>(OnWebStartup);
|
||||
}
|
||||
|
||||
private void OnSpiderMapInit(EntityUid uid, SpiderComponent component, MapInitEvent args)
|
||||
private void OnSpiderStartup(EntityUid uid, SpiderComponent component, ComponentStartup args)
|
||||
{
|
||||
if (_net.IsClient)
|
||||
return;
|
||||
|
||||
_action.AddAction(uid, Spawn(component.WebAction), null);
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
icon: Interface/Actions/harmOff.png
|
||||
iconOn: Interface/Actions/harm.png
|
||||
event: !type:ToggleCombatActionEvent
|
||||
priority: -100
|
||||
|
||||
- type: entity
|
||||
id: ActionCombatModeToggleOff
|
||||
@@ -155,6 +156,7 @@
|
||||
- type: InstantAction
|
||||
enabled: false
|
||||
autoPopulate: false
|
||||
priority: -100
|
||||
|
||||
- type: entity
|
||||
id: ActionChangeVoiceMask
|
||||
|
||||
Reference in New Issue
Block a user