If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Place to get help with not working mods / modding interface.
kendoctor
Inserter
Inserter
Posts: 34
Joined: Wed Aug 05, 2020 6:43 pm
Contact:

If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by kendoctor »

In some cases, I need a property to temp store plain value. For example

Surface clone area will trigger on_entity_cloned.
if the origina entity which i used for a door or portal. I need listen this event to compare a cache table to find the cloned entity.
doors, a cache table , store all door entities unit_number => door entity

Code: Select all

script.on(...on_entity_cloned, function(e)
...  find  e.source in doors if exists that mean a door entity
e.destination will be cloned new door entity
 end )
but this cause lots of comparations and iterations
If entity has a private field for moder storing plain data, that will be more effcient for this targeting.
when create door, set entity.private_field = unique_id_with_a_role_tag
1. first method, searching in the cloned area with same private_field value
2. second method, on_entity_cloned, only identify this private_field value to determine if its' a door entity.
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 4034
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by boskid »

Unlikely to be ever implemented. This would increase memory usage for every entity or would require separate map implemented outside of the entity itself. There would be also issue with lifetime of such variable (if it would go over single tick, would need to be save/loaded) and would have to be decided if it should be shared or private for each mod. Really unlikely to be implemented.

on_entity_cloned event gives you a lot. Within mod state inside of global you may create a table that maps from unique identifier (some unique value from the entity that works as key in a table) into your state to avoid the comparing step. Table lookup is fast.

Unified unique identifier per every entity is more likely to happen than the requested private data per entity field. For a workaround, abusing a little the lua-api, you can call register_on_entity_destroyed and use the provided registration number as unified unique identifier since calling that function again on the same entity will return the same value.
kendoctor
Inserter
Inserter
Posts: 34
Joined: Wed Aug 05, 2020 6:43 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by kendoctor »

boskid wrote: Wed Aug 19, 2020 8:58 am Unlikely to be ever implemented. This would increase memory usage for every entity or would require separate map implemented outside of the entity itself. There would be also issue with lifetime of such variable (if it would go over single tick, would need to be save/loaded) and would have to be decided if it should be shared or private for each mod. Really unlikely to be implemented.

on_entity_cloned event gives you a lot. Within mod state inside of global you may create a table that maps from unique identifier (some unique value from the entity that works as key in a table) into your state to avoid the comparing step. Table lookup is fast.

Unified unique identifier per every entity is more likely to happen than the requested private data per entity field. For a workaround, abusing a little the lua-api, you can call register_on_entity_destroyed and use the provided registration number as unified unique identifier since calling that function again on the same entity will return the same value.
This would increase memory usage
If store the private data in global, is also consuming memory. That's the same.
There would be also issue with lifetime of such variable (if it would go over single tick, would need to be save/loaded) and would have to be decided if it should be shared or private for each mod. Really unlikely to be implemented.
If only for basic type, such string, number, even not include table
Why need this private field ?
for faster targetting, it can ignore lots of iterations and even events.
For example, this field can be like this : unit_number_cutstomer_id_role_tag , pratical example, 100_CUS-Many-TO-Many-001-ID_SuperCargoWagon_wagon
The length of this field can be limited, for 256. That's enough. but very flexiable for customize and extend intrinsic Facto classes.
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 4034
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by boskid »

kendoctor wrote: Wed Aug 19, 2020 12:04 pm
This would increase memory usage
If store the private data in global, is also consuming memory. That's the same.
Please read more careful. If you have 1000000 entities on map (lets say, trees, belts, biters, everything), adding 16 extra bytes to every entity would immediately give 16MB of extra memory usage. Difference is that when you store the data inside of the mod, you may have a table that has entries only for those entities that are of your interest. If you are interested in only a couple of entities, extra memory usage will be a lot less than 16MB.

And i still do not understand why you do not want to hold the map on the mod side? You seem to not understand that you do not have to iterate over a table if you know a key and want to get only single record using that key. This is a lot faster than what you are saying.
kendoctor
Inserter
Inserter
Posts: 34
Joined: Wed Aug 05, 2020 6:43 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by kendoctor »

boskid wrote: Wed Aug 19, 2020 12:12 pm
kendoctor wrote: Wed Aug 19, 2020 12:04 pm
This would increase memory usage
If store the private data in global, is also consuming memory. That's the same.
Please read more careful. If you have 1000000 entities on map (lets say, trees, belts, biters, everything), adding 16 extra bytes to every entity would immediately give 16MB of extra memory usage. Difference is that when you store the data inside of the mod, you may have a table that has entries only for those entities that are of your interest. If you are interested in only a couple of entities, extra memory usage will be a lot less than 16MB.

And i still do not understand why you do not want to hold the map on the mod side? You seem to not understand that you do not have to iterate over a table if you know a key and want to get only single record using that key. This is a lot faster than what you are saying.


1000000 entities , yes, you're right.
But, luaobject already has lots of properties. Is it right ? So the reason for this 1000000 entities says nothing.
As a moder, we hope to have more flexibility to extend the original game. you maybe never could know how further they will extend this game.
Anyway, I just give my suggestion. The balancing question is what u are thinking about.

Code: Select all

And i still do not understand why you do not want to hold the map on the mod side? You seem to not understand that you do not have to iterate over a table if you know a key and want to get only single record using that key.
For example, filters can not applied for mutiple handlers, on_entity_built or something like this, you only know this it's unit_number, you can not identify this entity what's role playing in mod.

you could say, all entities in a table
global.all_considered_entities[id]
yeah. searching by id is very quick. but this plain table is not fit for complex design.
for example
global.cars, global.trains, global.players, global.somethingelsecustomizedClasses
using id to search in all these tables ?
or just entity.CAR_unitnumber, i just split this string into two parts, it let me know what i'm searching for with CAR.
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 4034
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by boskid »

LuaEntity does not exists for every entity. They work as a pointer to the true Entity and are created when lua requests them in any way. If you have no references to given LuaEntity, lua's garbage collector will delete them, so your argument is invalid. There exists as much LuaEntities as mods are holding references to them.

For the id's, i gave you a simple to use workaround using register_on_entity_destroyed thtat will return unique registration number which you may use within the mod to perform your own translation. There are really no good reasons why your data should be so special is should be held in the game state and not in the mod state.
mrvn
Smart Inserter
Smart Inserter
Posts: 5969
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by mrvn »

I have a global.by_id that maps any entity unit_number I'm interested in to my internal data for that entity. If the entity name isn't enough to figure out the role then my internal data has a type field.

So it's always simple to do stuff:

Code: Select all

local data = global.by_id[entity.unit_number]
if data and data.type == "door" then
    -- entity is one of my doors
end
mrvn
Smart Inserter
Smart Inserter
Posts: 5969
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by mrvn »

boskid wrote: Wed Aug 19, 2020 2:00 pm LuaEntity does not exists for every entity. They work as a pointer to the true Entity and are created when lua requests them in any way. If you have no references to given LuaEntity, lua's garbage collector will delete them, so your argument is invalid. There exists as much LuaEntities as mods are holding references to them.

For the id's, i gave you a simple to use workaround using register_on_entity_destroyed thtat will return unique registration number which you may use within the mod to perform your own translation. There are really no good reasons why your data should be so special is should be held in the game state and not in the mod state.
boskid: Why use register_on_entity_destroyed instead of just entity.unit_number?
User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5405
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by Klonan »

mrvn wrote: Wed Aug 19, 2020 2:03 pm
boskid: Why use register_on_entity_destroyed instead of just entity.unit_number?
Things like trees and resources don't have a unit_number
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 4034
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by boskid »

mrvn wrote: Wed Aug 19, 2020 2:03 pm
boskid wrote: Wed Aug 19, 2020 2:00 pm LuaEntity does not exists for every entity. They work as a pointer to the true Entity and are created when lua requests them in any way. If you have no references to given LuaEntity, lua's garbage collector will delete them, so your argument is invalid. There exists as much LuaEntities as mods are holding references to them.

For the id's, i gave you a simple to use workaround using register_on_entity_destroyed thtat will return unique registration number which you may use within the mod to perform your own translation. There are really no good reasons why your data should be so special is should be held in the game state and not in the mod state.
boskid: Why use register_on_entity_destroyed instead of just entity.unit_number?
If you are using only entities that have unit_number then yeah, unit_number is a lot better to be used. However not every entity has unit_number, for example trees. If you are using entities that do not have unit_number, then there is the backup way to identify the entities. Also in some extreme cases, unit_number being uint32 is not guaranteed to be unique.
kendoctor
Inserter
Inserter
Posts: 34
Joined: Wed Aug 05, 2020 6:43 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by kendoctor »

mrvn wrote: Wed Aug 19, 2020 2:02 pm I have a global.by_id that maps any entity unit_number I'm interested in to my internal data for that entity. If the entity name isn't enough to figure out the role then my internal data has a type field.

So it's always simple to do stuff:

Code: Select all

local data = global.by_id[entity.unit_number]
if data and data.type == "door" then
    -- entity is one of my doors
end
then, find all doors
you iterating all over this table ?
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 4034
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by boskid »

kendoctor wrote: Wed Aug 19, 2020 2:23 pm then, find all doors
you iterating all over this table ?
Now you are shifting onto a different problem. First one was to convert entity into data held in mod context, that can be done using unit_number or the backup one using registration. Second one is a different problem to solve. If you know you will be requesting all the doors, you should keep an array with all the doors you are interested in iterating over so you do not have the cost of filtering doors from all the entities held in your table. Another approach would be to use LuaSurface::find_entities_filtered over whole surface but then you are not gaining any speed, just moving your inefficient algorithm onto the C++ side.
Pi-C
Smart Inserter
Smart Inserter
Posts: 1756
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by Pi-C »

boskid wrote: Wed Aug 19, 2020 2:07 pm
mrvn wrote: Wed Aug 19, 2020 2:03 pm boskid: Why use register_on_entity_destroyed instead of just entity.unit_number?
If you are using only entities that have unit_number then yeah, unit_number is a lot better to be used. However not every entity has unit_number, for example trees. If you are using entities that do not have unit_number, then there is the backup way to identify the entities. Also in some extreme cases, unit_number being uint32 is not guaranteed to be unique.
Very interesting! In Water Turret, I currently use hidden combat-robots to mark fires (turrets can attack combat-robots, but not fires). I've always felt that was too expensive, and I've tried using a simple-entity-with-force instead, but the problem was that I didn't know how to be notified when it dies. So, using register_on_entity_destroyed whenever I create a simple-entity-with-force seems to be a way around that problem.

While I'm at it: I want my fire markers to be attacked by water turrets, nothing else. Currently, they are on a special force that has ceasefire and friend status set for all forces without players, and is enemy to all forces that have players. I suppose the markers must have a force in order to be attacked by turrets automatically. Is that correct, or could I use just a simple-entity as well?
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
kendoctor
Inserter
Inserter
Posts: 34
Joined: Wed Aug 05, 2020 6:43 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by kendoctor »

boskid wrote: Wed Aug 19, 2020 2:34 pm
kendoctor wrote: Wed Aug 19, 2020 2:23 pm then, find all doors
you iterating all over this table ?
Now you are shifting onto a different problem. First one was to convert entity into data held in mod context, that can be done using unit_number or the backup one using registration. Second one is a different problem to solve. If you know you will be requesting all the doors, you should keep an array with all the doors you are interested in iterating over so you do not have the cost of filtering doors from all the entities held in your table. Another approach would be to use LuaSurface::find_entities_filtered over whole surface but then you are not gaining any speed, just moving your inefficient algorithm onto the C++ side.
This not shifting problem.

1. undentify entity -> search in one table table[id] -> get data to indentify role. flat strategy. but all roles in one table
2. undentify entity but has a private field, string -> split into parts, get role info -> then push into role table
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 4034
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by boskid »

kendoctor wrote: Wed Aug 19, 2020 3:00 pm 1. undentify entity -> search in one table table[id] -> get data to indentify role. flat strategy. but all roles in one table
2. undentify entity but has a private field, string -> split into parts, get role info -> then push into role table
Stringly typed system. But what is the difference between taking data from "private tag" (not implemented) vs taking data from a table that is held in mod context? Second approach is better because you can store different data and not be forced into doing string split that would cost time.
kendoctor
Inserter
Inserter
Posts: 34
Joined: Wed Aug 05, 2020 6:43 pm
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by kendoctor »

boskid wrote: Wed Aug 19, 2020 3:10 pm
kendoctor wrote: Wed Aug 19, 2020 3:00 pm 1. undentify entity -> search in one table table[id] -> get data to indentify role. flat strategy. but all roles in one table
2. undentify entity but has a private field, string -> split into parts, get role info -> then push into role table
Stringly typed system. But what is the difference between taking data from "private tag" (not implemented) vs taking data from a table that is held in mod context? Second approach is better because you can store different data and not be forced into doing string split that would cost time.
I hope u could understand my question. Although it's very simple, although it's figured already.
Targetting and identify.
That's no about meta data storaging .
If dev team never will consider this question, i give up. that's it. no argue. We all retreat this question politely. :D
mrvn
Smart Inserter
Smart Inserter
Posts: 5969
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by mrvn »

boskid wrote: Wed Aug 19, 2020 2:07 pm
mrvn wrote: Wed Aug 19, 2020 2:03 pm
boskid wrote: Wed Aug 19, 2020 2:00 pm LuaEntity does not exists for every entity. They work as a pointer to the true Entity and are created when lua requests them in any way. If you have no references to given LuaEntity, lua's garbage collector will delete them, so your argument is invalid. There exists as much LuaEntities as mods are holding references to them.

For the id's, i gave you a simple to use workaround using register_on_entity_destroyed thtat will return unique registration number which you may use within the mod to perform your own translation. There are really no good reasons why your data should be so special is should be held in the game state and not in the mod state.
boskid: Why use register_on_entity_destroyed instead of just entity.unit_number?
If you are using only entities that have unit_number then yeah, unit_number is a lot better to be used. However not every entity has unit_number, for example trees. If you are using entities that do not have unit_number, then there is the backup way to identify the entities. Also in some extreme cases, unit_number being uint32 is not guaranteed to be unique.
Well, ... how unique is it? Do you mean at some point it will loop around and reuse unit numbers that are no longer in use? Or will it even reuse a unit number that is still existing? The former would be perfectly fine but limit the game to 2^32 entities at any one time. The later would probably break a lot of mods.

Lets look a the risk. Every tick a bot can be taked by the roboports and again by a personal roboport. So in a vanilla single player game it takes 2^32/60/60/60/24/2 = 414.25 days at constant full building speed before a warp around occurs. Half that with 4 players which is still over 200 days of constant maximum speed building.

With mods that might come down a lot though:

1) vehicles with equipment grid can have roboports
2) some entities have hidden entities so placing one uses up multiple unit numbers

119 vehicles with roboports could cause a warp around in under a week. Not sure where you would find a CPU that can run at 60UPS with that though. So it would probably be month to get a week game time.

PS: I just remembered reading that the Spidertron can have a roboport in vanilla. So that cuts down the potential time till a warp arround can occur in vanilla too.


I just hope the game doesn't reuse unit numbers that still exist.
Rseding91
Factorio Staff
Factorio Staff
Posts: 15881
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by Rseding91 »

mrvn wrote: Mon Aug 24, 2020 1:13 pm I just hope the game doesn't reuse unit numbers that still exist.
It just wraps around and will get re-used. You aren't going to hit it in any non-artificial case so it's irrelevant.
If you want to get ahold of me I'm almost always on Discord.
mrvn
Smart Inserter
Smart Inserter
Posts: 5969
Joined: Mon Sep 05, 2016 9:10 am
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by mrvn »

Rseding91 wrote: Mon Aug 24, 2020 1:18 pm
mrvn wrote: Mon Aug 24, 2020 1:13 pm I just hope the game doesn't reuse unit numbers that still exist.
It just wraps around and will get re-used. You aren't going to hit it in any non-artificial case so it's irrelevant.
Tell me that in 10 years when it warps around on the first megabase :)
Rseding91
Factorio Staff
Factorio Staff
Posts: 15881
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: If LuaObject or LuaEntity has a property for caching private data, even a string value. Helpful

Post by Rseding91 »

mrvn wrote: Mon Aug 24, 2020 1:36 pm
Rseding91 wrote: Mon Aug 24, 2020 1:18 pm
mrvn wrote: Mon Aug 24, 2020 1:13 pm I just hope the game doesn't reuse unit numbers that still exist.
It just wraps around and will get re-used. You aren't going to hit it in any non-artificial case so it's irrelevant.
Tell me that in 10 years when it warps around on the first megabase :)
You'll have overflowed the tick long before that point.
If you want to get ahold of me I'm almost always on Discord.
Post Reply

Return to “Modding help”