Buckle improvements (#2508)

* Buckle improvements

* Update doc

* Remove redundant argument name

* Remove import
This commit is contained in:
DrSmugleaf
2020-11-06 15:15:02 +01:00
committed by GitHub
parent 560f89b297
commit b5d00a2cf6
3 changed files with 93 additions and 151 deletions

View File

@@ -302,7 +302,7 @@ namespace Content.IntegrationTests.Tests.Buckle
human.Transform.LocalPosition += (100, 0); human.Transform.LocalPosition += (100, 0);
}); });
await WaitUntil(server, () => !buckle.Buckled, maxTicks: 10); await WaitUntil(server, () => !buckle.Buckled, 10);
Assert.False(buckle.Buckled); Assert.False(buckle.Buckled);

View File

@@ -15,21 +15,16 @@ using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces; using Content.Shared.Interfaces;
using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility; using Content.Shared.Utility;
using NFluidsynth;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Server.GameObjects.EntitySystemMessages;
using Robust.Server.GameObjects.EntitySystems; using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.ComponentDependencies; using Robust.Shared.GameObjects.ComponentDependencies;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Timing; using Robust.Shared.Interfaces.Timing;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -39,8 +34,6 @@ namespace Content.Server.GameObjects.Components.Buckle
[RegisterComponent] [RegisterComponent]
public class BuckleComponent : SharedBuckleComponent, IInteractHand public class BuckleComponent : SharedBuckleComponent, IInteractHand
{ {
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IGameTiming _gameTiming = default!;
[ComponentDependency] public readonly AppearanceComponent? AppearanceComponent = null; [ComponentDependency] public readonly AppearanceComponent? AppearanceComponent = null;
@@ -69,7 +62,10 @@ namespace Content.Server.GameObjects.Components.Buckle
[ViewVariables] [ViewVariables]
private TimeSpan _buckleTime; private TimeSpan _buckleTime;
public Vector2? BuckleOffset { get; private set; } /// <summary>
/// The position offset that is being applied to this entity if buckled.
/// </summary>
public Vector2 BuckleOffset { get; private set; }
private StrapComponent? _buckledTo; private StrapComponent? _buckledTo;
@@ -91,20 +87,6 @@ namespace Content.Server.GameObjects.Components.Buckle
[ViewVariables] [ViewVariables]
public override bool Buckled => BuckledTo != null; public override bool Buckled => BuckledTo != null;
/// <summary>
/// True if the entity was inserted or removed from a container
/// before updating, false otherwise.
/// </summary>
[ViewVariables]
private bool ContainerChanged { get; set; }
/// <summary>
/// True if the entity was forcefully moved while buckled and should
/// unbuckle next update, false otherwise
/// </summary>
[ViewVariables]
private bool Moved { get; set; }
/// <summary> /// <summary>
/// The amount of space that this entity occupies in a /// The amount of space that this entity occupies in a
/// <see cref="StrapComponent"/>. /// <see cref="StrapComponent"/>.
@@ -116,18 +98,20 @@ namespace Content.Server.GameObjects.Components.Buckle
/// Shows or hides the buckled status effect depending on if the /// Shows or hides the buckled status effect depending on if the
/// entity is buckled or not. /// entity is buckled or not.
/// </summary> /// </summary>
private void BuckleStatus() private void UpdateBuckleStatus()
{ {
if (_serverStatusEffectsComponent != null) if (_serverStatusEffectsComponent == null)
{ {
if (Buckled) return;
{ }
_serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon);
} if (Buckled)
else {
{ _serverStatusEffectsComponent.ChangeStatusEffectIcon(StatusEffect.Buckled, BuckledTo!.BuckledIcon);
_serverStatusEffectsComponent.RemoveStatusEffect(StatusEffect.Buckled); }
} 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. /// Reattaches this entity to the strap, modifying its position and rotation.
/// </summary> /// </summary>
/// <param name="strap">The strap to reattach to.</param> /// <param name="strap">The strap to reattach to.</param>
private void ReAttach(StrapComponent strap) public void ReAttach(StrapComponent strap)
{ {
var ownTransform = Owner.Transform; var ownTransform = Owner.Transform;
var strapTransform = strap.Owner.Transform; var strapTransform = strap.Owner.Transform;
@@ -161,7 +145,7 @@ namespace Content.Server.GameObjects.Components.Buckle
if (strapTransform.WorldRotation.GetCardinalDir() == Direction.North) if (strapTransform.WorldRotation.GetCardinalDir() == Direction.North)
{ {
BuckleOffset = (0, 0.15f); BuckleOffset = (0, 0.15f);
ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset!.Value; ownTransform.WorldPosition = strapTransform.WorldPosition + BuckleOffset;
} }
else else
{ {
@@ -266,8 +250,7 @@ namespace Content.Server.GameObjects.Components.Buckle
return false; return false;
} }
_entitySystem.GetEntitySystem<AudioSystem>() EntitySystem.Get<AudioSystem>().PlayFromEntity(strap.BuckleSound, Owner);
.PlayFromEntity(strap.BuckleSound, Owner);
if (!strap.TryAdd(this)) if (!strap.TryAdd(this))
{ {
@@ -283,7 +266,7 @@ namespace Content.Server.GameObjects.Components.Buckle
BuckledTo = strap; BuckledTo = strap;
ReAttach(strap); ReAttach(strap);
BuckleStatus(); UpdateBuckleStatus();
SendMessage(new BuckleMessage(Owner, to)); SendMessage(new BuckleMessage(Owner, to));
@@ -312,12 +295,12 @@ namespace Content.Server.GameObjects.Components.Buckle
/// </returns> /// </returns>
public bool TryUnbuckle(IEntity user, bool force = false) public bool TryUnbuckle(IEntity user, bool force = false)
{ {
if (!Buckled) if (BuckledTo == null)
{ {
return false; return false;
} }
StrapComponent oldBuckledTo = BuckledTo!; var oldBuckledTo = BuckledTo;
if (!force) if (!force)
{ {
@@ -357,16 +340,12 @@ namespace Content.Server.GameObjects.Components.Buckle
EntitySystem.Get<StandingStateSystem>().Standing(Owner); EntitySystem.Get<StandingStateSystem>().Standing(Owner);
} }
if (_mobStateManagerComponent != null) _mobStateManagerComponent?.CurrentMobState.EnterState(Owner);
{
_mobStateManagerComponent.CurrentMobState.EnterState(Owner);
}
BuckleStatus(); UpdateBuckleStatus();
oldBuckledTo.Remove(this); oldBuckledTo.Remove(this);
_entitySystem.GetEntitySystem<AudioSystem>() EntitySystem.Get<AudioSystem>().PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner);
.PlayFromEntity(oldBuckledTo.UnbuckleSound, Owner);
SendMessage(new UnbuckleMessage(Owner, oldBuckledTo.Owner)); SendMessage(new UnbuckleMessage(Owner, oldBuckledTo.Owner));
@@ -397,90 +376,6 @@ namespace Content.Server.GameObjects.Components.Buckle
return TryBuckle(user, to); return TryBuckle(user, to);
} }
/// <summary>
/// Checks if a buckled entity should be unbuckled from moving
/// too far from its strap.
/// </summary>
/// <param name="moveEvent">The move event of a buckled entity.</param>
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;
}
/// <summary>
/// Called when the owner is inserted or removed from a container,
/// to synchronize the state of buckling.
/// </summary>
/// <param name="message">The message received</param>
private void InsertIntoContainer(ContainerModifiedMessage message)
{
if (message.Entity != Owner)
{
return;
}
ContainerChanged = true;
}
/// <summary>
/// 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.
/// </summary>
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) public override void ExposeData(ObjectSerializer serializer)
{ {
base.ExposeData(serializer); base.ExposeData(serializer);
@@ -494,32 +389,21 @@ namespace Content.Server.GameObjects.Components.Buckle
_unbuckleDelay = TimeSpan.FromSeconds(seconds); _unbuckleDelay = TimeSpan.FromSeconds(seconds);
} }
public override void Initialize()
{
base.Initialize();
_entityManager.EventBus.SubscribeEvent<EntInsertedIntoContainerMessage>(EventSource.Local, this, InsertIntoContainer);
_entityManager.EventBus.SubscribeEvent<EntRemovedFromContainerMessage>(EventSource.Local, this, InsertIntoContainer);
}
protected override void Startup() protected override void Startup()
{ {
base.Startup(); base.Startup();
BuckleStatus(); UpdateBuckleStatus();
} }
public override void OnRemove() public override void OnRemove()
{ {
base.OnRemove(); base.OnRemove();
_entityManager.EventBus.UnsubscribeEvents(this);
BuckledTo?.Remove(this); BuckledTo?.Remove(this);
TryUnbuckle(Owner, true); TryUnbuckle(Owner, true);
_buckleTime = default; _buckleTime = default;
BuckleStatus(); UpdateBuckleStatus();
} }
public override ComponentState GetComponentState() public override ComponentState GetComponentState()

View File

@@ -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 Content.Server.GameObjects.EntitySystems.Click;
using JetBrains.Annotations; using JetBrains.Annotations;
using Robust.Server.GameObjects.EntitySystemMessages;
using Robust.Server.GameObjects.EntitySystems; using Robust.Server.GameObjects.EntitySystems;
using Robust.Shared.GameObjects; using Robust.Shared.Containers;
using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Systems; using Robust.Shared.GameObjects.Systems;
@@ -17,7 +20,10 @@ namespace Content.Server.GameObjects.EntitySystems
UpdatesAfter.Add(typeof(InteractionSystem)); UpdatesAfter.Add(typeof(InteractionSystem));
UpdatesAfter.Add(typeof(InputSystem)); UpdatesAfter.Add(typeof(InputSystem));
SubscribeLocalEvent<MoveEvent>(MoveEvent); SubscribeLocalEvent<MoveEvent>(MoveEvent);
SubscribeLocalEvent<EntInsertedIntoContainerMessage>(ContainerModified);
SubscribeLocalEvent<EntRemovedFromContainerMessage>(ContainerModified);
} }
public override void Shutdown() public override void Shutdown()
@@ -29,17 +35,69 @@ namespace Content.Server.GameObjects.EntitySystems
private void MoveEvent(MoveEvent ev) 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<BuckleComponent>()) 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);
} }
} }
} }