2019-12-16 10:17:39 +00:00
using System ;
2019-06-15 07:39:08 +00:00
using System.Reflection ;
2019-06-15 00:51:06 +00:00
using System.Collections.Generic ;
2019-06-17 01:11:35 +00:00
using System.Linq ;
2019-06-24 19:14:37 +00:00
using Encompass.Exceptions ;
2019-12-29 05:39:35 +00:00
using MoonTools.FastCollections ;
2019-06-15 00:51:06 +00:00
2019-06-16 01:05:56 +00:00
namespace Encompass
{
2019-10-24 19:48:36 +00:00
/// <summary>
/// Engines are the Encompass notion of an ECS System.
/// They are responsible for reading the World state, reading messages, emitting messages, and creating or mutating Entities and Components.
/// Engines run once per World Update.
/// </summary>
2019-10-24 20:13:43 +00:00
public abstract class Engine : IEquatable < Engine >
2019-06-16 01:05:56 +00:00
{
2020-03-20 07:09:57 +00:00
internal Guid _id ;
2019-10-24 20:13:43 +00:00
2020-03-20 07:09:57 +00:00
internal readonly HashSet < Type > ReadTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > ReadImmediateTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > SendTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > ReceiveTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > WriteTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > WriteImmediateTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > QueryWithTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > QueryWithoutTypes = new HashSet < Type > ( ) ;
internal readonly Dictionary < Type , int > WritePriorities = new Dictionary < Type , int > ( ) ;
internal readonly int DefaultWritePriority = 0 ;
2019-06-15 07:39:08 +00:00
2019-11-21 21:53:33 +00:00
/// <summary>
2019-12-05 20:10:33 +00:00
/// If false, the Engine will ignore time dilation.
2019-11-21 21:53:33 +00:00
/// </summary>
2020-03-20 07:09:57 +00:00
internal bool _usesTimeDilation = true ;
public bool TimeDilationActive { get = > _usesTimeDilation & & _timeManager . TimeDilationActive ; }
2019-11-21 21:53:33 +00:00
2020-03-20 07:09:57 +00:00
private EntityManager _entityManager ;
private MessageManager _messageManager ;
private ComponentManager _componentManager ;
private TimeManager _timeManager ;
private TrackingManager _trackingManager ;
2019-06-15 00:51:06 +00:00
2020-03-20 07:09:57 +00:00
private EntitySetQuery _entityQuery ;
2019-12-23 02:13:35 +00:00
2020-03-20 07:09:57 +00:00
private readonly HashSet < int > _trackedEntities = new HashSet < int > ( ) ;
2019-12-29 21:54:08 +00:00
protected IEnumerable < Entity > TrackedEntities
{
get
{
foreach ( var entityID in _trackedEntities )
{
2020-03-20 07:09:57 +00:00
yield return _entityManager . GetEntity ( entityID ) ;
2019-12-29 21:54:08 +00:00
}
}
}
2019-12-28 21:53:02 +00:00
2020-03-20 07:09:57 +00:00
private readonly HashSet < int > _newlyCreatedEntities = new HashSet < int > ( ) ;
2020-03-17 02:00:42 +00:00
2019-06-20 17:46:15 +00:00
protected Engine ( )
2019-06-16 01:05:56 +00:00
{
2020-03-20 07:09:57 +00:00
_id = Guid . NewGuid ( ) ;
2019-10-24 20:13:43 +00:00
2019-07-19 19:47:17 +00:00
var sendsAttribute = GetType ( ) . GetCustomAttribute < Sends > ( false ) ;
if ( sendsAttribute ! = null )
2019-06-16 01:55:35 +00:00
{
2020-03-20 07:09:57 +00:00
SendTypes = sendsAttribute . SendTypes ;
2019-07-19 19:47:17 +00:00
}
2019-12-24 03:04:26 +00:00
var activatesAttribute = GetType ( ) . GetCustomAttribute < WritesImmediate > ( false ) ;
2019-07-19 19:47:17 +00:00
if ( activatesAttribute ! = null )
{
2020-03-20 07:09:57 +00:00
WriteImmediateTypes = activatesAttribute . WriteImmediateTypes ;
2019-07-19 19:47:17 +00:00
}
2019-12-06 08:36:54 +00:00
var defaultWritePriorityAttribute = GetType ( ) . GetCustomAttribute < DefaultWritePriority > ( false ) ;
if ( defaultWritePriorityAttribute ! = null )
{
2020-03-20 07:09:57 +00:00
DefaultWritePriority = defaultWritePriorityAttribute . WritePriority ;
2019-12-06 08:36:54 +00:00
}
2019-12-06 03:55:17 +00:00
foreach ( var writesAttribute in GetType ( ) . GetCustomAttributes < Writes > ( false ) )
2019-07-20 00:50:13 +00:00
{
2020-03-20 07:09:57 +00:00
WriteTypes . UnionWith ( writesAttribute . WriteTypes ) ;
WritePriorities = new Dictionary < Type , int > [ 2 ] { WritePriorities , writesAttribute . Priorities } . SelectMany ( dict = > dict ) . ToDictionary ( pair = > pair . Key , pair = > pair . Value ) ;
2019-07-20 00:50:13 +00:00
}
2019-07-19 19:47:17 +00:00
var receivesAttribute = GetType ( ) . GetCustomAttribute < Receives > ( false ) ;
if ( receivesAttribute ! = null )
{
2020-03-20 07:09:57 +00:00
ReceiveTypes = receivesAttribute . ReceiveTypes ;
2019-06-16 01:55:35 +00:00
}
2019-06-20 03:37:46 +00:00
var readsAttribute = GetType ( ) . GetCustomAttribute < Reads > ( false ) ;
2019-06-16 01:55:35 +00:00
if ( readsAttribute ! = null )
{
2020-03-20 07:09:57 +00:00
ReadTypes = readsAttribute . ReadTypes ;
2019-06-16 01:55:35 +00:00
}
2019-07-23 17:17:53 +00:00
2019-12-24 03:04:26 +00:00
var readsImmediateAttribute = GetType ( ) . GetCustomAttribute < ReadsImmediate > ( false ) ;
if ( readsImmediateAttribute ! = null )
2019-07-23 17:17:53 +00:00
{
2020-03-20 07:09:57 +00:00
ReadImmediateTypes = readsImmediateAttribute . ReadImmediateTypes ;
2019-07-23 17:17:53 +00:00
}
2019-12-23 02:13:35 +00:00
var queryWithAttribute = GetType ( ) . GetCustomAttribute < QueryWith > ( false ) ;
if ( queryWithAttribute ! = null )
{
2020-03-20 21:13:26 +00:00
QueryWithTypes = queryWithAttribute . QueryWithTypes ;
2019-12-23 02:13:35 +00:00
}
2020-07-12 22:17:38 +00:00
foreach ( var queryType in QueryWithTypes )
{
ReadTypes . Add ( queryType ) ;
}
2019-12-23 02:13:35 +00:00
var queryWithoutAttribute = GetType ( ) . GetCustomAttribute < QueryWithout > ( false ) ;
if ( queryWithoutAttribute ! = null )
{
2020-03-20 07:09:57 +00:00
QueryWithoutTypes = queryWithoutAttribute . QueryWithoutTypes ;
2019-12-23 02:13:35 +00:00
}
2020-07-12 22:17:38 +00:00
foreach ( var queryType in QueryWithoutTypes )
{
ReadTypes . Add ( queryType ) ;
}
2019-06-15 07:39:08 +00:00
}
2019-10-24 20:13:43 +00:00
public override bool Equals ( object obj )
{
2019-12-06 06:32:09 +00:00
if ( obj is Engine engine )
2019-10-24 20:13:43 +00:00
{
2019-12-06 06:32:09 +00:00
return Equals ( engine ) ;
2019-10-24 20:13:43 +00:00
}
return false ;
}
public bool Equals ( Engine other )
{
2020-03-20 07:09:57 +00:00
return other . _id = = _id ;
2019-10-24 20:13:43 +00:00
}
public override int GetHashCode ( )
{
2020-03-20 07:09:57 +00:00
return HashCode . Combine ( _id ) ;
2019-10-24 20:13:43 +00:00
}
2019-06-16 01:05:56 +00:00
internal void AssignEntityManager ( EntityManager entityManager )
{
2020-03-20 07:09:57 +00:00
_entityManager = entityManager ;
2019-06-15 00:51:06 +00:00
}
2019-06-16 01:05:56 +00:00
internal void AssignComponentManager ( ComponentManager componentManager )
{
2020-03-20 07:09:57 +00:00
_componentManager = componentManager ;
2019-06-15 00:51:06 +00:00
}
2019-06-16 01:55:35 +00:00
internal void AssignMessageManager ( MessageManager messageManager )
{
2020-03-20 07:09:57 +00:00
_messageManager = messageManager ;
2019-06-16 01:55:35 +00:00
}
2019-11-21 21:53:33 +00:00
internal void AssignTimeManager ( TimeManager timeManager )
{
2020-03-20 07:09:57 +00:00
_timeManager = timeManager ;
2019-11-21 21:53:33 +00:00
}
2019-12-28 21:53:02 +00:00
internal void AssignTrackingManager ( TrackingManager trackingManager )
{
2020-03-20 07:09:57 +00:00
_trackingManager = trackingManager ;
2019-12-28 21:53:02 +00:00
}
2020-03-17 02:00:42 +00:00
internal void CheckMessageRead < TMessage > ( ) where TMessage : struct , IMessage
{
2020-03-20 07:09:57 +00:00
if ( ! ReceiveTypes . Contains ( typeof ( TMessage ) ) )
2020-03-17 02:00:42 +00:00
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Message {1}" , this . GetType ( ) . Name , typeof ( TMessage ) . Name ) ;
}
}
private bool EntityCreatedThisFrame ( int entityID )
{
return _newlyCreatedEntities . Contains ( entityID ) ;
}
2020-03-17 22:29:16 +00:00
internal void ClearNewlyCreatedEntities ( )
{
_newlyCreatedEntities . Clear ( ) ;
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Runs once per World update with the calculated delta-time.
/// </summary>
/// <param name="dt">The time in seconds that has elapsed since the previous frame.</param>
2019-06-24 19:14:37 +00:00
public abstract void Update ( double dt ) ;
2019-06-15 00:51:06 +00:00
2019-10-24 19:48:36 +00:00
/// <summary>
/// Creates and returns a new empty Entity.
/// </summary>
2019-06-16 01:05:56 +00:00
protected Entity CreateEntity ( )
{
2020-03-20 07:09:57 +00:00
var entity = _entityManager . CreateEntity ( ) ;
2020-03-17 02:00:42 +00:00
_newlyCreatedEntities . Add ( entity . ID ) ;
return entity ;
2019-06-20 03:37:46 +00:00
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Returns true if an Entity with the specified ID exists.
/// </summary>
2020-03-23 02:10:28 +00:00
protected bool EntityExists ( in Entity entity )
2019-07-13 00:37:31 +00:00
{
2020-03-20 07:09:57 +00:00
return _entityManager . EntityExists ( entity . ID ) ;
2019-07-13 00:37:31 +00:00
}
2020-03-18 00:40:11 +00:00
/// <summary>
/// Returns true if an Entity with the specified ID exists.
/// </summary>
protected bool EntityExists ( int entityID )
{
2020-03-20 07:09:57 +00:00
return _entityManager . EntityExists ( entityID ) ;
2020-03-18 00:40:11 +00:00
}
2019-10-24 19:48:36 +00:00
/// <summary>
2019-11-17 18:48:39 +00:00
/// Returns all Entities containing the specified Component type.
2019-10-24 19:48:36 +00:00
/// </summary>
2020-11-16 07:21:51 +00:00
protected ReadOnlySpan < Entity > ReadEntities < TComponent > ( ) where TComponent : struct , IComponent
2019-07-20 21:10:06 +00:00
{
2020-03-20 07:09:57 +00:00
var immediateRead = ReadImmediateTypes . Contains ( typeof ( TComponent ) ) ;
var existingRead = ReadTypes . Contains ( typeof ( TComponent ) ) ;
2019-12-24 03:04:26 +00:00
if ( existingRead & & immediateRead )
2019-07-20 21:10:06 +00:00
{
2020-03-23 02:10:28 +00:00
return _componentManager . GetExistingAndImmediateEntities < TComponent > ( ) ;
2019-07-20 21:10:06 +00:00
}
2019-07-23 17:17:53 +00:00
else if ( existingRead )
{
2020-03-23 02:10:28 +00:00
return _componentManager . GetExistingEntities < TComponent > ( ) ;
2019-07-23 17:17:53 +00:00
}
2019-12-24 03:04:26 +00:00
else if ( immediateRead )
2019-07-23 17:17:53 +00:00
{
2020-03-23 02:10:28 +00:00
return _componentManager . GetImmediateEntities < TComponent > ( ) ;
2019-07-23 17:17:53 +00:00
}
2019-07-20 21:10:06 +00:00
else
2019-07-18 21:02:57 +00:00
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
}
2019-07-20 21:10:06 +00:00
}
2019-07-18 21:02:57 +00:00
2020-03-23 02:20:55 +00:00
/// <summary>
/// Returns an Entity containing the specified Component type.
/// </summary>
2020-03-25 04:28:56 +00:00
protected ref readonly Entity ReadEntity < TComponent > ( ) where TComponent : struct , IComponent
2020-03-23 02:20:55 +00:00
{
var immediateRead = ReadImmediateTypes . Contains ( typeof ( TComponent ) ) ;
var existingRead = ReadTypes . Contains ( typeof ( TComponent ) ) ;
if ( existingRead & & immediateRead )
{
return ref _componentManager . ExistingOrImmediateSingularEntity < TComponent > ( ) ;
}
else if ( existingRead )
{
return ref _componentManager . ExistingSingularEntity < TComponent > ( ) ;
}
else if ( immediateRead )
{
return ref _componentManager . ImmediateSingularEntity < TComponent > ( ) ;
}
else
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
}
}
2019-10-24 19:48:36 +00:00
/// <summary>
2019-11-21 03:01:29 +00:00
/// Returns all of the Components with the specified Component Type.
2019-11-14 04:08:11 +00:00
/// </summary>
2020-11-16 07:21:51 +00:00
protected ReadOnlySpan < TComponent > ReadComponents < TComponent > ( ) where TComponent : struct , IComponent
2019-11-14 04:08:11 +00:00
{
2020-03-23 02:10:28 +00:00
var immediateRead = ReadImmediateTypes . Contains ( typeof ( TComponent ) ) ;
var existingRead = ReadTypes . Contains ( typeof ( TComponent ) ) ;
if ( existingRead & & immediateRead )
2019-12-17 04:40:15 +00:00
{
2020-03-23 02:10:28 +00:00
return _componentManager . ReadExistingAndImmediateComponentsByType < TComponent > ( ) ;
2019-12-17 04:40:15 +00:00
}
2020-03-23 02:10:28 +00:00
else if ( existingRead )
{
return _componentManager . GetExistingComponents < TComponent > ( ) ;
}
else if ( immediateRead )
{
return _componentManager . ReadImmediateComponentsByType < TComponent > ( ) ;
}
else
2019-12-24 02:45:49 +00:00
{
2020-03-23 02:10:28 +00:00
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
2019-12-24 02:45:49 +00:00
}
2019-11-21 03:01:29 +00:00
}
2020-03-23 02:10:28 +00:00
/// <summary>
/// Returns a Component with the specified Component Type. If multiples exist, an arbitrary Component is returned.
/// </summary>
2020-03-25 04:28:56 +00:00
protected ref readonly TComponent ReadComponent < TComponent > ( ) where TComponent : struct , IComponent
2019-07-20 21:10:06 +00:00
{
2020-03-20 07:09:57 +00:00
var immediateRead = ReadImmediateTypes . Contains ( typeof ( TComponent ) ) ;
var existingRead = ReadTypes . Contains ( typeof ( TComponent ) ) ;
2019-12-24 03:04:26 +00:00
if ( existingRead & & immediateRead )
2019-08-01 23:24:57 +00:00
{
2020-03-23 02:10:28 +00:00
return ref _componentManager . ExistingOrImmediateSingular < TComponent > ( ) ;
2019-08-01 23:24:57 +00:00
}
else if ( existingRead )
{
2020-03-23 02:10:28 +00:00
return ref _componentManager . ExistingSingular < TComponent > ( ) ;
2019-08-01 23:24:57 +00:00
}
2019-12-24 03:04:26 +00:00
else if ( immediateRead )
2019-08-01 23:24:57 +00:00
{
2020-03-23 02:10:28 +00:00
return ref _componentManager . ImmediateSingular < TComponent > ( ) ;
2019-08-01 23:24:57 +00:00
}
else
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
}
2019-07-19 19:47:17 +00:00
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Returns true if any Component with the specified Component Type exists.
/// </summary>
2020-03-25 04:28:56 +00:00
protected bool SomeComponent < TComponent > ( ) where TComponent : struct , IComponent
2019-07-19 19:47:17 +00:00
{
2020-03-20 07:09:57 +00:00
var immediateRead = ReadImmediateTypes . Contains ( typeof ( TComponent ) ) ;
var existingRead = ReadTypes . Contains ( typeof ( TComponent ) ) ;
2019-12-24 03:04:26 +00:00
if ( existingRead & & immediateRead )
2019-08-01 23:24:57 +00:00
{
2020-03-20 07:09:57 +00:00
return _componentManager . SomeExistingOrImmediateComponent < TComponent > ( ) ;
2019-08-01 23:24:57 +00:00
}
else if ( existingRead )
{
2020-03-20 07:09:57 +00:00
return _componentManager . SomeExistingComponent < TComponent > ( ) ;
2019-08-01 23:24:57 +00:00
}
2019-12-24 03:04:26 +00:00
else if ( immediateRead )
2019-08-01 23:24:57 +00:00
{
2020-03-20 07:09:57 +00:00
return _componentManager . SomeImmediateComponent < TComponent > ( ) ;
2019-08-01 23:24:57 +00:00
}
else
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
}
2019-07-19 19:47:17 +00:00
}
2020-03-25 04:28:56 +00:00
private ref TComponent GetComponentHelper < TComponent > ( int entityID ) where TComponent : struct , IComponent
2019-07-17 18:24:21 +00:00
{
2020-03-20 07:09:57 +00:00
var immediateRead = ReadImmediateTypes . Contains ( typeof ( TComponent ) ) ;
var existingRead = ReadTypes . Contains ( typeof ( TComponent ) ) ;
2019-12-24 03:04:26 +00:00
if ( existingRead & & immediateRead )
2019-08-01 23:24:57 +00:00
{
2020-03-20 07:09:57 +00:00
return ref _componentManager . ReadImmediateOrExistingComponentByEntityAndType < TComponent > ( entityID ) ;
2019-08-01 23:24:57 +00:00
}
else if ( existingRead )
{
2020-03-20 07:09:57 +00:00
return ref _componentManager . ReadExistingComponentByEntityAndType < TComponent > ( entityID ) ;
2019-08-01 23:24:57 +00:00
}
2019-12-24 03:04:26 +00:00
else if ( immediateRead )
2019-08-01 23:24:57 +00:00
{
2020-03-20 07:09:57 +00:00
return ref _componentManager . ReadImmediateComponentByEntityAndType < TComponent > ( entityID ) ;
2019-08-01 23:24:57 +00:00
}
else
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
}
2019-07-17 18:24:21 +00:00
}
2019-11-13 21:24:20 +00:00
/// <summary>
/// Returns a Component with the specified Type that exists on the Entity.
/// </summary>
/// <exception cref="Encompass.Exceptions.NoComponentOfTypeOnEntityException">
/// Thrown when the Entity does not have a Component of the specified Type
/// </exception>
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it reads the given Component Type.
/// </exception>
2020-03-25 04:28:56 +00:00
protected ref readonly TComponent GetComponent < TComponent > ( in Entity entity ) where TComponent : struct , IComponent
2019-11-21 03:01:29 +00:00
{
2020-03-19 22:44:04 +00:00
return ref GetComponentHelper < TComponent > ( entity . ID ) ;
2019-11-21 03:01:29 +00:00
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Returns true if the Entity has a Component of the given Type.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that is Reads the given Component Type.
/// </exception>
2020-03-25 04:28:56 +00:00
protected bool HasComponent < TComponent > ( in Entity entity ) where TComponent : struct , IComponent
2019-07-17 18:24:21 +00:00
{
2020-03-20 07:09:57 +00:00
var immediateRead = ReadImmediateTypes . Contains ( typeof ( TComponent ) ) ;
var existingRead = ReadTypes . Contains ( typeof ( TComponent ) ) ;
2019-08-01 23:24:57 +00:00
2019-12-24 03:04:26 +00:00
if ( immediateRead & & existingRead )
2019-08-01 23:24:57 +00:00
{
2020-03-20 07:09:57 +00:00
return _componentManager . HasExistingOrImmediateComponent < TComponent > ( entity . ID ) ;
2019-08-01 23:24:57 +00:00
}
else if ( existingRead )
{
2020-03-20 07:09:57 +00:00
return _componentManager . HasExistingComponent < TComponent > ( entity . ID ) ;
2019-08-01 23:24:57 +00:00
}
2019-12-24 03:04:26 +00:00
else if ( immediateRead )
2019-08-01 23:24:57 +00:00
{
2020-03-20 07:09:57 +00:00
return _componentManager . HasImmediateComponent < TComponent > ( entity . ID ) ;
2019-08-01 23:24:57 +00:00
}
else
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
}
2019-07-17 18:24:21 +00:00
}
2019-11-13 21:15:43 +00:00
/// <summary>
/// Returns true if the Entity has a Component of the given Type.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that is Reads the given Component Type.
/// </exception>
2020-03-23 02:10:28 +00:00
protected bool HasComponent ( in Entity entity , Type type )
2019-11-13 21:15:43 +00:00
{
2020-03-20 07:09:57 +00:00
var immediateRead = ReadImmediateTypes . Contains ( type ) ;
var existingRead = ReadTypes . Contains ( type ) ;
2019-11-13 21:15:43 +00:00
2019-12-24 03:04:26 +00:00
if ( immediateRead & & existingRead )
2019-11-13 21:15:43 +00:00
{
2020-03-20 07:09:57 +00:00
return _componentManager . HasExistingOrImmediateComponent ( entity . ID , type ) ;
2019-11-13 21:15:43 +00:00
}
else if ( existingRead )
{
2020-03-20 07:09:57 +00:00
return _componentManager . HasExistingComponent ( entity . ID , type ) ;
2019-11-13 21:15:43 +00:00
}
2019-12-24 03:04:26 +00:00
else if ( immediateRead )
2019-11-13 21:15:43 +00:00
{
2020-03-20 07:09:57 +00:00
return _componentManager . HasImmediateComponent ( entity . ID , type ) ;
2019-11-13 21:15:43 +00:00
}
else
{
throw new IllegalReadException ( "Engine {0} tried to read undeclared Component {1}" , GetType ( ) . Name , type . Name ) ;
}
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Sets Component data for the specified Component Type on the specified Entity. If Component data for this Type already existed on the Entity, the component data is overwritten.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalWriteException">
/// Thrown when the Engine does not declare that it Writes the given Component Type.
/// </exception>
2020-03-25 04:28:56 +00:00
protected void SetComponent < TComponent > ( in Entity entity , in TComponent component ) where TComponent : struct , IComponent
2019-06-16 01:05:56 +00:00
{
2020-03-20 07:09:57 +00:00
var priority = WritePriorities . ContainsKey ( typeof ( TComponent ) ) ? WritePriorities [ typeof ( TComponent ) ] : DefaultWritePriority ;
2019-08-21 02:25:59 +00:00
2020-03-20 07:09:57 +00:00
if ( ! WriteTypes . Contains ( typeof ( TComponent ) ) )
2019-07-20 00:50:13 +00:00
{
2019-08-21 02:25:59 +00:00
throw new IllegalWriteException ( "Engine {0} tried to update undeclared Component {1}" , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
2019-07-20 00:50:13 +00:00
}
2019-12-06 08:36:54 +00:00
bool written ;
2020-03-20 07:09:57 +00:00
if ( WriteImmediateTypes . Contains ( typeof ( TComponent ) ) )
2019-08-21 02:25:59 +00:00
{
2020-03-20 07:09:57 +00:00
written = _componentManager . AddImmediateComponent ( entity . ID , component , priority ) ;
2019-12-28 22:30:26 +00:00
if ( written )
{
2020-03-20 07:09:57 +00:00
_trackingManager . ImmediateUpdateTracking ( entity . ID , typeof ( TComponent ) ) ;
2019-12-28 22:30:26 +00:00
}
2019-08-21 02:25:59 +00:00
}
2019-12-05 23:14:28 +00:00
else
{
2020-03-20 07:09:57 +00:00
written = _componentManager . UpdateComponent ( entity . ID , component , priority ) ;
2019-12-05 23:14:28 +00:00
}
2019-08-21 02:25:59 +00:00
2020-03-20 07:09:57 +00:00
if ( ! _componentManager . HasExistingComponent < TComponent > ( entity . ID ) )
2019-12-28 21:53:02 +00:00
{
2020-03-20 07:09:57 +00:00
_trackingManager . RegisterAddition ( entity . ID , typeof ( TComponent ) ) ;
2019-12-28 21:53:02 +00:00
}
2019-12-06 08:36:54 +00:00
if ( written & & component is IDrawableComponent drawableComponent )
2019-08-21 02:25:59 +00:00
{
2020-03-20 07:58:33 +00:00
_componentManager . RegisterDrawableComponent < TComponent > ( entity . ID , drawableComponent . Layer ) ;
2019-08-21 02:25:59 +00:00
}
2019-06-15 07:39:08 +00:00
}
2019-06-16 01:55:35 +00:00
2020-03-17 02:00:42 +00:00
/// <summary>
/// An alternative to SetComponent that can be used for new Entities and does not require setting write priority.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalWriteException">
/// Thrown when the Engine does not declare that it Writes the given Component Type.
/// </exception>
2020-03-25 04:28:56 +00:00
protected void AddComponent < TComponent > ( in Entity entity , in TComponent component ) where TComponent : struct , IComponent
2020-03-17 02:00:42 +00:00
{
2020-03-18 21:23:08 +00:00
if ( ! EntityCreatedThisFrame ( entity . ID ) )
2020-03-17 02:00:42 +00:00
{
throw new IllegalWriteException ( "AddComponent used on Entity that was not created in this context. Use SetComponent instead." ) ;
}
2020-03-20 07:09:57 +00:00
if ( WriteImmediateTypes . Contains ( typeof ( TComponent ) ) )
2020-03-17 22:29:16 +00:00
{
2020-03-20 07:09:57 +00:00
_componentManager . AddImmediateComponent ( entity . ID , component ) ;
_trackingManager . ImmediateUpdateTracking ( entity . ID , typeof ( TComponent ) ) ;
2020-03-17 22:29:16 +00:00
}
else
{
2020-03-20 07:09:57 +00:00
_componentManager . AddComponent ( entity . ID , component ) ;
2020-03-17 22:29:16 +00:00
}
2020-03-20 07:09:57 +00:00
_trackingManager . RegisterAddition ( entity . ID , typeof ( TComponent ) ) ;
2020-03-17 02:00:42 +00:00
if ( component is IDrawableComponent drawableComponent )
{
2020-03-20 07:58:33 +00:00
_componentManager . RegisterDrawableComponent < TComponent > ( entity . ID , drawableComponent . Layer ) ;
2020-03-17 02:00:42 +00:00
}
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Sends a Message.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalSendException">
/// Thrown when the Engine does not declare that it Sends the Message Type.
/// </exception>
2020-03-22 20:41:55 +00:00
protected void SendMessage < TMessage > ( in TMessage message ) where TMessage : struct , IMessage
2019-06-16 01:55:35 +00:00
{
2020-03-20 07:09:57 +00:00
if ( ! SendTypes . Contains ( typeof ( TMessage ) ) )
2019-06-16 01:55:35 +00:00
{
2019-07-20 00:50:13 +00:00
throw new IllegalSendException ( "Engine {0} tried to send undeclared Message {1}" , GetType ( ) . Name , typeof ( TMessage ) . Name ) ;
2019-06-16 01:55:35 +00:00
}
2019-07-16 18:17:07 +00:00
2020-03-20 07:09:57 +00:00
_messageManager . AddMessage ( message ) ;
2019-06-16 01:55:35 +00:00
}
2019-10-24 19:48:36 +00:00
/// <summary>
2019-11-21 22:22:10 +00:00
/// Sends a message after the specified number of seconds, respecting time dilation.
2019-10-24 19:48:36 +00:00
/// </summary>
/// <param name="time">The time in seconds that will elapse before the message is sent.</param>
2020-03-22 20:41:55 +00:00
protected void SendMessage < TMessage > ( in TMessage message , double time ) where TMessage : struct , IMessage
2019-08-20 02:05:18 +00:00
{
2020-03-20 07:09:57 +00:00
_messageManager . AddMessage ( message , time ) ;
2019-08-20 02:05:18 +00:00
}
2019-11-21 22:22:10 +00:00
/// <summary>
/// Sends a message after the specified number of seconds, ignoring time dilation.
/// </summary>
/// <param name="time">The time in seconds that will elapse before the message is sent.</param>
2020-03-22 20:41:55 +00:00
protected void SendMessageIgnoringTimeDilation < TMessage > ( in TMessage message , double time ) where TMessage : struct , IMessage
2019-11-21 22:22:10 +00:00
{
2020-03-20 07:09:57 +00:00
_messageManager . AddMessageIgnoringTimeDilation ( message , time ) ;
2019-07-29 05:25:34 +00:00
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Reads all messages of the specified Type.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it Receives the specified Message Type.
/// </exception>
2020-11-16 07:21:51 +00:00
protected ReadOnlySpan < TMessage > ReadMessages < TMessage > ( ) where TMessage : struct , IMessage
2019-06-16 01:55:35 +00:00
{
2020-03-17 02:00:42 +00:00
CheckMessageRead < TMessage > ( ) ;
2020-03-20 07:09:57 +00:00
return _messageManager . GetMessagesByType < TMessage > ( ) ;
2019-06-16 01:55:35 +00:00
}
2019-06-17 01:11:35 +00:00
2019-10-24 19:48:36 +00:00
/// <summary>
/// Reads an arbitrary message of the specified Type.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it Receives the specified Message Type.
/// </exception>
2020-03-22 21:24:59 +00:00
protected ref readonly TMessage ReadMessage < TMessage > ( ) where TMessage : struct , IMessage
2019-07-18 21:02:57 +00:00
{
2020-03-17 02:00:42 +00:00
CheckMessageRead < TMessage > ( ) ;
2020-03-22 21:24:59 +00:00
return ref _messageManager . First < TMessage > ( ) ;
2019-07-18 21:02:57 +00:00
}
2019-10-24 19:48:36 +00:00
/// <summary>
/// Returns true if a Message of the specified Type has been sent this frame.
/// </summary>
/// <exception cref="Encompass.Exceptions.IllegalReadException">
/// Thrown when the Engine does not declare that it Receives the specified Message Type.
/// </exception>
2019-07-17 18:46:54 +00:00
protected bool SomeMessage < TMessage > ( ) where TMessage : struct , IMessage
2019-06-17 01:11:35 +00:00
{
2020-03-17 02:00:42 +00:00
CheckMessageRead < TMessage > ( ) ;
2020-03-20 07:09:57 +00:00
return _messageManager . Any < TMessage > ( ) ;
2019-06-17 01:11:35 +00:00
}
2019-06-20 03:37:46 +00:00
2019-10-24 19:48:36 +00:00
/// <summary>
/// Destroys the specified Entity. This also removes all of the Components associated with the Entity.
/// Entity destruction takes place after all the Engines have been processed by World Update.
/// </summary>
2020-03-23 02:10:28 +00:00
protected void Destroy ( in Entity entity )
2019-10-24 19:48:36 +00:00
{
2020-03-20 07:09:57 +00:00
_entityManager . MarkForDestroy ( entity . ID ) ;
2019-10-24 19:48:36 +00:00
}
/// <summary>
/// Destroys an arbitrary Entity containing a Component of the specified Type.
/// Entity destruction takes place after all the Engines have been processed by World Update.
/// </summary>
2020-03-25 04:28:56 +00:00
protected void DestroyWith < TComponent > ( ) where TComponent : struct , IComponent
2019-10-24 19:48:36 +00:00
{
Destroy ( ReadEntity < TComponent > ( ) ) ;
}
/// <summary>
/// Destroys all Entities containing a Component of the specified Type.
/// Entity destruction takes place after all the Engines have been processed by World Update.
/// </summary>
2020-03-25 04:28:56 +00:00
protected void DestroyAllWith < TComponent > ( ) where TComponent : struct , IComponent
2019-10-24 19:48:36 +00:00
{
foreach ( var entity in ReadEntities < TComponent > ( ) )
{
Destroy ( entity ) ;
}
}
2019-11-17 18:48:39 +00:00
/// <summary>
/// Removes a Component with the specified type from the given Entity.
/// Note that the Engine must Read the Component type that is being removed.
2019-11-21 03:01:29 +00:00
/// If a Component with the specified type does not exist on the Entity, returns false and does not mutate the Entity.
2019-11-17 18:48:39 +00:00
/// </summary>
2020-03-25 04:28:56 +00:00
protected void RemoveComponent < TComponent > ( in Entity entity ) where TComponent : struct , IComponent
2019-11-17 18:48:39 +00:00
{
2020-03-20 07:09:57 +00:00
var priority = WritePriorities . ContainsKey ( typeof ( TComponent ) ) ? WritePriorities [ typeof ( TComponent ) ] : DefaultWritePriority ;
2019-12-24 02:01:49 +00:00
2020-03-20 07:09:57 +00:00
if ( ! WriteTypes . Contains ( typeof ( TComponent ) ) )
2019-12-24 02:01:49 +00:00
{
throw new IllegalWriteException ( "Engine {0} tried to remove undeclared Component {1}. Declare with Writes attribute." , GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
}
2019-11-21 03:01:29 +00:00
2020-03-20 07:09:57 +00:00
if ( WriteImmediateTypes . Contains ( typeof ( TComponent ) ) )
2019-12-24 02:01:49 +00:00
{
2020-03-20 07:09:57 +00:00
if ( _componentManager . RemoveImmediate < TComponent > ( entity . ID , priority ) )
2019-12-28 22:30:26 +00:00
{
2020-03-20 07:09:57 +00:00
_trackingManager . ImmediateUpdateTracking ( entity . ID , typeof ( TComponent ) ) ;
2019-12-28 22:30:26 +00:00
}
2019-12-24 02:01:49 +00:00
}
else
{
2020-03-20 07:09:57 +00:00
_componentManager . Remove < TComponent > ( entity . ID , priority ) ;
2019-12-24 02:01:49 +00:00
}
2019-12-28 21:53:02 +00:00
2020-03-20 07:09:57 +00:00
if ( _componentManager . HasExistingComponent < TComponent > ( entity . ID ) )
2019-12-28 21:53:02 +00:00
{
2020-03-20 07:09:57 +00:00
_trackingManager . RegisterRemoval ( entity . ID , typeof ( TComponent ) ) ;
2019-12-28 21:53:02 +00:00
}
2019-11-17 18:48:39 +00:00
}
2019-11-21 22:22:10 +00:00
/// <summary>
/// Activates the Encompass time dilation system.
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
2019-11-22 21:14:36 +00:00
/// If multiple time dilations are active they will be averaged.
2019-11-21 22:22:10 +00:00
/// </summary>
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
/// <param name="activeTime">The length of real time that time will be fully dilated.</param>
/// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
2019-12-22 01:58:07 +00:00
protected void ActivateTimeDilation ( double factor , double easeInTime , double activeTime , double easeOutTime )
2019-11-21 21:53:33 +00:00
{
2020-03-20 07:09:57 +00:00
_timeManager . ActivateTimeDilation ( factor , easeInTime , activeTime , easeOutTime ) ;
2019-11-21 21:53:33 +00:00
}
2019-11-21 22:22:10 +00:00
/// <summary>
/// Activates the Encompass time dilation system.
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
2019-11-22 21:14:36 +00:00
/// If multiple time dilations are active they will be averaged.
2019-11-21 22:22:10 +00:00
/// </summary>
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
/// <param name="easeInFunction">An easing function for the easing in of time dilation.</param>
/// <param name="activeTime">The length of real time that time will be fully dilated.</param>
/// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
2019-12-22 01:58:07 +00:00
protected void ActivateTimeDilation ( double factor , double easeInTime , System . Func < double , double , double , double , double > easeInFunction , double activeTime , double easeOutTime )
2019-11-21 21:53:33 +00:00
{
2020-03-20 07:09:57 +00:00
_timeManager . ActivateTimeDilation ( factor , easeInTime , easeInFunction , activeTime , easeOutTime ) ;
2019-11-21 21:53:33 +00:00
}
2019-11-21 22:22:10 +00:00
/// <summary>
/// Activates the Encompass time dilation system.
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
2019-11-22 21:14:36 +00:00
/// If multiple time dilations are active they will be averaged.
2019-11-21 22:22:10 +00:00
/// </summary>
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
/// <param name="activeTime">The length of real time that time will be fully dilated.</param>
/// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
/// <param name="easeOutFunction">An easing function for the easing out of time dilation.</param>
2019-12-22 01:58:07 +00:00
protected void ActivateTimeDilation ( double factor , double easeInTime , double activeTime , double easeOutTime , System . Func < double , double , double , double , double > easeOutFunction )
2019-11-21 21:53:33 +00:00
{
2020-03-20 07:09:57 +00:00
_timeManager . ActivateTimeDilation ( factor , easeInTime , activeTime , easeOutTime , easeOutFunction ) ;
2019-11-21 21:53:33 +00:00
}
2019-11-21 22:22:10 +00:00
/// <summary>
/// Activates the Encompass time dilation system.
/// Engines that have the IgnoresTimeDilation property will ignore all time dilation.
2019-11-22 21:14:36 +00:00
/// If multiple time dilations are active they will be averaged.
2019-11-21 22:22:10 +00:00
/// </summary>
/// <param name="factor">The time dilation factor, which is multiplied by real delta time.</param>
/// <param name="easeInTime">The time that will elapse before time is fully dilated, in real time.</param>
/// <param name="easeInFunction">An easing function for the easing in of time dilation.</param>
/// <param name="activeTime">The length of real time that time will be fully dilated.</param>
/// <param name="easeOutTime">The time that will elapse before time is fully undilated.</param>
/// <param name="easeOutFunction">An easing function for the easing out of time dilation.</param>
2019-12-22 01:58:07 +00:00
protected void ActivateTimeDilation ( double factor , double easeInTime , System . Func < double , double , double , double , double > easeInFunction , double activeTime , double easeOutTime , System . Func < double , double , double , double , double > easeOutFunction )
2019-11-21 21:53:33 +00:00
{
2020-03-20 07:09:57 +00:00
_timeManager . ActivateTimeDilation ( factor , easeInTime , easeInFunction , activeTime , easeOutTime , easeOutFunction ) ;
2019-11-21 21:53:33 +00:00
}
2019-12-20 19:10:42 +00:00
2019-12-30 07:55:48 +00:00
/// <summary>
2020-03-17 02:00:42 +00:00
/// Efficiently reads Messages of a given type that all reference the given Entity.
2019-12-30 07:55:48 +00:00
/// </summary>
/// <typeparam name="TMessage">The Message subtype.</typeparam>
/// <param name="entity">The entity that all messages in the IEnumerable refer to.</param>
/// <returns></returns>
2020-03-23 02:10:28 +00:00
protected IEnumerable < TMessage > ReadMessagesWithEntity < TMessage > ( in Entity entity ) where TMessage : struct , IMessage , IHasEntity
2019-12-30 04:36:23 +00:00
{
2020-03-17 02:00:42 +00:00
CheckMessageRead < TMessage > ( ) ;
2020-03-20 07:09:57 +00:00
return _messageManager . WithEntity < TMessage > ( entity . ID ) ;
2019-12-30 04:36:23 +00:00
}
2020-03-17 02:00:42 +00:00
/// <summary>
/// Efficiently reads a single Message of a given type that references a given Entity.
/// It is recommended to use this method in conjunction with SomeMessageWithEntity to prevent errors.
/// </summary>
2020-03-23 02:10:28 +00:00
protected ref readonly TMessage ReadMessageWithEntity < TMessage > ( in Entity entity ) where TMessage : struct , IMessage , IHasEntity
2020-03-17 02:00:42 +00:00
{
CheckMessageRead < TMessage > ( ) ;
2020-03-22 21:20:22 +00:00
return ref _messageManager . WithEntitySingular < TMessage > ( entity . ID ) ;
2020-03-17 02:00:42 +00:00
}
/// <summary>
/// Efficiently checks if any Message of a given type referencing a given Entity exists.
/// </summary>
2020-03-23 02:10:28 +00:00
protected bool SomeMessageWithEntity < TMessage > ( in Entity entity ) where TMessage : struct , IMessage , IHasEntity
2020-01-13 22:59:18 +00:00
{
2020-03-17 02:00:42 +00:00
CheckMessageRead < TMessage > ( ) ;
2020-03-20 07:09:57 +00:00
return _messageManager . SomeWithEntity < TMessage > ( entity . ID ) ;
2020-01-13 22:59:18 +00:00
}
2019-12-29 21:54:08 +00:00
internal void CheckAndUpdateTracking ( int entityID )
2019-12-28 21:53:02 +00:00
{
2020-03-20 07:09:57 +00:00
if ( _trackedEntities . Contains ( entityID ) & & ! _entityQuery . CheckEntity ( entityID , _componentManager . ExistingBits ) )
2019-12-28 22:30:26 +00:00
{
2019-12-29 21:54:08 +00:00
_trackedEntities . Remove ( entityID ) ;
2019-12-28 22:30:26 +00:00
}
2020-03-20 07:09:57 +00:00
else if ( ! _trackedEntities . Contains ( entityID ) & & _entityQuery . CheckEntity ( entityID , _componentManager . ExistingBits ) )
2019-12-28 21:53:02 +00:00
{
2019-12-29 21:54:08 +00:00
_trackedEntities . Add ( entityID ) ;
2019-12-28 21:53:02 +00:00
}
}
2019-12-29 21:54:08 +00:00
internal void ImmediateCheckAndUpdateTracking ( int entityID )
2019-12-23 02:13:35 +00:00
{
2020-03-20 07:09:57 +00:00
if ( _trackedEntities . Contains ( entityID ) & & ! _entityQuery . ImmediateCheckEntity ( entityID , _componentManager . ImmediateBits , _componentManager . ExistingBits ) )
2019-12-23 02:13:35 +00:00
{
2019-12-29 21:54:08 +00:00
_trackedEntities . Remove ( entityID ) ;
2019-12-23 02:13:35 +00:00
}
2020-03-20 07:09:57 +00:00
else if ( ! _trackedEntities . Contains ( entityID ) & & _entityQuery . ImmediateCheckEntity ( entityID , _componentManager . ImmediateBits , _componentManager . ExistingBits ) )
2019-12-28 22:30:26 +00:00
{
2019-12-29 21:54:08 +00:00
_trackedEntities . Add ( entityID ) ;
2019-12-28 22:30:26 +00:00
}
2019-12-23 02:13:35 +00:00
}
2019-12-22 09:15:58 +00:00
/// <summary>
/// Returns an empty EntitySetQuery. Can be modified and iterated over to obtain Entities that fit the given criteria.
/// </summary>
2019-12-23 02:13:35 +00:00
internal void BuildEntityQuery ( )
2019-12-23 01:16:54 +00:00
{
2019-12-29 05:39:35 +00:00
var withMask = BitSet512 . Zero ;
2020-03-20 07:09:57 +00:00
foreach ( var type in QueryWithTypes )
2019-12-23 02:13:35 +00:00
{
2020-03-20 22:45:58 +00:00
if ( ! _componentManager . TypeToIndex . ContainsKey ( type ) ) { _componentManager . TypeToIndex . Add ( type , _componentManager . TypeToIndex . Count ) ; }
2020-03-20 07:09:57 +00:00
withMask = withMask . Set ( _componentManager . TypeToIndex [ type ] ) ;
2019-12-23 02:13:35 +00:00
}
2019-12-29 05:39:35 +00:00
var withoutMask = BitSet512 . Zero ;
2020-03-20 07:09:57 +00:00
foreach ( var type in QueryWithoutTypes )
2019-12-23 02:13:35 +00:00
{
2020-03-20 22:45:58 +00:00
if ( ! _componentManager . TypeToIndex . ContainsKey ( type ) ) { _componentManager . TypeToIndex . Add ( type , _componentManager . TypeToIndex . Count ) ; }
2020-03-20 07:09:57 +00:00
withoutMask = withoutMask . Set ( _componentManager . TypeToIndex [ type ] ) ;
2019-12-23 02:13:35 +00:00
}
2019-12-29 05:39:35 +00:00
var immediateMask = BitSet512 . Zero ;
2020-03-20 07:09:57 +00:00
foreach ( var type in ReadImmediateTypes )
2019-12-23 02:13:35 +00:00
{
2020-03-20 22:45:58 +00:00
if ( ! _componentManager . TypeToIndex . ContainsKey ( type ) ) { _componentManager . TypeToIndex . Add ( type , _componentManager . TypeToIndex . Count ) ; }
2020-03-20 07:09:57 +00:00
immediateMask = immediateMask . Set ( _componentManager . TypeToIndex [ type ] ) ;
2019-12-23 02:13:35 +00:00
}
2019-12-29 05:39:35 +00:00
var existingMask = BitSet512 . Zero ;
2020-03-20 07:09:57 +00:00
foreach ( var type in ReadTypes )
2019-12-23 02:13:35 +00:00
{
2020-03-20 22:45:58 +00:00
if ( ! _componentManager . TypeToIndex . ContainsKey ( type ) ) { _componentManager . TypeToIndex . Add ( type , _componentManager . TypeToIndex . Count ) ; }
2020-03-20 07:09:57 +00:00
existingMask = existingMask . Set ( _componentManager . TypeToIndex [ type ] ) ;
2019-12-23 02:13:35 +00:00
}
2020-03-20 07:09:57 +00:00
_entityQuery = new EntitySetQuery (
2019-12-29 05:39:35 +00:00
withMask & immediateMask ,
withMask & existingMask ,
withoutMask & immediateMask ,
withoutMask & existingMask ,
~ withMask
2019-12-23 01:16:54 +00:00
) ;
2019-12-20 19:10:42 +00:00
}
2019-12-29 00:16:21 +00:00
2019-12-29 21:54:08 +00:00
internal void RegisterDestroyedEntity ( int entityID )
2019-12-29 00:16:21 +00:00
{
2019-12-29 21:54:08 +00:00
_trackedEntities . Remove ( entityID ) ;
2019-12-29 00:16:21 +00:00
}
2019-06-15 00:51:06 +00:00
}
}