diff --git a/Content.Client/Actions/ActionsSystem.cs b/Content.Client/Actions/ActionsSystem.cs index 55ced8632c..2d9b777abd 100644 --- a/Content.Client/Actions/ActionsSystem.cs +++ b/Content.Client/Actions/ActionsSystem.cs @@ -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(); - var added = new List(); + var added = new List<(EntityUid Id, BaseActionComponent Comp)>(); var query = GetEntityQuery(); var queue = new Queue(_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(); diff --git a/Content.Client/CombatMode/CombatModeSystem.cs b/Content.Client/CombatMode/CombatModeSystem.cs index 00ac48a798..9fccfd173e 100644 --- a/Content.Client/CombatMode/CombatModeSystem.cs +++ b/Content.Client/CombatMode/CombatModeSystem.cs @@ -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; diff --git a/Content.Server/Abilities/Mime/MimePowersComponent.cs b/Content.Server/Abilities/Mime/MimePowersComponent.cs index 35393093b7..fd4fc2c2af 100644 --- a/Content.Server/Abilities/Mime/MimePowersComponent.cs +++ b/Content.Server/Abilities/Mime/MimePowersComponent.cs @@ -20,10 +20,10 @@ namespace Content.Server.Abilities.Mime /// The wall prototype to use. /// [DataField("wallPrototype", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string WallPrototype = "ActionMimeInvisibleWall"; + public string WallPrototype = "WallInvisible"; [DataField("invisibleWallAction", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? InvisibleWallAction; + public string? InvisibleWallAction = "ActionMimeInvisibleWall"; [DataField("invisibleWallActionEntity")] public EntityUid? InvisibleWallActionEntity; diff --git a/Content.Server/Abilities/Mime/MimePowersSystem.cs b/Content.Server/Abilities/Mime/MimePowersSystem.cs index 5a47fb1d8d..abc3b080fc 100644 --- a/Content.Server/Abilities/Mime/MimePowersSystem.cs +++ b/Content.Server/Abilities/Mime/MimePowersSystem.cs @@ -28,7 +28,6 @@ namespace Content.Server.Abilities.Mime { base.Initialize(); SubscribeLocalEvent(OnComponentInit); - SubscribeLocalEvent(OnComponentMapInit); SubscribeLocalEvent(OnInvisibleWall); } @@ -55,10 +54,6 @@ namespace Content.Server.Abilities.Mime { EnsureComp(uid); _alertsSystem.ShowAlert(uid, AlertType.VowOfSilence); - } - - private void OnComponentMapInit(EntityUid uid, MimePowersComponent component, MapInitEvent args) - { _actionsSystem.AddAction(uid, ref component.InvisibleWallActionEntity, component.InvisibleWallAction, uid); } diff --git a/Content.Server/Dragon/DragonSystem.cs b/Content.Server/Dragon/DragonSystem.cs index 0169e16c44..f132e0041e 100644 --- a/Content.Server/Dragon/DragonSystem.cs +++ b/Content.Server/Dragon/DragonSystem.cs @@ -48,7 +48,6 @@ public sealed partial class DragonSystem : EntitySystem base.Initialize(); SubscribeLocalEvent(OnStartup); - SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnDragonRift); SubscribeLocalEvent(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); } } diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index 3b63bdfdc4..c7941fa7a5 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -47,7 +47,6 @@ namespace Content.Server.Ghost SubscribeLocalEvent(OnGhostStartup); SubscribeLocalEvent(OnGhostShutdown); - SubscribeLocalEvent(OnGhostMapInit); SubscribeLocalEvent(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); diff --git a/Content.Server/Guardian/GuardianSystem.cs b/Content.Server/Guardian/GuardianSystem.cs index 323a0fc515..0cfcbe032e 100644 --- a/Content.Server/Guardian/GuardianSystem.cs +++ b/Content.Server/Guardian/GuardianSystem.cs @@ -46,7 +46,6 @@ namespace Content.Server.Guardian SubscribeLocalEvent(OnGuardianUnplayer); SubscribeLocalEvent(OnHostInit); - SubscribeLocalEvent(OnHostMapInit); SubscribeLocalEvent(OnHostMove); SubscribeLocalEvent(OnHostStateChange); SubscribeLocalEvent(OnHostShutdown); @@ -90,10 +89,6 @@ namespace Content.Server.Guardian private void OnHostInit(EntityUid uid, GuardianHostComponent component, ComponentInit args) { component.GuardianContainer = uid.EnsureContainer("GuardianContainer"); - } - - private void OnHostMapInit(EntityUid uid, GuardianHostComponent component, MapInitEvent args) - { _actionSystem.AddAction(uid, ref component.ActionEntity, component.Action); } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs index 500ce761cf..ec5af2a15c 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactComponent.cs @@ -91,6 +91,8 @@ public sealed partial class ArtifactComponent : Component Volume = 3f } }; + + [DataField("activateActionEntity")] public EntityUid? ActivateActionEntity; } /// diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Actions.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Actions.cs index 91aaaa417a..6c4089a2db 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Actions.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/ArtifactSystem.Actions.cs @@ -18,21 +18,21 @@ public partial class ArtifactSystem /// public void InitializeActions() { - SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnRemove); SubscribeLocalEvent(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) diff --git a/Content.Server/Zombies/ZombieSystem.Transform.cs b/Content.Server/Zombies/ZombieSystem.Transform.cs index 4bfe961b78..5da7c6e8cd 100644 --- a/Content.Server/Zombies/ZombieSystem.Transform.cs +++ b/Content.Server/Zombies/ZombieSystem.Transform.cs @@ -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(target); - var combat = AddComp(target); + var combat = EnsureComp(target); + _combat.SetCanDisarm(target, false, combat); _combat.SetInCombatMode(target, true, combat); //This is the actual damage of the zombie. We assign the visual appearance diff --git a/Content.Shared/Actions/ActionsComponent.cs b/Content.Shared/Actions/ActionsComponent.cs index c84484dfc0..bceb08b121 100644 --- a/Content.Shared/Actions/ActionsComponent.cs +++ b/Content.Shared/Actions/ActionsComponent.cs @@ -13,15 +13,17 @@ public sealed partial class ActionsComponent : Component /// [ViewVariables] public readonly Dictionary OldClientActions = new(); + [ViewVariables] public readonly HashSet Actions = new(); + public override bool SendOnlyToOwner => true; } [Serializable, NetSerializable] public sealed class ActionsComponentState : ComponentState { - public readonly List Actions; + public readonly HashSet Actions; - public ActionsComponentState(List actions) + public ActionsComponentState(HashSet actions) { Actions = actions; } diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 00514fcea3..12e5c2260a 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -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(OnGetActionData); SubscribeLocalEvent(OnGetActionData); + SubscribeLocalEvent(OnEntGotRemovedFromContainer); + SubscribeLocalEvent(OnEntGotRemovedFromContainer); + SubscribeLocalEvent(OnEntGotRemovedFromContainer); + SubscribeAllEvent(OnActionRequest); } @@ -127,6 +133,21 @@ public abstract class SharedActionsSystem : EntitySystem args.Action = component; } + private void OnEntGotRemovedFromContainer(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(holderId, ActionContainerId); + return providerId == null + ? _containerSystem.EnsureContainer(holderId, ActionContainerId) + : _containerSystem.EnsureContainer(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(); - 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); } /// @@ -561,7 +590,7 @@ public abstract class SharedActionsSystem : EntitySystem comp ??= EnsureComp(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 /// /// Remove any actions that were enabled by some other entity. Useful when unequiping items that grant actions. /// - 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()); } /// /// Removes all actions with the given prototype id. /// - 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); } } diff --git a/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs b/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs index d049699d9d..bb9c8dcf43 100644 --- a/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs +++ b/Content.Shared/Bed/Sleep/SharedSleepingSystem.cs @@ -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(OnStartup); - SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnSpeakAttempt); SubscribeLocalEvent(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); diff --git a/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs index 06ef6728fa..ae143e1f90 100644 --- a/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs @@ -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 _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."); diff --git a/Content.Shared/CombatMode/SharedCombatModeSystem.cs b/Content.Shared/CombatMode/SharedCombatModeSystem.cs index 5b208a08f9..263f3e8311 100644 --- a/Content.Shared/CombatMode/SharedCombatModeSystem.cs +++ b/Content.Shared/CombatMode/SharedCombatModeSystem.cs @@ -17,12 +17,12 @@ public abstract class SharedCombatModeSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnStartup); + SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(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); } diff --git a/Content.Shared/Devour/SharedDevourSystem.cs b/Content.Shared/Devour/SharedDevourSystem.cs index 5ac052d3a4..bdc198034b 100644 --- a/Content.Shared/Devour/SharedDevourSystem.cs +++ b/Content.Shared/Devour/SharedDevourSystem.cs @@ -21,11 +21,11 @@ public abstract class SharedDevourSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnStartup); SubscribeLocalEvent(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! diff --git a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs index 2f98093525..15780138f9 100644 --- a/Content.Shared/Implants/SharedSubdermalImplantSystem.cs +++ b/Content.Shared/Implants/SharedSubdermalImplantSystem.cs @@ -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)) diff --git a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs b/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs index 76c3be24bb..95dd906e35 100644 --- a/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs +++ b/Content.Shared/Mech/EntitySystems/SharedMechSystem.cs @@ -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); diff --git a/Content.Shared/Mobs/Systems/MobStateActionsSystem.cs b/Content.Shared/Mobs/Systems/MobStateActionsSystem.cs index acb1483b52..1e5695229e 100644 --- a/Content.Shared/Mobs/Systems/MobStateActionsSystem.cs +++ b/Content.Shared/Mobs/Systems/MobStateActionsSystem.cs @@ -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; /// public sealed class MobStateActionsSystem : EntitySystem { - [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly INetManager _net = default!; [Dependency] private readonly SharedActionsSystem _actions = default!; /// @@ -20,6 +20,9 @@ public sealed class MobStateActionsSystem : EntitySystem private void OnMobStateChanged(EntityUid uid, MobStateActionsComponent component, MobStateChangedEvent args) { + if (_net.IsClient) + return; + if (!TryComp(uid, out var action)) return; @@ -30,10 +33,6 @@ public sealed class MobStateActionsSystem : EntitySystem foreach (var item in acts) { - if (!_proto.TryIndex(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); } } } diff --git a/Content.Shared/Spider/SharedSpiderSystem.cs b/Content.Shared/Spider/SharedSpiderSystem.cs index 7871e55e57..f6ee5711e7 100644 --- a/Content.Shared/Spider/SharedSpiderSystem.cs +++ b/Content.Shared/Spider/SharedSpiderSystem.cs @@ -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(OnSpiderMapInit); + SubscribeLocalEvent(OnSpiderStartup); SubscribeLocalEvent(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); } diff --git a/Resources/Prototypes/Actions/types.yml b/Resources/Prototypes/Actions/types.yml index 518f19f1f9..67c6cc619c 100644 --- a/Resources/Prototypes/Actions/types.yml +++ b/Resources/Prototypes/Actions/types.yml @@ -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