Entity System, Boolean, Double Messages

Hello Everyone,

I am wondering the correct way to go about using an entity system to create basically a boolean. Currently I am using a empty component called “OnABoat” that I add when my player entity is on a boat and then remove when I am no longer on a boat. I seem to be getting a weird behavior when I do it this way which I am a bit confused about. I have added OnABoat.class to the serializer because I need it for visualization on the client.

First time I am on a boat, seems fine:

20:07:55,518 INFO [MessageDebugger] Received:EntityDataMessage[3, [ComponentData[EntityId[2], [[OnABoat]]]]]

I remove the entity and put it back on later … the message doubles

20:08:37,408 INFO [MessageDebugger] Received:EntityDataMessage[3, [ComponentData[EntityId[2], [[OnABoat]]]]]
20:08:37,408 INFO [MessageDebugger] Received:EntityDataMessage[4, [ComponentData[EntityId[2], [[OnABoat]]]]]

etc etc, it continues to add a message every time I remove and re-add the component.

Is this expected behavior?

ed.removeComponent(entityId, OnABoat.class);
ed.setComponent(entityId, new OnABoat());

is how I am adding/removing the component.

Thanks

It’s not expected behavior.

Makes me wonder if you are creating a new EntitySet each time and then not releasing an old one. Hard to say without knowing what you are doing with OnABoat on the client.

There is no reason for it to be sent more than once unless requested more than once.

The code I’m using on the client is as below

        EntitySet es;
        
        public Mob(Entity entity) {
            this.entity = entity;

            this.spatial = createModel(entity);

            BodyPosition bodyPos = entity.get(BodyPosition.class);
            // BodyPosition requires special management to make
            // sure all instances of BodyPosition are sharing the same
            // thread-safe history buffer.  Everywhere it's used, it should
            // be 'initialized'.            
            bodyPos.initialize(entity.getId(), 12);
            buffer = bodyPos.getBuffer();

            // Starts invisible until we know otherwise           
            resetVisibility();
            
            int tankType = ed.getStrings().getStringId("tank", false);
            ComponentFilter filter = Filters.fieldEquals(ObjectType.class, "type", tankType);
            es = ed.getEntities(filter, OnABoat.class);

        }

        public void updateSpatial(long time) {

            // Look back in the brief history that we've kept and
            // pull an interpolated value.  To do this, we grab the
            // span of time that contains the time we want.  PositionTransition
            // represents a starting and an ending pos+rot over a span of time.
            PositionTransition trans = buffer.getTransition(time);
            if (trans != null) {
                //log.info("UpdatingEntityId: " + entity.getId());
                //log.info("Entity: " + entity.toString());
                spatial.setLocalTranslation(trans.getPosition(time, true));
                spatial.setLocalRotation(trans.getRotation(time, true));
                setVisible(trans.getVisibility(time));

                if (es.applyChanges()) {
                    
                    Set<Entity> removedEntities = es.getRemovedEntities();
                    Set<Entity> addedEntities = es.getAddedEntities();

                    if (!removedEntities.isEmpty()) {
                        if (spatial.getName().contains("tank")) {
                            for (Entity ent : removedEntities) {
                                ((Node) spatial).getChild("Models/BoatMesh.blend").setCullHint(Spatial.CullHint.Always);
                            }
                        }
                    }

                    if (!addedEntities.isEmpty()) {
                        if (spatial.getName().contains("tank")) {
                            for (Entity ent : addedEntities) {

                                ((Node) spatial).getChild("Models/BoatMesh.blend").setCullHint(Spatial.CullHint.Inherit);
                            }
                        }
                    }

                }
            }
        }

In class Mob

Thanks for your help :smiley:

So for every Mob you create a new entity set that asks for all tanks on a boat. That’s definitely not right design-wise.

What is it that you are actually trying to do?

I am trying to track globally which tanks are currently on boats for the purposes of updating the visuals. Tanks are always players.

Thinking about it a bit more this should probably be an AppState rather than part of the mob class.

Yes, definitely.

As it is now, you aren’t tracking it globally… you are tracking everyone in everyone. n x n

I switched these sections of code over to an AppState and now it works as expected. Thank you for your help pspeed. I was having a derp moment when I wrote that code originally lol.

Mithrin