Entreri: A new entity-component framework

I would like to announce the completion (or at least perfectly usable state) of my entity-component framework, Entreri. If you’re a fan (or not a fan) of R.A. Salvatore, you might get the pun on the name with the existing entity framework, Artemis.

The project is hosted on Google Code here: http://entreri.googlecode.com/
It will be hosted on one of the central Maven repositories soon enough, but is otherwise fully Maven enabled.

The API was designed to be clean and simple, although defining Component types can be a little complicated (which I will go into below). You create an EntitySystem and add Entitites to it. You add and remove Components from Entitites. Entities can be queried by sets of Components they must have, and by single component type. Each Component type is assigned a so-called TypedId that functions much like a .class handle but can be used for constant-time access of an entity’s components (1 if-branch and an array lookup).

Inspired by Riven’s MappedObject’s library, all component data is packed into primitive arrays. The API for this is all in Java and does not use byte-code transformation. This does make the definition of Components a little more complicated than just defining fields, getters, and setters but it has essentially the same performance benefits of using the MappedObject approach.

It also allows for dynamic decoration of new properties onto a Component type such that all components of a given type in a system can be updated to have an extra “vector” or “matrix” or “X” field. This is primarily useful for caching internal data by each controller that processes the system.

Although it is fully java-doc’ed, it does not have any getting-started information. I will be adding that soon, hopefully, otherwise questions can be asked here. I hope people are able to find it a useful tool if they are interested in exploring an entity-component design in their game and are looking for an alternative to existing frameworks.

Thanks

Interesting (I’m the one who made that thread about entity systems), but the “complicated” Component system scares me enough to not bother experimenting with it. Some wiki articles or a small tutorial would be awesome, or you can just give me a few days/hours until my curiosity overwhelms me. xD

Can’t quite wrap my head around:

    @Parameter(type=int.class, value="3")
    private FloatProperty property;

Each Component type can only declare fields that extend from Property (that is how I can manage the data storage within an entity system properly). Each instance of a Component type in a system share the same Property instances, and just have a different index into the data of the property (which grows as the number of component instances grows).

So to make that work, I decided to use reflection to assign the Property instances to the created Component’s fields. To support flexible constructor arguments, I added the @Parameter annotation and @Parameters annotation to select the constructor to use when creating the Property.

If your question is purely over why FloatProperty has a single parameter, it is so that a vector or matrix could easily enough be stored as a FloatProperty, so you could say that 3 floats make up the property.

The implementations of properties and components within the test cases aren’t the best examples of what to do, but were done in haste purely to shove data around.

I’m not sold on the idea of Component/Entity systems.

What might convince me to use such a system: a) Seeing decent games being made with it. b) Seeing that the source code for those games is neater than it typically is for my games.

But then maybe I’m the sort of fussy, demanding person you’d rather not have as a customer. ;D

Simon

i’m with dishmoth on that point, but that is just personal preference, I think this is a great idea, and a couple ears ago i would have jumped right on board, but now I love being able to tear all my code apart to accomplish something because I know how it all works since (for the most part) I wrote it.

but don’t take what I am saying as anything negative, I am just saying that people with a little more experience will likely want to use their own stuff. However, this is probably going to be a godsend for many newer programmers!

BTW, I love Entreri, def my favorite character, and I am pissed that he isn’t in the stories anymore…

I totally agree with you here, the main reason I wrote this was for my own stuff because I like the idea of entity-component systems. And instead of reusing one, I of course had to write my own (or more like 4 different ones before I settled on this one). I’ll be using it in all of my projects, but I just wanted to put it out there in case others were interested too.

The reason I decided that entity component systems would be best for me was dealing with the issue of adding and changing materials of rendered objects, and controlling said-objects (by billboarding them, or skinning them, etc.) and applying physics to the objects. I didn’t like the idea of creating a super general hierarchy for all of that, so the component system appealed to me. Mostly this works because I am working on a game engine, and not a game. If I was just doing a game, I would be happier to just use OO directly.

Not everyone is interested in all aspects of game programming. To me entity systems are pretty annoying, because I like programming graphics things. Using somebody else’s lib or framework for the things I’m not too interested in is good for keeping my motivation up. xD

Cool, took a quick gander at the code. I’m still uneasy about game specific entity/component systems, but that’s just because I’ve embraced component architectures whole hog and everything in my efforts utilizes the approach. I think small light weight efforts like Entreri are good to have out there though. Congrats on finally settling on an implementation approach.

@lhkbob have you tried any tests on Android?

Recently in the finalization / release engineering process of unifying my component architecture / entity system efforts I happened to roll in some annotation usage into the core architecture and immediately performance dropped off… It appears Android API 1-13 suffers from horrible annotation support and this is for Class annotation access let alone field and method usage which there are further inefficiencies in certain methods like “equals” in Method / Field doing insane string building / string comparisons, etc. Just a heads up that performance may suffer greatly on Android due to annotation usage.

I posted more about it here with the relevant code snippets:
https://plus.google.com/u/0/117904596907381647757/posts/WBxsvqgP4iP

:frowning: Very sad panda as I can’t believe such inefficiency was never caught for many years. As things go there is apparently a fix for Android 4.0 / ICS, but I’ll believe it when I see it at this point. However, this doesn’t help usage on the hundreds of millions of existing Android devices that won’t see ICS.

I got around this by implementing my own annotation caching in my component architecture. You might have to do something similar for your ES if it is annotation bound / depends on it deeply.

I have not done any tests with Android, although you’re welcome to try :slight_smile:

I only use annotations the first time that a type’s ID is created. After that, everything is done with pure-java code (barring the reflection to set property values on instances, and that is done using Field.set(), I don’t need to scan through the Class’s fields after the first check).

As a side note, I’ve pushed release 1.0.0 to Maven so it should be showing up soon enough for people who are into that sort of thing.

Not having looked too closely an Entreri are type IDs cached or is this something that gets hit every time a component or entity is created? If it’s not cached you may see performance drop off considerably. Even so, something to test and keep in mind when you get a chance to looking at Android performance. I was very frustrated by yet another gaping hole in the Android API / core Java language support.

Yes, TypedIds are cached. They basically wrap an int and a generic parameter so that fetches/adds/etc. of components can look a little cleaner. After they are created the 1st time, they are stored in a thread-safe map that is checked first. It is also recommended for Components to expose their own TypedId as a static field.

So something might look like:


class Transform extends Component {
   public static final TypedId<Transform> ID = Component.getTypedId(Transform.class);

   ...
}

and then it can be used easily:


EntitySystem system = new EntitySystem();

Entity e = system.addEntity();
Transform trans = e.add(Transform.ID);
// then edit trans ...

You might check out reflectasm if you feel like optimizing something that may not be an actual bottleneck… :wink:
http://code.google.com/p/reflectasm/

Yeah, although it looks like a cool project, it is probably premature optimization for me, and then I would bring back in ASM generators which is why I avoided Riven’s MappedObjects in the first place.

Also, I’ve added a couple of getting started and tutorial pages and have plans for more (so some links might not work): http://code.google.com/p/entreri/wiki/GettingStarted?tm=6

I honestly think bytecode transformation is the only way to make an entity system in Java. Without, the sourcecode just becomes too messy to work with. The Java language simply doesn’t fit this non-OOP approach.

You might be right, after writing up a tutorial on all the rules you have to follow to implement a component in my system, it certainly can be a little much to keep track of.

Being the one who wrote the library, I’m perfectly okay with it as is. I’ve been leery of byte code transformations for a while because I haven’t taken the time to understand them fully. Maybe it is something I can work with in my next version. For now, the external API is stable and I want to get the chance to really use it in my own games :slight_smile:

@Riven: Can you expand on this a little more? I may have missed earlier discussion in other posts if you shared anything before.

So far I’ve not seen a need for bytecode transformation in my efforts nor want to really go that way given J2SE / Android compatibility; I assume there may be some difficulty there. I admit maybe I’m missing something here. I’ve not pragmatically worked with bytecode transformation and things seem just fine without it for the component architecture / ES / and the whole expanded library of components with my efforts (600+ platform components!). Thanks for your thoughts.