0 days without buckle breaking (#1366)

This commit is contained in:
DrSmugleaf
2020-07-17 10:43:10 +02:00
committed by GitHub
parent 5c723ea70e
commit f313a9267a
13 changed files with 370 additions and 127 deletions

View File

@@ -1,11 +1,13 @@
#nullable enable
using System;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Strap;
using Content.Server.Interfaces;
using Content.Server.Interfaces.GameObjects.Components.Interaction;
using Content.Server.Mobs;
using Content.Server.Utility;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Buckle;
using Content.Shared.GameObjects.Components.Mobs;
using Content.Shared.GameObjects.Components.Strap;
using Content.Shared.GameObjects.EntitySystems;
@@ -22,7 +24,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
namespace Content.Server.GameObjects.Components.Mobs
namespace Content.Server.GameObjects.Components.Buckle
{
[RegisterComponent]
public class BuckleComponent : SharedBuckleComponent, IInteractHand, IDragDrop
@@ -34,29 +36,32 @@ namespace Content.Server.GameObjects.Components.Mobs
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
#pragma warning restore 649
/// <summary>
/// The amount of space that this entity occupies in a <see cref="StrapComponent"/>.
/// </summary>
private int _size;
/// <summary>
/// The range from which this entity can buckle to a <see cref="StrapComponent"/>.
/// </summary>
[ViewVariables]
private float _range;
/// <summary>
/// The amount of time that must pass for this entity to
/// be able to unbuckle after recently buckling.
/// </summary>
[ViewVariables]
private TimeSpan _unbuckleDelay;
/// <summary>
/// The time that this entity buckled at.
/// </summary>
[ViewVariables]
private TimeSpan _buckleTime;
private StrapComponent? _buckledTo;
/// <summary>
/// The strap that this component is buckled to.
/// </summary>
[ViewVariables]
public StrapComponent? BuckledTo
{
@@ -70,13 +75,25 @@ namespace Content.Server.GameObjects.Components.Mobs
}
[ViewVariables]
protected override bool Buckled => BuckledTo != null;
public override bool Buckled => BuckledTo != null;
public bool ContainerChanged { get; private set; }
/// <summary>
/// True if the entity was inserted or removed from a container
/// before updating, false otherwise.
/// </summary>
[ViewVariables]
private bool ContainerChanged { get; set; }
/// <summary>
/// The amount of space that this entity occupies in a <see cref="StrapComponent"/>.
/// </summary>
[ViewVariables]
public int Size => _size;
/// <summary>
/// Shows or hides the buckled status effect depending on if the
/// entity is buckled or not.
/// </summary>
private void BuckleStatus()
{
if (Owner.TryGetComponent(out ServerStatusEffectsComponent status))
@@ -88,6 +105,10 @@ namespace Content.Server.GameObjects.Components.Mobs
}
}
/// <summary>
/// Reattaches this entity to the strap, modifying its position and rotation
/// </summary>
/// <param name="strap">The strap to reattach to</param>
private void ReAttach(StrapComponent strap)
{
var ownTransform = Owner.Transform;
@@ -112,7 +133,18 @@ namespace Content.Server.GameObjects.Components.Mobs
}
}
private bool TryBuckle(IEntity user, IEntity to)
/// <summary>
/// Tries to make an entity buckle the owner of this component to another.
/// </summary>
/// <param name="user">
/// The entity buckling the owner of this component, can be the owner itself.
/// </param>
/// <param name="to">The entity to buckle the owner of this component to.</param>
/// <returns>
/// true if the owner was buckled, otherwise false even if the owner was
/// previously already buckled.
/// </returns>
public bool TryBuckle(IEntity user, IEntity to)
{
if (user == null || user == to)
{
@@ -142,8 +174,10 @@ namespace Content.Server.GameObjects.Components.Mobs
return false;
}
// If in a container
if (ContainerHelpers.TryGetContainer(Owner, out var ownerContainer))
{
// And not in the same container as the strap
if (!ContainerHelpers.TryGetContainer(strap.Owner, out var strapContainer) ||
ownerContainer != strapContainer)
{
@@ -218,6 +252,18 @@ namespace Content.Server.GameObjects.Components.Mobs
return true;
}
/// <summary>
/// Tries to unbuckle the Owner of this component from its current strap.
/// </summary>
/// <param name="user">The entity doing the unbuckling.</param>
/// <param name="force">
/// Whether to force the unbuckling or not. Does not guarantee true to
/// be returned, but guarantees the owner to be unbuckled afterwards.
/// </param>
/// <returns>
/// true if the owner was unbuckled, otherwise false even if the owner
/// was previously already unbuckled.
/// </returns>
public bool TryUnbuckle(IEntity user, bool force = false)
{
if (BuckledTo == null)
@@ -288,16 +334,35 @@ namespace Content.Server.GameObjects.Components.Mobs
return true;
}
public bool ToggleBuckle(IEntity user, IEntity to)
/// <summary>
/// Makes an entity toggle the buckling status of the owner to a
/// specific entity.
/// </summary>
/// <param name="user">The entity doing the buckling/unbuckling.</param>
/// <param name="to">
/// The entity to toggle the buckle status of the owner to.
/// </param>
/// <param name="force">
/// Whether to force the unbuckling or not, if it happens. Does not
/// guarantee true to be returned, but guarantees the owner to be
/// unbuckled afterwards.
/// </param>
/// <returns>true if the buckling status was changed, false otherwise.</returns>
public bool ToggleBuckle(IEntity user, IEntity to, bool force = false)
{
if (BuckledTo?.Owner == to)
{
return TryUnbuckle(user);
return TryUnbuckle(user, force);
}
return TryBuckle(user, to);
}
/// <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)
@@ -308,6 +373,12 @@ namespace Content.Server.GameObjects.Components.Mobs
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 (!ContainerChanged || BuckledTo == null)
@@ -401,6 +472,10 @@ namespace Content.Server.GameObjects.Components.Mobs
return TryBuckle(eventArgs.User, eventArgs.Target);
}
/// <summary>
/// Allows the unbuckling of the owning entity through a verb if
/// anyone right clicks them.
/// </summary>
[Verb]
private sealed class BuckleVerb : Verb<BuckleComponent>
{

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Buckle;
using Content.Shared.GameObjects.Components.Mobs;
using JetBrains.Annotations;
using Robust.Shared.GameObjects;

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Content.Server.GameObjects.Components.Mobs;
using Content.Server.GameObjects.Components.Buckle;
using Content.Server.Interfaces.GameObjects.Components.Interaction;
using Content.Shared.GameObjects;
using Content.Shared.GameObjects.Components.Strap;
@@ -17,30 +17,34 @@ namespace Content.Server.GameObjects.Components.Strap
[RegisterComponent]
public class StrapComponent : SharedStrapComponent, IInteractHand
{
private HashSet<IEntity> _buckledEntities;
private StrapPosition _position;
private string _buckleSound;
private string _unbuckleSound;
private string _buckledIcon;
/// <summary>
/// The angle in degrees to rotate the player by when they get strapped
/// </summary>
[ViewVariables]
private int _rotation;
/// <summary>
/// The size of the strap which is compared against when buckling entities
/// </summary>
[ViewVariables]
private int _size;
private int _occupiedSize;
/// <summary>
/// The entity that is currently buckled here, synced from <see cref="BuckleComponent.BuckledTo"/>
/// </summary>
private HashSet<IEntity> BuckledEntities { get; set; }
public IReadOnlyCollection<IEntity> BuckledEntities => _buckledEntities;
/// <summary>
/// The change in position to the strapped mob
/// </summary>
public override StrapPosition Position
{
get => _position;
protected set
{
_position = value;
Dirty();
}
}
public StrapPosition Position => _position;
/// <summary>
/// The sound to be played when a mob is buckled
@@ -60,34 +64,29 @@ namespace Content.Server.GameObjects.Components.Strap
[ViewVariables]
public string BuckledIcon => _buckledIcon;
/// <summary>
/// The angle in degrees to rotate the player by when they get strapped
/// </summary>
[ViewVariables]
public int Rotation => _rotation;
/// <summary>
/// The size of the strap which is compared against when buckling entities
/// </summary>
[ViewVariables]
public int Size => _size;
/// <summary>
/// The sum of the sizes of all the buckled entities in this strap
/// </summary>
[ViewVariables]
private int OccupiedSize { get; set; }
public int OccupiedSize => _occupiedSize;
/// <summary>
/// Checks if this strap has enough space for a new occupant.
/// </summary>
/// <param name="buckle">The new occupant</param>
/// <returns>true if there is enough space, false otherwise</returns>
public bool HasSpace(BuckleComponent buckle)
{
return OccupiedSize + buckle.Size <= _size;
}
/// <summary>
/// Adds a buckled entity. Called from <see cref="BuckleComponent.TryBuckle"/>
/// Adds a buckled entity. Called from <see cref="BuckleComponent.TryBuckle"/>
/// </summary>
/// <param name="buckle">The component to add</param>
/// <param name="force">Whether or not to check if the strap has enough space</param>
/// <param name="force">
/// Whether or not to check if the strap has enough space
/// </param>
/// <returns>True if added, false otherwise</returns>
public bool TryAdd(BuckleComponent buckle, bool force = false)
{
@@ -96,12 +95,12 @@ namespace Content.Server.GameObjects.Components.Strap
return false;
}
if (!BuckledEntities.Add(buckle.Owner))
if (!_buckledEntities.Add(buckle.Owner))
{
return false;
}
OccupiedSize += buckle.Size;
_occupiedSize += buckle.Size;
if (buckle.Owner.TryGetComponent(out AppearanceComponent appearance))
{
@@ -112,14 +111,15 @@ namespace Content.Server.GameObjects.Components.Strap
}
/// <summary>
/// Removes a buckled entity. Called from <see cref="BuckleComponent.TryUnbuckle"/>
/// Removes a buckled entity.
/// Called from <see cref="BuckleComponent.TryUnbuckle"/>
/// </summary>
/// <param name="buckle">The component to remove</param>
public void Remove(BuckleComponent buckle)
{
if (BuckledEntities.Remove(buckle.Owner))
if (_buckledEntities.Remove(buckle.Owner))
{
OccupiedSize -= buckle.Size;
_occupiedSize -= buckle.Size;
}
}
@@ -136,16 +136,16 @@ namespace Content.Server.GameObjects.Components.Strap
var defaultSize = 100;
serializer.DataField(ref _size, "size", defaultSize);
BuckledEntities = new HashSet<IEntity>(_size / defaultSize);
_buckledEntities = new HashSet<IEntity>(_size / defaultSize);
OccupiedSize = 0;
_occupiedSize = 0;
}
public override void OnRemove()
{
base.OnRemove();
foreach (var entity in BuckledEntities)
foreach (var entity in _buckledEntities)
{
if (entity.TryGetComponent(out BuckleComponent buckle))
{
@@ -153,13 +153,8 @@ namespace Content.Server.GameObjects.Components.Strap
}
}
BuckledEntities.Clear();
OccupiedSize = 0;
}
public override ComponentState GetComponentState()
{
return new StrapComponentState(Position);
_buckledEntities.Clear();
_occupiedSize = 0;
}
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)