Trains in the "global" table

Place to get help with not working mods / modding interface.
User avatar
DaveMcW
Smart Inserter
Smart Inserter
Posts: 3749
Joined: Tue May 13, 2014 11:06 am
Contact:

Trains in the "global" table

Post by DaveMcW »

I want to add a custom property to every train, and have it persist across saves.

The obvious solution is to use the train object as an index, but that fails instantly as train objects are destroyed every tick.

Code: Select all

script.on_event(defines.events.on_train_changed_state, function(event)
	local train = event.train
	global.trains[train] = { myproperty = 1 }
end
I got it working for a while using carriages as an index. But that fails when I save and reload the game.

Code: Select all

script.on_event(defines.events.on_train_changed_state, function(event)
	local carriage = event.train.carriages[1]
	global.trains[carriage] = { myproperty = 1 }
end
I checked out a couple train mods, but the code looked like a mess of hacks and backup hacks. Is there no simple way to keep track of trains?
Choumiko
Smart Inserter
Smart Inserter
Posts: 1352
Joined: Fri Mar 21, 2014 10:51 pm
Contact:

Re: Trains in the "global" table

Post by Choumiko »

For your save/load problem: You can't use LuaObjects as indexes in global.

The messy thing with trains is: They consist of multiple Entities. Add/Remove a wagon/loco to a train and the old LuaTrain gets invalid. Even worse: Mine a wagon in the middle of a train and you end up with 2 LuaTrain objects. Not sure if a carriage reference gets invalid too if you mine another wagon of the same train.
SmartTrains/Farls "train tracking" works. I'm only touching it if it fails, because it is messy and hacky, just you said :)
SirRichie
Fast Inserter
Fast Inserter
Posts: 244
Joined: Wed Feb 25, 2015 4:50 pm
Contact:

Re: Trains in the "global" table

Post by SirRichie »

Getting back to the save/load problem: I know I am not really suggesting a solution, but is there anything that prevents you from re-building the index in the on_load event hook? If you can extract the index from the game state, then there is no need to save it, I think.

Does not reduce the messiness of detecting connected trains though...
Rseding91
Factorio Staff
Factorio Staff
Posts: 15912
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: Trains in the "global" table

Post by Rseding91 »

SirRichie wrote:Getting back to the save/load problem: I know I am not really suggesting a solution, but is there anything that prevents you from re-building the index in the on_load event hook? If you can extract the index from the game state, then there is no need to save it, I think.

Does not reduce the messiness of detecting connected trains though...
script.on_load doesn't have access to the game state.

As for your original issue: using LuaObjects as indexes in tables doesn't work for what you'd want it to because each LuaObject you get from a call to something like entity.train is a new wrapper object and as such won't match any existing indexes you have stored. LuaTrain can be persisted between save/load and is not invalidated every tick. It's only invalidated when the train changes (locomotives/carriages change).

The LuaTrain object really is only useful during the tick you access it off a given locomotive. Yes, it can be saved and loaded but it's not reliable. Not reliable in that you can't guarantee that every time a LuaTrain is invalidated you get a reference back to what you wanted it to point at. As said before: removing a rolling stock from the middle of a train will split it into 2 new LuaTrain instances. Which one did you want?

I'd need to know more about what you're attempting to do to provide a real solution.
If you want to get ahold of me I'm almost always on Discord.
User avatar
Afforess
Filter Inserter
Filter Inserter
Posts: 422
Joined: Tue May 05, 2015 6:07 pm
Contact:

Re: Trains in the "global" table

Post by Afforess »

From the code in the OP, I'd wager he is trying to associate meta-data with an entity. I was going to open a new topic to suggest this (and I still might), but I believe this whole problem could be solved if mods could attach data to entities. Mods can only associate data with the global object, so if I want to associate a key - value pair of data, with the key as the entity, the only way is to store all the key-values together as a tuple, then scan a giant list looking for that specific entity. If entities had a "mod_data" that serialized just like global data, the code in the OP would look like this instead:

Code: Select all

script.on_event(defines.events.on_train_changed_state, function(event)
   local train = event.train
   train.mod_data["my-property"] = 1
end
And that's it, because it would be associated with the C++ entity. This also has the added advantage of having the data automatically be deleted when the entity dies (as opposed to invalid entities having to be pruned from a global list over time).
User avatar
DaveMcW
Smart Inserter
Smart Inserter
Posts: 3749
Joined: Tue May 13, 2014 11:06 am
Contact:

Re: Trains in the "global" table

Post by DaveMcW »

Rseding91 wrote:I'd need to know more about what you're attempting to do to provide a real solution.
My basic design is:

1. Identify an interesting train. Insert a pointer to it, into the interesting_trains table.
2. Do nothing for a few hundred ticks.
3. In on_tick(), examine every train in the interesting_trains table. Modify or remove them if certain conditions are met.

The ability to store entity pointers in the global table would make this trivial. However, I could rebuild the interesting_trains table when a save is loaded if I have another way to attach the "interesting_train" flag to a train.
Post Reply

Return to “Modding help”