using System;
using System.Collections.Generic;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.ViewVariables;
namespace Robust.Shared.GameObjects
{
[RegisterComponent, NetworkedComponent, Access(typeof(SharedUserInterfaceSystem))]
public sealed partial class UserInterfaceComponent : Component
{
///
/// The currently open interfaces. Used clientside to store the UI.
///
[ViewVariables, Access(Friend = AccessPermissions.ReadWriteExecute, Other = AccessPermissions.ReadWriteExecute)]
public readonly Dictionary ClientOpenInterfaces = new();
[DataField]
internal Dictionary Interfaces = new();
///
/// Actors that currently have interfaces open.
///
[DataField]
public Dictionary> Actors = new();
///
/// Legacy data, new BUIs should be using comp states.
///
public Dictionary States = new();
[Serializable, NetSerializable]
internal sealed class UserInterfaceComponentState(
Dictionary> actors,
Dictionary states,
Dictionary data)
: IComponentState
{
public Dictionary> Actors = actors;
public Dictionary States = states;
public Dictionary Data = data;
}
}
[DataDefinition, Serializable, NetSerializable]
public sealed partial class InterfaceData
{
[DataField("type", required: true)]
public string ClientType { get; private set; } = default!;
///
/// Maximum range before a BUI auto-closes. A non-positive number means there is no limit.
///
[DataField]
public float InteractionRange = 2f;
// TODO BUI move to content?
// I've tried to keep the name general, but really this is a bool for: can ghosts/stunned/dead people press buttons on this UI?
///
/// Determines whether the server should verify that a client is capable of performing generic UI interactions when receiving UI messages.
///
///
/// Avoids requiring each system to individually validate client inputs. However, perhaps some BUIs are supposed to be bypass accessibility checks
///
[DataField]
public bool RequireInputValidation = true;
public InterfaceData(string type)
{
ClientType = type;
}
}
///
/// Raised whenever the server receives a BUI message from a client relating to a UI that requires input
/// validation.
///
public sealed class BoundUserInterfaceMessageAttempt(
EntityUid actor,
EntityUid target,
Enum uiKey,
BoundUserInterfaceMessage message)
: CancellableEntityEventArgs
{
public readonly EntityUid Actor = actor;
public readonly EntityUid Target = target;
public readonly Enum UiKey = uiKey;
public readonly BoundUserInterfaceMessage Message = message;
}
[NetSerializable, Serializable]
public abstract class BoundUserInterfaceState
{
}
///
/// Abstract class for local BUI events.
///
public abstract class BaseLocalBoundUserInterfaceEvent : BaseBoundUserInterfaceEvent
{
///
/// The Entity receiving the message.
/// Only set when the message is raised as a directed event.
///
public EntityUid Entity = EntityUid.Invalid;
}
///
/// Abstract class for all BUI events.
///
[Serializable, NetSerializable]
public abstract class BaseBoundUserInterfaceEvent : EntityEventArgs
{
///
/// The UI of this message.
/// Only set when the message is raised as a directed event.
///
public Enum UiKey = default!;
///
/// The session sending or receiving this message.
/// Only set when the message is raised as a directed event.
///
[NonSerialized]
public EntityUid Actor = default!;
}
///
/// Abstract class for networked BUI events.
///
[NetSerializable, Serializable]
public abstract class BoundUserInterfaceMessage : BaseBoundUserInterfaceEvent
{
///
/// The Entity receiving the message.
/// Only set when the message is raised as a directed event.
///
public NetEntity Entity { get; set; } = NetEntity.Invalid;
}
[NetSerializable, Serializable]
public sealed class OpenBoundInterfaceMessage : BoundUserInterfaceMessage
{
}
[NetSerializable, Serializable]
public sealed class CloseBoundInterfaceMessage : BoundUserInterfaceMessage
{
}
[Serializable, NetSerializable]
internal abstract class BaseBoundUIWrapMessage(NetEntity entity, BoundUserInterfaceMessage message, Enum uiKey)
: EntityEventArgs
{
public readonly NetEntity Entity = entity;
public readonly BoundUserInterfaceMessage Message = message;
public readonly Enum UiKey = uiKey;
}
///
/// Helper message raised from client to server.
///
[Serializable, NetSerializable]
internal sealed class BoundUIWrapMessage(NetEntity entity, BoundUserInterfaceMessage message, Enum uiKey)
: BaseBoundUIWrapMessage(entity, message, uiKey);
public sealed class BoundUIOpenedEvent : BaseLocalBoundUserInterfaceEvent
{
public BoundUIOpenedEvent(Enum uiKey, EntityUid uid, EntityUid actor)
{
UiKey = uiKey;
Entity = uid;
Actor = actor;
}
}
public sealed class BoundUIClosedEvent : BaseLocalBoundUserInterfaceEvent
{
public BoundUIClosedEvent(Enum uiKey, EntityUid uid, EntityUid actor)
{
UiKey = uiKey;
Entity = uid;
Actor = actor;
}
}
}