diff --git a/Content.Client/Storage/UI/StorageWindow.cs b/Content.Client/Storage/UI/StorageWindow.cs index fb3f7cd33f..b096e8d472 100644 --- a/Content.Client/Storage/UI/StorageWindow.cs +++ b/Content.Client/Storage/UI/StorageWindow.cs @@ -1,4 +1,5 @@ using System.Numerics; +using Content.Client.Items.Systems; using Content.Client.Message; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; @@ -23,6 +24,7 @@ namespace Content.Client.Storage.UI private readonly IEntityManager _entityManager; private readonly SharedStorageSystem _storage; + private readonly ItemSystem _item; private readonly RichTextLabel _information; public readonly ContainerButton StorageContainerButton; @@ -34,6 +36,7 @@ namespace Content.Client.Storage.UI { _entityManager = entityManager; _storage = _entityManager.System(); + _item = _entityManager.System(); SetSize = new Vector2(240, 320); Title = Loc.GetString("comp-storage-window-title"); RectClipContent = true; @@ -69,7 +72,7 @@ namespace Content.Client.Storage.UI _information.SetMessage(Loc.GetString("comp-storage-window-weight", ("weight", 0), ("maxWeight", 0), - ("size", SharedItemSystem.GetItemSizeLocale(ItemSize.Normal)))); + ("size", _item.GetItemSizeLocale(SharedStorageSystem.DefaultStorageMaxItemSize)))); vBox.AddChild(_information); @@ -117,14 +120,14 @@ namespace Content.Client.Storage.UI _information.SetMarkup(Loc.GetString("comp-storage-window-weight", ("weight", _storage.GetCumulativeItemSizes(uid, uid.Comp)), ("maxWeight", uid.Comp.MaxTotalWeight), - ("size", SharedItemSystem.GetItemSizeLocale(_storage.GetMaxItemSize((uid, uid.Comp)))))); + ("size", _item.GetItemSizeLocale(_storage.GetMaxItemSize((uid, uid.Comp)))))); } else { _information.SetMarkup(Loc.GetString("comp-storage-window-slots", ("itemCount", uid.Comp.Container.ContainedEntities.Count), ("maxCount", uid.Comp.MaxSlots), - ("size", SharedItemSystem.GetItemSizeLocale(_storage.GetMaxItemSize((uid, uid.Comp)))))); + ("size", _item.GetItemSizeLocale(_storage.GetMaxItemSize((uid, uid.Comp)))))); } } @@ -167,7 +170,7 @@ namespace Content.Client.Storage.UI { Align = Label.AlignMode.Right, Text = item?.Size != null - ? $"{SharedItemSystem.GetItemSizeWeight(item.Size)}" + ? $"{_item.GetItemSizeWeight(item.Size)}" : Loc.GetString("comp-storage-no-item-size") } } diff --git a/Content.IntegrationTests/Tests/StorageTest.cs b/Content.IntegrationTests/Tests/StorageTest.cs index e9781ef47a..a5944f4394 100644 --- a/Content.IntegrationTests/Tests/StorageTest.cs +++ b/Content.IntegrationTests/Tests/StorageTest.cs @@ -26,6 +26,9 @@ namespace Content.IntegrationTests.Tests var server = pair.Server; var protoManager = server.ResolveDependency(); + var entMan = server.ResolveDependency(); + + var itemSys = entMan.System(); await server.WaitAssertion(() => { @@ -37,7 +40,9 @@ namespace Content.IntegrationTests.Tests !proto.TryGetComponent("Item", out var item)) continue; - Assert.That(storage.MaxItemSize.Value, Is.LessThanOrEqualTo(item.Size), $"Found storage arbitrage on {proto.ID}"); + Assert.That(itemSys.GetSizePrototype(storage.MaxItemSize.Value).Weight, + Is.LessThanOrEqualTo(itemSys.GetSizePrototype(item.Size).Weight), + $"Found storage arbitrage on {proto.ID}"); } }); await pair.CleanReturnAsync(); @@ -77,10 +82,16 @@ namespace Content.IntegrationTests.Tests await using var pair = await PoolManager.GetServerClient(); var server = pair.Server; + var entMan = server.ResolveDependency(); var protoMan = server.ResolveDependency(); var compFact = server.ResolveDependency(); var id = compFact.GetComponentName(typeof(StorageFillComponent)); + var itemSys = entMan.System(); + + var allSizes = protoMan.EnumeratePrototypes().ToList(); + allSizes.Sort(); + Assert.Multiple(() => { foreach (var proto in PoolManager.GetPrototypesWithComponent(server)) @@ -97,14 +108,29 @@ namespace Content.IntegrationTests.Tests proto.TryGetComponent("Item", out var item); var fill = (StorageFillComponent) proto.Components[id].Component; - var size = GetFillSize(fill, false, protoMan); - var maxSize = storage.MaxItemSize ?? - (item?.Size == null - ? SharedStorageSystem.DefaultStorageMaxItemSize - : (ItemSize) Math.Max(0, (int) item.Size - 1)); + var size = GetFillSize(fill, false, protoMan, itemSys); + + var maxSize = storage.MaxItemSize; + if (storage.MaxItemSize == null) + { + if (item?.Size == null) + { + maxSize = SharedStorageSystem.DefaultStorageMaxItemSize; + } + else + { + var curIndex = allSizes.IndexOf(protoMan.Index(item.Size)); + var index = Math.Max(0, curIndex - 1); + maxSize = allSizes[index].ID; + } + } + + if (maxSize == null) + continue; + if (storage.MaxSlots != null) { - Assert.That(GetFillSize(fill, true, protoMan), Is.LessThanOrEqualTo(storage.MaxSlots), + Assert.That(GetFillSize(fill, true, protoMan, itemSys), Is.LessThanOrEqualTo(storage.MaxSlots), $"{proto.ID} storage fill has too many items."); } else @@ -123,14 +149,14 @@ namespace Content.IntegrationTests.Tests if (!fillItem.TryGetComponent("Item", out var entryItem)) continue; - Assert.That(entryItem.Size, Is.LessThanOrEqualTo(maxSize), + Assert.That(protoMan.Index(entryItem.Size).Weight, + Is.LessThanOrEqualTo(protoMan.Index(maxSize.Value).Weight), $"Entity {proto.ID} has storage-fill item, {entry.PrototypeId}, that is too large"); } } }); await pair.CleanReturnAsync(); - } [Test] @@ -139,10 +165,13 @@ namespace Content.IntegrationTests.Tests await using var pair = await PoolManager.GetServerClient(); var server = pair.Server; + var entMan = server.ResolveDependency(); var protoMan = server.ResolveDependency(); var compFact = server.ResolveDependency(); var id = compFact.GetComponentName(typeof(StorageFillComponent)); + var itemSys = entMan.System(); + Assert.Multiple(() => { foreach (var proto in PoolManager.GetPrototypesWithComponent(server)) @@ -157,7 +186,7 @@ namespace Content.IntegrationTests.Tests } var fill = (StorageFillComponent) proto.Components[id].Component; - var size = GetFillSize(fill, true, protoMan); + var size = GetFillSize(fill, true, protoMan, itemSys); Assert.That(size, Is.LessThanOrEqualTo(entStorage.Capacity), $"{proto.ID} storage fill is too large."); } @@ -165,7 +194,7 @@ namespace Content.IntegrationTests.Tests await pair.CleanReturnAsync(); } - private int GetEntrySize(EntitySpawnEntry entry, bool getCount, IPrototypeManager protoMan) + private int GetEntrySize(EntitySpawnEntry entry, bool getCount, IPrototypeManager protoMan, SharedItemSystem itemSystem) { if (entry.PrototypeId == null) return 0; @@ -179,20 +208,21 @@ namespace Content.IntegrationTests.Tests if (getCount) return entry.Amount; + if (proto.TryGetComponent("Item", out var item)) - return SharedItemSystem.GetItemSizeWeight(item.Size) * entry.Amount; + return itemSystem.GetItemSizeWeight(item.Size) * entry.Amount; Assert.Fail($"Prototype is missing item comp: {entry.PrototypeId}"); return 0; } - private int GetFillSize(StorageFillComponent fill, bool getCount, IPrototypeManager protoMan) + private int GetFillSize(StorageFillComponent fill, bool getCount, IPrototypeManager protoMan, SharedItemSystem itemSystem) { var totalSize = 0; var groups = new Dictionary(); foreach (var entry in fill.Contents) { - var size = GetEntrySize(entry, getCount, protoMan); + var size = GetEntrySize(entry, getCount, protoMan, itemSystem); if (entry.GroupId == null) totalSize += size; diff --git a/Content.Server/Storage/Components/SecretStashComponent.cs b/Content.Server/Storage/Components/SecretStashComponent.cs index 6c7095617c..a63cb074ad 100644 --- a/Content.Server/Storage/Components/SecretStashComponent.cs +++ b/Content.Server/Storage/Components/SecretStashComponent.cs @@ -3,6 +3,7 @@ using Content.Shared.Containers.ItemSlots; using Content.Shared.Item; using Content.Shared.Toilet; using Robust.Shared.Containers; +using Robust.Shared.Prototypes; namespace Content.Server.Storage.Components { @@ -19,7 +20,7 @@ namespace Content.Server.Storage.Components /// Max item size that can be fitted into secret stash. /// [DataField("maxItemSize")] - public ItemSize MaxItemSize = ItemSize.Small; + public ProtoId MaxItemSize = "Small"; /// /// IC secret stash name. For example "the toilet cistern". diff --git a/Content.Server/Storage/EntitySystems/SecretStashSystem.cs b/Content.Server/Storage/EntitySystems/SecretStashSystem.cs index 81e8bd431e..49be0a2f88 100644 --- a/Content.Server/Storage/EntitySystems/SecretStashSystem.cs +++ b/Content.Server/Storage/EntitySystems/SecretStashSystem.cs @@ -13,6 +13,7 @@ namespace Content.Server.Storage.EntitySystems [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; + [Dependency] private readonly SharedItemSystem _item = default!; public override void Initialize() { @@ -66,7 +67,7 @@ namespace Content.Server.Storage.EntitySystems } // check if item is too big to fit into secret stash - if (item.Size > component.MaxItemSize) + if (_item.GetSizePrototype(item.Size) > _item.GetSizePrototype(component.MaxItemSize)) { var msg = Loc.GetString("comp-secret-stash-action-hide-item-too-big", ("item", itemToHideUid), ("stash", GetSecretPartName(uid, component))); diff --git a/Content.Server/UserInterface/StatValuesCommand.cs b/Content.Server/UserInterface/StatValuesCommand.cs index 3021233a1c..9ec38753d4 100644 --- a/Content.Server/UserInterface/StatValuesCommand.cs +++ b/Content.Server/UserInterface/StatValuesCommand.cs @@ -127,6 +127,7 @@ public sealed class StatValuesCommand : IConsoleCommand private StatValuesEuiMessage GetItem() { var values = new List(); + var itemSystem = _entManager.System(); var metaQuery = _entManager.GetEntityQuery(); var itemQuery = _entManager.GetEntityQuery(); var items = new HashSet(1024); @@ -149,7 +150,7 @@ public sealed class StatValuesCommand : IConsoleCommand values.Add(new[] { id, - $"{SharedItemSystem.GetItemSizeLocale(itemComp.Size)}", + $"{itemSystem.GetItemSizeLocale(itemComp.Size)}", }); } diff --git a/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs b/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs index 80316d64f9..c943aeb7f0 100644 --- a/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs +++ b/Content.Server/Weapons/Melee/EnergySword/EnergySwordSystem.cs @@ -98,7 +98,7 @@ public sealed class EnergySwordSystem : EntitySystem { if (TryComp(uid, out ItemComponent? item)) { - _item.SetSize(uid, ItemSize.Small, item); + _item.SetSize(uid, "Small", item); } if (TryComp(uid, out var malus)) @@ -125,7 +125,7 @@ public sealed class EnergySwordSystem : EntitySystem { if (TryComp(uid, out ItemComponent? item)) { - _item.SetSize(uid, ItemSize.Huge, item); + _item.SetSize(uid, "Huge", item); } if (comp.IsSharp) diff --git a/Content.Shared/Inventory/InventorySystem.Equip.cs b/Content.Shared/Inventory/InventorySystem.Equip.cs index 23c0fbd0a2..7b6ccaf0d4 100644 --- a/Content.Shared/Inventory/InventorySystem.Equip.cs +++ b/Content.Shared/Inventory/InventorySystem.Equip.cs @@ -14,6 +14,7 @@ using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.Network; using Robust.Shared.Player; +using Robust.Shared.Prototypes; using Robust.Shared.Timing; namespace Content.Shared.Inventory; @@ -23,12 +24,16 @@ public abstract partial class InventorySystem [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeed = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly SharedItemSystem _item = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [ValidatePrototypeId] + private const string PocketableItemSize = "Small"; + private void InitializeEquip() { //these events ensure that the client also gets its proper events raised when getting its containerstate updated @@ -264,7 +269,9 @@ public abstract partial class InventorySystem if (slotDefinition.DependsOn != null && !TryGetSlotEntity(target, slotDefinition.DependsOn, out _, inventory)) return false; - var fittingInPocket = slotDefinition.SlotFlags.HasFlag(SlotFlags.POCKET) && item is { Size: <= ItemSize.Small }; + var fittingInPocket = slotDefinition.SlotFlags.HasFlag(SlotFlags.POCKET) && + item != null && + _item.GetSizePrototype(item.Size) <= _item.GetSizePrototype(PocketableItemSize); if (clothing == null && !fittingInPocket || clothing != null && !clothing.Slots.HasFlag(slotDefinition.SlotFlags) && !fittingInPocket) { diff --git a/Content.Shared/Item/ItemComponent.cs b/Content.Shared/Item/ItemComponent.cs index 2c667b778a..ef4d451320 100644 --- a/Content.Shared/Item/ItemComponent.cs +++ b/Content.Shared/Item/ItemComponent.cs @@ -1,5 +1,6 @@ using Content.Shared.Hands.Components; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; namespace Content.Shared.Item; @@ -15,7 +16,7 @@ public sealed partial class ItemComponent : Component { [DataField, ViewVariables(VVAccess.ReadWrite)] [Access(typeof(SharedItemSystem))] - public ItemSize Size = ItemSize.Small; + public ProtoId Size = "Small"; [Access(typeof(SharedItemSystem))] [DataField] @@ -38,10 +39,10 @@ public sealed partial class ItemComponent : Component [Serializable, NetSerializable] public sealed class ItemComponentState : ComponentState { - public ItemSize Size { get; } + public ProtoId Size { get; } public string? HeldPrefix { get; } - public ItemComponentState(ItemSize size, string? heldPrefix) + public ItemComponentState(ProtoId size, string? heldPrefix) { Size = size; HeldPrefix = heldPrefix; @@ -64,40 +65,3 @@ public sealed class VisualsChangedEvent : EntityEventArgs ContainerId = containerId; } } - -/// -/// Abstracted sizes for items. -/// Used to determine what can fit into inventories. -/// -public enum ItemSize -{ - /// - /// Items that can be held completely in one's hand. - /// - Tiny = 1, - - /// - /// Items that can fit inside of a standard pocket. - /// - Small = 2, - - /// - /// Items that can fit inside of a standard bag. - /// - Normal = 4, - - /// - /// Items that are too large to fit inside of standard bags, but can worn in exterior slots or placed in custom containers. - /// - Large = 8, - - /// - /// Items that are too large to place inside of any kind of container. - /// - Huge = 16, - - /// - /// Picture furry gf - /// - Ginormous = 32 -} diff --git a/Content.Shared/Item/ItemSizePrototype.cs b/Content.Shared/Item/ItemSizePrototype.cs new file mode 100644 index 0000000000..e498809593 --- /dev/null +++ b/Content.Shared/Item/ItemSizePrototype.cs @@ -0,0 +1,53 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Item; + +/// +/// This is a prototype for a category of an item's size. +/// +[Prototype("itemSize")] +public sealed partial class ItemSizePrototype : IPrototype, IComparable +{ + /// + [IdDataField] + public string ID { get; } = default!; + + /// + /// The amount of space in a bag an item of this size takes. + /// + [DataField] + public readonly int Weight = 1; + + /// + /// A player-facing name used to describe this size. + /// + [DataField] + public readonly LocId Name; + + public int CompareTo(ItemSizePrototype? other) + { + if (other is not { } otherItemSize) + return 0; + return Weight.CompareTo(otherItemSize.Weight); + } + + public static bool operator <(ItemSizePrototype a, ItemSizePrototype b) + { + return a.Weight < b.Weight; + } + + public static bool operator >(ItemSizePrototype a, ItemSizePrototype b) + { + return a.Weight > b.Weight; + } + + public static bool operator <=(ItemSizePrototype a, ItemSizePrototype b) + { + return a.Weight <= b.Weight; + } + + public static bool operator >=(ItemSizePrototype a, ItemSizePrototype b) + { + return a.Weight >= b.Weight; + } +} diff --git a/Content.Shared/Item/ItemToggleComponent.cs b/Content.Shared/Item/ItemToggleComponent.cs index 250306f8c7..eb25f259ae 100644 --- a/Content.Shared/Item/ItemToggleComponent.cs +++ b/Content.Shared/Item/ItemToggleComponent.cs @@ -1,6 +1,7 @@ using Content.Shared.Item; using Robust.Shared.Audio; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; namespace Content.Server.Weapons.Melee.ItemToggle; @@ -21,11 +22,11 @@ public sealed partial class ItemToggleComponent : Component [ViewVariables(VVAccess.ReadWrite)] [DataField("offSize")] - public ItemSize OffSize = ItemSize.Small; + public ProtoId OffSize = "Small"; [ViewVariables(VVAccess.ReadWrite)] [DataField("onSize")] - public ItemSize OnSize = ItemSize.Huge; + public ProtoId OnSize = "Huge"; } [ByRefEvent] diff --git a/Content.Shared/Item/SharedItemSystem.cs b/Content.Shared/Item/SharedItemSystem.cs index 4317a2307f..ee4dc1e45f 100644 --- a/Content.Shared/Item/SharedItemSystem.cs +++ b/Content.Shared/Item/SharedItemSystem.cs @@ -6,12 +6,14 @@ using Content.Shared.Examine; using JetBrains.Annotations; using Robust.Shared.Containers; using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Shared.Item; public abstract class SharedItemSystem : EntitySystem { + [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] protected readonly SharedContainerSystem Container = default!; @@ -30,7 +32,7 @@ public abstract class SharedItemSystem : EntitySystem #region Public API - public void SetSize(EntityUid uid, ItemSize size, ItemComponent? component = null) + public void SetSize(EntityUid uid, ProtoId size, ItemComponent? component = null) { if (!Resolve(uid, ref component, false)) return; @@ -128,6 +130,11 @@ public abstract class SharedItemSystem : EntitySystem ("size", GetItemSizeLocale(component.Size)))); } + public ItemSizePrototype GetSizePrototype(ProtoId id) + { + return _prototype.Index(id); + } + /// /// Notifies any entity that is holding or wearing this item that they may need to update their sprite. /// @@ -140,14 +147,14 @@ public abstract class SharedItemSystem : EntitySystem } [PublicAPI] - public static string GetItemSizeLocale(ItemSize size) + public string GetItemSizeLocale(ProtoId size) { - return Robust.Shared.Localization.Loc.GetString($"item-component-size-{size.ToString()}"); + return Loc.GetString(GetSizePrototype(size).Name); } [PublicAPI] - public static int GetItemSizeWeight(ItemSize size) + public int GetItemSizeWeight(ProtoId size) { - return (int) size; + return GetSizePrototype(size).Weight; } } diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index 9140588398..63f5ba39a5 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -19,21 +19,23 @@ using Content.Shared.Timing; using Content.Shared.Verbs; using Robust.Shared.Containers; using Robust.Shared.Map; +using Robust.Shared.Prototypes; using Robust.Shared.Random; namespace Content.Shared.Storage.EntitySystems; public abstract class SharedStorageSystem : EntitySystem { + [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] protected readonly IRobustRandom Random = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private readonly EntityLookupSystem _entityLookupSystem = default!; [Dependency] protected readonly SharedEntityStorageSystem EntityStorage = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + [Dependency] private readonly SharedItemSystem _item = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedHandsSystem _sharedHandsSystem = default!; - [Dependency] private readonly SharedInteractionSystem _sharedInteractionSystem = default!; [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] protected readonly SharedAudioSystem Audio = default!; @@ -46,7 +48,8 @@ public abstract class SharedStorageSystem : EntitySystem private EntityQuery _stackQuery; private EntityQuery _xformQuery; - public const ItemSize DefaultStorageMaxItemSize = ItemSize.Normal; + [ValidatePrototypeId] + public const string DefaultStorageMaxItemSize = "Normal"; /// public override void Initialize() @@ -474,14 +477,15 @@ public abstract class SharedStorageSystem : EntitySystem if (!_stackQuery.TryGetComponent(insertEnt, out var stack) || !HasSpaceInStacks(uid, stack.StackTypeId)) { - if (item.Size > GetMaxItemSize((uid, storageComp))) + var maxSize = _item.GetSizePrototype(GetMaxItemSize((uid, storageComp))); + if (_item.GetSizePrototype(item.Size) > maxSize) { reason = "comp-storage-too-big"; return false; } if (TryComp(insertEnt, out var insertStorage) - && GetMaxItemSize((insertEnt, insertStorage)) >= GetMaxItemSize((uid, storageComp))) + && _item.GetSizePrototype(GetMaxItemSize((insertEnt, insertStorage))) >= maxSize) { reason = "comp-storage-too-big"; return false; @@ -495,7 +499,7 @@ public abstract class SharedStorageSystem : EntitySystem return false; } } - else if (SharedItemSystem.GetItemSizeWeight(item.Size) + GetCumulativeItemSizes(uid, storageComp) > storageComp.MaxTotalWeight) + else if (_item.GetItemSizeWeight(item.Size) + GetCumulativeItemSizes(uid, storageComp) > storageComp.MaxTotalWeight) { reason = "comp-storage-insufficient-capacity"; return false; @@ -643,7 +647,7 @@ public abstract class SharedStorageSystem : EntitySystem /// true if inserted, false otherwise public bool PlayerInsertEntityInWorld(Entity uid, EntityUid player, EntityUid toInsert) { - if (!Resolve(uid, ref uid.Comp) || !_sharedInteractionSystem.InRangeUnobstructed(player, uid)) + if (!Resolve(uid, ref uid.Comp) || !_interactionSystem.InRangeUnobstructed(player, uid)) return false; if (!Insert(uid, toInsert, out _, user: player, uid.Comp)) @@ -706,13 +710,13 @@ public abstract class SharedStorageSystem : EntitySystem { if (!_itemQuery.TryGetComponent(item, out var itemComp)) continue; - sum += SharedItemSystem.GetItemSizeWeight(itemComp.Size); + sum += _item.GetItemSizeWeight(itemComp.Size); } return sum; } - public ItemSize GetMaxItemSize(Entity uid) + public ProtoId GetMaxItemSize(Entity uid) { if (!Resolve(uid, ref uid.Comp)) return DefaultStorageMaxItemSize; @@ -723,12 +727,14 @@ public abstract class SharedStorageSystem : EntitySystem if (!_itemQuery.TryGetComponent(uid, out var item)) return DefaultStorageMaxItemSize; + var size = _item.GetSizePrototype(item.Size); // if there is no max item size specified, the value used // is one below the item size of the storage entity, clamped at ItemSize.Tiny - var sizes = Enum.GetValues().ToList(); - var currentSizeIndex = sizes.IndexOf(item.Size); - return sizes[Math.Max(currentSizeIndex - 1, 0)]; + var sizes = _prototype.EnumeratePrototypes().ToList(); + sizes.Sort(); + var currentSizeIndex = sizes.IndexOf(size); + return sizes[Math.Max(currentSizeIndex - 1, 0)].ID; } public FixedPoint2 GetStorageFillPercentage(Entity uid) diff --git a/Content.Shared/Storage/StorageComponent.cs b/Content.Shared/Storage/StorageComponent.cs index 2c05cb4eed..56aa07d649 100644 --- a/Content.Shared/Storage/StorageComponent.cs +++ b/Content.Shared/Storage/StorageComponent.cs @@ -5,6 +5,7 @@ using Robust.Shared.Audio; using Robust.Shared.Containers; using Robust.Shared.GameStates; using Robust.Shared.Map; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization; namespace Content.Shared.Storage @@ -34,7 +35,7 @@ namespace Content.Shared.Storage /// [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] [Access(typeof(SharedStorageSystem))] - public ItemSize? MaxItemSize; + public ProtoId? MaxItemSize; /// /// The max number of entities that can be inserted into this storage. diff --git a/Resources/Prototypes/Catalog/Fills/Boxes/general.yml b/Resources/Prototypes/Catalog/Fills/Boxes/general.yml index 5daaf8d748..ae5f01301d 100644 --- a/Resources/Prototypes/Catalog/Fills/Boxes/general.yml +++ b/Resources/Prototypes/Catalog/Fills/Boxes/general.yml @@ -414,8 +414,6 @@ parent: BoxCardboard id: BoxCandle components: - - type: Item - size: 30 - type: Sprite layers: - state: box @@ -434,14 +432,12 @@ amount: 3 - id: CandlePurple amount: 3 - + - type: entity name: small candle box parent: BoxCardboard id: BoxCandleSmall components: - - type: Item - size: 30 - type: Sprite layers: - state: box diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml index 5223ab926b..ea8e3b17f1 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml @@ -202,7 +202,6 @@ - state: equipped-FEET offset: "0, -0.04" - type: Item - size: 10 sprite: Clothing/Shoes/Specific/skates.rsi - type: ClothingSpeedModifier walkModifier: 1.3 diff --git a/Resources/Prototypes/Entities/Objects/Fun/candy_bucket.yml b/Resources/Prototypes/Entities/Objects/Fun/candy_bucket.yml index 5bdf80f645..d78def0c94 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/candy_bucket.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/candy_bucket.yml @@ -13,7 +13,7 @@ threshold: 1 - type: Item heldPrefix: empty - size: 20 + size: Normal - type: Appearance - type: GenericVisualizer visuals: diff --git a/Resources/Prototypes/Entities/Objects/Misc/candles.yml b/Resources/Prototypes/Entities/Objects/Misc/candles.yml index d86b20caf6..bef37e5fd0 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/candles.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/candles.yml @@ -11,14 +11,14 @@ - state: candle-big color: "#decb8e" - type: Item - size: 2 + size: Small - type: Appearance - type: Reactive groups: Flammable: [ Touch ] Extinguish: [ Touch ] - type: ExtinguishOnInteract - extinguishAttemptSound: + extinguishAttemptSound: path: /Audio/Items/candle_blowing.ogg params: variation: 0.05 @@ -28,9 +28,9 @@ fireSpread: false canResistFire: false alwaysCombustible: true - canExtinguish: true + canExtinguish: true firestacksOnIgnite: 3.0 - firestackFade: -0.01 + firestackFade: -0.01 damage: types: Heat: 0.1 @@ -56,7 +56,7 @@ behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] - + - type: entity name: red candle parent: Candle @@ -120,7 +120,7 @@ - type: Sprite layers: - state: candle-big - color: "#5d997e" + color: "#5d997e" - type: Item inhandVisuals: left: @@ -149,13 +149,13 @@ color: "#984aa1" -- type: entity +- type: entity name: small candle parent: Candle id: CandleSmall components: - type: Item - size: 1 + size: Tiny - type: Sprite layers: - state: candle-small @@ -236,7 +236,7 @@ - type: Sprite layers: - state: candle-small - color: "#5d997e" + color: "#5d997e" - type: Item inhandVisuals: left: @@ -266,8 +266,8 @@ #Purely decorative candles for mappers. Do not have any functionality. -- type: entity - name: magic candle +- type: entity + name: magic candle description: It's either magic or high tech, but this candle never goes out. On the other hand, its flame is quite cold. parent: BaseItem suffix: Decorative @@ -354,7 +354,7 @@ - type: Sprite layers: - state: candle-big - color: "#5d997e" + color: "#5d997e" - state: fire-big shader: unshaded - type: Item @@ -444,7 +444,7 @@ color: "#1b1724" right: - state: inhand-right - color: "#1b1724" + color: "#1b1724" - type: entity name: small magic green candle @@ -456,7 +456,7 @@ - state: candle-small color: "#5d997e" - state: fire-small - shader: unshaded + shader: unshaded - type: Item inhandVisuals: left: @@ -464,7 +464,7 @@ color: "#5d997e" right: - state: inhand-right - color: "#5d997e" + color: "#5d997e" - type: entity name: small magic purple candle @@ -484,4 +484,4 @@ color: "#984aa1" right: - state: inhand-right - color: "#984aa1" + color: "#984aa1" diff --git a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml index 9e988bb977..2de09112c1 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Xenoarchaeology/item_artifacts.yml @@ -178,7 +178,7 @@ wizardball6: "" - type: Appearance - type: Item - size: 150 + size: Normal - type: Tag tags: - ArtifactFragment @@ -202,5 +202,3 @@ components: - type: Stack count: 1 - - type: Item - size: 5 diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml index 8a3754c035..3a0eb0ab2c 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/sledgehammer.yml @@ -19,4 +19,4 @@ Blunt: 10 Structural: 60 - type: Item - size: 80 + size: Large diff --git a/Resources/Prototypes/item_size.yml b/Resources/Prototypes/item_size.yml new file mode 100644 index 0000000000..47d1fe3db4 --- /dev/null +++ b/Resources/Prototypes/item_size.yml @@ -0,0 +1,35 @@ +# Items that can be held completely in one's hand. +- type: itemSize + id: Tiny + weight: 1 + name: item-component-size-Tiny + +# Items that can fit inside of a standard pocket. +- type: itemSize + id: Small + weight: 2 + name: item-component-size-Small + +# Items that can fit inside of a standard bag. +- type: itemSize + id: Normal + weight: 4 + name: item-component-size-Normal + +# Items that are too large to fit inside of standard bags, but can worn in exterior slots or placed in custom containers. +- type: itemSize + id: Large + weight: 8 + name: item-component-size-Large + +# Items that are too large to place inside of any kind of container. +- type: itemSize + id: Huge + weight: 16 + name: item-component-size-Huge + +# Picture furry gf +- type: itemSize + id: Ginormous + weight: 32 + name: item-component-size-Ginormous