diff --git a/Content.IntegrationTests/PoolManager.cs b/Content.IntegrationTests/PoolManager.cs index 92e96bd15c..7c7f442ef5 100644 --- a/Content.IntegrationTests/PoolManager.cs +++ b/Content.IntegrationTests/PoolManager.cs @@ -670,6 +670,25 @@ we are just going to end this here to save a lot of time. This is the exception Assert.That(passed); } + + /// + /// Helper method that retrieves all entity prototypes that have some component. + /// + public static List GetEntityPrototypes(RobustIntegrationTest.IntegrationInstance instance) where T : Component + { + var protoMan = instance.ResolveDependency(); + var compFact = instance.ResolveDependency(); + + var id = compFact.GetComponentName(typeof(T)); + var list = new List(); + foreach (var ent in protoMan.EnumeratePrototypes()) + { + if (ent.Components.ContainsKey(id)) + list.Add(ent); + } + + return list; + } } /// diff --git a/Content.IntegrationTests/Tests/StorageTest.cs b/Content.IntegrationTests/Tests/StorageTest.cs index 21b5e7c40a..fca27733ba 100644 --- a/Content.IntegrationTests/Tests/StorageTest.cs +++ b/Content.IntegrationTests/Tests/StorageTest.cs @@ -1,10 +1,15 @@ #nullable enable +using System; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Content.Server.Storage.Components; using Content.Shared.Item; using Content.Shared.Storage; using NUnit.Framework; +using Robust.Shared.GameObjects; using Robust.Shared.Prototypes; +using Robust.UnitTesting; namespace Content.IntegrationTests.Tests { @@ -60,5 +65,84 @@ namespace Content.IntegrationTests.Tests }); await pairTracker.CleanReturnAsync(); } + + [Test] + public async Task TestSufficientSpaceForFill() + { + await using var pairTracker = await PoolManager.GetServerClient(new PoolSettings{NoClient = true}); + var server = pairTracker.Pair.Server; + + var protoMan = server.ResolveDependency(); + var compFact = server.ResolveDependency(); + var id = compFact.GetComponentName(typeof(StorageFillComponent)); + + Assert.Multiple(() => + { + foreach (var proto in PoolManager.GetEntityPrototypes(server)) + { + int capacity; + var isEntStorage = false; + + if (proto.TryGetComponent("Storage", out var storage)) + { + capacity = storage.StorageCapacityMax; + } + else if (proto.TryGetComponent("EntityStorage", out var entStorage)) + { + capacity = entStorage.Capacity; + isEntStorage = true; + } + else + { + Assert.Fail($"Entity {proto.ID} has storage-fill without a storage component!"); + continue; + } + + var fill = (StorageFillComponent) proto.Components[id].Component; + var size = GetFillSize(fill, isEntStorage); + Assert.That(size, Is.LessThanOrEqualTo(capacity), $"{proto.ID} storage fill is too large."); + } + }); + + int GetEntrySize(EntitySpawnEntry entry, bool isEntStorage) + { + if (entry.PrototypeId == null) + return 0; + + if (!protoMan.TryIndex(entry.PrototypeId, out var proto)) + { + Assert.Fail($"Unknown prototype: {entry.PrototypeId}"); + return 0; + } + + if (isEntStorage) + return entry.Amount; + + if (proto.TryGetComponent("Item", out var item)) + return item.Size * entry.Amount; + + Assert.Fail($"Prototype is missing item comp: {entry.PrototypeId}"); + return 0; + } + + int GetFillSize(StorageFillComponent fill, bool isEntStorage) + { + var totalSize = 0; + var groups = new Dictionary(); + foreach (var entry in fill.Contents) + { + var size = GetEntrySize(entry, isEntStorage); + + if (entry.GroupId == null) + totalSize += size; + else + groups[entry.GroupId] = Math.Max(size, groups.GetValueOrDefault(entry.GroupId)); + } + + return totalSize + groups.Values.Sum(); + } + + await pairTracker.CleanReturnAsync(); + } } } diff --git a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml index 9c0d1058f8..be11fbdd3f 100644 --- a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml @@ -506,9 +506,9 @@ - type: Clothing sprite: Clothing/Belt/militarywebbingmed.rsi - type: Item - size: 60 + size: 70 - type: Storage - capacity: 60 + capacity: 70 - type: entity parent: ClothingBeltBase