I'm very much in the same situation as you are. I also started some GameEngine approach based on entities and components. Although I didn't start to realize the components as plugins I wanted to try this in the next weeks.
I think event handling is the most important functionality of the engine if you want to design a clean and flexible implementation. Currently I have some kind of sendEvent Function for each entity that will send a GameEvent with a GameEventData struct to all components listening for this event within the entity.
But I'm not very happy with this approach because the type of available events are fixed and you have to introduce a new event for new functionality.
But that may be also an advantage if it comes to integrating a new component. Since you know about the existing events you can just register the component to the existing events and easily exchange an existing one with your new one.
But what I'm really not sure about is the handling of the messages. Lets suppose the following example:
We have an entity 'Player' that aggregates a physics, graphical and keyboard controller component. And we have a room where the player entity will be placed in.
Now the player will be moved by the keyboard component and therefore will send a transformation event. Normaly the graphical component will take the event and adjust the graphical representation of the entity. But what if the physics component is present and want to block the transformation change because there is a collision with one of the room's walls.
Currently I have the concept of a checkEvent and executeEvent method. If a component want to change the transformation it first calls the checkEvent method with the transformation event's data. If none of the components aggregated in the entity returned false, it will call the executeEvent method and all components interested in the tranformation are updated.
So in the example above the physics component will return false in the checkEvent method. Additionally it will take the transformation send to the checkEvent method and integrate it into it's internal world representation. On the next update iteration of the physics world the physics component will try to send the transformation adjusted by the physical calculations to the other components. This way things like collision or friction etc. have been integrated into the transformation change initially triggered by the keyboard controller component.
Next to some things I don't have figured out yet, there a two problems with this approach:
- Transformation changes will be finally integrated with a delay of one update iteration (usally one frame if you call the physics update every frame)
- If more than one component returns false in the checkEvent method the transformation may be never integrated because each time a component want to execute it's adjusted transformation event it will be catched by the other component that want to control the transformation.
I hope my contribution to this discussion doesn't cause another headache