* Start work on stripping. * more strippable work * Stripping works * Nullable * MORE NULLABLE * nullable moment * life is pain * Interaction check. * Update Content.Client/GameObjects/Components/HUD/Inventory/StrippableBoundUserInterface.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Client/GameObjects/Components/HUD/Inventory/StrippableBoundUserInterface.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/HandsComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/HandsComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/HandsComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/StrippableComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/StrippableComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/HandsComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/StrippableComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/StrippableComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Shared/GameObjects/Components/GUI/SharedStrippableComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Update Content.Server/GameObjects/Components/GUI/StrippableComponent.cs Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Rename InventoryComponent and HandsComponent's OnChanged event to OnItemChanged * Apply suggestions from code review Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com> * Use static EquipmentSlotDefines * Do not expose ContainerSlot on Inventory or Hands. Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
263 lines
7.1 KiB
C#
263 lines
7.1 KiB
C#
#nullable enable
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using Content.Client.UserInterface;
|
|
using Content.Shared.GameObjects.Components.Items;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Interfaces.GameObjects.Components;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.Interfaces.GameObjects;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.ViewVariables;
|
|
|
|
namespace Content.Client.GameObjects.Components.Items
|
|
{
|
|
[RegisterComponent]
|
|
[ComponentReference(typeof(ISharedHandsComponent))]
|
|
public class HandsComponent : SharedHandsComponent
|
|
{
|
|
private HandsGui? _gui;
|
|
|
|
#pragma warning disable 649
|
|
[Dependency] private readonly IGameHud _gameHud = default!;
|
|
#pragma warning restore 649
|
|
|
|
/// <inheritdoc />
|
|
private readonly List<Hand> _hands = new List<Hand>();
|
|
|
|
[ViewVariables] public IReadOnlyList<Hand> Hands => _hands;
|
|
|
|
[ViewVariables] public string? ActiveIndex { get; private set; }
|
|
|
|
[ViewVariables] private ISpriteComponent? _sprite;
|
|
|
|
[ViewVariables] public IEntity? ActiveHand => GetEntity(ActiveIndex);
|
|
|
|
private void AddHand(Hand hand)
|
|
{
|
|
_hands.Insert(hand.Index, hand);
|
|
}
|
|
|
|
public Hand? GetHand(string? name)
|
|
{
|
|
return Hands.FirstOrDefault(hand => hand.Name == name);
|
|
}
|
|
|
|
private bool TryHand(string name, [MaybeNullWhen(false)] out Hand hand)
|
|
{
|
|
return (hand = GetHand(name)) != null;
|
|
}
|
|
|
|
public IEntity? GetEntity(string? handName)
|
|
{
|
|
if (handName == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return GetHand(handName)?.Entity;
|
|
}
|
|
|
|
public override void OnRemove()
|
|
{
|
|
base.OnRemove();
|
|
|
|
_gui?.Dispose();
|
|
}
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
if (Owner.TryGetComponent(out _sprite))
|
|
{
|
|
foreach (var hand in _hands)
|
|
{
|
|
_sprite.LayerMapReserveBlank($"hand-{hand.Name}");
|
|
UpdateHandSprites(hand);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
|
{
|
|
if (curState == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var cast = (HandsComponentState) curState;
|
|
foreach (var sharedHand in cast.Hands)
|
|
{
|
|
if (!TryHand(sharedHand.Name, out var hand))
|
|
{
|
|
hand = new Hand(sharedHand, Owner.EntityManager);
|
|
AddHand(hand);
|
|
}
|
|
else
|
|
{
|
|
hand.Location = sharedHand.Location;
|
|
|
|
hand.Entity = sharedHand.EntityUid.HasValue
|
|
? Owner.EntityManager.GetEntity(sharedHand.EntityUid.Value)
|
|
: null;
|
|
}
|
|
|
|
UpdateHandSprites(hand);
|
|
}
|
|
|
|
foreach (var currentHand in _hands.ToList())
|
|
{
|
|
if (cast.Hands.All(newHand => newHand.Name != currentHand.Name))
|
|
{
|
|
_hands.Remove(currentHand);
|
|
_gui?.RemoveHand(currentHand);
|
|
HideHand(currentHand);
|
|
}
|
|
}
|
|
|
|
ActiveIndex = cast.ActiveIndex;
|
|
|
|
_gui?.UpdateHandIcons();
|
|
RefreshInHands();
|
|
}
|
|
|
|
private void HideHand(Hand hand)
|
|
{
|
|
_sprite?.LayerSetVisible($"hand-{hand.Name}", false);
|
|
}
|
|
|
|
private void UpdateHandSprites(Hand hand)
|
|
{
|
|
if (_sprite == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var entity = hand.Entity;
|
|
var name = hand.Name;
|
|
|
|
if (entity == null)
|
|
{
|
|
if (_sprite.LayerMapTryGet($"hand-{name}", out var layer))
|
|
{
|
|
_sprite.LayerSetVisible(layer, false);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (!entity.TryGetComponent(out ItemComponent item)) return;
|
|
|
|
var maybeInHands = item.GetInHandStateInfo(hand.Location);
|
|
|
|
if (!maybeInHands.HasValue)
|
|
{
|
|
_sprite.LayerSetVisible($"hand-{name}", false);
|
|
}
|
|
else
|
|
{
|
|
var (rsi, state) = maybeInHands.Value;
|
|
_sprite.LayerSetVisible($"hand-{name}", true);
|
|
_sprite.LayerSetState($"hand-{name}", state, rsi);
|
|
}
|
|
}
|
|
|
|
public void RefreshInHands()
|
|
{
|
|
if (!Initialized) return;
|
|
|
|
foreach (var hand in _hands)
|
|
{
|
|
UpdateHandSprites(hand);
|
|
}
|
|
}
|
|
|
|
protected override void Startup()
|
|
{
|
|
ActiveIndex = _hands.LastOrDefault()?.Name;
|
|
}
|
|
|
|
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
|
{
|
|
base.HandleMessage(message, component);
|
|
|
|
switch (message)
|
|
{
|
|
case PlayerAttachedMsg _:
|
|
if (_gui == null)
|
|
{
|
|
_gui = new HandsGui();
|
|
}
|
|
else
|
|
{
|
|
_gui.Parent?.RemoveChild(_gui);
|
|
}
|
|
|
|
_gameHud.HandsContainer.AddChild(_gui);
|
|
_gui.UpdateHandIcons();
|
|
break;
|
|
|
|
case PlayerDetachedMsg _:
|
|
_gui?.Parent?.RemoveChild(_gui);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void SendChangeHand(string index)
|
|
{
|
|
SendNetworkMessage(new ClientChangedHandMsg(index));
|
|
}
|
|
|
|
public void AttackByInHand(string index)
|
|
{
|
|
SendNetworkMessage(new ClientAttackByInHandMsg(index));
|
|
}
|
|
|
|
public void UseActiveHand()
|
|
{
|
|
if (GetEntity(ActiveIndex) != null)
|
|
{
|
|
SendNetworkMessage(new UseInHandMsg());
|
|
}
|
|
}
|
|
|
|
public void ActivateItemInHand(string handIndex)
|
|
{
|
|
if (GetEntity(handIndex) == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SendNetworkMessage(new ActivateInHandMsg(handIndex));
|
|
}
|
|
}
|
|
|
|
public class Hand
|
|
{
|
|
// TODO: Separate into server hand and client hand
|
|
public Hand(SharedHand hand, IEntityManager manager, HandButton? button = null)
|
|
{
|
|
Index = hand.Index;
|
|
Name = hand.Name;
|
|
Location = hand.Location;
|
|
Button = button;
|
|
|
|
if (!hand.EntityUid.HasValue)
|
|
{
|
|
return;
|
|
}
|
|
|
|
manager.TryGetEntity(hand.EntityUid.Value, out var entity);
|
|
Entity = entity;
|
|
}
|
|
|
|
public int Index { get; }
|
|
public string Name { get; }
|
|
public HandLocation Location { get; set; }
|
|
public IEntity? Entity { get; set; }
|
|
public HandButton? Button { get; set; }
|
|
}
|
|
}
|