Page 1 of 1

Too Many Local Variables

Posted: Tue Jun 21, 2016 2:09 am
by Shrooblord
Hey modders,

I'm creating a mod but I'm running into a problem regarding local variables used in the control.lua. I have entities in the world that store values concerning themselves as local variables, but if there's too many of these entities in the world, on world load, the game will return an error, telling you the maximum limit of local variables is 200, and this save file has exceeded this.

The only way to restore the file is to uninstall the mod, load the save file, have it kill all entities and items pertaining to that mod automatically, save that game, exit and reinstall the mod and reload the level.


I'm asking you help on solving this case - how can I either reduce the number of local variables I need (work-around); limit the amount of entities placed of this type (worse work-around - factorio is all about going big; putting a hard limit on certain entities seems silly); increase the local variable limit (possibly this means overriding/hacking into base game defaults - something not all users would be happy with); come up with a way to not need local variables?

In my case, I'm setting up the local variables so they can later be altered through research; i.e. have their values altered depending on the amount of research done in a particular, custom tech tree.

Thanks,
Shrooblord

Re: Too Many Local Variables

Posted: Tue Jun 21, 2016 2:24 am
by DaveMcW
Store all the variables in one table?

Re: Too Many Local Variables

Posted: Tue Jun 21, 2016 6:24 am
by Shrooblord
How do you do that? Do you define a global table and store all variables there?

Basically, don't use local variables? (That goes against everything my programmer brain tells me to do. :P )

Re: Too Many Local Variables

Posted: Tue Jun 21, 2016 6:40 am
by DaveMcW
instead of:
local a = 1
local b = 2
local c = 3

do:
local var = {}
var.a = 1
var.b = 2
var.c = 3

Re: Too Many Local Variables

Posted: Tue Jun 21, 2016 8:13 am
by bobingabout
Talking about entities in existence, I assume this is in the control.lua file?

If this is the case, why are you storing information about entities in local variables in the first place? is this a one off calculation, and all these local variables are dismissed on the very next tick? If the answer is no, you're probably doing it wrong.

Only the global table is saved to the save game, as such any information stored in a local is not saved, and due to the way the game works, is not guaranteed to exist on the next tick, because that next tick might be a save/load away.


As a general rule, only use local for storing "to be used on the same tick" information, everything else should be a variable, or sub-table in the global table.

Re: Too Many Local Variables

Posted: Tue Jun 21, 2016 11:49 am
by Shrooblord
bobingabout wrote:Talking about entities in existence, I assume this is in the control.lua file?
Yes.
As a general rule, only use local for storing "to be used on the same tick" information, everything else should be a variable, or sub-table in the global table.
Okay, I'm sort of doing both. I did run into this problem before, and in moving other local variables to the global table, then placing more than 200 entities of the offending type, saving and reloading, did not encounter the error. I guess I should just continue that trend for variables that need their value stored across ticks. Thanks.
However, I'm not currently using any such variables as locals anymore.
I'm doing some operations on a per-tick basis that require a local variable. For example, I'm spawning in entities where there were other entities before, each of which has a variable entry in the global table. So their spawn code is:

Code: Select all

if (spawn condition) then
   local newEntity = game.get_surface(1).create_entity({ name='myEntity2', amount=1, position=k});
   global.shr.growing[newEntity.position] = math.floor(game.tick / 60);
end
Where the position k is a key value in a for k, v in pairs loop that can be read as thisEntity.position as the key x in global.shr.growing[x] - it can be interpreted as a unique identifier for a single entity: only one entity with position newEntity.position and that specific creation time can exist in one place at any given moment, therefore this variable points to specific entities.

Beforehand, the previous entity thisEntity was destroyed (see below for the findAndDestroyEntity function) and the new entity is put in its place. After the spawning code, the old entity's data in the global table is wiped:

Code: Select all

global.shr.growing[k] = nil;
Thus clearing the memory used by the old entity thisEntity now that it has been destroyed.

Do I need to manually clean up the local variable newEntity right before the end statement in this if block by redefining it as nil? I'd assume the local variable is thrown away automatically once the if statement has ended. Is this assumption wrong?


For the rest I just have two local variables remaining: a local string that details the name of the type of an entity that was recently destroyed to make way for a new one that's replacing it. This string is only used in an if pyramid straight afterwards and its value is not needed for any further ticks. Do I need to manually clean this local up too?
The other is a variable named checkAlive, whose value is removed from memory as soon as we're done with it :
checkAlive
The function call findAndDestroyEntity with the second argument passed as false is what finds entities using find_entities_filtered in a tiny area and then destroys them (I should say, 'it', as realistically only one entity can exist in the area I'm searching in) unless the second argument is passed as false :
findAndDestroyEntity

Am I using any of these variables wrong?
[W]hy are you storing information about entities in local variables in the first place? is this a one off calculation, and all these local variables are dismissed on the very next tick? If the answer is no, you're probably doing it wrong.
So, the variables I use are either the unique identifiers stored in a table that is defined at the very top of the code and is called from everywhere using global.shr.growing[] (I'm assuming this is the global table you mean); or they are locals used solely in the place they're needed (therefore used as locals rather than global variables to save on program performance).


EDIT:
In an attempt to solve the problem myself, I removed all local variables from the script and instead turned them all into global variables stored in the main table (I know, bad coding practice, but I'm experimenting). However, the error still persists. There are too many local variables... except there are no local variables???

Re: Too Many Local Variables

Posted: Fri Jun 24, 2016 4:43 pm
by Shrooblord
Would any of you be so kind to take a look at my mod in progress? I could really do with some help.
TreeSaplings_0.1.3.zip
Sapling Mod, Shrooblord Edition
(202.49 KiB) Downloaded 144 times
It's a continuation of the Sapling Mod. I hope its original author doesn't mind me using his work to create a derivate inspired by its potential, but seeing great opportunity for progress.