How does ZayES compare with Ashley?

Well that question is not really Zay es specific,

What you often do in an ES system is to have normal java pojos doing the processing. For example the largest use case for that in my game would be the ship computers.

In the es there is a component specifying the computer’s existence and a few properties, like processing speed.
The Computer system basically then maintains a filter and a map uuid of entity with computer to a luaj runtime object.

This way I have a clean ES state of the game, but can still use extensive oo based librarys for processing the data they represent.

(i’m a user of my own Empire-ES :P, but zay es and my system are actually behaving pretty much 100% the same way)

I wouldn’t recommand it.

ECS can give headache on it’s own. Mixing it with traditional OOP will brake the contracts that help you keeping things simple and stupid. You wil probably find it strange and unpredicatable where ECS is definitly not.

I recommand to do as much ECS as possible, or none.

1 Like

So let’s suppose I am on a dungeon and I have an “HitPoint component” with value 100. Then I wear a magic ring that gives me a boost of hitpoints (component “hitpoint booster”). Then I drink a magic potion that gives me a temporary boost of hitpoint.

Does this scenario require “nesting” of components? So that the magic ring is like the potion, except for that the latter has a decay?

How should the original HitPoint component keep track of all the boosting components?

This has been covered in other threads a few times… even recently.

The ‘buffs’ would be their own entities attached to the player. You’d have one system somewhere that was responsible for adjusting player hitpoints up/down depending on damage entities or buff entities attached to the player.

Then you can decay those entities just like anything else… either to stop the effect of the potion or let the fire burn out on that fire damage.

1 Like

And note, the beauty of the ES is that this is not even specific to players. It would work for anything with buff/damage entities and hitpoints. So you could even light a chair on fire if it had a Hitpoints component.

1 Like

I would highly suggest to study first the asteroid panic from @pspeed. There is a thread Asteroid Panic: Why is Spatial in HashMap instead a Component - #18 by ia97lies of mine where I did try to understand that implementation. I asked a lot of stupid questions and got a lot of good and very detailed answers there. With that help it took me about 2 days to write my own simple clone of invaders with ES :smile:

And this is as well a helpful thread ES Design Question - #33 by pspeed with a lot of good advices/hints/explanations.

Just one remark on this all or none. I think on the same abstraction level, yes absolute. But on a different abstraction level not necessarily true in my opinion. On a different abstraction level you can have also more “traditional” code. Game logic, AI and the like.

Well that’s true. I’ve found myself overkilling the “ECS at al cost” rule many times, like when I wanted to manage IA behaviors as component, or the terrains node as entites.

An ECS can effectively communicate with a physic engine, an IA behavior tree or state machine, a terrain generator. It actually is communicating with the viewing managed by jMonkey in our case.

But all those are now systems for the ECS :smile:

        node.setUserData("eid", myEntityID);

I thought it was a cool idead to attach an entity to a spatial, so that on collision (managed by the scene graph) I can pull the game logic. My first attempt didn’t go well… I’ll do something else :stuck_out_tongue:

GRAVE: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.IllegalArgumentException: Unsupported type: com.simsilica.es.EntityId
at com.jme3.scene.UserData.getObjectType(UserData.java:124)
at com.jme3.scene.Spatial.setUserData(Spatial.java:1357)

EDIT: maybe this will work?

node.setUserData("eid", myEntityID.getId());

EDIT2: Ahem… is there a way to get the EntityID from the “entity ID”? :confused:

spatial.setUserData("EntityId", entity.getId().getId());

Works for me. user data only accept primitive values :

public static byte getObjectType(Object type) {
    if (type instanceof Integer) {
        return 0;
    } else if (type instanceof Float) {
        return 1;
    } else if (type instanceof Boolean) {
        return 2;
    } else if (type instanceof String) {
        return 3;
    } else if (type instanceof Long) {
        return 4;
    } else {
        throw new IllegalArgumentException("Unsupported type: " + type.getClass().getName());
    }
}

Thanks! But how do I retrieve the EntityID… from the entity ID? :stuck_out_tongue:

By the way, setUserData accepts Savable. So you can put virtually anything on a spatial :smile:

But I don’t want to extend EntityID to make it savable… hope there is a better way (besides managing the scene graph from the entity system)

EDIT: to clarify, I’d like to use something like this:

EntityData.getEntityByID(long id)

…so that I can retrieve the EntityID which was attached to the aforementioned Spatial.

EntityId id = new EntityId(spatial.getUserData("EntityId"));
entityData.getEntity(id, MyComp1.class, MyComp2.class);

You have to know that you can’t retreive an Entity, expecting an object with all its components attached. The object Entity represent a bucket, filled with the component you ask like in my exemple.

If you want to get a specific component of an entity, it may be simplier to write :

MyComp c = entityData.getComponent(eid, MyComp.class);

Knowing that it could be null if no such component is attached on that entity

Nope, for now I just need the EntityId. Added the method on my fork:

https://github.com/Pesegato/zay-es/commit/892b18f81559b61b6141821e8ed36cc6748fad3b

@pspeed probably this is an antipattern for some reason, however should I make a PR? :wink:

Why would you want the EntitData to save EntityId objects and provide them back?

EntityId implements comparable and overrides hashCode() and equals(). Just build a new EntityId from your long value ^^

???

EntityId entityId = new EntityId(someId);

…that’s how you get an EntityId from an entity ID. Don’t know why you need to add a method for it.

EntityId instances or not NOR SHALL THEY EVER BE considered ==. Just don’t do it. You will screw yourself up 10000 ways.

Not to mention, storing them in a map is a HORRIBLE HORRIBL 1000 times over approach.

You may have MILLIONS of entity IDs in the course of a game. You definitely DO NOT want to save them around like that. Just really bad. Don’t do. Can’t stress this enough.

It’s a sign that you misunderstand something about ES somewhere.

Okay I hadn’t noticed the intention was to use the “==” logical comparator. As it can’t be overriden in java, just use equals instead.

I admit that for 6 months I use zay-es, I’ve never had to compare EntityIds, thought ^^ but I can’t tell if it’s wrong.

I don’t know that it’s the intention but I was giving the benefit of the doubt as to why it would feel necessary to keep the instances around.

It’s not. Just a bad idea.

I use EntityIds in hashmap all the time. I compare them if I’m writing .equals() for components that have EntityIds. That’s probably it. I use .equals() in all cases, though.

I’ll try to explain.

I want to attach an entity “effect” to a Spatial, so that when the Spatial collides with another Spatial, I can retrieve the original effect from it and attach a “touching” component; so that I can later retrieve all the “effect”+“touching” entities and process them…