mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-15 14:52:35 +02:00
* Added new ComponentEventBus, combined it with IEventBus. * Removed all traces of IEntity from ComponentDependencies. Removed IEntityManager dependency from ComponentManager. * Added entity create/delete events to IEntityManager. * ComponentEvents now use EntitySystemMessages instead of their custom ComponentEvent class. * Component events are now just overloads of entity events. * Removed obsolete EntitySystemMessage, now everything uses the base EntityEventArgs. * Add a bool argument for if the message should be broadcast as well as directed. Fix ordering and init issues of events in EntityManager. * Changed names from Component/Entity events to Directed/Broadcast. * Fix bugs and unit tests.
294 lines
14 KiB
C#
294 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using Robust.Shared.Prototypes;
|
|
|
|
namespace Robust.Shared.GameObjects
|
|
{
|
|
/// <summary>
|
|
/// Used by <see cref="EntityPrototype" /> to determine whether a component is available.
|
|
/// This distinction is important because prototypes are shared across client and server, but the two might have different components.
|
|
/// </summary>
|
|
/// <seealso cref="IComponentFactory" />
|
|
public enum ComponentAvailability : byte
|
|
{
|
|
/// <summary>
|
|
/// The component is available and can be instantiated.
|
|
/// </summary>
|
|
Available,
|
|
|
|
/// <summary>
|
|
/// The component is not available, but should be ignored (prevent warnings for missing components).
|
|
/// </summary>
|
|
Ignore,
|
|
|
|
/// <summary>
|
|
/// The component is unknown entirely. This may warrant a warning or error.
|
|
/// </summary>
|
|
Unknown
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles the registration and spawning of components.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <p>
|
|
/// When referring to component names, this is the name the component has been registered as,
|
|
/// and what's used in prototypes. However, most commonly the type is referred through by an interface.
|
|
/// </p>
|
|
/// <p>
|
|
/// Before a component can be spawned, it must be registered so things such as name, networking ID, type, etc...
|
|
/// are known to the factory.
|
|
/// Components are registered into a registry.
|
|
/// The relevant methods for writing to this registry are <see cref="Register" /> and <see cref="RegisterReference" />.
|
|
/// The data is exposed for reading through <see cref="GetRegistration" /> and its overloads.
|
|
/// This data is returned in the form of a <see cref="IComponentRegistration" />, which represents one component's registration.
|
|
/// </p>
|
|
/// </remarks>
|
|
/// <seealso cref="IComponentRegistration" />
|
|
/// <seealso cref="IComponent" />
|
|
public interface IComponentFactory
|
|
{
|
|
event Action<IComponentRegistration> ComponentAdded;
|
|
event Action<(IComponentRegistration, Type)> ComponentReferenceAdded;
|
|
event Action<string> ComponentIgnoreAdded;
|
|
|
|
/// <summary>
|
|
/// All IComponent types that are currently registered to this factory.
|
|
/// </summary>
|
|
IEnumerable<Type> AllRegisteredTypes { get; }
|
|
|
|
/// <summary>
|
|
/// Get whether a component is available right now.
|
|
/// </summary>
|
|
/// <param name="componentName">The name of the component to check.</param>
|
|
/// <param name="ignoreCase">Whether or not to ignore casing on <see cref="componentName"/></param>
|
|
/// <returns>The availability of the component.</returns>
|
|
ComponentAvailability GetComponentAvailability(string componentName, bool ignoreCase = false);
|
|
|
|
/// <summary>
|
|
/// Registers a prototype to be available for spawning.
|
|
/// </summary>
|
|
/// <param name="overwrite">If the component already exists, will this replace it?</param>
|
|
/// <remarks>
|
|
/// This implicitly calls <see cref="RegisterReference{TTarget, TInterface}"/>
|
|
/// with a <c>TTarget</c> and <c>TInterface</c> of <typeparamref name="T"/>.
|
|
/// </remarks>
|
|
|
|
[Obsolete("Use RegisterClass and Attributes instead of the Register/RegisterReference combo")]
|
|
void Register<T>(bool overwrite = false) where T : IComponent, new();
|
|
|
|
/// <summary>
|
|
/// Registers a component class with the factory.
|
|
/// </summary>
|
|
/// <param name="overwrite">If the component already exists, will this replace it?</param>
|
|
/// <remarks>
|
|
/// Unlike <see cref="Register{T}"/>, this reads the attributes. No more Register/RegisterReference combos.
|
|
/// </remarks>
|
|
void RegisterClass<T>(bool overwrite = false) where T : IComponent, new();
|
|
|
|
/// <summary>
|
|
/// Registers a component name as being ignored.
|
|
/// </summary>
|
|
/// <param name="name">The name to be ignored.</param>
|
|
/// <param name="overwrite">Whether to overrde existing settings instead of throwing an exception in the case of duplicates.</param>
|
|
void RegisterIgnore(string name, bool overwrite = false);
|
|
|
|
// NOTE: no overwrite here, it'd overcomplicate RegisterReference a LOT.
|
|
// If you need to overwrite references for some sick reason overwrite the component too.
|
|
/// <summary>
|
|
/// Registers <typeparamref name="TTarget" /> to be referenced when
|
|
/// <typeparamref name="TInterface"/> is used in methods like <see cref="IEntity.GetComponent{T}"/>
|
|
/// </summary>
|
|
[Obsolete("Use RegisterClass and Attributes instead of the Register/RegisterReference combo")]
|
|
void RegisterReference<TTarget, TInterface>() where TTarget : TInterface, IComponent, new();
|
|
|
|
/// <summary>
|
|
/// Gets a new component instantiated of the specified type.
|
|
/// </summary>
|
|
/// <param name="componentType">type of component to make</param>
|
|
/// <returns>A Component</returns>
|
|
/// <exception cref="InvalidOperationException">
|
|
/// Thrown if no component of type <see cref="componentType"/> is registered.
|
|
/// </exception>
|
|
IComponent GetComponent(Type componentType);
|
|
|
|
/// <summary>
|
|
/// Gets a new component instantiated of the specified type.
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of component to make.</typeparam>
|
|
/// <returns>A Component</returns>
|
|
/// <exception cref="InvalidOperationException">
|
|
/// Thrown if no component of type <see cref="T"/> is registered.
|
|
/// </exception>
|
|
T GetComponent<T>() where T : IComponent, new();
|
|
|
|
/// <summary>
|
|
/// Gets a new component instantiated of the specified <see cref="IComponent.Name"/>.
|
|
/// </summary>
|
|
/// <param name="componentName">name of component to make</param>
|
|
/// <param name="ignoreCase">Whether or not to ignore casing on <see cref="componentName"/></param>
|
|
/// <returns>A Component</returns>
|
|
/// <exception cref="UnknownComponentException">
|
|
/// Thrown if no component exists with the given name <see cref="componentName"/>.
|
|
/// </exception>
|
|
IComponent GetComponent(string componentName, bool ignoreCase = false);
|
|
|
|
/// <summary>
|
|
/// Gets a new component instantiated of the specified network ID.
|
|
/// </summary>
|
|
/// <param name="netId">net id of component to make</param>
|
|
/// <returns>A Component</returns>
|
|
/// <exception cref="UnknownComponentException">
|
|
/// Thrown if no component exists with the given id <see cref="netId"/>.
|
|
/// </exception>
|
|
IComponent GetComponent(uint netId);
|
|
|
|
/// <summary>
|
|
/// Gets the registration belonging to a component, throwing an exception if it does not exist.
|
|
/// </summary>
|
|
/// <param name="componentName">The name of the component.</param>
|
|
/// <param name="ignoreCase">Whether or not to ignore casing on <see cref="componentName"/></param>
|
|
/// <exception cref="UnknownComponentException">
|
|
/// Thrown if no component exists with the given name <see cref="componentName"/>.
|
|
/// </exception>
|
|
IComponentRegistration GetRegistration(string componentName, bool ignoreCase = false);
|
|
|
|
/// <summary>
|
|
/// Gets the registration belonging to a component, throwing an exception if it does not exist.
|
|
/// </summary>
|
|
/// <param name="reference">The type of the component to lookup.</param>
|
|
/// <exception cref="UnknownComponentException">
|
|
/// Thrown if no component exists of type <see cref="reference"/>.
|
|
/// </exception>
|
|
IComponentRegistration GetRegistration(Type reference);
|
|
|
|
/// <summary>
|
|
/// Gets the registration belonging to a component, throwing an exception if it does not exist.
|
|
/// </summary>
|
|
/// <typeparam name="T">A type referencing the component.</typeparam>
|
|
/// <exception cref="UnknownComponentException">
|
|
/// Thrown if no component of type <see cref="T"/> exists.
|
|
/// </exception>
|
|
IComponentRegistration GetRegistration<T>() where T : IComponent, new();
|
|
|
|
/// <summary>
|
|
/// Gets the registration belonging to a component, throwing an
|
|
/// exception if it does not exist.
|
|
/// </summary>
|
|
/// <param name="netID">The network ID corresponding to the component.</param>
|
|
/// <returns></returns>
|
|
/// <exception cref="UnknownComponentException">
|
|
/// Thrown if no component with id <see cref="netID"/> exists.
|
|
/// </exception>
|
|
IComponentRegistration GetRegistration(uint netID);
|
|
|
|
/// <summary>
|
|
/// Gets the registration of a component, throwing an exception if
|
|
/// it does not exist.
|
|
/// </summary>
|
|
/// <param name="component">An instance of the component.</param>
|
|
/// <returns></returns>
|
|
/// <exception cref="UnknownComponentException">
|
|
/// Thrown if no registration exists for component <see cref="component"/>.
|
|
/// </exception>
|
|
IComponentRegistration GetRegistration(IComponent component);
|
|
|
|
/// <summary>
|
|
/// Tries to get the registration belonging to a component.
|
|
/// </summary>
|
|
/// <param name="componentName">The name of the component.</param>
|
|
/// <param name="registration">The registration if found, null otherwise.</param>
|
|
/// <param name="ignoreCase">Whether or not to ignore casing on <see cref="componentName"/></param>
|
|
/// <returns>true it found, false otherwise.</returns>
|
|
bool TryGetRegistration(string componentName, [NotNullWhen(true)] out IComponentRegistration? registration, bool ignoreCase = false);
|
|
|
|
/// <summary>
|
|
/// Tries to get the registration belonging to a component.
|
|
/// </summary>
|
|
/// <param name="reference">A reference corresponding to the component to look up.</param>
|
|
/// <param name="registration">The registration if found, null otherwise.</param>
|
|
/// <returns>true it found, false otherwise.</returns>
|
|
bool TryGetRegistration(Type reference, [NotNullWhen(true)] out IComponentRegistration? registration);
|
|
|
|
/// <summary>
|
|
/// Tries to get the registration belonging to a component.
|
|
/// </summary>
|
|
/// <typeparam name="T">A type referencing the component.</typeparam>
|
|
/// <param name="registration">The registration if found, null otherwise.</param>
|
|
/// <returns>true it found, false otherwise.</returns>
|
|
bool TryGetRegistration<T>([NotNullWhen(true)] out IComponentRegistration? registration) where T : IComponent, new();
|
|
|
|
/// <summary>
|
|
/// Tries to get the registration belonging to a component.
|
|
/// </summary>
|
|
/// <param name="netID">The network ID corresponding to the component.</param>
|
|
/// <param name="registration">The registration if found, null otherwise.</param>
|
|
/// <returns>true it found, false otherwise.</returns>
|
|
bool TryGetRegistration(uint netID, [NotNullWhen(true)] out IComponentRegistration? registration);
|
|
|
|
/// <summary>
|
|
/// Tries to get the registration of a component.
|
|
/// </summary>
|
|
/// <param name="component">An instance of the component.</param>
|
|
/// <param name="registration">The registration if found, null otherwise.</param>
|
|
/// <returns>true it found, false otherwise.</returns>
|
|
bool TryGetRegistration(IComponent component, [NotNullWhen(true)] out IComponentRegistration? registration);
|
|
|
|
/// <summary>
|
|
/// Automatically create registrations for all components with a <see cref="RegisterComponentAttribute" />
|
|
/// </summary>
|
|
void DoAutoRegistrations();
|
|
|
|
IEnumerable<Type> GetAllRefTypes();
|
|
|
|
IEnumerable<uint> GetAllNetIds();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a component registered into a <see cref="IComponentFactory" />.
|
|
/// </summary>
|
|
/// <seealso cref="IComponentFactory" />
|
|
/// <seealso cref="IComponent" />
|
|
public interface IComponentRegistration
|
|
{
|
|
/// <summary>
|
|
/// The name of the component.
|
|
/// This is used as the <c>type</c> field in the component declarations if entity prototypes.
|
|
/// </summary>
|
|
/// <seealso cref="IComponent.Name" />
|
|
string Name { get; }
|
|
|
|
/// <summary>
|
|
/// ID used to reference the component type across the network.
|
|
/// If null, no network synchronization will be available for this component.
|
|
/// </summary>
|
|
/// <seealso cref="IComponent.NetID" />
|
|
uint? NetID { get; }
|
|
|
|
/// <summary>
|
|
/// True if the addition and removal of the component will be synchronized to clients.
|
|
/// This means that if the server adds or removes the component outside of prototype-based creation,
|
|
/// the client will update accordingly.
|
|
/// If false the client will ignore missing components even when the net ID checks out and could be instantiated.
|
|
/// and the client won't delete the component if no state was sent for it.
|
|
/// </summary>
|
|
/// <seealso cref="IComponent.NetworkSynchronizeExistence" />
|
|
bool NetworkSynchronizeExistence { get; }
|
|
|
|
/// <summary>
|
|
/// The type that will be instantiated if this component is created.
|
|
/// </summary>
|
|
Type Type { get; }
|
|
|
|
/// <summary>
|
|
/// A list of type references that can be used to get a reference to an instance of this component,
|
|
/// for methods like <see cref="IEntity.GetComponent{T}" />.
|
|
/// These are not unique and can overlap with other components.
|
|
/// Unlike the other properties, this data is not gotten from a component instance,
|
|
/// instead this data is set with <see cref="IComponentFactory.RegisterReference{TTarget, TInterface}" />
|
|
/// </summary>
|
|
IReadOnlyList<Type> References { get; }
|
|
}
|
|
}
|