diff --git a/Content.Client/GameObjects/Components/Clothing/ClothingComponent.cs b/Content.Client/GameObjects/Components/Clothing/ClothingComponent.cs index e2b6abd950..bb08aa0808 100644 --- a/Content.Client/GameObjects/Components/Clothing/ClothingComponent.cs +++ b/Content.Client/GameObjects/Components/Clothing/ClothingComponent.cs @@ -1,19 +1,23 @@ -using Content.Client.GameObjects.Components.HUD.Inventory; +#nullable enable +using Content.Client.GameObjects.Components.HUD.Inventory; using Content.Client.GameObjects.Components.Items; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Items; +using Content.Shared.GameObjects.Components.Storage; using Robust.Client.Graphics; +using Robust.Client.ResourceManagement; using Robust.Shared.Containers; using Robust.Shared.GameObjects; +using Robust.Shared.IoC; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.ViewVariables; namespace Content.Client.GameObjects.Components.Clothing { [RegisterComponent] + [ComponentReference(typeof(SharedItemComponent))] [ComponentReference(typeof(ItemComponent))] - [ComponentReference(typeof(IItemComponent))] public class ClothingComponent : ItemComponent { [DataField("femaleMask")] @@ -64,17 +68,9 @@ namespace Content.Client.GameObjects.Components.Clothing public (RSI rsi, RSI.StateId stateId)? GetEquippedStateInfo(EquipmentSlotDefines.SlotFlags slot, string? speciesId=null) { if (RsiPath == null) - { return null; - } - - var rsi = GetRSI(); - - if (rsi == null) - { - return null; - } + var rsi = IoCManager.Resolve().GetResource(SharedSpriteComponent.TextureRoot / RsiPath).RSI; var prefix = ClothingEquippedPrefix ?? EquippedPrefix; var stateId = prefix != null ? $"{prefix}-equipped-{slot}" : $"equipped-{slot}"; if (speciesId != null) diff --git a/Content.Client/GameObjects/Components/Items/HandsComponent.cs b/Content.Client/GameObjects/Components/Items/HandsComponent.cs index b272174a85..1a76e8f49a 100644 --- a/Content.Client/GameObjects/Components/Items/HandsComponent.cs +++ b/Content.Client/GameObjects/Components/Items/HandsComponent.cs @@ -4,7 +4,9 @@ using System.Linq; using Content.Client.Animations; using Content.Client.UserInterface; using Content.Shared.GameObjects.Components.Items; +using Content.Shared.GameObjects.Components.Storage; using Robust.Client.GameObjects; +using Robust.Client.ResourceManagement; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Network; @@ -161,20 +163,26 @@ namespace Content.Client.GameObjects.Components.Items return; } - if (!entity.TryGetComponent(out ItemComponent? item)) return; + if (!entity.TryGetComponent(out SharedItemComponent? item)) + return; - var maybeInHands = item.GetInHandStateInfo(hand.Location); - - if (!maybeInHands.HasValue) + if (item.RsiPath == null) { _sprite.LayerSetVisible($"hand-{name}", false); } else { - var (rsi, state, color) = maybeInHands.Value; + var rsi = IoCManager.Resolve().GetResource(SharedSpriteComponent.TextureRoot / item.RsiPath).RSI; + + var handName = hand.Location.ToString().ToLowerInvariant(); + var prefix = item.EquippedPrefix; + var state = prefix != null ? $"{prefix}-inhand-{handName}" : $"inhand-{handName}"; + + var color = item.Color; + _sprite.LayerSetColor($"hand-{name}", color); _sprite.LayerSetVisible($"hand-{name}", true); - _sprite.LayerSetState($"hand-{name}", state, rsi); + _sprite.LayerSetState($"hand-{name}", state, rsi); } } diff --git a/Content.Client/GameObjects/Components/Items/ItemComponent.cs b/Content.Client/GameObjects/Components/Items/ItemComponent.cs index c25833cb07..fc1835f255 100644 --- a/Content.Client/GameObjects/Components/Items/ItemComponent.cs +++ b/Content.Client/GameObjects/Components/Items/ItemComponent.cs @@ -1,102 +1,26 @@ -using Content.Client.GameObjects.Components.Disposal; -using Content.Shared.GameObjects; -using Content.Shared.GameObjects.Components.Items; -using Content.Shared.Interfaces.GameObjects.Components; -using Robust.Client.Graphics; -using Robust.Client.ResourceManagement; +#nullable enable +using Content.Shared.GameObjects.Components.Storage; using Robust.Shared.Containers; using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Maths; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.Utility; -using Robust.Shared.ViewVariables; namespace Content.Client.GameObjects.Components.Items { [RegisterComponent] - [ComponentReference(typeof(IItemComponent))] - public class ItemComponent : Component, IItemComponent, IDraggable + [ComponentReference(typeof(SharedItemComponent))] + public class ItemComponent : SharedItemComponent { - [Dependency] private readonly IResourceCache _resourceCache = default!; - - public override string Name => "Item"; - public override uint? NetID => ContentNetIDs.ITEM; - - [ViewVariables] - [DataField("sprite")] - protected ResourcePath? RsiPath; - - [ViewVariables(VVAccess.ReadWrite)] - [DataField("color")] - protected Color Color = Color.White; - - [DataField("HeldPrefix")] - private string? _equippedPrefix; - - [ViewVariables(VVAccess.ReadWrite)] - public string? EquippedPrefix + public override bool TryPutInHand(IEntity user) { - get => _equippedPrefix; - set - { - _equippedPrefix = value; - - if (!Owner.TryGetContainer(out var container)) - return; - - if (container.Owner.TryGetComponent(out HandsComponent? hands)) - hands.RefreshInHands(); - } + return false; } - public (RSI rsi, RSI.StateId stateId, Color color)? GetInHandStateInfo(HandLocation hand) + protected override void OnEquippedPrefixChange() { - var rsi = GetRSI(); - - if (rsi == null) - { - return null; - } - - var handName = hand.ToString().ToLowerInvariant(); - var stateId = EquippedPrefix != null ? $"{EquippedPrefix}-inhand-{handName}" : $"inhand-{handName}"; - - if (rsi.TryGetState(stateId, out _)) - { - return (rsi, stateId, Color); - } - - return null; - } - - protected RSI? GetRSI() - { - if (RsiPath == null) - { - return null; - } - - return _resourceCache.GetResource(SharedSpriteComponent.TextureRoot / RsiPath).RSI; - } - - public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) - { - if (curState is not ItemComponentState state) + if (!Owner.TryGetContainer(out var container)) return; - EquippedPrefix = state.EquippedPrefix; - } - - bool IDraggable.CanDrop(CanDropEventArgs args) - { - return args.Target.HasComponent(); - } - - bool IDraggable.Drop(DragDropEventArgs args) - { - // TODO: Shared item class - return false; + if (container.Owner.TryGetComponent(out HandsComponent? hands)) + hands.RefreshInHands(); } } } diff --git a/Content.Client/GameObjects/Components/Storage/StorableComponent.cs b/Content.Client/GameObjects/Components/Storage/StorableComponent.cs deleted file mode 100644 index 6b1b79b6d5..0000000000 --- a/Content.Client/GameObjects/Components/Storage/StorableComponent.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Content.Shared.GameObjects.Components.Storage; -using Robust.Shared.GameObjects; - -namespace Content.Client.GameObjects.Components.Storage -{ - [RegisterComponent] - [ComponentReference(typeof(SharedStorableComponent))] - public class StorableComponent : SharedStorableComponent - { - private int _size; - - public override int Size - { - get => _size; - set - { - if (_size == value) - { - return; - } - - _size = value; - - Dirty(); - } - } - - public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) - { - base.HandleComponentState(curState, nextState); - - if (curState is not StorableComponentState state) - { - return; - } - - _size = state.Size; - } - } -} diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index b87324296a..5db13ba33a 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -252,6 +252,7 @@ namespace Content.Client "RandomSpawner", "SpawnAfterInteract", "DisassembleOnActivate", + "ExplosionLaunched", }; } } diff --git a/Content.Server/GameObjects/Components/Explosion/ExplosionLaunchedComponent.cs b/Content.Server/GameObjects/Components/Explosion/ExplosionLaunchedComponent.cs new file mode 100644 index 0000000000..e660e63668 --- /dev/null +++ b/Content.Server/GameObjects/Components/Explosion/ExplosionLaunchedComponent.cs @@ -0,0 +1,30 @@ +using Content.Server.GameObjects.Components.Items; +using Content.Shared.GameObjects.EntitySystems; +using Robust.Shared.GameObjects; + +namespace Content.Server.GameObjects.Components.Explosion +{ + [RegisterComponent] + public class ExplosionLaunchedComponent : Component, IExAct + { + public override string Name => "ExplosionLaunched"; + + void IExAct.OnExplosion(ExplosionEventArgs eventArgs) + { + if (Owner.Deleted) + return; + + var sourceLocation = eventArgs.Source; + var targetLocation = eventArgs.Target.Transform.Coordinates; + var direction = (targetLocation.ToMapPos(Owner.EntityManager) - sourceLocation.ToMapPos(Owner.EntityManager)).Normalized; + + var throwForce = eventArgs.Severity switch + { + ExplosionSeverity.Heavy => 30, + ExplosionSeverity.Light => 20, + _ => 0, + }; + Owner.TryThrow(direction * throwForce); + } + } +} diff --git a/Content.Server/GameObjects/Components/GUI/HumanInventoryControllerComponent.cs b/Content.Server/GameObjects/Components/GUI/HumanInventoryControllerComponent.cs index 34b2f7eafa..ee5745bc1a 100644 --- a/Content.Server/GameObjects/Components/GUI/HumanInventoryControllerComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/HumanInventoryControllerComponent.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Content.Server.GameObjects.Components.Items.Storage; +using Content.Shared.GameObjects.Components.Storage; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Localization; diff --git a/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs b/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs index cdcd519eb4..f195780aa7 100644 --- a/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Clothing/ClothingComponent.cs @@ -1,4 +1,4 @@ -using Content.Server.GameObjects.Components.GUI; +using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Items; @@ -14,10 +14,8 @@ using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefine namespace Content.Server.GameObjects.Components.Items.Clothing { [RegisterComponent] + [ComponentReference(typeof(SharedItemComponent))] [ComponentReference(typeof(ItemComponent))] - [ComponentReference(typeof(StorableComponent))] - [ComponentReference(typeof(SharedStorableComponent))] - [ComponentReference(typeof(IItemComponent))] public class ClothingComponent : ItemComponent, IUse { public override string Name => "Clothing"; diff --git a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs index e0c9f0956c..bc894bc7cd 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs @@ -209,7 +209,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage continue; // only items that can be stored in an inventory, or a mob, can be eaten by a locker - if (!entity.HasComponent() && + if (!entity.HasComponent() && !entity.HasComponent()) continue; diff --git a/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs index 47ab0722c2..ebbbbf0660 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs @@ -1,46 +1,23 @@ +#nullable enable using Content.Server.GameObjects.Components.GUI; using Content.Server.Interfaces.GameObjects.Components.Items; -using Content.Shared.GameObjects; -using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Storage; -using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; -using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.Localization; using Robust.Shared.Physics; -using Robust.Shared.Players; -using Robust.Shared.Serialization.Manager.Attributes; namespace Content.Server.GameObjects.Components.Items.Storage { [RegisterComponent] - [ComponentReference(typeof(StorableComponent))] - [ComponentReference(typeof(SharedStorableComponent))] - [ComponentReference(typeof(IItemComponent))] - public class ItemComponent : StorableComponent, IInteractHand, IExAct, IEquipped, IUnequipped, IItemComponent + [ComponentReference(typeof(SharedItemComponent))] + public class ItemComponent : SharedItemComponent { - public override string Name => "Item"; - public override uint? NetID => ContentNetIDs.ITEM; - - [DataField("HeldPrefix")] - private string? _equippedPrefix; - - public string? EquippedPrefix - { - get => _equippedPrefix; - set - { - _equippedPrefix = value; - Dirty(); - } - } - - public void RemovedFromSlot() + public override void RemovedFromSlot() { foreach (var component in Owner.GetAllComponents()) { @@ -48,7 +25,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage } } - public void EquippedToSlot() + public override void EquippedToSlot() { foreach (var component in Owner.GetAllComponents()) { @@ -56,44 +33,20 @@ namespace Content.Server.GameObjects.Components.Items.Storage } } - public virtual void Equipped(EquippedEventArgs eventArgs) + public override bool TryPutInHand(IEntity user) { - EquippedToSlot(); - } - - public virtual void Unequipped(UnequippedEventArgs eventArgs) - { - RemovedFromSlot(); - } - - public bool CanPickup(IEntity user) - { - if (!ActionBlockerSystem.CanPickup(user)) - { + if (!CanPickup(user)) return false; - } - if (user.Transform.MapID != Owner.Transform.MapID) - { + if (!user.TryGetComponent(out IHandsComponent? hands)) return false; - } - if (Owner.TryGetComponent(out IPhysBody? physics) && - physics.BodyType == BodyType.Static) - { + var activeHand = hands.ActiveHand; + + if (activeHand == null) return false; - } - return user.InRangeUnobstructed(Owner, ignoreInsideBlocker: true, popup: true); - } - - bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) - { - if (!CanPickup(eventArgs.User) || - !eventArgs.User.TryGetComponent(out IHandsComponent? hands) || - hands.ActiveHand == null) return false; - - hands.PutInHand(this, hands.ActiveHand, false); + hands.PutInHand(this, activeHand, false); return true; } @@ -110,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage return; } - data.Text = Loc.GetString("Pick up"); + data.Text = Loc.GetString("Pick Up"); } protected override void Activate(IEntity user, ItemComponent component) @@ -121,34 +74,5 @@ namespace Content.Server.GameObjects.Components.Items.Storage } } } - - public override ComponentState GetComponentState(ICommonSession session) - { - return new ItemComponentState(EquippedPrefix); - } - - public void OnExplosion(ExplosionEventArgs eventArgs) - { - var sourceLocation = eventArgs.Source; - var targetLocation = eventArgs.Target.Transform.Coordinates; - var dirVec = (targetLocation.ToMapPos(Owner.EntityManager) - sourceLocation.ToMapPos(Owner.EntityManager)).Normalized; - - float throwForce; - - switch (eventArgs.Severity) - { - case ExplosionSeverity.Destruction: - throwForce = 30.0f; - break; - case ExplosionSeverity.Heavy: - throwForce = 20.0f; - break; - default: - throwForce = 10.0f; - break; - } - - Owner.TryThrow(dirVec * throwForce); - } } } diff --git a/Content.Server/GameObjects/Components/Items/Storage/SecretStashComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/SecretStashComponent.cs index d79c45a232..606c7c74a4 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/SecretStashComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/SecretStashComponent.cs @@ -1,6 +1,7 @@ #nullable enable using Content.Server.GameObjects.Components.GUI; using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Shared.GameObjects.Components.Storage; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Interfaces; using Robust.Shared.Containers; diff --git a/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs index cb26ce2358..25bca32aa3 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/ServerStorageComponent.cs @@ -94,7 +94,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage foreach (var entity in _storage.ContainedEntities) { - var item = entity.GetComponent(); + var item = entity.GetComponent(); _storageUsed += item.Size; } } @@ -114,7 +114,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage return false; } - if (entity.TryGetComponent(out StorableComponent? store) && + if (entity.TryGetComponent(out SharedItemComponent? store) && store.Size > _storageCapacityMax - _storageUsed) { return false; @@ -152,7 +152,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage Logger.DebugS(LoggerName, $"Storage (UID {Owner.Uid}) had entity (UID {message.Entity.Uid}) inserted into it."); var size = 0; - if (message.Entity.TryGetComponent(out StorableComponent? storable)) + if (message.Entity.TryGetComponent(out SharedItemComponent? storable)) size = storable.Size; _storageUsed += size; @@ -495,14 +495,14 @@ namespace Content.Server.GameObjects.Components.Items.Storage // Pick up all entities in a radius around the clicked location. // The last half of the if is because carpets exist and this is terrible - if(_areaInsert && (eventArgs.Target == null || !eventArgs.Target.HasComponent())) + if(_areaInsert && (eventArgs.Target == null || !eventArgs.Target.HasComponent())) { var validStorables = new List(); foreach (var entity in Owner.EntityManager.GetEntitiesInRange(eventArgs.ClickLocation, 1)) { if (!entity.Transform.IsMapTransform || entity == eventArgs.User - || !entity.HasComponent()) + || !entity.HasComponent()) continue; validStorables.Add(entity); } @@ -529,7 +529,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage // Check again, situation may have changed for some entities, but we'll still pick up any that are valid if (!entity.Transform.IsMapTransform || entity == eventArgs.User - || !entity.HasComponent()) + || !entity.HasComponent()) continue; var coords = entity.Transform.Coordinates; if (PlayerInsertEntityInWorld(eventArgs.User, entity)) @@ -558,7 +558,7 @@ namespace Content.Server.GameObjects.Components.Items.Storage if (eventArgs.Target == null || !eventArgs.Target.Transform.IsMapTransform || eventArgs.Target == eventArgs.User - || !eventArgs.Target.HasComponent()) + || !eventArgs.Target.HasComponent()) return false; var position = eventArgs.Target.Transform.Coordinates; if(PlayerInsertEntityInWorld(eventArgs.User, eventArgs.Target)) diff --git a/Content.Server/GameObjects/Components/Items/Storage/StorableComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/StorableComponent.cs deleted file mode 100644 index 45efc80ffb..0000000000 --- a/Content.Server/GameObjects/Components/Items/Storage/StorableComponent.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Content.Shared.GameObjects.Components.Storage; -using Robust.Shared.GameObjects; -using Robust.Shared.Players; - -namespace Content.Server.GameObjects.Components.Items.Storage -{ - [RegisterComponent] - [ComponentReference(typeof(SharedStorableComponent))] - public class StorableComponent : SharedStorableComponent - { - private int _size; - - public override int Size - { - get => _size; - set - { - if (_size == value) - { - return; - } - - _size = value; - - Dirty(); - } - } - - public override ComponentState GetComponentState(ICommonSession player) - { - return new StorableComponentState(_size); - } - } - - /// - /// Enum for the storage capacity of various containers - /// - public enum ReferenceSizes - { - Wallet = 4, - Pocket = 12, - Box = 24, - Belt = 30, - Toolbox = 60, - Backpack = 100, - NoStoring = 9999 - } -} diff --git a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs index f6923370ad..95d2f0e681 100644 --- a/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs +++ b/Content.Shared/GameObjects/Components/Disposal/SharedDisposalUnitComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; using Content.Shared.GameObjects.Components.Body; @@ -168,7 +168,7 @@ namespace Content.Shared.GameObjects.Components.Disposal return false; // TODO: Probably just need a disposable tag. - if (!entity.TryGetComponent(out SharedStorableComponent? storable) && + if (!entity.TryGetComponent(out SharedItemComponent? storable) && !entity.HasComponent()) { return false; @@ -182,7 +182,6 @@ namespace Content.Shared.GameObjects.Components.Disposal return false; } } - return true; } diff --git a/Content.Shared/GameObjects/Components/Items/ClothingComponentState.cs b/Content.Shared/GameObjects/Components/Items/ClothingComponentState.cs index eab5ff6d90..701d36ae80 100644 --- a/Content.Shared/GameObjects/Components/Items/ClothingComponentState.cs +++ b/Content.Shared/GameObjects/Components/Items/ClothingComponentState.cs @@ -1,17 +1,21 @@ -#nullable enable +#nullable enable using System; +using Robust.Shared.GameObjects; using Robust.Shared.Serialization; namespace Content.Shared.GameObjects.Components.Items { [Serializable, NetSerializable] - public class ClothingComponentState : ItemComponentState + public class ClothingComponentState : ComponentState { - public string? ClothingEquippedPrefix { get; set; } + public string? ClothingEquippedPrefix { get; } - public ClothingComponentState(string? clothingEquippedPrefix, string? equippedPrefix) : base(equippedPrefix, ContentNetIDs.CLOTHING) + public string? EquippedPrefix { get; } + + public ClothingComponentState(string? clothingEquippedPrefix, string? equippedPrefix) : base(ContentNetIDs.CLOTHING) { ClothingEquippedPrefix = clothingEquippedPrefix; + EquippedPrefix = equippedPrefix; } } } diff --git a/Content.Shared/GameObjects/Components/Items/IItemComponent.cs b/Content.Shared/GameObjects/Components/Items/IItemComponent.cs deleted file mode 100644 index 686ade5745..0000000000 --- a/Content.Shared/GameObjects/Components/Items/IItemComponent.cs +++ /dev/null @@ -1,10 +0,0 @@ -#nullable enable -using Robust.Shared.GameObjects; - -namespace Content.Shared.GameObjects.Components.Items -{ - public interface IItemComponent : IComponent - { - - } -} diff --git a/Content.Shared/GameObjects/Components/Items/ItemComponentState.cs b/Content.Shared/GameObjects/Components/Items/ItemComponentState.cs deleted file mode 100644 index e601c8d58b..0000000000 --- a/Content.Shared/GameObjects/Components/Items/ItemComponentState.cs +++ /dev/null @@ -1,23 +0,0 @@ -#nullable enable -using System; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization; - -namespace Content.Shared.GameObjects.Components.Items -{ - [Serializable, NetSerializable] - public class ItemComponentState : ComponentState - { - public string? EquippedPrefix { get; set; } - - public ItemComponentState(string? equippedPrefix) : base(ContentNetIDs.ITEM) - { - EquippedPrefix = equippedPrefix; - } - - protected ItemComponentState(string? equippedPrefix, uint netId) : base(netId) - { - EquippedPrefix = equippedPrefix; - } - } -} diff --git a/Content.Shared/GameObjects/Components/Storage/SharedItemComponent.cs b/Content.Shared/GameObjects/Components/Storage/SharedItemComponent.cs new file mode 100644 index 0000000000..6cc6a433ea --- /dev/null +++ b/Content.Shared/GameObjects/Components/Storage/SharedItemComponent.cs @@ -0,0 +1,184 @@ +#nullable enable +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Utility; +using Robust.Shared.GameObjects; +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; +using System; + +namespace Content.Shared.GameObjects.Components.Storage +{ + /// + /// Players can pick up, drop, and put items in bags, and they can be seen in player's hands. + /// + public abstract class SharedItemComponent : Component, IEquipped, IUnequipped, IInteractHand + { + public override string Name => "Item"; + + public override uint? NetID => ContentNetIDs.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(ICommonSession player) + { + 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) + { + if (!ActionBlockerSystem.CanPickup(user)) + return false; + + if (user.Transform.MapID != Owner.Transform.MapID) + return false; + + if (!Owner.TryGetComponent(out IPhysBody? physics) || physics.BodyType == BodyType.Static) + return false; + + return user.InRangeUnobstructed(Owner, ignoreInsideBlocker: true, popup: true); + } + + void IEquipped.Equipped(EquippedEventArgs eventArgs) + { + EquippedToSlot(); + } + + void IUnequipped.Unequipped(UnequippedEventArgs eventArgs) + { + RemovedFromSlot(); + } + + bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) + { + return TryPutInHand(eventArgs.User); + } + + /// + /// Tries to put this item in a player's hands. + /// TODO: Move server implementation here once hands are in shared. + /// + public abstract bool TryPutInHand(IEntity user); + + 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) : base(ContentNetIDs.ITEM) + { + 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 + } +} diff --git a/Content.Shared/GameObjects/Components/Storage/SharedStorableComponent.cs b/Content.Shared/GameObjects/Components/Storage/SharedStorableComponent.cs deleted file mode 100644 index 31b749390d..0000000000 --- a/Content.Shared/GameObjects/Components/Storage/SharedStorableComponent.cs +++ /dev/null @@ -1,28 +0,0 @@ -#nullable enable -using System; -using Robust.Shared.GameObjects; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization; -using Robust.Shared.Serialization.Manager.Attributes; - -namespace Content.Shared.GameObjects.Components.Storage -{ - public abstract class SharedStorableComponent : Component - { - public override string Name => "Storable"; - public override uint? NetID => ContentNetIDs.STORABLE; - - [DataField("size")] public virtual int Size { get; set; } = 1; - } - - [Serializable, NetSerializable] - public class StorableComponentState : ComponentState - { - public readonly int Size; - - public StorableComponentState(int size) : base(ContentNetIDs.STORABLE) - { - Size = size; - } - } -} diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs index 7fa3f85cb8..3ea051c940 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs @@ -1,7 +1,8 @@ -#nullable enable +#nullable enable using System.Diagnostics.CodeAnalysis; using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameObjects.Components.Storage; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Physics; using Content.Shared.Physics.Pull; diff --git a/Resources/Prototypes/Entities/Objects/base.yml b/Resources/Prototypes/Entities/Objects/base.yml index caa3b7f4ff..b3791997fd 100644 --- a/Resources/Prototypes/Entities/Objects/base.yml +++ b/Resources/Prototypes/Entities/Objects/base.yml @@ -31,3 +31,4 @@ drawdepth: Items noRot: false - type: Pullable + - type: ExplosionLaunched