JMonkey Entity System

JMonkey Entity System

Introduction:
If you are new to this topic I recommend you to read Sploregs An introduction to Entity Systems:

Why not using Artemis? (The Artemis Framework: Entity and Component Game Design | Gamadu)
I decided to make an entity system jmonkey core team style.
Artemis for example has some disadvantages. Artemis Components have getters and setters, it does not support
multiple threads and the term System does not stand for everything else than the components.
Furthermore I am not sure if the Artemis group concept fits into an entity system.

Concept:
The concept is based on Pspeed and Normens Comments they wrote in the other entity system threads:
(mainly http://hub.jmonkeyengine.org/forum/topic/entitymonkey-a-simple-entity-system-for-jme/#post-186678 and
http://hub.jmonkeyengine.org/forum/topic/an-introduction-to-entity-systems/#post-196576)

Short comprehension:
1)Components have only getters and 1 constructor. You do not change the component of the entity, you replace it with a new one.
2)An entity can only have 1 component of the same class.
3)Systems are not special classes attached to the entity system.
Simply all objects that use entitys/components can be called a system.
4) Inside the Entity System Entities are only an Id. (long)
5) To work with the Entity System you use EntitySets.
You create an EntitySet by calling a method of the EntitySystem and passing all Component classes of the
components you are intrested in.
6)The EntitySet contains Entity objects which only contain the data that are relevant for this EntitySet.
7)Changing one of this Entity Objects creates an EntityEvent that is passed via the EntitySystem to all
other EntitySets who contain this Entity (Id) and are stored in a list.
To update your EntitySet call the applyChange() method and all entity objects of this set will be updated.

Class Graph:

Event Graph:

Examples:
Create a new Entity
[java]entitySystem.newEntity(new TestComponent(“TestData”));[/java]

Create an EntitySet
[java]EntitySet entitySet = EntitySystem.getInstance().getEntitySet(TestComponent.class);[/java]

Work with changed entitys:
[java]if(entitySet.applyChanges())
{
add(entitySet.getAddedEntities());
changed(entitySet.getChangedEntities());
removed(entitySet.getRemovedEntities());
}[/java]

Iterator through the EntitySet
[java]Iterator iterator = entitySet.getIterator();

while (iterator.hasNext()) {
Entity entity = iterator.next();

//do something
}[/java]

To Do:
-Hear and consider feedback (Maybe I made some mistakes in the concept)
-Make filter for entitysset to allow and/or combinations of component classes
-Add a SQL implementation of the EntityData
-Search bugs/test multithreading

Download (pre-alpha):
This is the very first release, i do not recommend to use it in a project because it can contain many bugs
EntitySystem
EntitySystem example
(Make sure that the EntitySystem project and the testAssets are included in the example)

I would love to get some feedback from the entity system experts here.

Edit: Again my post got eaten by the forum, I hate it.

9 Likes

It seems this is a great project! That’s what JME needs!

Wow, great work. This is how I imagine OSS development, thanks for marking that what we say and do doesn’t just vaporize in the depths of the web :wink:

I’ll look at it some time soon but atm I am quite busy at work because a colleague is sick and I have to replace him. I guess @pspeed will also but I know that he also doesn’t have much time at the moment. Thanks a lot for doing and sharing this!

Thanks a lot for doing this! Why is EntitySystem a singleton?

Looks like you extracted the design from those conversations pretty well. I might only quibble over naming.

Recognizing that all of that is 100% subjective I will still share my thoughts on the matter.

  1. I chose to completely remove the word “System” from mine because in the topic of “entity systems” the word “system” is overloaded and dangerous. That’s why my main access class is “EntityData”… it is the thing that lets you get at the entity data. Where you have EntityData I have the internal interface ComponentHandler… it’s responsible for handling one type of component.
  2. You use addComponent() where I use setComponent(). The first (to me) implies that I might be able to add more than one of a particular type of component. “set” makes it clearer that you can only have one NameComponent.
  3. On what you call EntityData and I call ComponentHandler, I have a getEntities(args) that simply returns a Set instead of your more longly named version. In retrospect, I kind of wish I’d called it findEntities(). I have another method already findEntity() which returns just the first one found.

Random things:
-I think it might be better to abstract all of the “long” as an actual immutable EntityId class.
-the singleton approach is sensible but a little dangerous here. I can conceive of a few hypothetical examples where more than one “entity system” instance might be needed… and at any rate when more than one isn’t needed generally the application already has some singleton they could hang the entity system instance off of.
-my ComponentHandler automatically assumes the component type so that it doesn’t need to be passed, but…
-my EntityData (your EntitySystem) is just an interface so I can have multiple implementations at that level (in fact I have several). This negates the need to have multiclass-capable ComponentHandlers and simplifies their interface a lot.

[java]
public interface ComponentHandler<T extends EntityComponent>
{
public void setComponent( EntityId entityId, T component );
public boolean removeComponent( EntityId entityId );
public T getComponent( EntityId entityId );
public Set getEntities();
public Set getEntities( ComponentFilter filter );
public EntityId findEntity( ComponentFilter filter );
}
[/java]

It is then the main “entity system”'s (EntityData for me) job to figure out which component handler to call based on what is passed to findEntities.

For posterity her is my main entrypoint interface. You captured most of this already in your EntitySystem.

[java]
public interface EntityData
{
public EntityId createEntity();
public void removeEntity( EntityId entityId );
public void setComponent( EntityId entityId, EntityComponent component );
public void setComponents( EntityId entityId, EntityComponent… components );
public boolean removeComponent( EntityId entityId, Class type );
public T getComponent( EntityId entityId, Class<T> type );
public Entity getEntity( EntityId entityId, Class… types );
public EntityId findEntity( ComponentFilter filter, Class… types );
public Set findEntities( ComponentFilter filter, Class… types );
public EntitySet getEntities( Class… types );
public EntitySet getEntities( ComponentFilter filter, Class… types );
public void releaseEntitySet( EntitySet entities );

public void execute( EntityProcessor proc );
public void close();  

}[/java]

I’ve always meant to release mine but I don’t have time to support it right now. Now I’d worry about stepping on toes so hopefully my comments are well received. :slight_smile:

2 Likes
@pspeed said: (...) I've always meant to release mine but I don't have time to support it right now. Now I'd worry about stepping on toes so hopefully my comments are well received. :)
You might never have time to support it, so now might be as good a time as any to release it. It'd give ogerlord another great point of reference, and it's probably also interesting to look at for any one of the many developers who've already received some advice from you about entity systems on this forum.

@ogerlord this is a wonderful contribution. We might finally have the one link to rule them all when people come here asking questions to make their entity systems “the jME way”. Big chunks of the advice the developers have shared on this forum really ought to be made easily accessible in wiki pages. If you can help us organize all this info, that’d be a huge contribution to the community at large.

1 Like

@pspeed
I know that you dislike the word system but I do not see such a big difficulty here.
But i agree that renaming addComponent to setComponent makes it more clear.

You use the EntityId in your main class?
In my approach you only interact with the entitys via the EntitySets. Thats why I removed the setComponent/removeComponent/removeEntity methods from my EntitySystem class.
Now you are only able to change the entitys by using one of the Entity Objects.
This is my interpretation of Normens “Do not pass naked longs”. Ok, you use your EntityId class (which saves memory), but I am not sure in which cases it is useful to have this direct access.

the singleton approach is sensible but a little dangerous here
I thought the singleton approach would be a good idea because I do not pass the EntitySystem to every single Entity Object. But I dont like the singleton pattern, too. I felt dirty implementing it. Maybe you could name some of you hypothetical examples with mutliple Entity Systems, for me it sounds more like a conflict. But the fact that your EntityData is an interface means you already use different EntitySystems?

@ogerlord One usecase for multiple entity systems could be in a game server which is hosting more than one game at a time.

It really shouldn’t be a problem as long as theres not too many locks. In the end each application, game or sub-application will only use its set of entities with its id’s. If you don’t reuse your ID’s you basically cannot run into issues.

Suppose I have two games running in the same entity system, none of the games have anything to do with each other. Then I query for all entities with componentX, I will get a result containing entities from both games. How can this not be an issue?

@ogerlord said: @pspeed I know that you dislike the word system but I do not see such a big difficulty here. But i agree that renaming addComponent to setComponent makes it more clear.

You use the EntityId in your main class?
In my approach you only interact with the entitys via the EntitySets. Thats why I removed the setComponent/removeComponent/removeEntity methods from my EntitySystem class.
Now you are only able to change the entitys by using one of the Entity Objects.
This is my interpretation of Normens “Do not pass naked longs”. Ok, you use your EntityId class (which saves memory), but I am not sure in which cases it is useful to have this direct access.

I thought the singleton approach would be a good idea because I do not pass the EntitySystem to every single Entity Object.
But I dont like the singleton pattern, too. I felt dirty implementing it.
Maybe you could name some of you hypothetical examples with mutliple Entity Systems, for me it sounds more like a conflict.
But the fact that your EntityData is an interface means you already use different EntitySystems?

I have different entity system implementations. For example, I have a RemoteEntitySystem for interacting with the server. I don’t necessarily have them instantiated at the same time but I can imagine such use cases. Actually, I think I cheat and have a static field on my DefaultEntity class (Entity is an interface also). That’s set when a particular implementation is initialized. So I can’t have more than one at a time either… but I avoided a singleton pattern since I have multiple implementations that can be swapped in and out.

I use EntityId for the cases where I want the ID and not the whole entity. Also, an Entity will only return the components that you originally asked for. If you want different components then you have to go directly to EntityData.

But mostly, 90% of my EntityComponents have an EntityId field pointing to a parent or to relationships between entities, etc… It’s extremely important.

I have some cases where I query just the EntityIds and not full Entity implementations. I’d have to look in my code to see what I needed this for but I added it specifically at some point.

@kwando said: Suppose I have two games running in the same entity system, none of the games have anything to do with each other. Then I query for all entities with componentX, I will get a result containing entities from both games. How can this not be an issue?

Yes, that’s true… though really I would think multiple games in a server should be in there own isolated class loaders for about a hundred reasons. In that case, singletons would still be game specific.

@pspeed Hmm, I have never used custom class loaders before so I did not know about all the magic they could do… seems like there is never-ending stream of new stuff to learn =)

]But mostly, 90% of my EntityComponents have an EntityId field pointing to a parent or to relationships between entities, etc.. It’s extremely important.
Okay, thats a good point. Added the EntityId class.

Meanwhile i finished the first example:

Its a simple game where you must shoot the enemys who tries to reach you. (move WASD, aim and shoot with the mouse)
To display the models I use the EntityControl class Normen posted in the other thread.
For every task I made a new AppState (PlayerInput/Movement/Display/Collision…)

This is how the AppState for the expires time of the bullets works:
[java]public class ExpiresAppState extends AbstractAppState {

private EntitySet entitySet;

@Override
public void initialize(AppStateManager stateManager, Application app) {
entitySet = EntitySystem.getInstance().getEntitySet(ExpiresComponent.class);
}

@Override
public void update(float tpf) {
entitySet.applyChanges();

Iterator iterator = entitySet.getIterator();

while (iterator.hasNext()) {
Entity entity = iterator.next();

float time = entity.getComponent(ExpiresComponent.class).getTime()-tpf;

if(time <= 0)
{
entity.destroy();
}else{
entity.setComponent(new ExpiresComponent(time));
}
}
}
}[/java]

3 Likes

@pspeed
I have a few SQL questions, I thought about using reflection to save and load components:
-What do you do if a component has a Vector or some other non basic type as an attribute?
-Is it possible to prevent that multiple EntityId/Component objects are created instead of using the only instance that would be necessary?
-How can i create the instance of a class if the components do not have the standard empty constructor?
-Which SQL driver would you recommend?
I am not that familiar with this topic

@ogerlord said: Okay, thats a good point. Added the EntityId class.

Meanwhile i finished the first example:

Its a simple game where you must shoot the enemys who tries to reach you. (move WASD, aim and shoot with the mouse)
To display the models I use the EntityControl class Normen posted in the other thread.
For every task I made a new AppState (PlayerInput/Movement/Display/Collision…)

This is how the AppState for the expires time of the bullets works:
[java]public class ExpiresAppState extends AbstractAppState {

private EntitySet entitySet;

@Override
public void initialize(AppStateManager stateManager, Application app) {
entitySet = EntitySystem.getInstance().getEntitySet(ExpiresComponent.class);
}

@Override
public void update(float tpf) {
entitySet.applyChanges();

Iterator iterator = entitySet.getIterator();

while (iterator.hasNext()) {
Entity entity = iterator.next();

float time = entity.getComponent(ExpiresComponent.class).getTime()-tpf;

if(time <= 0)
{
entity.destroy();
}else{
entity.setComponent(new ExpiresComponent(time));
}
}
}
}[/java]

Good things… Some possible remarks:

  • i think bullets should not be entities. If you shoot 1000 bullets per second… you will get out of Long/Integer range.
  • Normen’s code has Spatial system as Control.class. Are you sure this is a good idea to have every control per model? if you will have 2000 entities with 2000 control’s updates? Possibly artemis makes it in some way smarter? I mean update of entities.

PS: possibly i’m wrong. As i’m not so advanced in this topic…

The way I managed projectiles (very short lived objects) was to use an IdPool for generating reusable Ids, and then overriding entityId and setting it as the negative pool id.

Same way can be done for whatever you dont need to actually have a unique id over a long time, static objects predefined by the world for example.
For any entities you wish to save for a long time (using database or similar) you will use the positive id space.

ie:
Players/Items (Positive Long range) (stored in database)
Static objects/Projectiles/NPCs (Negative Long range) (short lived or reinstanced every server restart)

1 Like
@perfecticus said: The way I managed projectiles (very short lived objects) was to use an IdPool for generating reusable Ids, and then overriding entityId and setting it as the negative pool id.

Same way can be done for whatever you dont need to actually have a unique id over a long time, static objects predefined by the world for example.
For any entities you wish to save for a long time (using database or similar) you will use the positive id space.

ie:
Players/Items (Positive Long range) (stored in database)
Static objects/Projectiles/NPCs (Negative Long range) (short lived or reinstanced every server restart)

Then this is ok.
But @pspeed and @normen advised not to reuse IDs. Possibly here should be a final discussion about reusing IDs.

Nobody forces you to use int/long id’s. I use String for example

Regarding the performance problem, if you move 2000 bullets you always have to update 2000 objects, if they are entitys or POJO’s doesn’t matter.
Additionally for a current average computer 2000 entites is ‘nothing to do’. The thing gets interesting when it comes to a few 100k entities…

No way you’ll ever get out of Long values. That’s more values than there are atoms in the universe, and certainly more than there are bytes in any computer.
Even Integer is hard to overflow, 1000 values/s, the overflow will occur after roughly 2 million seconds or 23 days.
Lesson to take home: use longs and stop worrying :slight_smile:

On some older topics, just my 2 cents:

  • I’d avoid System as a term. It’s far too overloaded and generic and those reading the code won’t understand what it’s good for. Worse, the library design won’t understand it either, and experience shows that such classes tend to become the cruft bucket where everything is thrown into.
  • I’d also avoid singletons. They restrict the design space of those using them. People might want to keep a backup of old state around (for persisting, or to provide historic data in some lag compensation schemes); people might want to run multiple games in the same JVM (and, no, “you don’t want to do that” is not a valid reason, there are always trade-offs for or against a specific design); people might want to define a subclass; or there might be something entirely different that none of us is thinking about right now. Reread the secion on the Singleton pattern, each pattern comes with a list of downsides, and that list is pretty long for Singleton.
  • That said, a convenience class that provides a singleton instance of an entity system is okay. Just don’t make the remaining code depend on that singleton, always pass the object around explicitly.
  • In general, singletons are a good pattern only for stuff that is GUARANTEED to exist just once. Physical constants like speed of light, the map of Earth and similar stuff come to mind. The objects managing a loaded native library would be an example from programming - you can’t load the same lib multiple times in Java anyway, so there’s no point in trying to avoid Singleton there.