2019-06-15 07:39:08 +00:00
using System ;
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-06-15 00:51:06 +00:00
2019-06-16 01:05:56 +00:00
namespace Encompass
{
public abstract class Engine
{
2019-07-17 18:31:18 +00:00
internal readonly HashSet < Type > writeTypes = new HashSet < Type > ( ) ;
internal readonly HashSet < Type > readTypes = new HashSet < Type > ( ) ;
2019-06-15 07:39:08 +00:00
2019-06-15 00:51:06 +00:00
private EntityManager entityManager ;
private ComponentManager componentManager ;
2019-06-16 01:55:35 +00:00
private MessageManager messageManager ;
2019-06-15 00:51:06 +00:00
2019-06-20 17:46:15 +00:00
protected Engine ( )
2019-06-16 01:05:56 +00:00
{
2019-07-17 18:31:18 +00:00
var writesAttribute = GetType ( ) . GetCustomAttribute < Writes > ( false ) ;
if ( writesAttribute ! = null )
2019-06-16 01:55:35 +00:00
{
2019-07-17 18:31:18 +00:00
writeTypes = writesAttribute . writeTypes ;
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 )
{
2019-07-16 16:47:58 +00:00
readTypes = readsAttribute . readTypes ;
2019-06-16 01:55:35 +00:00
}
2019-06-15 07:39:08 +00:00
}
2019-06-16 01:05:56 +00:00
internal void AssignEntityManager ( EntityManager entityManager )
{
2019-06-15 00:51:06 +00:00
this . entityManager = entityManager ;
}
2019-06-16 01:05:56 +00:00
internal void AssignComponentManager ( ComponentManager componentManager )
{
2019-06-15 00:51:06 +00:00
this . componentManager = componentManager ;
}
2019-06-16 01:55:35 +00:00
internal void AssignMessageManager ( MessageManager messageManager )
{
this . messageManager = messageManager ;
}
2019-06-24 19:14:37 +00:00
public abstract void Update ( double dt ) ;
2019-06-15 00:51:06 +00:00
2019-06-16 01:05:56 +00:00
protected Entity CreateEntity ( )
{
2019-06-20 03:37:46 +00:00
return entityManager . CreateEntity ( ) ;
}
2019-07-13 00:37:31 +00:00
protected bool EntityExists ( Guid entityID )
{
return entityManager . EntityExists ( entityID ) ;
}
2019-06-20 03:37:46 +00:00
protected Entity GetEntity ( Guid entityID )
{
return entityManager . GetEntity ( entityID ) ;
}
2019-06-22 00:50:01 +00:00
protected Guid GetEntityIDByComponentID ( Guid componentID )
2019-06-20 03:37:46 +00:00
{
2019-06-22 00:50:01 +00:00
return componentManager . GetEntityIDByComponentID ( componentID ) ;
2019-06-15 00:51:06 +00:00
}
2019-06-22 00:50:01 +00:00
protected Entity GetEntityByComponentID ( Guid componentID )
2019-06-22 00:44:07 +00:00
{
2019-06-22 00:50:01 +00:00
return GetEntity ( GetEntityIDByComponentID ( componentID ) ) ;
2019-06-22 00:44:07 +00:00
}
protected TComponent GetComponentByID < TComponent > ( Guid componentID ) where TComponent : struct , IComponent
{
2019-07-16 18:17:07 +00:00
if ( componentManager . GetComponentTypeByID ( componentID ) ! = typeof ( TComponent ) )
2019-06-22 00:44:07 +00:00
{
throw new ComponentTypeMismatchException ( "Expected Component to be of type {0} but was actually of type {1}" , typeof ( TComponent ) . Name , componentManager . GetComponentTypeByID ( componentID ) . Name ) ;
}
2019-07-16 18:17:07 +00:00
return ( TComponent ) componentManager . GetComponentByID ( componentID ) ;
2019-06-22 00:44:07 +00:00
}
2019-06-27 23:55:12 +00:00
protected IEnumerable < ValueTuple < Guid , TComponent > > ReadComponents < TComponent > ( ) where TComponent : struct , IComponent
2019-06-16 01:05:56 +00:00
{
2019-06-20 03:37:46 +00:00
return componentManager . GetActiveComponentsByType < TComponent > ( ) ;
2019-06-15 00:51:06 +00:00
}
2019-06-27 23:55:12 +00:00
protected ValueTuple < Guid , TComponent > ReadComponent < TComponent > ( ) where TComponent : struct , IComponent
2019-06-16 01:05:56 +00:00
{
2019-06-20 03:37:46 +00:00
return componentManager . GetActiveComponentByType < TComponent > ( ) ;
2019-06-15 00:51:06 +00:00
}
2019-06-15 07:39:08 +00:00
2019-07-17 18:24:21 +00:00
protected Guid AddComponent < TComponent > ( Entity entity , TComponent component ) where TComponent : struct , IComponent
{
return componentManager . AddComponent ( entity . ID , component ) ;
}
protected Guid AddDrawComponent < TComponent > ( Entity entity , TComponent component , int layer = 0 ) where TComponent : struct , IComponent
{
return componentManager . AddDrawComponent ( entity . ID , component , layer ) ;
}
protected void ActivateComponent ( Guid componentID )
{
2019-07-18 01:12:29 +00:00
componentManager . MarkForActivation ( componentID ) ;
2019-07-17 18:24:21 +00:00
}
protected void DeactivateComponent ( Guid componentID )
{
2019-07-18 01:12:29 +00:00
componentManager . MarkForDeactivation ( componentID ) ;
2019-07-17 18:24:21 +00:00
}
protected IEnumerable < ValueTuple < Guid , TComponent > > GetComponents < TComponent > ( Entity entity ) where TComponent : struct , IComponent
{
return componentManager . GetComponentsByEntityAndType < TComponent > ( entity . ID ) ;
}
protected ValueTuple < Guid , TComponent > GetComponent < TComponent > ( Entity entity ) where TComponent : struct , IComponent
{
return GetComponents < TComponent > ( entity ) . First ( ) ;
}
protected bool HasComponent < TComponent > ( Entity entity ) where TComponent : struct , IComponent
{
return componentManager . EntityHasComponentOfType < TComponent > ( entity . ID ) ;
}
2019-06-17 18:33:38 +00:00
internal void UpdateComponentInWorld < TComponent > ( Guid componentID , TComponent newComponent ) where TComponent : struct , IComponent
2019-06-16 01:05:56 +00:00
{
2019-07-16 18:17:07 +00:00
if ( ! writeTypes . Contains ( typeof ( TComponent ) ) )
2019-06-16 01:05:56 +00:00
{
2019-07-16 18:17:07 +00:00
throw new IllegalWriteException ( "Engine {0} tried to write undeclared Component {1}" , this . GetType ( ) . Name , typeof ( TComponent ) . Name ) ;
2019-06-15 18:40:42 +00:00
}
2019-07-16 18:17:07 +00:00
2019-07-18 01:53:31 +00:00
componentManager . AddUpdateComponentOperation ( componentID , newComponent ) ;
2019-06-15 18:40:42 +00:00
}
2019-06-17 18:33:38 +00:00
protected void UpdateComponent < TComponent > ( Guid componentID , TComponent newComponentValue ) where TComponent : struct , IComponent
2019-06-16 01:05:56 +00:00
{
2019-06-20 03:37:46 +00:00
UpdateComponentInWorld ( componentID , newComponentValue ) ;
2019-06-15 07:39:08 +00:00
}
2019-06-16 01:55:35 +00:00
protected void EmitMessage < TMessage > ( TMessage message ) where TMessage : struct , IMessage
{
2019-07-16 18:17:07 +00:00
if ( ! writeTypes . Contains ( typeof ( TMessage ) ) )
2019-06-16 01:55:35 +00:00
{
2019-07-18 01:12:29 +00:00
throw new IllegalWriteException ( "Engine {0} tried to write undeclared Message {1}" , this . GetType ( ) . Name , typeof ( TMessage ) . Name ) ;
2019-06-16 01:55:35 +00:00
}
2019-07-16 18:17:07 +00:00
messageManager . AddMessage ( message ) ;
2019-06-16 01:55:35 +00:00
}
protected IEnumerable < TMessage > ReadMessages < TMessage > ( ) where TMessage : struct , IMessage
{
2019-07-16 18:17:07 +00:00
if ( ! readTypes . Contains ( typeof ( TMessage ) ) )
2019-06-16 01:55:35 +00:00
{
2019-07-16 18:17:07 +00:00
throw new IllegalReadException ( "Engine {0} tried to read undeclared Message {1}" , this . GetType ( ) . Name , typeof ( TMessage ) . Name ) ;
2019-06-16 01:55:35 +00:00
}
2019-07-16 18:17:07 +00:00
return messageManager . GetMessagesByType < TMessage > ( ) ;
2019-06-16 01:55:35 +00:00
}
2019-06-17 01:11:35 +00:00
2019-07-17 18:46:54 +00:00
protected bool SomeMessage < TMessage > ( ) where TMessage : struct , IMessage
2019-06-17 01:11:35 +00:00
{
2019-07-16 18:17:07 +00:00
if ( ! readTypes . Contains ( typeof ( TMessage ) ) )
2019-06-17 01:11:35 +00:00
{
2019-07-16 18:17:07 +00:00
throw new IllegalReadException ( "Engine {0} tried to read undeclared Message {1}" , this . GetType ( ) . Name , typeof ( TMessage ) . Name ) ;
2019-06-17 01:11:35 +00:00
}
2019-07-16 18:17:07 +00:00
return messageManager . GetMessagesByType < TMessage > ( ) . Any ( ) ;
2019-06-17 01:11:35 +00:00
}
2019-06-20 03:37:46 +00:00
2019-07-17 18:46:54 +00:00
protected bool SomeComponent < TComponent > ( ) where TComponent : struct , IComponent
{
return componentManager . GetActiveComponentsByType < TComponent > ( ) . Any ( ) ;
}
2019-06-20 03:37:46 +00:00
protected void Destroy ( Guid entityID )
{
entityManager . MarkForDestroy ( entityID ) ;
}
2019-07-17 18:24:21 +00:00
protected void RemoveComponent ( Guid componentID )
{
2019-07-18 01:12:29 +00:00
componentManager . MarkForRemoval ( componentID ) ;
2019-07-17 18:24:21 +00:00
}
2019-06-15 00:51:06 +00:00
}
}