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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -91,6 +91,8 @@ public sealed partial class ArtifactComponent : Component
Volume = 3f
}
};
[DataField("activateActionEntity")] public EntityUid? ActivateActionEntity;
}
/// <summary>

View File

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

View File

@@ -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

View File

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

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

View File

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

View File

@@ -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.");

View File

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

View File

@@ -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!

View File

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

View File

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

View File

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

View File

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

View File

@@ -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