using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
namespace Content.Shared.Popups;
///
/// System for displaying small text popups on users' screens.
///
public abstract partial class SharedPopupSystem : EntitySystem
{
[Dependency] protected IGameTiming Timing = default!;
///
/// Shows a popup at a user's cursor.
///
/// The message to display.
/// The entity whose attached player will see the popup.
/// Used to customize how this popup should appear visually.
public abstract void PopupCursor(string? message, EntityUid? recipient, PopupType type = PopupType.Small);
///
/// Shows a popup at a user's cursor.
///
/// The message to display.
/// The player session that will see the popup.
/// Used to customize how this popup should appear visually.
public abstract void PopupCursor(string? message, ICommonSession recipient, PopupType type = PopupType.Small);
///
/// Shows a popup at some users' cursors.
///
/// The message to display.
/// Filter for the clients that will see this popup.
/// If true, this pop-up will be considered as a globally visible pop-up that gets shown during replays.
/// Used to customize how this popup should appear visually.
public abstract void PopupCursor(string? message, Filter filter, bool recordReplay, PopupType type = PopupType.Small);
///
/// Shows a popup at a world location to every entity in PVS range.
///
/// The message to display.
/// The coordinates where to display the message.
/// Used to customize how this popup should appear visually.
/// Additional key used to uniquely identify this popup event for prediction purposes.
///
/// In case your popup is predicted and may show up multiple times at different locations in a single tick, for each popup you should use a different prediction key,
/// which server and client have to agree on. Otherwise, the client may ignore some of the popups.
/// This is needed because the coordinates themselves cannot be part of the PredictionInstance, since they slightly differ between server and client due to
/// floating point precision issues and predictive movement, so two popups at different locations with the same message in the same tick would be considered identical.
/// The most common use case for this is when you delete an entity and spawn a popup at its location. For this you can use the NetEntity ID of the deleted entity as the prediction key.
///
public abstract void PopupCoordinates(string? message, EntityCoordinates coordinates, PopupType type = PopupType.Small, int predictionKey = 0);
///
/// Variant of that sends a popup to the player attached to some entity.
///
/// The message to display.
/// The coordinates where to display the message.
/// The entity whose attached player will see the popup.
/// Used to customize how this popup should appear visually.
/// Additional key used to uniquely identify this popup event for prediction purposes.
public abstract void PopupCoordinates(string? message, EntityCoordinates coordinates, EntityUid? recipient, PopupType type = PopupType.Small, int predictionKey = 0);
///
/// Variant of that sends a popup to a specific player.
///
/// The message to display.
/// The coordinates where to display the message.
/// The player session that will see the popup.
/// Used to customize how this popup should appear visually.
/// Additional key used to uniquely identify this popup event for prediction purposes.
public abstract void PopupCoordinates(string? message, EntityCoordinates coordinates, ICommonSession recipient, PopupType type = PopupType.Small, int predictionKey = 0);
///
/// Filtered variant of , which should only be used
/// if the filtering has to be more specific than simply PVS range based.
///
/// The message to display.
/// The coordinates where to display the message.
/// Filter for the clients that will see this popup.
/// If true, this pop-up will be considered as a globally visible pop-up that gets shown during replays.
/// Used to customize how this popup should appear visually.
/// Additional key used to uniquely identify this popup event for prediction purposes.
public abstract void PopupCoordinates(string? message, EntityCoordinates coordinates, Filter filter, bool recordReplay, PopupType type = PopupType.Small, int predictionKey = 0);
///
/// Shows a popup above an entity for every player in PVS range.
///
/// The message to display.
/// The entity above which to display the popup.
/// Used to customize how this popup should appear visually.
public abstract void PopupEntity(string? message, EntityUid uid, PopupType type = PopupType.Small);
///
/// Variant of that shows the popup only to some specific client.
///
/// The message to display.
/// The entity above which to display the popup.
/// The entity whose attached player will see the popup.Used to customize how this popup should appear visually.
public abstract void PopupEntity(string? message, EntityUid uid, EntityUid? recipient, PopupType type = PopupType.Small);
///
/// Variant of that shows the popup only to some specific client.
///
/// The message to display.
/// The entity above which to display the popup.
/// The player session that will see the popup.
/// Used to customize how this popup should appear visually.
public abstract void PopupEntity(string? message, EntityUid uid, ICommonSession recipient, PopupType type = PopupType.Small);
///
/// Filtered variant of , which should only be used
/// if the filtering has to be more specific than simply PVS range based.
///
/// The message to display.
/// The entity above which to display the popup.
/// Filter for the clients that will see this popup.
/// If true, this pop-up will be considered as a globally visible pop-up that gets shown during replays.
/// Used to customize how this popup should appear visually.
public abstract void PopupEntity(string? message, EntityUid uid, Filter filter, bool recordReplay, PopupType type = PopupType.Small);
///
/// Variant of that displays
/// to the recipient and to everyone else in PVS range.
///
/// The message to display to the recipient.
/// The message to display to everyone else in PVS range.
/// The entity above which to display the popup.
/// The entity whose attached player will see the recipient message.
/// Used to customize how this popup should appear visually.
/// Common base for all popup network events.
///
[Serializable, NetSerializable]
public abstract class PopupEvent(string message, PopupType type, GameTick tick) : EntityEventArgs
{
///
/// The message to display.
///
public string Message = message;
///
/// The type of the popup.
///
public PopupType Type = type;
///
/// The game tick at which the popup was created.
///
public GameTick Tick = tick;
}
///
/// Interface for a prediction instance of a popup event.
/// Used to keep track if a popup has already been predicted and displayed on the client side, to avoid duplicate popups.
///
public interface IPopupPredictionInstance
{
///
/// The game tick at which the popup was created.
///
GameTick Tick { get; }
}
///
/// Network event for displaying a popup on the user's cursor.
///
[Serializable, NetSerializable]
public sealed class PopupCursorEvent(string message, PopupType type, GameTick tick) : PopupEvent(message, type, tick)
{
///
/// Creates a new prediction instance for this popup event.
///
public readonly record struct PredictionInstance(string Message, PopupType Type, GameTick Tick) : IPopupPredictionInstance;
}
///
/// Network event for displaying a popup at a world location.
///
[Serializable, NetSerializable]
public sealed class PopupCoordinatesEvent(string message, PopupType type, GameTick tick, NetCoordinates coordinates, int predictionKey) : PopupEvent(message, type, tick)
{
///
/// The coordinates where the popup should be displayed.
///
public NetCoordinates Coordinates = coordinates;
///
/// The key used to identify this popup event for prediction purposes.
///
public int PredictionKey = predictionKey;
///
/// Creates a new prediction instance for this popup event.
///
///
/// TODO: remove coords, as they are not used for prediction.
///
public readonly record struct PredictionInstance(string Message, PopupType Type, GameTick Tick, int PredictionKey) : IPopupPredictionInstance;
}
///
/// Network event for displaying a popup above an entity.
///
[Serializable, NetSerializable]
public sealed class PopupEntityEvent(string message, PopupType type, GameTick tick, NetEntity uid) : PopupEvent(message, type, tick)
{
///
/// The entity above which the popup should be displayed.
///
public NetEntity Uid = uid;
///
/// Creates a new prediction instance for this popup event.
///
public readonly record struct PredictionInstance(string Message, PopupType Type, GameTick Tick, NetEntity Uid) : IPopupPredictionInstance;
}
///
/// Used to determine how a popup should appear visually to the client. Caution variants simply have a red color.
///
///
/// Actions which can fail or succeed should use a smaller popup for failure and a larger popup for success.
/// Actions which have different popups for the user vs. others should use a larger popup for the user and a smaller popup for others.
/// Actions which result in harm or are otherwise dangerous should always show as the caution variant.
///
[Serializable, NetSerializable]
public enum PopupType : byte
{
///
/// Small popups are the default, and denote actions that may be spammable or are otherwise unimportant.
///
Small,
SmallCaution,
///
/// Medium popups should be used for actions which are not spammable but may not be particularly important.
///
Medium,
MediumCaution,
///
/// Large popups should be used for actions which may be important or very important to one or more users,
/// but is not life-threatening.
///
Large,
LargeCaution
}