My flurry of activity on Entreri has a reached its culmination and 1.6 has been released. It should be synced to the Maven Central Repository within the next couple of hours. The release notes have been summarized on the project’s main page on Bitbucket but I’ll talk a little bit about the major changes here:
The biggest is that the entire Controller and ControllerManager API has been removed. I was never happy with this view of the world, it was too easy when designing your entity setup to just lump everything into a single controller or far too many controllers. And to be honest, the name bothered me some too. Now, there are Tasks that process the EntitySystem–or a subset thereof–to produce results. These results are either mutations to the system, computations passed onto future tasks, or output such as rendering to a window. Tasks are grouped into jobs that can be scheduled and threaded independently, but to achieve good performance it is critical that Tasks implement ParallelAware. Jobs can be scheduled repeatedly at a fixed rate, as fast as possible, or invoked under more customized control.
The next change added is the concept of ownership. As an example to motivate this, consider a 3D renderer that has particle systems and renderable shapes. For maximum reuse, it’d be nice if the particle system can just update its geometry component automatically, and then depend on the rendering engine to render all shapes. However, it is annoying for the programmer to know that the particle system requires a geometry component and add or remove it as necessary. In comes ownership to clean this mess up. Components and entities can be the owners of other components and entities. When a component or entity is removed, all objects owned by it are also removed from the system.
With ownership, the particle system task can add the geometry if necessary and mark the particle system as the owner. Then when the particle system is removed, the geometry is removed. This can be used when one entity produces multiple intermediate entities, such as an avatar with a detachable weapon or helmet, or a unit of troops.
The last large change is relatively straight-forward. Properly implemented ComponentData definitions can report data changes by incrementing a version flag that is per-Component. Tasks can take advantage of this by remembering the last processed version per-entity and comparing the two before doing any heavy computation. In some cases it is more cost effective to just perform the computation than store and compare versions. Using decorated properties is a convenient way for a task to store the last version.
Oh and that reminds me, the other significant change is that there is no more ‘undecorate’ required when you decorate a component data type. Instead, the system only stores a weak reference to the new property, so when the decorating task no longer keeps a reference to it, Java will garbage collect it and its cleanup is handled gracefully by the entity system.