esper icon indicating copy to clipboard operation
esper copied to clipboard

Create an entity with a specific id

Open woogyface opened this issue 1 year ago • 2 comments

Hello,

i use esper for my roguelike game. I save entities in a sqlite database where i also save the entity id to have a relation between entities and the components.

Saving is pretty easy. Loading not so much. Let me explain

my db looks like this (shortend for better explanation) Entity Table

id entity_id
1 13
2 27
3 5

Position Table

id entity_id x y z
1 13 0 10 0
2 27 10 3 0
3 5 7 2 0

as you can see it pretty easy to see how these tables are releated. to get the position of an entity i query the db for the position where the entity_id is the same as in the Entity table.

As i found no other solution this is how i do it now:

  1. I select the entity (i.e 13) with all it components in my db
  2. create an entity with world.create_entity() (i.e i get 55 as id)
  3. add all the components from entity 13 to the new entity 55
  4. update the old entity id 13 in the db with the new id 55 and all its components that relates to id 13

that is pretty dirty imo. it would be awsome to create a "known entity" so i don't have to update the db everytime the id is changing. i.e:

entity = world.create_known_entity(13)
world.add_component(entity, position)
...

sorry for my english. i tried my best to explain my problem. if there are any questions i can try to explain it better

woogyface avatar Aug 04 '22 22:08 woogyface

Thanks for opening the ticket, and I'm glad you're enjoying esper.

Can I ask why it's important that entities have the same ID after loading? The proposed patch would work, but it's a bit outside of typical ECS structure. The Entity ID happens to be an integer, but it's meant as a throw-away value.

Instead of storing the ID, if possible, I would recommend using a Component to "tag" specific Entities.

class Player:
    pass

class EnemyTypeA:
    pass

class EnemyTypeB:
    pass

There may of course be multiple of the enemy types, but there would only be one entity tagged with Player. This allows you to specifically query that entity, if you need to.

benmoran56 avatar Aug 05 '22 09:08 benmoran56

I already use components as "Tags" and it works fine how i use it but my game has "unpredictable" Enemies aka an Entity with a random set of Components. It may work with a restructure of my db layout. I might make it possible without using the entity id as a key but changing components would be hard.

having a db without entity id as key might be look like this: Entity

row_id components
1 "Position(7,3,0);Color(255,0,0);Faction(12);IsGiant();IsOrc();IsNPC();DialogTree(44);Level(3)"
2 "Position(7,3,0);Color(255,0,0);Faction(12);MoreRandomComponents()"
3 "Position(7,3,0);Color(255,0,0);Faction(12);EvenMoreComponents()"

that way i have just one table in my db (what i don't really want to happen) and i don't need the entity id as a key as i can distinguish by the components. Now just imaging what i have to do to change the Position of a specific entity. i gets messy real fast.

my other solution would be to add a secondary id component to my entities like a RandomEntity having components Position, Color, Faction, etc AND a must have SecondaryIdComponent() like a string or another int which is different for every Entity.

It just might be "the problem saving ECS to a DB". I've never done it and it might be a stupid use case but i want to do like that to learn it.

Having a way to create known entities with specific ids would be the easiest solution for me. if it's not complieant with an ECS than that's ok. I have ways to work around it but it would make my life a little bit easier :D

woogyface avatar Aug 05 '22 10:08 woogyface

Sorry for leaving this hanging for so long. I think for the main Esper releases I want to keep it as-is, just for performance reasons (even if very small).

That said, it would be pretty easy to subclass World with a custom create_known_entity(id) method. It could probably work alongside the existing method as well. Would that work for you?

benmoran56 avatar Oct 01 '22 08:10 benmoran56

Closing this due to lack of follow up.
On careful consideration, I don't think this makes sense in mainline esper, due to placing relevance on what is supposed to be nothing more than a UUID (even if it's an int in implementation).

This behavior can be achieved using a custom function. If you need help in producing something like that, please follow up or open a new ticket. Thanks!

benmoran56 avatar Oct 04 '23 02:10 benmoran56