From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Sat, 18 Nov 2023 06:26:08 +0000 (+1300) Subject: Add item sprite test (#21599) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=69af5672691563ffd25da4836a2138f9df774866;p=space-station-14.git Add item sprite test (#21599) --- diff --git a/Content.IntegrationTests/Pair/TestPair.Helpers.cs b/Content.IntegrationTests/Pair/TestPair.Helpers.cs index 574644f67e..554807b2d2 100644 --- a/Content.IntegrationTests/Pair/TestPair.Helpers.cs +++ b/Content.IntegrationTests/Pair/TestPair.Helpers.cs @@ -1,7 +1,9 @@ #nullable enable +using System.Collections.Generic; using System.Linq; using Robust.Shared.GameObjects; using Robust.Shared.Map; +using Robust.Shared.Prototypes; using Robust.UnitTesting; namespace Content.IntegrationTests.Pair; @@ -95,4 +97,33 @@ public sealed partial class TestPair await Client.ExecuteCommand(cmd); await RunTicksSync(numTicks); } + + /// + /// Retrieve all entity prototypes that have some component. + /// + public List GetPrototypesWithComponent( + HashSet? ignored = null, + bool ignoreAbstract = true, + bool ignoreTestPrototypes = true) + where T : IComponent + { + var id = Server.ResolveDependency().GetComponentName(typeof(T)); + var list = new List(); + foreach (var proto in Server.ProtoMan.EnumeratePrototypes()) + { + if (ignored != null && ignored.Contains(proto.ID)) + continue; + + if (ignoreAbstract && proto.Abstract) + continue; + + if (ignoreTestPrototypes && IsTestPrototype(proto)) + continue; + + if (proto.Components.ContainsKey(id)) + list.Add(proto); + } + + return list; + } } diff --git a/Content.IntegrationTests/PoolManager.cs b/Content.IntegrationTests/PoolManager.cs index a2015f3fdb..d60f6cb4bd 100644 --- a/Content.IntegrationTests/PoolManager.cs +++ b/Content.IntegrationTests/PoolManager.cs @@ -425,25 +425,6 @@ 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 GetPrototypesWithComponent(RobustIntegrationTest.IntegrationInstance instance) where T : IComponent - { - 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; - } - /// /// Initialize the pool manager. /// diff --git a/Content.IntegrationTests/Tests/Sprite/ItemSpriteTest.cs b/Content.IntegrationTests/Tests/Sprite/ItemSpriteTest.cs new file mode 100644 index 0000000000..96f710d468 --- /dev/null +++ b/Content.IntegrationTests/Tests/Sprite/ItemSpriteTest.cs @@ -0,0 +1,64 @@ +#nullable enable +using System.Collections.Generic; +using Content.Shared.Item; +using Robust.Client.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; + +namespace Content.IntegrationTests.Tests.Sprite; + +/// +/// This test checks that all items have a visible sprite. The general rationale is that all items can be picked up +/// by players, thus they need to be visible and have a sprite that can be rendered on screen and in their hands GUI. +/// This has nothing to do with in-hand sprites. +/// +/// +/// If a prototype fails this test, its probably either because it: +/// - Should be marked abstract +/// - inherits from BaseItem despite not being an item +/// - Shouldn't have an item component +/// - Is missing the required sprite information. +/// If none of the abveo are true, it might need to be added to the list of ignored components, see +/// +/// +[TestFixture] +public sealed class PrototypeSaveTest +{ + private static HashSet _ignored = new() + { + // The only prototypes that should get ignored are those that REQUIRE setup to get a sprite. At that point it is + // the responsibility of the spawner to ensure that a valid sprite is set. + "HandVirtualItem" + }; + + [Test] + public async Task AllItemsHaveSpritesTest() + { + var settings = new PoolSettings() {Connected = true}; // client needs to be in-game + await using var pair = await PoolManager.GetServerClient(settings); + List badPrototypes = new(); + + await pair.Client.WaitPost(() => + { + foreach (var proto in pair.GetPrototypesWithComponent(_ignored)) + { + var dummy = pair.Client.EntMan.Spawn(proto.ID); + pair.Client.EntMan.RunMapInit(dummy, pair.Client.MetaData(dummy)); + var spriteComponent = pair.Client.EntMan.GetComponentOrNull(dummy); + if (spriteComponent?.Icon == null) + badPrototypes.Add(proto); + pair.Client.EntMan.DeleteEntity(dummy); + } + }); + + Assert.Multiple(() => + { + foreach (var proto in badPrototypes) + { + Assert.Fail($"Item prototype has no sprite: {proto.ID}. It should probably either be marked as abstract, not be an item, or have a valid sprite"); + } + }); + + await pair.CleanReturnAsync(); + } +} diff --git a/Content.IntegrationTests/Tests/StorageTest.cs b/Content.IntegrationTests/Tests/StorageTest.cs index a5944f4394..c618616cd2 100644 --- a/Content.IntegrationTests/Tests/StorageTest.cs +++ b/Content.IntegrationTests/Tests/StorageTest.cs @@ -94,7 +94,7 @@ namespace Content.IntegrationTests.Tests Assert.Multiple(() => { - foreach (var proto in PoolManager.GetPrototypesWithComponent(server)) + foreach (var proto in pair.GetPrototypesWithComponent()) { if (proto.HasComponent(compFact)) continue; @@ -174,7 +174,7 @@ namespace Content.IntegrationTests.Tests Assert.Multiple(() => { - foreach (var proto in PoolManager.GetPrototypesWithComponent(server)) + foreach (var proto in pair.GetPrototypesWithComponent()) { if (proto.HasComponent(compFact)) continue; diff --git a/Resources/Prototypes/Body/Parts/base.yml b/Resources/Prototypes/Body/Parts/base.yml index e293d8845d..a27059f59f 100644 --- a/Resources/Prototypes/Body/Parts/base.yml +++ b/Resources/Prototypes/Body/Parts/base.yml @@ -23,6 +23,7 @@ id: BaseTorso name: "torso" parent: BasePart + abstract: true components: - type: BodyPart partType: Torso @@ -31,6 +32,7 @@ id: BaseHead name: "head" parent: BasePart + abstract: true components: - type: BodyPart partType: Head @@ -45,6 +47,7 @@ id: BaseLeftArm name: "left arm" parent: BasePart + abstract: true components: - type: BodyPart partType: Arm @@ -54,6 +57,7 @@ id: BaseRightArm name: "right arm" parent: BasePart + abstract: true components: - type: BodyPart partType: Arm @@ -63,6 +67,7 @@ id: BaseLeftHand name: "left hand" parent: BasePart + abstract: true components: - type: BodyPart partType: Hand @@ -72,6 +77,7 @@ id: BaseRightHand name: "right hand" parent: BasePart + abstract: true components: - type: BodyPart partType: Hand @@ -81,6 +87,7 @@ id: BaseLeftLeg name: "left leg" parent: BasePart + abstract: true components: - type: BodyPart partType: Leg @@ -91,6 +98,7 @@ id: BaseRightLeg name: "right leg" parent: BasePart + abstract: true components: - type: BodyPart partType: Leg @@ -101,6 +109,7 @@ id: BaseLeftFoot name: "left foot" parent: BasePart + abstract: true components: - type: BodyPart partType: Foot @@ -110,6 +119,7 @@ id: BaseRightFoot name: "right foot" parent: BasePart + abstract: true components: - type: BodyPart partType: Foot diff --git a/Resources/Prototypes/Body/Parts/rat.yml b/Resources/Prototypes/Body/Parts/rat.yml index ad8eecf3df..6a66eecc48 100644 --- a/Resources/Prototypes/Body/Parts/rat.yml +++ b/Resources/Prototypes/Body/Parts/rat.yml @@ -13,3 +13,8 @@ - type: Tag tags: - Trash + # TODO get a proper rat king & servant torso sprite. + # currently their torso is just a small dead rat.... + - type: Sprite + sprite: Mobs/Animals/mouse.rsi + state: splat-0 diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml index 82c31a01c5..8294f64fe1 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/snacks.yml @@ -443,6 +443,7 @@ parent: BaseItem id: FoodPacketTrash description: This is rubbish. + abstract: true components: - type: Sprite sprite: Objects/Consumable/Food/snacks.rsi diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 0e5238316f..5e8807f770 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -3,7 +3,7 @@ id: IDCardStandard name: identification card description: A card necessary to access various areas aboard the station. - noSpawn: true + abstract: true components: - type: Sprite sprite: Objects/Misc/id_cards.rsi diff --git a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml index f893ba91d4..0ab56e02c5 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/subdermal_implants.yml @@ -117,8 +117,6 @@ whitelist: components: - Hands # no use giving a mouse a storage implant, but a monkey is another story... - - type: Item - size: Ginormous - type: Storage maxSlots: 4 maxItemSize: Small diff --git a/Resources/Prototypes/Entities/Objects/Tools/cable_coils.yml b/Resources/Prototypes/Entities/Objects/Tools/cable_coils.yml index 1b97467049..b090b38447 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/cable_coils.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/cable_coils.yml @@ -4,7 +4,7 @@ - type: entity id: CableStack - noSpawn: true + abstract: true parent: BaseItem name: cable stack suffix: Full