change attributes

pull/5/head
Evan Hemsley 2019-07-18 18:20:38 -07:00
parent 3deff94dfe
commit c8c5a8c7c4
12 changed files with 120 additions and 91 deletions

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Encompass.Exceptions;
namespace Encompass
{
[AttributeUsage(AttributeTargets.Class)]
public class Sends : Attribute
{
public readonly HashSet<Type> sendTypes;
public Sends(params Type[] sendTypes)
{
foreach (var sendType in sendTypes)
{
var isMessage = sendType.GetInterfaces().Contains(typeof(IMessage));
if (!isMessage)
{
throw new IllegalWriteTypeException("{0} must be a Message", sendType.Name);
}
}
this.sendTypes = new HashSet<Type>(sendTypes);
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Encompass.Exceptions;
namespace Encompass
{
[AttributeUsage(AttributeTargets.Class)]
public class Updates : Attribute
{
public readonly HashSet<Type> updateTypes;
public Updates(params Type[] updateTypes)
{
foreach (var updateType in updateTypes)
{
var isComponent = updateType.GetInterfaces().Contains(typeof(IComponent));
if (!isComponent)
{
throw new IllegalUpdateTypeException("{0} must be a Component", updateType.Name);
}
}
this.updateTypes = new HashSet<Type>(updateTypes);
}
}
}

View File

@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Encompass.Exceptions;
namespace Encompass
{
[AttributeUsage(AttributeTargets.Class)]
public class Writes : Attribute
{
public readonly HashSet<Type> writeTypes;
public Writes(params Type[] writeTypes)
{
foreach (var writeType in writeTypes)
{
if (!writeType.GetInterfaces().Contains(typeof(IMessage)) && !writeType.GetInterfaces().Contains(typeof(IComponent)))
{
throw new IllegalWriteTypeException("{0} must be a Message or Component", writeType.Name);
}
}
if (writeTypes.Any((type) => type.GetInterfaces().Contains(typeof(IMessage))) && writeTypes.Any((type) => type.GetInterfaces().Contains(typeof(IComponent))))
{
throw new ComponentAndMessageWriteException("An Engine which writes Components cannot also write Messages");
}
this.writeTypes = new HashSet<Type>(writeTypes);
}
}
}

View File

@ -8,9 +8,10 @@ namespace Encompass
{
public abstract class Engine
{
internal readonly HashSet<Type> writeTypes = new HashSet<Type>();
internal readonly HashSet<Type> sendTypes = new HashSet<Type>();
internal readonly HashSet<Type> readTypes = new HashSet<Type>();
internal readonly HashSet<Type> activateTypes = new HashSet<Type>();
internal readonly HashSet<Type> updateTypes = new HashSet<Type>();
private EntityManager entityManager;
private ComponentManager componentManager;
@ -18,10 +19,10 @@ namespace Encompass
protected Engine()
{
var writesAttribute = GetType().GetCustomAttribute<Writes>(false);
var writesAttribute = GetType().GetCustomAttribute<Sends>(false);
if (writesAttribute != null)
{
writeTypes = writesAttribute.writeTypes;
sendTypes = writesAttribute.sendTypes;
}
var readsAttribute = GetType().GetCustomAttribute<Reads>(false);
@ -35,6 +36,16 @@ namespace Encompass
{
activateTypes = activatesAttribute.activateTypes;
}
var updatesAttribute = GetType().GetCustomAttribute<Updates>(false);
if (updatesAttribute != null)
{
updateTypes = updatesAttribute.updateTypes;
if (sendTypes.Any())
{
throw new IllegalEngineAttributesException("Engine {0} sends Message(s) and updates Component(s)", GetType().Name);
}
}
}
internal void AssignEntityManager(EntityManager entityManager)
@ -181,7 +192,7 @@ namespace Encompass
internal void UpdateComponentInWorld<TComponent>(Guid componentID, TComponent newComponent) where TComponent : struct, IComponent
{
if (!writeTypes.Contains(typeof(TComponent)))
if (!updateTypes.Contains(typeof(TComponent)))
{
throw new IllegalWriteException("Engine {0} tried to write undeclared Component {1}", this.GetType().Name, typeof(TComponent).Name);
}
@ -196,7 +207,7 @@ namespace Encompass
protected void EmitMessage<TMessage>(TMessage message) where TMessage : struct, IMessage
{
if (!writeTypes.Contains(typeof(TMessage)))
if (!sendTypes.Contains(typeof(TMessage)))
{
throw new IllegalWriteException("Engine {0} tried to write undeclared Message {1}", this.GetType().Name, typeof(TMessage).Name);
}

View File

@ -6,13 +6,13 @@ namespace Encompass.Engines
{
public ComponentMessageEmitter() : base()
{
var writesAttribute = GetType().GetCustomAttribute<Writes>(false);
var writesAttribute = GetType().GetCustomAttribute<Sends>(false);
if (writesAttribute != null)
{
writesAttribute.writeTypes.Add(typeof(ComponentMessage<TComponent>));
writesAttribute.sendTypes.Add(typeof(ComponentMessage<TComponent>));
}
writeTypes.Add(typeof(ComponentMessage<TComponent>));
sendTypes.Add(typeof(ComponentMessage<TComponent>));
}
public override void Update(double dt)

View File

@ -3,9 +3,9 @@ using System;
namespace Encompass.Exceptions
{
public class ComponentAndMessageWriteException : Exception
public class IllegalEngineAttributesException : Exception
{
public ComponentAndMessageWriteException(
public IllegalEngineAttributesException(
string format,
params object[] args
) : base(string.Format(format, args)) { }

View File

@ -2,9 +2,9 @@ using System;
namespace Encompass.Exceptions
{
public class UnregisteredComponentReadException : Exception
public class IllegalUpdateTypeException : Exception
{
public UnregisteredComponentReadException(
public IllegalUpdateTypeException(
string format,
params object[] args
) : base(string.Format(format, args)) { }

View File

@ -77,11 +77,11 @@ namespace Encompass
foreach (var activateType in engine.activateTypes)
{
engine.writeTypes.Add(activateType);
engine.sendTypes.Add(activateType);
}
var messageReadTypes = engine.readTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage)));
var messageSendTypes = engine.writeTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage)));
var messageSendTypes = engine.sendTypes;
if (messageReadTypes.Intersect(messageSendTypes).Any())
{
@ -144,7 +144,7 @@ namespace Encompass
{
foreach (var senderEngine in senders)
{
foreach (var messageType in senderEngine.writeTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage))))
foreach (var messageType in senderEngine.sendTypes.Where((type) => type.GetInterfaces().Contains(typeof(IMessage))))
{
if (typeToReaders.ContainsKey(messageType))
{
@ -181,29 +181,25 @@ namespace Encompass
foreach (var engine in engines)
{
var writeAttribute = engine.GetType().GetCustomAttribute<Writes>(false);
if (writeAttribute != null)
foreach (var updateType in engine.updateTypes)
{
foreach (var writeType in writeAttribute.writeTypes)
if (updateType.GetInterfaces().Contains(typeof(IComponent))) // if our write type is a component
{
if (writeType.GetInterfaces().Contains(typeof(IComponent))) // if our write type is a component
if (mutatedComponentTypes.Contains(updateType))
{
if (mutatedComponentTypes.Contains(writeType))
{
duplicateMutations.Add(writeType);
duplicateMutations.Add(updateType);
}
else
{
mutatedComponentTypes.Add(writeType);
mutatedComponentTypes.Add(updateType);
}
if (!componentToEngines.ContainsKey(writeType))
if (!componentToEngines.ContainsKey(updateType))
{
componentToEngines[writeType] = new List<Engine>();
componentToEngines[updateType] = new List<Engine>();
}
componentToEngines[writeType].Add(engine);
}
componentToEngines[updateType].Add(engine);
}
}
}

View File

@ -85,7 +85,7 @@ namespace Tests
public MockComponent mockComponent;
}
[Writes(typeof(AddMockComponentMessage))]
[Sends(typeof(AddMockComponentMessage))]
class EmitMockComponentMessageEngine : Engine
{
private Entity entity;
@ -359,7 +359,7 @@ namespace Tests
}
[Reads(typeof(RemoveComponentTestMessage))]
[Writes(typeof(CheckHasMockComponentMessage))]
[Sends(typeof(CheckHasMockComponentMessage))]
class DoRemoveCheckEngine : Engine
{
private Entity entity;
@ -440,7 +440,7 @@ namespace Tests
}
[Reads(typeof(ActivateComponentMessage))]
[Writes(typeof(CheckHasMockComponentMessage))]
[Sends(typeof(CheckHasMockComponentMessage))]
class DoActivateCheckEngine : Engine
{
private Entity entity;
@ -509,7 +509,6 @@ namespace Tests
}
[Reads(typeof(DeactivateComponentMessage))]
[Writes(typeof(MockComponent))]
class DeactivateComponentEngine : Engine
{
public override void Update(double dt)
@ -522,7 +521,7 @@ namespace Tests
}
[Reads(typeof(DeactivateComponentMessage))]
[Writes(typeof(CheckHasMockComponentMessage))]
[Sends(typeof(CheckHasMockComponentMessage))]
class DoDeactivateCheckEngine : Engine
{
private Entity entity;

View File

@ -120,7 +120,7 @@ namespace Tests
}
[Reads(typeof(MockComponent))]
[Writes(typeof(MockComponent))]
[Updates(typeof(MockComponent))]
public class UpdateComponentTestEngine : Engine
{
public override void Update(double dt)
@ -200,7 +200,7 @@ namespace Tests
public string myString;
}
[Writes(typeof(MockMessage))]
[Sends(typeof(MockMessage))]
public class MessageEmitEngine : Engine
{
public override void Update(double dt)
@ -284,7 +284,7 @@ namespace Tests
static bool someTest;
[Writes(typeof(MockMessage))]
[Sends(typeof(MockMessage))]
class EmitMockMessageEngine : Engine
{
public override void Update(double dt)
@ -481,7 +481,6 @@ namespace Tests
}
[Reads(typeof(DestroyerComponent), typeof(MockComponent))]
[Writes(typeof(MockComponent))]
class DestroyAndAddComponentEngine : Engine
{
public override void Update(double dt)
@ -646,7 +645,8 @@ namespace Tests
Assert.IsFalse(hasEntity);
}
[Writes(typeof(MockComponent), typeof(MockMessage))]
[Sends(typeof(MockMessage))]
[Updates(typeof(MockComponent))]
class EngineThatWritesComponentAndMessage : Engine
{
public override void Update(double dt) { }
@ -657,7 +657,7 @@ namespace Tests
{
var worldBuilder = new WorldBuilder();
Assert.Throws<ComponentAndMessageWriteException>(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage()));
Assert.Throws<IllegalEngineAttributesException>(() => worldBuilder.AddEngine(new EngineThatWritesComponentAndMessage()));
}
struct MockComponentUpdateMessage : IMessage
@ -667,7 +667,7 @@ namespace Tests
}
[Reads(typeof(MockComponentUpdateMessage))]
[Writes(typeof(MockComponent))]
[Updates(typeof(MockComponent))]
class RepeatUpdateEngine : Engine
{
public override void Update(double dt)

View File

@ -14,7 +14,7 @@ namespace Tests
static Entity resultEntity;
[Writes(typeof(SpawnMessageA))]
[Sends(typeof(SpawnMessageA))]
class MessageEmitter : Engine
{
public override void Update(double dt)

View File

@ -14,7 +14,7 @@ namespace Tests
struct BMessage : IMessage { }
[Reads(typeof(AMessage))]
[Writes(typeof(BMessage))]
[Sends(typeof(BMessage))]
class AEngine : Engine
{
public override void Update(double dt)
@ -25,7 +25,7 @@ namespace Tests
}
[Reads(typeof(BMessage))]
[Writes(typeof(AMessage))]
[Sends(typeof(AMessage))]
class BEngine : Engine
{
public override void Update(double dt)
@ -54,7 +54,7 @@ namespace Tests
struct DMessage : IMessage { }
[Reads(typeof(AMessage))]
[Writes(typeof(BMessage))]
[Sends(typeof(BMessage))]
class AEngine : Engine
{
public override void Update(double dt)
@ -65,7 +65,7 @@ namespace Tests
}
[Reads(typeof(BMessage))]
[Writes(typeof(CMessage))]
[Sends(typeof(CMessage))]
class BEngine : Engine
{
public override void Update(double dt)
@ -76,7 +76,7 @@ namespace Tests
}
[Reads(typeof(CMessage))]
[Writes(typeof(DMessage))]
[Sends(typeof(DMessage))]
class CEngine : Engine
{
public override void Update(double dt)
@ -87,7 +87,7 @@ namespace Tests
}
[Reads(typeof(DMessage))]
[Writes(typeof(AMessage))]
[Sends(typeof(AMessage))]
class DEngine : Engine
{
public override void Update(double dt)
@ -114,13 +114,13 @@ namespace Tests
{
struct AComponent : IComponent { }
[Writes(typeof(AComponent))]
[Updates(typeof(AComponent))]
class AEngine : Engine
{
public override void Update(double dt) { }
}
[Writes(typeof(AComponent))]
[Updates(typeof(AComponent))]
class BEngine : Engine
{
public override void Update(double dt) { }
@ -142,7 +142,7 @@ namespace Tests
struct AMessage : IMessage { }
[Reads(typeof(AMessage))]
[Writes(typeof(AMessage))]
[Sends(typeof(AMessage))]
class AEngine : Engine
{
public override void Update(double dt)
@ -186,7 +186,7 @@ namespace Tests
{
struct ANonMessage { }
[Writes(typeof(ANonMessage))]
[Sends(typeof(ANonMessage))]
class MyEngine : Engine
{
public override void Update(double dt)
@ -216,7 +216,7 @@ namespace Tests
struct CMessage : IMessage { }
struct DMessage : IMessage { }
[Writes(typeof(AMessage))]
[Sends(typeof(AMessage))]
class AEngine : Engine
{
public override void Update(double dt)
@ -225,7 +225,7 @@ namespace Tests
}
}
[Writes(typeof(BMessage))]
[Sends(typeof(BMessage))]
class BEngine : Engine
{
public override void Update(double dt)
@ -235,7 +235,7 @@ namespace Tests
}
[Reads(typeof(AMessage), typeof(BMessage))]
[Writes(typeof(DMessage))]
[Sends(typeof(DMessage))]
class CEngine : Engine
{
public override void Update(double dt)