Partial buckling refactor (#29031)
* partial buckling refactor * git mv test * change test namespace * git mv test * Update test namespace * Add pulling test * Network BuckleTime * Add two more tests * smelly
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Buckle.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||
/// <summary>
|
||||
/// This component allows an entity to be buckled to an entity with a <see cref="StrapComponent"/>.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[Access(typeof(SharedBuckleSystem))]
|
||||
public sealed partial class BuckleComponent : Component
|
||||
{
|
||||
@@ -14,31 +19,23 @@ public sealed partial class BuckleComponent : Component
|
||||
/// across a table two tiles away" problem.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Range = SharedInteractionSystem.InteractionRange / 1.4f;
|
||||
|
||||
/// <summary>
|
||||
/// True if the entity is buckled, false otherwise.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[AutoNetworkedField]
|
||||
public bool Buckled;
|
||||
|
||||
[ViewVariables]
|
||||
[AutoNetworkedField]
|
||||
public EntityUid? LastEntityBuckledTo;
|
||||
[MemberNotNullWhen(true, nameof(BuckledTo))]
|
||||
public bool Buckled => BuckledTo != null;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not collisions should be possible with the entity we are strapped to
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField, AutoNetworkedField]
|
||||
[DataField]
|
||||
public bool DontCollide;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not we should be allowed to pull the entity we are strapped to
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public bool PullStrap;
|
||||
|
||||
@@ -47,20 +44,18 @@ public sealed partial class BuckleComponent : Component
|
||||
/// be able to unbuckle after recently buckling.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public TimeSpan Delay = TimeSpan.FromSeconds(0.25f);
|
||||
|
||||
/// <summary>
|
||||
/// The time that this entity buckled at.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public TimeSpan BuckleTime;
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan? BuckleTime;
|
||||
|
||||
/// <summary>
|
||||
/// The strap that this component is buckled to.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[AutoNetworkedField]
|
||||
[DataField]
|
||||
public EntityUid? BuckledTo;
|
||||
|
||||
/// <summary>
|
||||
@@ -68,7 +63,6 @@ public sealed partial class BuckleComponent : Component
|
||||
/// <see cref="StrapComponent"/>.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int Size = 100;
|
||||
|
||||
/// <summary>
|
||||
@@ -77,11 +71,90 @@ public sealed partial class BuckleComponent : Component
|
||||
[ViewVariables] public int? OriginalDrawDepth;
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
public record struct BuckleAttemptEvent(EntityUid StrapEntity, EntityUid BuckledEntity, EntityUid UserEntity, bool Buckling, bool Cancelled = false);
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class BuckleState(NetEntity? buckledTo, bool dontCollide, TimeSpan? buckleTime) : ComponentState
|
||||
{
|
||||
public readonly NetEntity? BuckledTo = buckledTo;
|
||||
public readonly bool DontCollide = dontCollide;
|
||||
public readonly TimeSpan? BuckleTime = buckleTime;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a strap entity before some entity gets buckled to it.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct BuckleChangeEvent(EntityUid StrapEntity, EntityUid BuckledEntity, bool Buckling);
|
||||
public record struct StrapAttemptEvent(
|
||||
Entity<StrapComponent> Strap,
|
||||
Entity<BuckleComponent> Buckle,
|
||||
EntityUid? User,
|
||||
bool Popup)
|
||||
{
|
||||
public bool Cancelled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a buckle entity before it gets buckled to some strap entity.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct BuckleAttemptEvent(
|
||||
Entity<StrapComponent> Strap,
|
||||
Entity<BuckleComponent> Buckle,
|
||||
EntityUid? User,
|
||||
bool Popup)
|
||||
{
|
||||
public bool Cancelled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a strap entity before some entity gets unbuckled from it.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct UnstrapAttemptEvent(
|
||||
Entity<StrapComponent> Strap,
|
||||
Entity<BuckleComponent> Buckle,
|
||||
EntityUid? User,
|
||||
bool Popup)
|
||||
{
|
||||
public bool Cancelled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a buckle entity before it gets unbuckled.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct UnbuckleAttemptEvent(
|
||||
Entity<StrapComponent> Strap,
|
||||
Entity<BuckleComponent> Buckle,
|
||||
EntityUid? User,
|
||||
bool Popup)
|
||||
{
|
||||
public bool Cancelled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a strap entity after something has been buckled to it.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct StrappedEvent(Entity<StrapComponent> Strap, Entity<BuckleComponent> Buckle);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a buckle entity after it has been buckled.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct BuckledEvent(Entity<StrapComponent> Strap, Entity<BuckleComponent> Buckle);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a strap entity after something has been unbuckled from it.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct UnstrappedEvent(Entity<StrapComponent> Strap, Entity<BuckleComponent> Buckle);
|
||||
|
||||
/// <summary>
|
||||
/// Event raised directed at a buckle entity after it has been unbuckled from some strap entity.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public readonly record struct UnbuckledEvent(Entity<StrapComponent> Strap, Entity<BuckleComponent> Buckle);
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum BuckleVisuals
|
||||
|
||||
@@ -13,117 +13,77 @@ namespace Content.Shared.Buckle.Components;
|
||||
public sealed partial class StrapComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The entities that are currently buckled
|
||||
/// The entities that are currently buckled to this strap.
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[ViewVariables] // TODO serialization
|
||||
[ViewVariables]
|
||||
public HashSet<EntityUid> BuckledEntities = new();
|
||||
|
||||
/// <summary>
|
||||
/// Entities that this strap accepts and can buckle
|
||||
/// If null it accepts any entity
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public EntityWhitelist? Whitelist;
|
||||
|
||||
/// <summary>
|
||||
/// Entities that this strap does not accept and cannot buckle.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public EntityWhitelist? Blacklist;
|
||||
|
||||
/// <summary>
|
||||
/// The change in position to the strapped mob
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public StrapPosition Position = StrapPosition.None;
|
||||
|
||||
/// <summary>
|
||||
/// The distance above which a buckled entity will be automatically unbuckled.
|
||||
/// Don't change it unless you really have to
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dont set this below 0.2 because that causes audio issues with <see cref="SharedBuckleSystem.OnBuckleMove"/>
|
||||
/// My guess after testing is that the client sets BuckledTo to the strap in *some* ticks for some reason
|
||||
/// whereas the server doesnt, thus the client tries to unbuckle like 15 times because it passes the strap null check
|
||||
/// This is why this needs to be above 0.1 to make the InRange check fail in both client and server.
|
||||
/// </remarks>
|
||||
[DataField, AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float MaxBuckleDistance = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets and clamps the buckle offset to MaxBuckleDistance
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public Vector2 BuckleOffsetClamped => Vector2.Clamp(
|
||||
BuckleOffset,
|
||||
Vector2.One * -MaxBuckleDistance,
|
||||
Vector2.One * MaxBuckleDistance);
|
||||
|
||||
/// <summary>
|
||||
/// The buckled entity will be offset by this amount from the center of the strap object.
|
||||
/// If this offset it too big, it will be clamped to <see cref="MaxBuckleDistance"/>
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Vector2 BuckleOffset = Vector2.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The angle to rotate the player by when they get strapped
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Angle Rotation;
|
||||
|
||||
/// <summary>
|
||||
/// The size of the strap which is compared against when buckling entities
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int Size = 100;
|
||||
|
||||
/// <summary>
|
||||
/// If disabled, nothing can be buckled on this object, and it will unbuckle anything that's already buckled
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool Enabled = true;
|
||||
|
||||
/// <summary>
|
||||
/// You can specify the offset the entity will have after unbuckling.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Vector2 UnbuckleOffset = Vector2.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The sound to be played when a mob is buckled
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier BuckleSound = new SoundPathSpecifier("/Audio/Effects/buckle.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// The sound to be played when a mob is unbuckled
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public SoundSpecifier UnbuckleSound = new SoundPathSpecifier("/Audio/Effects/unbuckle.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// ID of the alert to show when buckled
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public ProtoId<AlertPrototype> BuckledAlertType = "Buckled";
|
||||
|
||||
/// <summary>
|
||||
/// The sum of the sizes of all the buckled entities in this strap
|
||||
/// </summary>
|
||||
[AutoNetworkedField]
|
||||
[ViewVariables]
|
||||
public int OccupiedSize;
|
||||
}
|
||||
|
||||
public enum StrapPosition
|
||||
|
||||
Reference in New Issue
Block a user