Actions System + UI (#2710)
Co-authored-by: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Shared.Prototypes.Kitchen;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -8,41 +6,28 @@ using Robust.Shared.Prototypes;
|
||||
namespace Content.Shared.Alert
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to all configured alerts. Ability to encode/decode a given state
|
||||
/// to an int.
|
||||
/// Provides access to all configured alerts by alert type.
|
||||
/// </summary>
|
||||
public class AlertManager
|
||||
{
|
||||
[Dependency]
|
||||
private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
private AlertPrototype[] _orderedAlerts;
|
||||
private Dictionary<AlertType, byte> _typeToIndex;
|
||||
private Dictionary<AlertType, AlertPrototype> _typeToAlert;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
// order by type value so we can map between the id and an integer index and use
|
||||
// the index for compact alert change messages
|
||||
_orderedAlerts =
|
||||
_prototypeManager.EnumeratePrototypes<AlertPrototype>()
|
||||
.OrderBy(prototype => prototype.AlertType).ToArray();
|
||||
_typeToIndex = new Dictionary<AlertType, byte>();
|
||||
_typeToAlert = new Dictionary<AlertType, AlertPrototype>();
|
||||
|
||||
for (var i = 0; i < _orderedAlerts.Length; i++)
|
||||
foreach (var alert in _prototypeManager.EnumeratePrototypes<AlertPrototype>())
|
||||
{
|
||||
if (i > byte.MaxValue)
|
||||
{
|
||||
Logger.ErrorS("alert", "too many alerts for byte encoding ({0})! encoding will need" +
|
||||
" to be changed to use a ushort rather than byte", _typeToIndex.Count);
|
||||
break;
|
||||
}
|
||||
if (!_typeToIndex.TryAdd(_orderedAlerts[i].AlertType, (byte) i))
|
||||
if (!_typeToAlert.TryAdd(alert.AlertType, alert))
|
||||
{
|
||||
Logger.ErrorS("alert",
|
||||
"Found alert with duplicate id {0}", _orderedAlerts[i].AlertType);
|
||||
"Found alert with duplicate alertType {0} - all alerts must have" +
|
||||
" a unique alerttype, this one will be skipped", alert.AlertType);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -51,74 +36,7 @@ namespace Content.Shared.Alert
|
||||
/// <returns>true if found</returns>
|
||||
public bool TryGet(AlertType alertType, out AlertPrototype alert)
|
||||
{
|
||||
if (_typeToIndex.TryGetValue(alertType, out var idx))
|
||||
{
|
||||
alert = _orderedAlerts[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
alert = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the alert of the indicated type along with its encoding
|
||||
/// </summary>
|
||||
/// <returns>true if found</returns>
|
||||
public bool TryGetWithEncoded(AlertType alertType, out AlertPrototype alert, out byte encoded)
|
||||
{
|
||||
if (_typeToIndex.TryGetValue(alertType, out var idx))
|
||||
{
|
||||
alert = _orderedAlerts[idx];
|
||||
encoded = (byte) idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
alert = null;
|
||||
encoded = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the compact encoded representation of this alert
|
||||
/// </summary>
|
||||
/// <returns>true if successful</returns>
|
||||
public bool TryEncode(AlertPrototype alert, out byte encoded)
|
||||
{
|
||||
return TryEncode(alert.AlertType, out encoded);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the compact encoded representation of the alert with
|
||||
/// the indicated id
|
||||
/// </summary>
|
||||
/// <returns>true if successful</returns>
|
||||
public bool TryEncode(AlertType alertType, out byte encoded)
|
||||
{
|
||||
if (_typeToIndex.TryGetValue(alertType, out var idx))
|
||||
{
|
||||
encoded = idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
encoded = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the alert from the encoded representation
|
||||
/// </summary>
|
||||
/// <returns>true if successful</returns>
|
||||
public bool TryDecode(byte encodedAlert, out AlertPrototype alert)
|
||||
{
|
||||
if (encodedAlert >= _orderedAlerts.Length)
|
||||
{
|
||||
alert = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
alert = _orderedAlerts[encodedAlert];
|
||||
return true;
|
||||
return _typeToAlert.TryGetValue(alertType, out alert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Content.Shared.Interfaces;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -70,6 +72,11 @@ namespace Content.Shared.Alert
|
||||
/// </summary>
|
||||
public bool SupportsSeverity => MaxSeverity != -1;
|
||||
|
||||
/// <summary>
|
||||
/// Defines what to do when the alert is clicked.
|
||||
/// </summary>
|
||||
public IAlertClick OnClick { get; private set; }
|
||||
|
||||
public void LoadFrom(YamlMappingNode mapping)
|
||||
{
|
||||
var serializer = YamlObjectSerializer.NewReader(mapping);
|
||||
@@ -94,6 +101,9 @@ namespace Content.Shared.Alert
|
||||
Category = alertCategory;
|
||||
}
|
||||
AlertKey = new AlertKey(AlertType, Category);
|
||||
|
||||
if (IoCManager.Resolve<IModuleManager>().IsClientModule) return;
|
||||
serializer.DataField(this, x => x.OnClick, "onClick", null);
|
||||
}
|
||||
|
||||
/// <param name="severity">severity level, if supported by this alert</param>
|
||||
@@ -143,30 +153,26 @@ namespace Content.Shared.Alert
|
||||
[Serializable, NetSerializable]
|
||||
public struct AlertKey
|
||||
{
|
||||
private readonly AlertType? _alertType;
|
||||
private readonly AlertCategory? _alertCategory;
|
||||
public readonly AlertType? AlertType;
|
||||
public readonly AlertCategory? AlertCategory;
|
||||
|
||||
/// NOTE: if the alert has a category you must pass the category for this to work
|
||||
/// properly as a key. I.e. if the alert has a category and you pass only the ID, and you
|
||||
/// compare this to another AlertKey that has both the category and the same ID, it will not consider them equal.
|
||||
/// properly as a key. I.e. if the alert has a category and you pass only the alert type, and you
|
||||
/// compare this to another AlertKey that has both the category and the same alert type, it will not consider them equal.
|
||||
public AlertKey(AlertType? alertType, AlertCategory? alertCategory)
|
||||
{
|
||||
// if there is a category, ignore the alerttype.
|
||||
if (alertCategory != null)
|
||||
{
|
||||
_alertCategory = alertCategory;
|
||||
_alertType = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
_alertCategory = null;
|
||||
_alertType = alertType;
|
||||
}
|
||||
AlertCategory = alertCategory;
|
||||
AlertType = alertType;
|
||||
}
|
||||
|
||||
public bool Equals(AlertKey other)
|
||||
{
|
||||
return _alertType == other._alertType && _alertCategory == other._alertCategory;
|
||||
// compare only on alert category if we have one
|
||||
if (AlertCategory.HasValue)
|
||||
{
|
||||
return other.AlertCategory == AlertCategory;
|
||||
}
|
||||
return AlertType == other.AlertType && AlertCategory == other.AlertCategory;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
@@ -176,11 +182,14 @@ namespace Content.Shared.Alert
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(_alertType, _alertCategory);
|
||||
// use only alert category if we have one
|
||||
if (AlertCategory.HasValue) return AlertCategory.GetHashCode();
|
||||
return AlertType.GetHashCode();
|
||||
}
|
||||
|
||||
/// <param name="category">alert category, must not be null</param>
|
||||
/// <returns>An alert key for the provided alert category</returns>
|
||||
/// <returns>An alert key for the provided alert category. This must only be used for
|
||||
/// queries and never storage, as it is lacking an alert type.</returns>
|
||||
public static AlertKey ForCategory(AlertCategory category)
|
||||
{
|
||||
return new(null, category);
|
||||
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
/// <summary>
|
||||
/// Every kind of alert. Corresponds to alertType field in alert prototypes defined in YML
|
||||
/// NOTE: Using byte for a compact encoding when sending this in messages, can upgrade
|
||||
/// to ushort
|
||||
/// </summary>
|
||||
public enum AlertType
|
||||
public enum AlertType : byte
|
||||
{
|
||||
Error,
|
||||
LowPressure,
|
||||
|
||||
37
Content.Shared/Alert/IAlertClick.cs
Normal file
37
Content.Shared/Alert/IAlertClick.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Serialization;
|
||||
|
||||
namespace Content.Shared.Alert
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines what should happen when an alert is clicked.
|
||||
/// </summary>
|
||||
public interface IAlertClick : IExposeData
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Invoked on server side when user clicks an alert.
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
void AlertClicked(ClickAlertEventArgs args);
|
||||
}
|
||||
|
||||
public class ClickAlertEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Player clicking the alert
|
||||
/// </summary>
|
||||
public readonly IEntity Player;
|
||||
/// <summary>
|
||||
/// Alert that was clicked
|
||||
/// </summary>
|
||||
public readonly AlertPrototype Alert;
|
||||
|
||||
public ClickAlertEventArgs(IEntity player, AlertPrototype alert)
|
||||
{
|
||||
Player = player;
|
||||
Alert = alert;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user