Resolves StackVisualizer is Obsolete (#13908)

This commit is contained in:
TemporalOroboros
2023-05-17 23:16:53 -07:00
committed by GitHub
parent 2db40904b5
commit a1715666f0
20 changed files with 651 additions and 444 deletions

View File

@@ -1,16 +1,22 @@
using Content.Client.Items;
using Content.Client.Storage.Systems;
using Content.Shared.Stacks;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
namespace Content.Client.Stack
{
[UsedImplicitly]
public sealed class StackSystem : SharedStackSystem
{
[Dependency] private readonly AppearanceSystem _appearanceSystem = default!;
[Dependency] private readonly ItemCounterSystem _counterSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<StackComponent, ItemStatusCollectMessage>(OnItemStatus);
SubscribeLocalEvent<StackComponent, AppearanceChangeEvent>(OnAppearanceChange);
}
private void OnItemStatus(EntityUid uid, StackComponent component, ItemStatusCollectMessage args)
@@ -36,5 +42,26 @@ namespace Content.Client.Stack
if (component is StackComponent clientComp)
clientComp.UiUpdateNeeded = true;
}
private void OnAppearanceChange(EntityUid uid, StackComponent comp, ref AppearanceChangeEvent args)
{
if (args.Sprite == null || comp.LayerStates.Count < 1)
return;
// Skip processing if no actual
if (!_appearanceSystem.TryGetData<int>(uid, StackVisuals.Actual, out var actual, args.Component))
return;
if (!_appearanceSystem.TryGetData<int>(uid, StackVisuals.MaxCount, out var maxCount, args.Component))
maxCount = comp.LayerStates.Count;
if (!_appearanceSystem.TryGetData<bool>(uid, StackVisuals.Hide, out var hidden, args.Component))
hidden = false;
if (comp.IsComposite)
_counterSystem.ProcessCompositeSprite(uid, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite);
else
_counterSystem.ProcessOpaqueSprite(uid, comp.BaseLayer, actual, maxCount, comp.LayerStates, hidden, sprite: args.Sprite);
}
}
}

View File

@@ -1,162 +0,0 @@
using System.Collections.Generic;
using Content.Shared.Rounding;
using Content.Shared.Stacks;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Utility;
namespace Content.Client.Stack
{
/// <summary>
/// Visualizer for items that come in stacks and have different appearance
/// depending on the size of the stack. Visualizer can work by switching between different
/// icons in <c>_spriteLayers</c> or if the sprite layers are supposed to be composed as transparent layers.
/// The former behavior is default and the latter behavior can be defined in prototypes.
///
/// <example>
/// <para>To define a Stack Visualizer prototype insert the following
/// snippet (you can skip Appearance if already defined)
/// </para>
/// <code>
/// - type: Appearance
/// visuals:
/// - type: StackVisualizer
/// stackLayers:
/// - goldbar_10
/// - goldbar_20
/// - goldbar_30
/// </code>
/// </example>
/// <example>
/// <para>Defining a stack visualizer with composable transparent layers</para>
/// <code>
/// - type: StackVisualizer
/// composite: true
/// stackLayers:
/// - cigarette_1
/// - cigarette_2
/// - cigarette_3
/// - cigarette_4
/// - cigarette_5
/// - cigarette_6
/// </code>
/// </example>
/// <seealso cref="_spriteLayers"/>
/// </summary>
[UsedImplicitly]
public sealed class StackVisualizer : AppearanceVisualizer
{
/// <summary>
/// Default IconLayer stack.
/// </summary>
private const int IconLayer = 0;
/// <summary>
/// Sprite layers used in stack visualizer. Sprites first in layer correspond to lower stack states
/// e.g. <code>_spriteLayers[0]</code> is lower stack level than <code>_spriteLayers[1]</code>.
/// </summary>
[DataField("stackLayers")] private readonly List<string> _spriteLayers = new();
/// <summary>
/// Determines if the visualizer uses composite or non-composite layers for icons. Defaults to false.
///
/// <list type="bullet">
/// <item>
/// <description>false: they are opaque and mutually exclusive (e.g. sprites in a cable coil). <b>Default value</b></description>
/// </item>
/// <item>
/// <description>true: they are transparent and thus layered one over another in ascending order first</description>
/// </item>
/// </list>
///
/// </summary>
[DataField("composite")] private bool _isComposite;
[DataField("sprite")] private ResPath? _spritePath;
[Obsolete("Subscribe to your component being initialised instead.")]
public override void InitializeEntity(EntityUid entity)
{
base.InitializeEntity(entity);
if (_isComposite
&& _spriteLayers.Count > 0
&& IoCManager.Resolve<IEntityManager>().TryGetComponent<SpriteComponent?>(entity, out var spriteComponent))
{
var spritePath = _spritePath ?? spriteComponent.BaseRSI!.Path!;
foreach (var sprite in _spriteLayers)
{
spriteComponent.LayerMapReserveBlank(sprite);
spriteComponent.LayerSetSprite(sprite, new SpriteSpecifier.Rsi(spritePath, sprite));
spriteComponent.LayerSetVisible(sprite, false);
}
}
}
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
public override void OnChangeData(AppearanceComponent component)
{
base.OnChangeData(component);
var entities = IoCManager.Resolve<IEntityManager>();
if (entities.TryGetComponent(component.Owner, out SpriteComponent? spriteComponent))
{
if (_isComposite)
{
ProcessCompositeSprites(component, spriteComponent);
}
else
{
ProcessOpaqueSprites(component, spriteComponent);
}
}
}
private void ProcessOpaqueSprites(AppearanceComponent component, SpriteComponent spriteComponent)
{
// Skip processing if no actual
if (!component.TryGetData<int>(StackVisuals.Actual, out var actual)) return;
if (!component.TryGetData<int>(StackVisuals.MaxCount, out var maxCount))
{
maxCount = _spriteLayers.Count;
}
var activeLayer = ContentHelpers.RoundToEqualLevels(actual, maxCount, _spriteLayers.Count);
spriteComponent.LayerSetState(IconLayer, _spriteLayers[activeLayer]);
}
private void ProcessCompositeSprites(AppearanceComponent component, SpriteComponent spriteComponent)
{
// If hidden, don't render any sprites
if (component.TryGetData<bool>(StackVisuals.Hide, out var hide)
&& hide)
{
foreach (var transparentSprite in _spriteLayers)
{
spriteComponent.LayerSetVisible(transparentSprite, false);
}
return;
}
// Skip processing if no actual/maxCount
if (!component.TryGetData<int>(StackVisuals.Actual, out var actual)) return;
if (!component.TryGetData<int>(StackVisuals.MaxCount, out var maxCount))
{
maxCount = _spriteLayers.Count;
}
var activeTill = ContentHelpers.RoundToNearestLevels(actual, maxCount, _spriteLayers.Count);
for (var i = 0; i < _spriteLayers.Count; i++)
{
spriteComponent.LayerSetVisible(_spriteLayers[i], i < activeTill);
}
}
}
}