diff --git a/Content.IntegrationTests/Tests/FillLevelSpriteTest.cs b/Content.IntegrationTests/Tests/FillLevelSpriteTest.cs
new file mode 100644
index 0000000000..37e777fa8c
--- /dev/null
+++ b/Content.IntegrationTests/Tests/FillLevelSpriteTest.cs
@@ -0,0 +1,71 @@
+using System.Linq;
+using Content.Shared.Chemistry.Components;
+using Robust.Client.GameObjects;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Prototypes;
+
+namespace Content.IntegrationTests.Tests;
+
+///
+/// Tests to see if any entity prototypes specify solution fill level sprites that don't exist.
+///
+[TestFixture]
+public sealed class FillLevelSpriteTest
+{
+ private static readonly string[] HandStateNames = ["left", "right"];
+
+ [Test]
+ public async Task FillLevelSpritesExist()
+ {
+ await using var pair = await PoolManager.GetServerClient();
+ var client = pair.Client;
+ var protoMan = client.ResolveDependency();
+ var componentFactory = client.ResolveDependency();
+
+ await client.WaitAssertion(() =>
+ {
+ var protos = protoMan.EnumeratePrototypes()
+ .Where(p => !p.Abstract)
+ .Where(p => !pair.IsTestPrototype(p))
+ .Where(p => p.TryGetComponent(out _, componentFactory))
+ .OrderBy(p => p.ID)
+ .ToList();
+
+ foreach (var proto in protos)
+ {
+ Assert.That(proto.TryGetComponent(out var visuals, componentFactory));
+ Assert.That(proto.TryGetComponent(out var sprite, componentFactory));
+
+ var rsi = sprite.BaseRSI;
+
+ // Test base sprite fills
+ if (!string.IsNullOrEmpty(visuals.FillBaseName))
+ {
+ for (var i = 1; i <= visuals.MaxFillLevels; i++)
+ {
+ var state = $"{visuals.FillBaseName}{i}";
+ Assert.That(rsi.TryGetState(state, out _), @$"{proto.ID} has SolutionContainerVisualsComponent with
+ MaxFillLevels = {visuals.MaxFillLevels}, but {rsi.Path} doesn't have state {state}!");
+ }
+ }
+
+ // Test inhand sprite fills
+ if (!string.IsNullOrEmpty(visuals.InHandsFillBaseName))
+ {
+ for (var i = 1; i <= visuals.InHandsMaxFillLevels; i++)
+ {
+ foreach (var handname in HandStateNames)
+ {
+ var state = $"inhand-{handname}{visuals.InHandsFillBaseName}{i}";
+ Assert.That(rsi.TryGetState(state, out _), @$"{proto.ID} has SolutionContainerVisualsComponent with
+ InHandsMaxFillLevels = {visuals.InHandsMaxFillLevels}, but {rsi.Path} doesn't have state {state}!");
+ }
+
+ }
+ }
+ }
+ });
+
+ await pair.CleanReturnAsync();
+ }
+}
diff --git a/Resources/Prototypes/Entities/Objects/Fun/darts.yml b/Resources/Prototypes/Entities/Objects/Fun/darts.yml
index 36c841995e..c0b5eb3399 100644
--- a/Resources/Prototypes/Entities/Objects/Fun/darts.yml
+++ b/Resources/Prototypes/Entities/Objects/Fun/darts.yml
@@ -83,10 +83,6 @@
max: 1
- !type:DoActsBehavior
acts: [ "Destruction" ]
- - type: Appearance
- - type: SolutionContainerVisuals
- maxFillLevels: 1
- fillBaseName: dart
- type: entity
parent: Dart
diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml
index ce0e0b629a..dd15a90baa 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml
@@ -233,6 +233,8 @@
sprite: Objects/Specific/Chemistry/beaker_cryostasis.rsi
layers:
- state: beakernoreact
+ - type: SolutionContainerVisuals
+ maxFillLevels: 0
- type: SolutionContainerManager
solutions:
beaker:
@@ -251,6 +253,8 @@
sprite: Objects/Specific/Chemistry/beaker_bluespace.rsi
layers:
- state: beakerbluespace
+ - type: SolutionContainerVisuals
+ maxFillLevels: 0
- type: SolutionContainerManager
solutions:
beaker: