Page 1 of 1
Trains in the "global" table
Posted: Wed Jan 20, 2016 11:12 am
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?
Re: Trains in the "global" table
Posted: Thu Jan 21, 2016 1:00 pm
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

Re: Trains in the "global" table
Posted: Fri Jan 22, 2016 3:40 pm
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...
Re: Trains in the "global" table
Posted: Fri Jan 22, 2016 7:48 pm
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.
Re: Trains in the "global" table
Posted: Sat Jan 23, 2016 4:27 am
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).
Re: Trains in the "global" table
Posted: Sat Jan 23, 2016 6:03 am
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.