Actions System + UI (#2710)

Co-authored-by: Vera Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
This commit is contained in:
chairbender
2020-12-13 14:28:20 -08:00
committed by GitHub
parent fd0df9a00a
commit 7a3c281f60
150 changed files with 7283 additions and 854 deletions

View File

@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Shared.Alert;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Serialization;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Shared.GameObjects.Components.Mobs
@@ -18,16 +15,30 @@ namespace Content.Shared.GameObjects.Components.Mobs
/// </summary>
public abstract class SharedAlertsComponent : Component
{
private static readonly AlertState[] NO_ALERTS = new AlertState[0];
[Dependency]
protected readonly AlertManager AlertManager = default!;
public override string Name => "AlertsUI";
public override string Name => "Alerts";
public override uint? NetID => ContentNetIDs.ALERTS;
[ViewVariables]
private Dictionary<AlertKey, ClickableAlertState> _alerts = new();
[ViewVariables] private Dictionary<AlertKey, AlertState> _alerts = new();
public override void HandleComponentState(ComponentState curState, ComponentState nextState)
{
base.HandleComponentState(curState, nextState);
if (curState is not AlertsComponentState state)
{
return;
}
_alerts = state.Alerts;
}
public override ComponentState GetComponentState()
{
return new AlertsComponentState(_alerts);
}
/// <returns>true iff an alert of the indicated alert category is currently showing</returns>
public bool IsShowingAlertCategory(AlertCategory alertCategory)
@@ -53,82 +64,14 @@ namespace Content.Shared.GameObjects.Components.Mobs
return _alerts.ContainsKey(alertKey);
}
protected IEnumerable<AlertState> EnumerateAlertStates()
protected IEnumerable<KeyValuePair<AlertKey, AlertState>> EnumerateAlertStates()
{
return _alerts.Values.Select(alertData => alertData.AlertState);
}
/// <summary>
/// Invokes the alert's specified callback if there is one.
/// Not intended to be used on clientside.
/// </summary>
protected void PerformAlertClickCallback(AlertPrototype alert, IEntity owner)
{
if (_alerts.TryGetValue(alert.AlertKey, out var alertStateCallback))
{
alertStateCallback.OnClickAlert?.Invoke(new ClickAlertEventArgs(owner, alert));
}
else
{
Logger.DebugS("alert", "player {0} attempted to invoke" +
" alert click for {1} but that alert is not currently" +
" showing", owner.Name, alert.AlertType);
}
}
/// <summary>
/// Creates a new array containing all of the current alert states.
/// </summary>
/// <returns></returns>
protected AlertState[] CreateAlertStatesArray()
{
if (_alerts.Count == 0) return NO_ALERTS;
var states = new AlertState[_alerts.Count];
// because I don't trust LINQ
var idx = 0;
foreach (var alertData in _alerts.Values)
{
states[idx++] = alertData.AlertState;
}
return states;
return _alerts;
}
protected bool TryGetAlertState(AlertKey key, out AlertState alertState)
{
if (_alerts.TryGetValue(key, out var alertData))
{
alertState = alertData.AlertState;
return true;
}
alertState = default;
return false;
}
/// <summary>
/// Replace the current active alerts with the specified alerts. Any
/// OnClickAlert callbacks on the active alerts will be erased.
/// </summary>
protected void SetAlerts(AlertState[] alerts)
{
var newAlerts = new Dictionary<AlertKey, ClickableAlertState>();
foreach (var alertState in alerts)
{
if (AlertManager.TryDecode(alertState.AlertEncoded, out var alert))
{
newAlerts[alert.AlertKey] = new ClickableAlertState
{
AlertState = alertState
};
}
else
{
Logger.ErrorS("alert", "unrecognized encoded alert {0}", alertState.AlertEncoded);
}
}
_alerts = newAlerts;
return _alerts.TryGetValue(key, out alertState);
}
/// <summary>
@@ -136,30 +79,24 @@ namespace Content.Shared.GameObjects.Components.Mobs
/// it will be updated / replaced with the specified values.
/// </summary>
/// <param name="alertType">type of the alert to set</param>
/// <param name="onClickAlert">callback to invoke when ClickAlertMessage is received by the server
/// after being clicked by client. Has no effect when specified on the clientside.</param>
/// <param name="severity">severity, if supported by the alert</param>
/// <param name="cooldown">cooldown start and end, if null there will be no cooldown (and it will
/// be erased if there is currently a cooldown for the alert)</param>
public void ShowAlert(AlertType alertType, short? severity = null, OnClickAlert onClickAlert = null,
ValueTuple<TimeSpan, TimeSpan>? cooldown = null)
public void ShowAlert(AlertType alertType, short? severity = null, ValueTuple<TimeSpan, TimeSpan>? cooldown = null)
{
if (AlertManager.TryGetWithEncoded(alertType, out var alert, out var encoded))
if (AlertManager.TryGet(alertType, out var alert))
{
if (_alerts.TryGetValue(alert.AlertKey, out var alertStateCallback) &&
alertStateCallback.AlertState.AlertEncoded == encoded &&
alertStateCallback.AlertState.Severity == severity && alertStateCallback.AlertState.Cooldown == cooldown)
alert.AlertType == alertType &&
alertStateCallback.Severity == severity && alertStateCallback.Cooldown == cooldown)
{
alertStateCallback.OnClickAlert = onClickAlert;
return;
}
_alerts[alert.AlertKey] = new ClickableAlertState
{
AlertState = new AlertState
{Cooldown = cooldown, AlertEncoded = encoded, Severity = severity},
OnClickAlert = onClickAlert
};
_alerts[alert.AlertKey] = new AlertState
{Cooldown = cooldown, Severity = severity};
AfterShowAlert();
Dirty();
@@ -212,7 +149,12 @@ namespace Content.Shared.GameObjects.Components.Mobs
}
/// <summary>
/// Invoked after clearing an alert prior to dirtying the control
/// Invoked after showing an alert prior to dirtying the component
/// </summary>
protected virtual void AfterShowAlert() { }
/// <summary>
/// Invoked after clearing an alert prior to dirtying the component
/// </summary>
protected virtual void AfterClearAlert() { }
}
@@ -220,9 +162,9 @@ namespace Content.Shared.GameObjects.Components.Mobs
[Serializable, NetSerializable]
public class AlertsComponentState : ComponentState
{
public AlertState[] Alerts;
public Dictionary<AlertKey, AlertState> Alerts;
public AlertsComponentState(AlertState[] alerts) : base(ContentNetIDs.ALERTS)
public AlertsComponentState(Dictionary<AlertKey, AlertState> alerts) : base(ContentNetIDs.ALERTS)
{
Alerts = alerts;
}
@@ -234,46 +176,19 @@ namespace Content.Shared.GameObjects.Components.Mobs
[Serializable, NetSerializable]
public class ClickAlertMessage : ComponentMessage
{
public readonly byte EncodedAlert;
public readonly AlertType AlertType;
public ClickAlertMessage(byte encodedAlert)
public ClickAlertMessage(AlertType alertType)
{
Directed = true;
EncodedAlert = encodedAlert;
AlertType = alertType;
}
}
[Serializable, NetSerializable]
public struct AlertState
{
public byte AlertEncoded;
public short? Severity;
public ValueTuple<TimeSpan, TimeSpan>? Cooldown;
}
public struct ClickableAlertState
{
public AlertState AlertState;
public OnClickAlert OnClickAlert;
}
public delegate void OnClickAlert(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;
}
}
}