Removing components from entityData, how to do it right?


#1

I want to remove a single component from an entity. I use an EntityContainer and I will add another component when I noticed that the first one was removed.

Here is a Test which does the remove and add in a simplified way. This will lead to a NPE

public class ESTest {

  public static void main(String[] args) {
	EntityData ed = new DefaultEntityData();
	EntitySet entitySet = ed.getEntities(Name.class);
	// add new entity
	ed.setComponents(ed.createEntity(), new Name("Test"));
	if (entitySet.applyChanges()) {
		for (Entity entity : entitySet.getAddedEntities()) {
			Name name = entity.get(Name.class);
			System.out.println(name.getName());
			ed.removeComponent(entity.getId(), Name.class);
		}
	}
	// since there is no Name component on the entity it
	// will be removed from the set
	if (entitySet.applyChanges()) {
		for (Entity entity : entitySet.getRemovedEntities()) {
			System.out.println(entity.getId());
			// now this will cause a NPE..
			entity.set(new CreatedBy());
		}
	}
    }
}

Exception location:

Exception in thread "main" java.lang.NullPointerException
 at com.simsilica.es.base.DefaultEntity.set(DefaultEntity.java:120)


...
@Override
public void set( EntityComponent c ) {

    for( int i = 0; i < components.length; i++ ) {        
        if(components[i].getClass().isInstance(c) ) {               
            ed.setComponent( getId(), c );
            components[i] = c;
            return;
        }             
    }
        
    // We can still pass through the value to the EntityData even
    // if we can't return it
    ed.setComponent( id, c );
}

components[i] is null. Checking if its null before getClass() is called would fix it.

Now, the question is. Do I use it correctly?


#2

I dont think you should modify an Entity set Manually at all and especially not while iterating.
Use entitydata.setComponent (eId, new XYZ ())


#3

I call the remove on the entity data, not the set.

In my case I want to add a component and “consume” it. Maybe it is the wrong concept…

In general should I ever use removeComponent?


#4

You can, if need be. There’s nothing wrong with it. Just use EntityData methods:


#5

Yes, it’s a wrong concept.

It sounds like you are trying to get around keeping system-local data in the system… but without further information about your use-case it’s hard to say.


#6

Thank you all for your answers.

I’ve added a component to set an “attached” state to remove the rigid body in the physics system and attach it to the an other block. Also I want to detach it and put it back to physics system.

You said my concept was wrong. So now I have an Attach component with a flag “isAttached”. I hope this is more the ES way :slight_smile:

Here is the current wip.


#7

Usually for something like this (without knowing more) you’d have an Attached component that pointed to the entity to which the child was attached. When it was no longer supposed to be attached then you’d remove the Attached component… which would logically take it out of the entity set. There is no reason at that point to set another component or anything.

It’s the swapping thing that caused you issues and its the swapping thing that seemed like a non-ES thing to do.