diff --git a/Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs b/Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs index 7e847038be..603c5a5396 100644 --- a/Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs +++ b/Content.Client/GameObjects/Components/Mobs/ClientAlertsComponent.cs @@ -25,7 +25,6 @@ namespace Content.Client.GameObjects.Components.Mobs public sealed class ClientAlertsComponent : SharedAlertsComponent { [Dependency] private readonly IPlayerManager _playerManager = default!; - [Dependency] private readonly IResourceCache _resourceCache = default!; private AlertsUI _ui; private AlertOrderPrototype _alertOrder; @@ -202,7 +201,7 @@ namespace Content.Client.GameObjects.Components.Mobs private AlertControl CreateAlertControl(AlertPrototype alert, AlertState alertState) { - var alertControl = new AlertControl(alert, alertState.Severity, _resourceCache) + var alertControl = new AlertControl(alert, alertState.Severity) { Cooldown = alertState.Cooldown }; diff --git a/Content.Client/UserInterface/Controls/AlertControl.cs b/Content.Client/UserInterface/Controls/AlertControl.cs index b7925e7b38..019a899417 100644 --- a/Content.Client/UserInterface/Controls/AlertControl.cs +++ b/Content.Client/UserInterface/Controls/AlertControl.cs @@ -1,10 +1,9 @@ #nullable enable using System; -using Content.Client.Utility; using Content.Shared.Alert; -using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; +using Robust.Client.Utility; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Maths; @@ -41,23 +40,20 @@ namespace Content.Client.UserInterface.Controls private readonly IGameTiming _gameTiming; private readonly TextureRect _icon; private readonly CooldownGraphic _cooldownGraphic; - private readonly IResourceCache _resourceCache; /// /// Creates an alert control reflecting the indicated alert + state /// /// alert to display /// severity of alert, null if alert doesn't have severity levels - /// resourceCache to use to load alert icon textures - public AlertControl(AlertPrototype alert, short? severity, IResourceCache resourceCache) + public AlertControl(AlertPrototype alert, short? severity) { _gameTiming = IoCManager.Resolve(); TooltipDelay = CustomTooltipDelay; TooltipSupplier = SupplyTooltip; - _resourceCache = resourceCache; Alert = alert; _severity = severity; - var texture = _resourceCache.GetTexture(alert.GetIconPath(_severity)); + var texture = alert.GetIcon(_severity).Frame0(); _icon = new TextureRect { TextureScale = (2, 2), @@ -83,7 +79,7 @@ namespace Content.Client.UserInterface.Controls if (_severity != severity) { _severity = severity; - _icon.Texture = _resourceCache.GetTexture(Alert.GetIconPath(_severity)); + _icon.Texture = Alert.GetIcon(_severity).Frame0(); } } diff --git a/Content.Shared/Alert/AlertPrototype.cs b/Content.Shared/Alert/AlertPrototype.cs index d7cf72bb88..7c7ba74014 100644 --- a/Content.Shared/Alert/AlertPrototype.cs +++ b/Content.Shared/Alert/AlertPrototype.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using Content.Shared.Interfaces; using Robust.Shared.IoC; using Robust.Shared.Log; @@ -28,7 +29,7 @@ namespace Content.Shared.Alert /// to get the correct icon path for a particular severity level. /// [ViewVariables] - public string IconPath { get; private set; } + public SpriteSpecifier Icon { get; private set; } /// /// Name to show in tooltip window. Accepts formatting. @@ -59,6 +60,7 @@ namespace Content.Shared.Alert /// -1 (no effect) unless MaxSeverity is specified. Defaults to 1. Minimum severity level supported by this state. /// public short MinSeverity => MaxSeverity == -1 ? (short) -1 : _minSeverity; + private short _minSeverity; /// @@ -87,7 +89,7 @@ namespace Content.Shared.Alert { var serializer = YamlObjectSerializer.NewReader(mapping); - serializer.DataField(this, x => x.IconPath, "icon", string.Empty); + serializer.DataField(this, x => x.Icon, "icon", SpriteSpecifier.Invalid); serializer.DataField(this, x => x.MaxSeverity, "maxSeverity", (short) -1); serializer.DataField(ref _minSeverity, "minSeverity", (short) 1); @@ -106,6 +108,7 @@ namespace Content.Shared.Alert { Category = alertCategory; } + AlertKey = new AlertKey(AlertType, Category); HasOnClick = serializer.TryReadDataField("onClick", out string _); @@ -116,40 +119,45 @@ namespace Content.Shared.Alert /// severity level, if supported by this alert /// the icon path to the texture for the provided severity level - public string GetIconPath(short? severity = null) + public SpriteSpecifier GetIcon(short? severity = null) { if (!SupportsSeverity && severity != null) { - Logger.WarningS("alert", "attempted to get icon path for severity level for alert {0}, but" + - " this alert does not support severity levels", AlertType); + throw new InvalidOperationException("This alert does not support severity"); } - if (!SupportsSeverity) return IconPath; + + if (!SupportsSeverity) + return Icon; + if (severity == null) { - Logger.WarningS("alert", "attempted to get icon path without severity level for alert {0}," + - " but this alert requires a severity level. Using lowest" + - " valid severity level instead...", AlertType); - severity = MinSeverity; + throw new ArgumentException("No severity specified but this alert has severity.", nameof(severity)); } if (severity < MinSeverity) { - Logger.WarningS("alert", "attempted to get icon path with severity level {0} for alert {1}," + - " but the minimum severity level for this alert is {2}. Using" + - " lowest valid severity level instead...", severity, AlertType, MinSeverity); - severity = MinSeverity; - } - if (severity > MaxSeverity) - { - Logger.WarningS("alert", "attempted to get icon path with severity level {0} for alert {1}," + - " but the max severity level for this alert is {2}. Using" + - " highest valid severity level instead...", severity, AlertType, MaxSeverity); - severity = MaxSeverity; + throw new ArgumentOutOfRangeException(nameof(severity), "Severity below minimum severity."); } - // split and add the severity number to the path - var ext = IconPath.LastIndexOf('.'); - return IconPath.Substring(0, ext) + severity + IconPath.Substring(ext, IconPath.Length - ext); + if (severity > MaxSeverity) + { + throw new ArgumentOutOfRangeException(nameof(severity), "Severity above maximum severity."); + } + + var severityText = severity.Value.ToString(CultureInfo.InvariantCulture); + switch (Icon) + { + case SpriteSpecifier.EntityPrototype entityPrototype: + throw new InvalidOperationException("Severity not supported for EntityPrototype icon"); + case SpriteSpecifier.Rsi rsi: + return new SpriteSpecifier.Rsi(rsi.RsiPath, rsi.RsiState + severityText); + case SpriteSpecifier.Texture texture: + var newName = texture.TexturePath.FilenameWithoutExtension + severityText; + return new SpriteSpecifier.Texture( + texture.TexturePath.WithName(newName + "." + texture.TexturePath.Extension)); + default: + throw new ArgumentOutOfRangeException(nameof(Icon)); + } } } @@ -180,6 +188,7 @@ namespace Content.Shared.Alert { return other.AlertCategory == AlertCategory; } + return AlertType == other.AlertType && AlertCategory == other.AlertCategory; } diff --git a/Content.Tests/Shared/Alert/AlertManagerTests.cs b/Content.Tests/Shared/Alert/AlertManagerTests.cs index 540444469b..c9cf51ce38 100644 --- a/Content.Tests/Shared/Alert/AlertManagerTests.cs +++ b/Content.Tests/Shared/Alert/AlertManagerTests.cs @@ -33,14 +33,14 @@ namespace Content.Tests.Shared.Alert alertManager.Initialize(); Assert.That(alertManager.TryGet(AlertType.LowPressure, out var lowPressure)); - Assert.That(lowPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/lowpressure.png")); + Assert.That(lowPressure.Icon, Is.EqualTo(new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/Alerts/Pressure/lowpressure.png")))); Assert.That(alertManager.TryGet(AlertType.HighPressure, out var highPressure)); - Assert.That(highPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/highpressure.png")); + Assert.That(highPressure.Icon, Is.EqualTo(new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/Alerts/Pressure/highpressure.png")))); Assert.That(alertManager.TryGet(AlertType.LowPressure, out lowPressure)); - Assert.That(lowPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/lowpressure.png")); + Assert.That(lowPressure.Icon, Is.EqualTo(new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/Alerts/Pressure/lowpressure.png")))); Assert.That(alertManager.TryGet(AlertType.HighPressure, out highPressure)); - Assert.That(highPressure.IconPath, Is.EqualTo("/Textures/Interface/Alerts/Pressure/highpressure.png")); + Assert.That(highPressure.Icon, Is.EqualTo(new SpriteSpecifier.Texture(new ResourcePath("/Textures/Interface/Alerts/Pressure/highpressure.png")))); } } } diff --git a/Content.Tests/Shared/Alert/AlertPrototypeTests.cs b/Content.Tests/Shared/Alert/AlertPrototypeTests.cs index b557fca622..23ae9c3cce 100644 --- a/Content.Tests/Shared/Alert/AlertPrototypeTests.cs +++ b/Content.Tests/Shared/Alert/AlertPrototypeTests.cs @@ -44,7 +44,7 @@ namespace Content.Tests.Shared.Alert { var alert = GetTestPrototype(); - Assert.That(alert.GetIconPath(severity), Is.EqualTo(expected)); + Assert.That(alert.GetIcon(severity), Is.EqualTo(new SpriteSpecifier.Texture(new ResourcePath(expected)))); } private AlertPrototype GetTestPrototype()