Custom EntityId set

Hi,

Consider I have my own HashSet of EntityId’s once populated for some system. How do I properly check if particular entity still exists? Simply checking if ed.getComponent() returns null? Thanks!

Well, an entity always “exists” because it is only the ID. If you have an ID then you have an entity by definition.

So yeah, the only way to tell if it exists in some context is to test that context. In your case, see if it still has the component.

The question seems to indicate that something else may be wrong with your approach, though, since usually systems are already only operating on the entities that have the components that they are interested in… and thus they will stop seeing the entity once those components are gone.

Well, the task is to have separate systems for “populating” the base and for “selecting entities that have this and this” from it. Back to my beloved space ship: it has, say, observation system that decides which entities (ships in this case) are visible, and target designation system that decides which ships are most dangerous and forms its own subset to pass it to fire control systems as targets. I was thinking using EntityId’s is simple enough way of achieving this behaviour. Am I wrong?

I don’t think I have enough information. I can think of a few different ways to do it but I’m not sure which one fits your description.

Well I don’t have them all implemented yet, but here is what I have: Observing system works for every ship that has observer component which contains maximum distance and precision (in square degrees). What it does it scans the space in all directions (casting rays), calculating every next vector based on how many scans already passed. Thus, when it meets geometry that belongs to a ship, it adds its EntityId to the base. On the other hand, my fire control system only has EntityId of current target. To make link between them I plan to invent a third system that will take the base of observer, think on it, and then pass required EnityId to every fire control system that belongs to it. Something like this.

I guess it’s the fire control system that I’m not clear on. It almost sounded like there was one fire control system per… what I’m not sure.

Can you describe what kind of game this is and what bases and ships are in relation to that? Is it like a tower defense game or something?

Sure. Not really, it’s not tower defense, it’s more like space simulator like TIE Fighter (if you recall, by a chance). What I’m trying to achieve is modelling bots behavior of how do they react on enemy presence. This is the top level. Going down, I want to model a particular capital ship (i.e. large Star Destroyer if you like) that has to react on ships and vessels attacking him by choosing which ones are the most dangerous to him and correspondingly correcting its fire. A Star Destroyer can have certain number of blaster batteries and missile launchers, and has to designate targets to them properly. A fire control system in this case is a system that controls every blaster, or another one that controls every missile launcher. Now, considering I have lots of them onboard (i.e. belonging to one EntityId), I need to coordinate their fire by designating proper target for each particular one (based on distance, emergency level, whatever else - this is AI part in the end). That’s the essence of the system I want to build. I want every Star Destroyer (i don’t mean to violate copyrights ofc, that’s on for instance) to be able to overview all the targets, consider which are the most dangerous/vulnerable now, and to distribute the targets to fire controls, which will do their job of targeting and firing then.

To me, the primary thing will be what targets that a particular blaster/launcher can fire on… for example, the blasters on the starboard side of the ship will have trouble firing on a fighter on the port side of the ship. In that case, I could imagine a gun-centric firing system that then simply coordinates “best” targets from there. (ie: a gun picks its best target and then it is not available for other guns unless another gun has a better firing solution.)

But even assuming you really did want to coordinate this ship-wide, I can think of some approaches. (And perhaps even if you did the above the whole-ship version could ‘check the math’ so to speak.)

Mostly in an ES, we want to think of things in data oriented functional-style iterations. input → function → output. Sometimes we can’t get away with it and still must aggregate.

So presuming you’ve done spatial queries and already linked potential targets to the starship with some linking entity. Entity[PossibleTarget[targetId, starshipId]] or whatever.

…then your fire control system could go through all of those entities and build up lists of targets for particular starships (guava’s multimap is great for this). Then you could do a pass through that to sort them based on some overall priority and divvy it out to guns.

“What if a target was destroyed?” …well, you potentially have to deal with that but really some systems are probably already running in lockstep. How did the target get destroyed while this system was running? Some things should not be done in parallel.

Gun-centric approach has its drawbacks such as if enemy vessel is really dangerous, and our ship has its turrets partially destroyed, it has to rearrange its orientation so that its fire against target will be maximized… or even initiate withdrawal sequence. The last option, however, seems more or less trivial.

Yeah, seems like the turret-centric approach could be used as the prep stage for the whole starship decision making. Then you’d also know not only about enemy ships in proximity but how many turrets could actually fire on them and how well.

…and this means I have to store available turrets (EntityIds) somewhere to provide the base for decision making. Which means we’re going back to some custom set of them.

Heheh… I start to wish this was easier to diagram… but the per turret problem is just a smaller version of the per starship problem from my point of view.

Even if you connect target and turret with a linking entity, you still just process that whole set of entities collecting a per-turret structure… which is necessarily per starship already depending on the data structure. That part doesn’t have to be modeled with entities necessarily. Just a data structure in the system itself.

I do this all the time, actually. System-specific state.

Operating with data structures is not my power point, thus it looks for me like it is easier to operate with units hierarchy than to create a logical structure that outsmarts the creator (how typical, huh?). For me the easiest way looks like “collect this data here” → “bring them there” → “now its their problem to decide”.

Well, to me a “unit hierarchy” seems like something the AI is aware of. But what the ES hands the AI could be a set of targeting solution entities that link targets to turrets or something.

At every level, if you can think of a way to break it into an iterative/functional approach it seems better to me. Even if you have to collect some aggregated data to make the bigger decisions.

I like to imagine a big ship where the turrets are actually manned by gun crews with their own targeting, etc… a certain level of autonomy with the main ship sending down priority targets.

Anyway, it’s an interesting problem… but regarding your initial question, the systems that do this or rely on linking entities will have to deal with those links potentially pointing to bad data depending on when they were updated. (Really it’s better if if the systems are ordered so this doesn’t happen but let’s assume for a moment that it’s impossible for some reason.)

So in this case, you don’t care if the entity has been deleted… you only care if it has the stuff to still be a valid target. I mean, maybe the entity itself still exists but has been cloaked and so doesn’t have a visible model anymore or something. The fire control system has some targetId and uses that against a set of components that mean it’s still a real target. Maybe it changed state so it isn’t, maybe it was fully deleted… the system doesn’t care how it happened.

I do stuff like this in one of my physics layers but for slightly different reasons. If I have a spring link between two bodies that is represented (let’s say) by a Spring component that has two entity IDs. So there is an EntitySet of those entities with Spring components. But there is also still an EntitySet with the components that make some entities potential spring endpoints and so at any time I can check the spring endpoint IDs against that set.

kinda offtopic, but speaking of functional approach, why don’t you use in components constructions like this:

public ComponentIonFire newChargingPercentage(float chargingPercentage){
        return new ComponentIonFire(this.range,this.speed,this.energy,
                this.rate, chargingPercentage, this.target);
    }

and then in corresponding system:

ComponentIonFire old_c = ed.getComponent(e.getId(), ComponentIonFire.class);
                           ComponentIonFire c = old_c.newChargingPercentage(0);
                           ed.setComponent(e.getId(), c);

Isn’t it basically the same as recreating components right in the logic code? To my noobish point, this kinda reduces flood of lines in logic.

In my own code, I do this all the time if I have components with many fields. All of the this.'s are even unnecessary and you can just cut and paste the methods with new names/parameters.

For example:

public class Position implements EntityComponent {
    private Vec3d location;
    private Quatd facing;
    
    public Position() {
        this(0, 0);
    }
    
    public Position( double x, double y ) {
        this(new Vec3d(x, y, 0), new Quatd());
    }
    
    public Position( Vec3d loc ) {
        this(loc, new Quatd());
    }
    
    public Position( Vec3d loc, Quatd quat ) {
        this.location = loc;
        this.facing = quat;
    }
    
    public Position changeLocation( Vec3d location ) {
        return new Position(location, facing);
    }

    public Position changeFacing( Quatd facing ) {
        return new Position(location, facing);
    }
    
    public Vec3d getLocation() {
        return location;
    }
    
    public Quatd getFacing() {
        return facing;
    }
    
    @Override
    public String toString() {
        return "Position[location=" + location + ", facing=" + facing + "]";
    }
}

Though in this case, 90% of the time I’m changing both values so I just use new.

I was referring primarily to Asteroid Panic code. But, you could outline recreation to show that there’s no setters once more, I agree. Well, thanks for the replies, I will think further in my “how to” :smile: