using System; using Content.Shared.ActionBlocker; using Content.Shared.Hands.Components; using Content.Shared.Interaction; using Content.Shared.Interaction.Helpers; using Content.Shared.Inventory; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.IoC; using Robust.Shared.Maths; using Robust.Shared.Physics; using Robust.Shared.Players; using Robust.Shared.Serialization; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Content.Shared.Item { /// /// Players can pick up, drop, and put items in bags, and they can be seen in player's hands. /// [NetworkedComponent()] public abstract class SharedItemComponent : Component, IEquipped, IUnequipped, IInteractHand { public override string Name => "Item"; /// /// How much big this item is. /// [ViewVariables(VVAccess.ReadWrite)] public int Size { get => _size; set { _size = value; Dirty(); } } [DataField("size")] private int _size; /// /// Part of the state of the sprite shown on the player when this item is in their hands. /// [ViewVariables(VVAccess.ReadWrite)] public string? EquippedPrefix { get => _equippedPrefix; set { _equippedPrefix = value; OnEquippedPrefixChange(); Dirty(); } } [DataField("HeldPrefix")] private string? _equippedPrefix; /// /// Color of the sprite shown on the player when this item is in their hands. /// [ViewVariables(VVAccess.ReadWrite)] public Color Color { get => _color; protected set { _color = value; Dirty(); } } [DataField("color")] private Color _color = Color.White; /// /// Rsi of the sprite shown on the player when this item is in their hands. /// [ViewVariables(VVAccess.ReadWrite)] public string? RsiPath { get => _rsiPath; set { _rsiPath = value; Dirty(); } } [DataField("sprite")] private string? _rsiPath; public override ComponentState GetComponentState() { return new ItemComponentState(Size, EquippedPrefix, Color, RsiPath); } public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { base.HandleComponentState(curState, nextState); if (curState is not ItemComponentState state) return; Size = state.Size; EquippedPrefix = state.EquippedPrefix; Color = state.Color; RsiPath = state.RsiPath; } /// /// If a player can pick up this item. /// public bool CanPickup(IEntity user, bool popup = true) { if (!EntitySystem.Get().CanPickup(user)) return false; if (IoCManager.Resolve().GetComponent(user).MapID != IoCManager.Resolve().GetComponent(Owner).MapID) return false; if (!IoCManager.Resolve().TryGetComponent(Owner, out IPhysBody? physics) || physics.BodyType == BodyType.Static) return false; return user.InRangeUnobstructed(Owner, ignoreInsideBlocker: true, popup: popup); } void IEquipped.Equipped(EquippedEventArgs eventArgs) { EquippedToSlot(); } void IUnequipped.Unequipped(UnequippedEventArgs eventArgs) { RemovedFromSlot(); } bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) { var user = eventArgs.User; if (!CanPickup(user)) return false; if (!IoCManager.Resolve().TryGetComponent(user, out SharedHandsComponent? hands)) return false; var activeHand = hands.ActiveHand; if (activeHand == null) return false; hands.TryPickupEntityToActiveHand(Owner); return true; } protected virtual void OnEquippedPrefixChange() { } public virtual void RemovedFromSlot() { } public virtual void EquippedToSlot() { } } [Serializable, NetSerializable] public class ItemComponentState : ComponentState { public int Size { get; } public string? EquippedPrefix { get; } public Color Color { get; } public string? RsiPath { get; } public ItemComponentState(int size, string? equippedPrefix, Color color, string? rsiPath) { Size = size; EquippedPrefix = equippedPrefix; Color = color; RsiPath = rsiPath; } } /// /// Reference sizes for common containers and items. /// public enum ReferenceSizes { Wallet = 4, Pocket = 12, Box = 24, Belt = 30, Toolbox = 60, Backpack = 100, NoStoring = 9999 } }