using System; using Content.Shared.Hands; using Content.Shared.Hands.Components; using Content.Shared.Interaction; using Content.Shared.Interaction.Helpers; using Content.Shared.Inventory; using Content.Shared.Sound; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.IoC; using Robust.Shared.Maths; 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 class SharedItemComponent : Component, IInteractHand { [Dependency] private readonly IEntityManager _entMan = default!; 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. /// // todo paul make this update slotvisuals on client on change [ViewVariables(VVAccess.ReadWrite)] public string? EquippedPrefix { get => _equippedPrefix; set { _equippedPrefix = value; OnEquippedPrefixChange(); Dirty(); } } [DataField("HeldPrefix")] private string? _equippedPrefix; [ViewVariables] [DataField("Slots")] public SlotFlags SlotFlags = SlotFlags.PREVENTEQUIP; //Different from None, NONE allows equips if no slot flags are required [DataField("EquipSound")] public SoundSpecifier? EquipSound { get; set; } = default!; /// /// Color of the sprite shown on the player when this item is in their hands. /// [ViewVariables(VVAccess.ReadWrite)] public Color Color { get => _color; 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; bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) { var user = eventArgs.User; if (!user.InRangeUnobstructed(Owner, ignoreInsideBlocker: true)) return false; if (!_entMan.TryGetComponent(user, out SharedHandsComponent hands)) return false; var activeHand = hands.ActiveHand; if (activeHand == null) return false; // hands checks action blockers return hands.TryPickupEntityToActiveHand(Owner, animateUser: true); } private void OnEquippedPrefixChange() { if (Owner.TryGetContainer(out var container)) EntitySystem.Get().UpdateHandVisuals(container.Owner); } public void RemovedFromSlot() { if (_entMan.TryGetComponent(Owner, out SharedSpriteComponent component)) component.Visible = true; } public virtual void EquippedToSlot() { if (_entMan.TryGetComponent(Owner, out SharedSpriteComponent component)) component.Visible = false; } } [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 } }