using System; using Robust.Shared.GameStates; using Robust.Shared.IoC; using Robust.Shared.Reflection; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Timing; using Robust.Shared.ViewVariables; namespace Robust.Shared.GameObjects { /// /// The base class for all ECS components. A component is a piece of data, ideally without methods, that is /// attached to or will be attached to some . Entities do not have any data without /// components to specify it. /// /// /// /// Components must be registered, usually with , for the ECS to /// recognize them. /// /// /// Components implicitly have , and are always valid for YAML ser/de. /// /// /// /// /// /// [Reflect(false)] [ImplicitDataDefinitionForInheritors] public abstract partial class Component : IComponent { [DataField("netsync")] [ViewVariables(VVAccess.ReadWrite)] private bool _netSync { get; set; } = true; internal bool Networked { get; set; } = true; bool IComponent.Networked { get => Networked; set => Networked = value; } /// public bool NetSyncEnabled { get => Networked && _netSync; set => _netSync = value; } /// [ViewVariables] [Obsolete("Update your API to allow accessing Owner through other means")] public EntityUid Owner { get; set; } = EntityUid.Invalid; [ViewVariables] public ComponentLifeStage LifeStage { get; internal set; } = ComponentLifeStage.PreAdd; ComponentLifeStage IComponent.LifeStage { get => LifeStage; set => LifeStage = value; } public virtual bool SendOnlyToOwner => false; public virtual bool SessionSpecific => false; /// [ViewVariables] public bool Initialized => LifeStage >= ComponentLifeStage.Initializing; /// [ViewVariables] public bool Running => ComponentLifeStage.Starting <= LifeStage && LifeStage <= ComponentLifeStage.Stopping; /// [ViewVariables] public bool Deleted => LifeStage >= ComponentLifeStage.Removing; /// /// This is the tick the component was created. /// [ViewVariables] public GameTick CreationTick { get; internal set; } GameTick IComponent.CreationTick { get => CreationTick; set => CreationTick = value; } /// /// Marks the component as dirty so that the network will re-sync it with clients. /// [ViewVariables] public GameTick LastModifiedTick { get; internal set; } GameTick IComponent.LastModifiedTick { get => LastModifiedTick; set => LastModifiedTick = value; } /// [Obsolete] public void Dirty(IEntityManager? entManager = null) { IoCManager.Resolve(ref entManager); entManager.Dirty(Owner, this); } // these two methods clear the LastModifiedTick/CreationTick to mark it as "not different from prototype load". // This is used as optimization in the game state system to avoid sending redundant component data. void IComponent.ClearTicks() { ClearTicks(); } private protected virtual void ClearTicks() { LastModifiedTick = GameTick.Zero; ClearCreationTick(); } void IComponent.ClearCreationTick() { ClearCreationTick(); } private protected void ClearCreationTick() { CreationTick = GameTick.Zero; } } /// /// The life stages of an ECS component. /// public enum ComponentLifeStage : byte { /// /// The component has just been allocated. /// PreAdd = 0, /// /// Currently being added to an entity. /// Adding, /// /// Has been added to an entity. /// Added, /// /// Currently being initialized. /// Initializing, /// /// Has been initialized. /// Initialized, /// /// Currently being started up. /// Starting, /// /// Has started up. /// Running, /// /// Currently shutting down. /// Stopping, /// /// Has been shut down. /// Stopped, /// /// Currently being removed from its entity. /// Removing, /// /// Removed from its entity, and is deleted. /// Deleted, } /// /// WARNING: Do not subscribe to this unless you know what you are doing! /// The component has been added to the entity. This is the first function /// to be called after the component has been allocated and (optionally) deserialized. /// [ComponentEvent] public readonly record struct ComponentAdd; /// /// Raised when all of the entity's other components have been added and are available, /// But are not necessarily initialized yet. DO NOT depend on the values of other components to be correct. /// [ComponentEvent] public sealed class ComponentInit : EntityEventArgs { } /// /// Starts up a component. This is called automatically after all components are Initialized and the entity is Initialized. /// This can be called multiple times during the component's life, and at any time. /// [ComponentEvent] public sealed class ComponentStartup : EntityEventArgs { } /// /// Shuts down the component. The is called Automatically by OnRemove. This can be called multiple times during /// the component's life, and at any time. /// [ComponentEvent] public sealed class ComponentShutdown : EntityEventArgs { } /// /// The component has been removed from the entity. This is the last function /// that is called before the component is freed. /// [ComponentEvent] public sealed class ComponentRemove : EntityEventArgs { } }