diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs
index 6e781970bd..6bcf4b5872 100644
--- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs
+++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs
@@ -302,7 +302,7 @@ namespace Content.IntegrationTests.Tests.Buckle
human.Transform.LocalPosition += (100, 0);
});
- await WaitUntil(server, () => !buckle.Buckled, maxTicks: 10);
+ await WaitUntil(server, () => !buckle.Buckled, 10);
Assert.False(buckle.Buckled);
diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs
index 7e956d89de..0eb0ffebea 100644
--- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs
+++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs
@@ -15,21 +15,16 @@ using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
-using NFluidsynth;
using Robust.Server.GameObjects;
-using Robust.Server.GameObjects.EntitySystemMessages;
using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.ComponentDependencies;
-using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
-using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
-using Robust.Shared.Log;
using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -39,8 +34,6 @@ namespace Content.Server.GameObjects.Components.Buckle
[RegisterComponent]
public class BuckleComponent : SharedBuckleComponent, IInteractHand
{
- [Dependency] private readonly IEntityManager _entityManager = default!;
- [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[ComponentDependency] public readonly AppearanceComponent? AppearanceComponent = null;
@@ -69,7 +62,10 @@ namespace Content.Server.GameObjects.Components.Buckle
[ViewVariables]
private TimeSpan _buckleTime;
- public Vector2? BuckleOffset { get; private set; }
+ ///
+ /// The position offset that is being applied to this entity if buckled.
+ ///
+ public Vector2 BuckleOffset { get; private set; }
private StrapComponent? _buckledTo;
@@ -91,20 +87,6 @@ namespace Content.Server.GameObjects.Components.Buckle
[ViewVariables]
public override bool Buckled => BuckledTo != null;
- ///
- /// True if the entity was inserted or removed from a container
- /// before updating, false otherwise.
- ///
- [ViewVariables]
- private bool ContainerChanged { get; set; }
-
- ///
- /// True if the entity was forcefully moved while buckled and should
- /// unbuckle next update, false otherwise
- ///
- [ViewVariables]
- private bool Moved { get; set; }
-
///
/// The amount of space that this entity occupies in a
/// .
@@ -116,18 +98,20 @@ namespace Content.Server.GameObjects.Components.Buckle
/// Shows or hides the buckled status effect depending on if the
/// entity is buckled or not.
///
- private void BuckleStatus()
+ private void UpdateBuckleStatus()
{
- if (_serverStatusEffectsComponent != null)
+ if (_serverStatusEffectsComponent == null)
{
- if (Buckled)
- {
- _serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon);
- }
- else
- {
- _serverStatusEffectsComponent.RemoveStatusEffect(StatusEffect.Buckled);
- }
+ return;
+ }
+
+ if (Buckled)
+ {
+ _serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon);
+ }
+ else
+ {
+ _serverStatusEffectsComponent.RemoveStatusEffect(StatusEffect.Buckled);
}
}
@@ -135,7 +119,7 @@ namespace Content.Server.GameObjects.Components.Buckle
/// Reattaches this entity to the strap, modifying its position and rotation.
///
/// The strap to reattach to.
- private void ReAttach(StrapComponent strap)
+ public void ReAttach(StrapComponent strap)
{
var ownTransform = Owner.Transform;
var strapTransform = strap.Owner.Transform;
@@ -161,7 +145,7 @@ namespace Content.Server.GameObjects.Components.Buckle
if (strapTransform.WorldRotation.GetCardinalDir() == Direction.North)
{
BuckleOffset = (0, 0.15f);
- ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset!.Value;
+ ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset;
}
else
{
@@ -266,8 +250,7 @@ namespace Content.Server.GameObjects.Components.Buckle
return false;
}
- _entitySystem.GetEntitySystem()
- .PlayFromEntity(strap.BuckleSound, Owner);
+ EntitySystem.Get().PlayFromEntity(strap.BuckleSound, Owner);
if (!strap.TryAdd(this))
{
@@ -283,7 +266,7 @@ namespace Content.Server.GameObjects.Components.Buckle
BuckledTo = strap;
ReAttach(strap);
- BuckleStatus();
+ UpdateBuckleStatus();
SendMessage(new BuckleMessage(Owner, to));
@@ -312,12 +295,12 @@ namespace Content.Server.GameObjects.Components.Buckle
///
public bool TryUnbuckle(IEntity user, bool force = false)
{
- if (!Buckled)
+ if (BuckledTo == null)
{
return false;
}
- StrapComponent oldBuckledTo = BuckledTo!;
+ var oldBuckledTo = BuckledTo;
if (!force)
{
@@ -357,16 +340,12 @@ namespace Content.Server.GameObjects.Components.Buckle
EntitySystem.Get().Standing(Owner);
}
- if (_mobStateManagerComponent != null)
- {
- _mobStateManagerComponent.CurrentMobState.EnterState(Owner);
- }
+ _mobStateManagerComponent?.CurrentMobState.EnterState(Owner);
- BuckleStatus();
+ UpdateBuckleStatus();
oldBuckledTo.Remove(this);
- _entitySystem.GetEntitySystem()
- .PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner);
+ EntitySystem.Get().PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner);
SendMessage(new UnbuckleMessage(Owner, oldBuckledTo.Owner));
@@ -397,90 +376,6 @@ namespace Content.Server.GameObjects.Components.Buckle
return TryBuckle(user, to);
}
- ///
- /// Checks if a buckled entity should be unbuckled from moving
- /// too far from its strap.
- ///
- /// The move event of a buckled entity.
- public void OnMoveEvent(MoveEvent moveEvent)
- {
- if (moveEvent.Sender != Owner)
- {
- return;
- }
-
- if (BuckledTo == null || !BuckleOffset.HasValue)
- {
- return;
- }
-
- var bucklePosition = BuckledTo.Owner.Transform.Coordinates.Offset(BuckleOffset.Value);
-
- if (moveEvent.NewPosition.InRange(_entityManager, bucklePosition, 0.2f))
- {
- return;
- }
-
- Moved = true;
- }
-
- ///
- /// Called when the owner is inserted or removed from a container,
- /// to synchronize the state of buckling.
- ///
- /// The message received
- private void InsertIntoContainer(ContainerModifiedMessage message)
- {
- if (message.Entity != Owner)
- {
- return;
- }
-
- ContainerChanged = true;
- }
-
- ///
- /// Synchronizes the state of buckling depending on whether the entity
- /// was inserted or removed from a container, and whether or not
- /// its current strap (if there is one) has also been put into or removed
- /// from the same container as well.
- ///
- public void Update()
- {
- if (BuckledTo == null)
- {
- return;
- }
-
- if (Moved)
- {
- TryUnbuckle(Owner, true);
- Moved = false;
- return;
- }
-
- if (!ContainerChanged)
- {
- return;
- }
-
- var contained = ContainerHelpers.TryGetContainer(Owner, out var ownContainer);
- var strapContained = ContainerHelpers.TryGetContainer(BuckledTo.Owner, out var strapContainer);
-
- if (contained != strapContained || ownContainer != strapContainer)
- {
- TryUnbuckle(Owner, true);
- return;
- }
-
- if (!contained && !strapContained)
- {
- ReAttach(BuckledTo);
- }
-
- ContainerChanged = false;
- }
-
public override void ExposeData(ObjectSerializer serializer)
{
base.ExposeData(serializer);
@@ -494,32 +389,21 @@ namespace Content.Server.GameObjects.Components.Buckle
_unbuckleDelay = TimeSpan.FromSeconds(seconds);
}
- public override void Initialize()
- {
- base.Initialize();
-
- _entityManager.EventBus.SubscribeEvent(EventSource.Local, this, InsertIntoContainer);
- _entityManager.EventBus.SubscribeEvent(EventSource.Local, this, InsertIntoContainer);
- }
-
protected override void Startup()
{
base.Startup();
- BuckleStatus();
+ UpdateBuckleStatus();
}
public override void OnRemove()
{
base.OnRemove();
- _entityManager.EventBus.UnsubscribeEvents(this);
-
BuckledTo?.Remove(this);
-
TryUnbuckle(Owner, true);
_buckleTime = default;
- BuckleStatus();
+ UpdateBuckleStatus();
}
public override ComponentState GetComponentState()
diff --git a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs
index 8e2f0c2422..c6bcb65591 100644
--- a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs
+++ b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs
@@ -1,8 +1,11 @@
-using Content.Server.GameObjects.Components.Buckle;
+#nullable enable
+using Content.Server.GameObjects.Components.Buckle;
+using Content.Server.GameObjects.Components.Strap;
using Content.Server.GameObjects.EntitySystems.Click;
using JetBrains.Annotations;
+using Robust.Server.GameObjects.EntitySystemMessages;
using Robust.Server.GameObjects.EntitySystems;
-using Robust.Shared.GameObjects;
+using Robust.Shared.Containers;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Systems;
@@ -17,7 +20,10 @@ namespace Content.Server.GameObjects.EntitySystems
UpdatesAfter.Add(typeof(InteractionSystem));
UpdatesAfter.Add(typeof(InputSystem));
+
SubscribeLocalEvent(MoveEvent);
+ SubscribeLocalEvent(ContainerModified);
+ SubscribeLocalEvent(ContainerModified);
}
public override void Shutdown()
@@ -29,17 +35,69 @@ namespace Content.Server.GameObjects.EntitySystems
private void MoveEvent(MoveEvent ev)
{
- if (ev.Sender.TryGetComponent(out BuckleComponent buckle))
+ if (!ev.Sender.TryGetComponent(out BuckleComponent? buckle))
{
- buckle.OnMoveEvent(ev);
+ return;
+ }
+
+ var strap = buckle.BuckledTo;
+
+ if (strap == null)
+ {
+ return;
+ }
+
+ var strapPosition = strap.Owner.Transform.Coordinates.Offset(buckle.BuckleOffset);
+
+ if (ev.NewPosition.InRange(EntityManager, strapPosition, 0.2f))
+ {
+ return;
+ }
+
+ buckle.TryUnbuckle(buckle.Owner, true);
+ }
+
+ private void ContainerModified(ContainerModifiedMessage message)
+ {
+ // Not returning is necessary in case an entity has both a buckle and strap component
+ if (message.Entity.TryGetComponent(out BuckleComponent? buckle))
+ {
+ ContainerModifiedReAttach(buckle, buckle.BuckledTo);
+ }
+
+ if (message.Entity.TryGetComponent(out StrapComponent? strap))
+ {
+ foreach (var buckledEntity in strap.BuckledEntities)
+ {
+ if (!buckledEntity.TryGetComponent(out BuckleComponent? buckled))
+ {
+ continue;
+ }
+
+ ContainerModifiedReAttach(buckled, strap);
+ }
}
}
- public override void Update(float frameTime)
+ private void ContainerModifiedReAttach(BuckleComponent buckle, StrapComponent? strap)
{
- foreach (var buckle in ComponentManager.EntityQuery())
+ if (strap == null)
{
- buckle.Update();
+ return;
+ }
+
+ var contained = ContainerHelpers.TryGetContainer(buckle.Owner, out var ownContainer);
+ var strapContained = ContainerHelpers.TryGetContainer(strap.Owner, out var strapContainer);
+
+ if (contained != strapContained || ownContainer != strapContainer)
+ {
+ buckle.TryUnbuckle(buckle.Owner, true);
+ return;
+ }
+
+ if (!contained)
+ {
+ buckle.ReAttach(strap);
}
}
}