A quick tour of Entity-Components in BotLG

I’ve started working on a better entity system for BotLG. The current code for dealing with entities — monsters, NPCs, things you can interact with in some way — is a bit of a rat’s nest of objects referencing each other, and creating a new monster or NPC means adding references in a half-dozen different places. It’s not ideal.

So, I’ve come up with a new system, using an Entity-Component pattern. There’s one base Entity class, which consists only of a unique identifier and properties for storing location and speed. More specific entities can be created by extending that class, but thanks to the Component system, they don’t really need to be. Components represent a bundle of properties about an entity, and the methods needed for working with them. For example, let’s make a rat.

let boris = new Entity();
boris.name = 'Boris the Rat';

(In actual fact, you wouldn’t make Boris like this. There’s an EntityManager class that creates entities and puts them in to a collection, so the rest of the game knows where to find entities, and the scheduler can loop through them, and so on.)

Now that Boris exists, we can add some components to him. Rats have legs, so they can move. So:

boris.addComponent(new canMove());

The canMove component (all of my components are in the format canDoThing or hasSomeProperty) gives Boris a .move(dx, dy) method, so he can be moved around the map. We should probably also give him some health, and the ability to die from any wounds taken:

boris.addComponent(new hasHealth());
boris.addComponent(new canDie());

Great! This highly modular approach means writing new actions and abilities for entities can be split into much smaller chunks, and entities can share components. It also means I can things like saying; this attack cripples creatures, making them unable to move, so:

boris.removeComponent('canMove');

One slight downside to this implementation is that you might have some code that ends up trying to perform a method call on an entity that doesn’t support it. What would happen if we tried (the hypothetical):

boris.fly(dx, dy);

Well, rats can’t fly. There’s no canFly component, and even if there was, Boris doesn’t have it. There are two options here. Either we wrap every attempt to do something up in a check:

if (boris.hasComponent('canFly')) {
boris.fly(dx, dy);
}

or we take advantage of the .try() method that every Entity has:

boris.try('fly', [dx, fy]);

Entities, components, actions and certificates

Saw this article about LetsEncrypt, the service I use to get my HTTPS certificates, accidentally revoking millions of certificates… and then noticed the email from them in my inbox informing me that they’re very sorry, but all of my domains are affected.

On Wednesday, March 4, Let’s Encrypt – the free, automated digital certificate authority – will briefly become Let’s Revoke, to undo the issuance of more than three million flawed HTTPS certs.

The Register: Let’s Encrypt? Let’s revoke 3 million HTTPS certificates on Wednesday

Luckily fixing it was as simple as SSH’ing into my server and running certbot renew –force-renewal, so it was no great emergency. Still, I imagine tomorrow a whole swathe of domains across the internet will be suddenly insecure and promoting browser warnings all over the place.

In roguelike development news, I for some work done on the new Entity/Component/Actions system I’m going to be using for BotLG.

So far I’m really pleased with it. Soon I’ll begin putting it into the BotLG codebase and converting the existing game verbs over. It’s so much cleaner and easier to expand than the current entity/NPC system.