Page 1 of 2

entity.id, a unique, persistent ID

Posted: Tue Jul 07, 2015 8:34 am
by ljdp
Add a unique and persistent identifier for entities.

Re: entity.id, a unique, persistent ID

Posted: Sat Aug 08, 2015 12:14 am
by Wyrm
This may not be necessary if entity references in the implementation do not change from load to load — in which case, entity.id already exists: this_entity.id == this_entity. Otherwise, it would be a great addition.

Re: entity.id, a unique, persistent ID

Posted: Sat Aug 08, 2015 4:14 am
by Choumiko
As long as you don't use it as a key , entity == entity 2 works.
Still, I'd like it at least for LuaPlayer, since player_index and player.name might change in MP games.

Re: entity.id, a unique, persistent ID

Posted: Sat Aug 08, 2015 5:27 am
by Rseding91
Choumiko wrote:As long as you don't use it as a key , entity == entity 2 works.
Still, I'd like it at least for LuaPlayer, since player_index and player.name might change in MP games.
You can do player == player2 to check if they're the same player.

You can do anything == anything - inventory references, entity references, GUI references - they all work with the == operator.

Re: entity.id, a unique, persistent ID

Posted: Sun Aug 09, 2015 11:45 am
by Wyrm
Rseding91 wrote:You can do player == player2 to check if they're the same player.

You can do anything == anything - inventory references, entity references, GUI references - they all work with the == operator.
Across play sessions?

Also, having entities be usable as keys is very, very handy. That way, I don't have to search through the table of paired values, seeking a particular entity. I can just say some_table[entity_as_key] and be done with it.

Re: entity.id, a unique, persistent ID

Posted: Mon Aug 10, 2015 3:19 am
by Rseding91
Wyrm wrote:
Rseding91 wrote:You can do player == player2 to check if they're the same player.

You can do anything == anything - inventory references, entity references, GUI references - they all work with the == operator.
Across play sessions?

Also, having entities be usable as keys is very, very handy. That way, I don't have to search through the table of paired values, seeking a particular entity. I can just say some_table[entity_as_key] and be done with it.
Yes across play sessions. When you compare 2 Factorio LuaObjects using == it calls an internal compare (__eq meta method if you know Lua).

I do however agree a unique ID per entity would be useful. Entities with an owner (entities with a force) already have such an ID and it would be simple to expose it. It wouldn't work for *everything* - trees wouldn't have it, items on the ground wouldn't have it but most entities that you'd want to store would have it.

Re: entity.id, a unique, persistent ID

Posted: Fri May 06, 2016 4:08 am
by ArderBlackard
Sorry for resurrecting the topic, but this request seems to be still quite relevant.
While the equality comparison between entity references works fine, it's very difficult to use entities as table keys. Two entities which are equal are not necessary the same and thus are considered different as table keys.

It also seems that the API functions always return different wrapper tables so even the code like this (assuming we point mouse at some entity):

Code: Select all

/c map = {}; 
map[game.player.selected] = "dummy"; 
game.player.print( tostring( map[game.player.selected] ) )
will print "nil" instead of "dummy"

while, of course, this:

Code: Select all

/c game.player.print( tostring( game.player.selected == game.player.selected ) )
will print "true"

As a result the only workaround I see so far is to store entities in arrays and find them using equality comparison, while using keys should be a more performant approach I guess.

Re: entity.id, a unique, persistent ID

Posted: Fri May 06, 2016 5:54 am
by Rseding91
As I've already said: there's no property or ID to expose that would solve this. Most entities in a given map don't have any unique identifier about them other than the memory address they have.

If an ID was added to every single entity we'd definitely need to make it an 8 byte unsigned int due to the amount of entities created and destroyed over the course of a game.

The map I have going has roughly 5.5 million entities on it. At 8 bytes per entity that would add 8 * 5,500,000 bytes of space to store the ID in RAM and in the save file. That would convert to roughly 42 megabytes of space required in the save file just to save IDs if each entity had one.

Re: entity.id, a unique, persistent ID

Posted: Fri May 06, 2016 6:22 am
by DaveMcW
If id was writable but defaulted to nil, how much space would that take on an unmodded save?

I'm thinking something like:

Code: Select all

function entity.getId()
  if not this.id then
    this.id = get_unique_id()
  end
  return this.id
end
It would only assign an id when a modder specifically asked for it.

Re: entity.id, a unique, persistent ID

Posted: Fri May 06, 2016 10:39 am
by ArderBlackard
Rseding91, thanks for the answer! Hardly ever we will need an ID of every entity in the game including all the doodads :D
But you have said earlier that
Rseding91 wrote:Entities with an owner (entities with a force) already have such an ID and it would be simple to expose it.
If implemented, this would be quite enough, as tracking "large" long-living objects is the most common usage I can imagine for these IDs.

And aside from the idea above just another crazy one:
Rseding91 wrote:As I've already said: there's no property or ID to expose that would solve this. Most entities in a given map don't have any unique identifier about them other than the memory address they have.
Still there is some way to detect whether two entities are equal or not. I mean the __eq metamethod is implemented somehow and it compares something (presumably the related c++ structures pointers/addresses?) Then these addresses seem to be good candidates for entity IDs (if they are not being moved in memory over time of course), dont' they? :) They may even be obfuscated in some way to prevent from exposing raw addresses (like xor-ing them with some value). Of course they would not be preserved across game sessions, but it's still something. And as DaveMcW suggested, the actual entity ID value can be lazy-computed and stored only per-request.
But as I've stated already, it's just a crazy idea :D

Re: entity.id, a unique, persistent ID

Posted: Fri May 06, 2016 2:57 pm
by Rseding91
Memory addresses aren't save load or MP stable so they won't work for key values. They work fine for equality comparison because that's done as a one-off thing and not something you can "save" - you can only save the result of which will be identical every time it's run on any system.

Re: entity.id, a unique, persistent ID

Posted: Fri May 06, 2016 3:35 pm
by ArderBlackard
Thanks for the explanation. Quite reasonable, I see :)
Anyway it would be nice to have access to the IDs of the object that actualy have them. Hope we will get this functionality sooner or later.

Re: entity.id, a unique, persistent ID

Posted: Sun May 08, 2016 1:54 am
by Afforess
I have a compromise proposal. Have a field in the data prototypes which turns on persistent entity ids for an entity (like persistent_id = true or something). By default, no entities have it. Then, if a modder wants a particular entity type to have persistent ids, they can set the data prototype field and enable it for individual entities, otherwise, regular users don't experience overhead.

Re: entity.id, a unique, persistent ID

Posted: Sun May 08, 2016 10:40 am
by ArderBlackard
From what I have read on the forum I guess that entities in C++ code have a rigid format without ability to change their number of fields. Not like in Lua, where you can add and remove fields in runtime. Even having a field for "per-request-computed" ID will still require memory for at least pointer-size variable in C++ entity representation.
So each entity either have or have not an ID and it's only a matter of exposing to Lua those IDs that exist.
Of course, it's just a speculation, I don't know the internal structures for sure.

Re: entity.id, a unique, persistent ID

Posted: Sun May 08, 2016 11:30 am
by ljdp
Alternatively there could be some hashing method that generates a hash depending on all it's unique properties (i.e position, name, etc).

Re: entity.id, a unique, persistent ID

Posted: Sun May 08, 2016 11:44 am
by DaveMcW
ljdp wrote:Alternatively there could be some hashing method that generates a hash depending on all it's unique properties (i.e position, name, etc).
That's the hack modders use now. But it doesn't work for anything that moves.

Re: entity.id, a unique, persistent ID

Posted: Tue May 10, 2016 12:41 am
by seronis
DaveMcW wrote:
ljdp wrote:Alternatively there could be some hashing method that generates a hash depending on all it's unique properties (i.e position, name, etc).
That's the hack modders use now. But it doesn't work for anything that moves.
Well position isnt something that should be used in hashes anyways. No non static data should be used in an id hash. In a different game i've modded that uses lua I just had my get_id(entity) function check for the presence of my id variable. If it was nil I would simply assign an unused id. I dont know if Factorio will serialize random mod added variables on default classes.

Re: entity.id, a unique, persistent ID

Posted: Tue May 10, 2016 1:13 am
by ArderBlackard
Factorio prevents setting any unknown fields to default entities, not to mention serialization.

Re: entity.id, a unique, persistent ID

Posted: Tue May 10, 2016 2:27 am
by Rseding91
seronis wrote:
DaveMcW wrote:
ljdp wrote:Alternatively there could be some hashing method that generates a hash depending on all it's unique properties (i.e position, name, etc).
That's the hack modders use now. But it doesn't work for anything that moves.
Well position isnt something that should be used in hashes anyways. No non static data should be used in an id hash. In a different game i've modded that uses lua I just had my get_id(entity) function check for the presence of my id variable. If it was nil I would simply assign an unused id. I dont know if Factorio will serialize random mod added variables on default classes.
All properties available in the Factorio Lua API are backed by some C++ class that holds and maintains the data so runtime properties are not supported. The only way to add new properties in is to change the source code and recompile the program on our end.

Re: entity.id, a unique, persistent ID

Posted: Tue May 10, 2016 2:17 pm
by Zeblote
Rseding91 wrote:As I've already said: there's no property or ID to expose that would solve this. Most entities in a given map don't have any unique identifier about them other than the memory address they have.

If an ID was added to every single entity we'd definitely need to make it an 8 byte unsigned int due to the amount of entities created and destroyed over the course of a game.

The map I have going has roughly 5.5 million entities on it. At 8 bytes per entity that would add 8 * 5,500,000 bytes of space to store the ID in RAM and in the save file. That would convert to roughly 42 megabytes of space required in the save file just to save IDs if each entity had one.
It doesn't need to have a unique id for everything. For example, there's no reason why iron plates on a belt should have one.

Surely you can add a unique id to specific classes like trains?