Page 1 of 1

add train_stop_id argument to LuaTrain::go_to_station()

Posted: Sat Oct 09, 2021 11:09 pm
by mrvn
TL;DR
Allow sending trains to specific train stops when multiple stops with the same name exist.
What ?
When sending a train to a station the game goes through all the train stops with the right name and picks one to send the train to. Allow passing the ID of the train stop to go to as optional argument. If the given train stop is enabled, reachable and has not reached it's train limit then it is used as destination of the train. On success the train ID is returned or nil.

Optional add a third argument "fail :: bool". If fail is true the call will return nil when the given station is not suitable. If fail is false then the given station is only taken as a suggestion and the normal algorithm is used when unsuitable.
Why ?
When enhancing the train experience to allow more dynamic schedules it often is desirable to pick the train stop based on criteria other than the path cost. And then mod wants the train to go to specific stations but the game does not allow directing the train that specifically.

Note: As a workaround mods can insert a temporary train stop to send the train to a specific rail tile (that of the train stop) and then the train stop has a path cost of 0 and will be picked. Usually that is. Not so if the train comes from the wrong direction since temporary train stops don't have a direction and the wrong direction (for the train stop) might be cheaper. Using a temporary train stop also hides which stop the train is targeting in the train overview. So overall not the ideal solution.

This request would allow mods to properly send trains to where they are supposed to go according to the mods logic.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Tue Oct 12, 2021 7:20 am
by boskid
This is outside of the train schedule implementation scope. LuaTrain::go_to_station only chooses an index of a schedule which should be used by a train. There are multiple issues with the ID approach: 1/ feedback to the player which would see a station name in the schedule but a train could be complaining "no path" if the only stop selected is not reachable but all the others are. 2/ trains can repath anytime when traveling which would make the ID to become a part of the game state and would need to be cleared at specific points in time after the record was reached (or there would be another request to allow to set it as "once/every time"). If you want to send a train to a specific train stop you can change the schedule and replace the station record with a rail record. Concept of a station is that it should group all the train stops between which you do not care where the train should go, and your request is literally "i care to which stop the train wants to go". Nope.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Tue Oct 12, 2021 3:23 pm
by mrvn
1) It can't be "no path". The call to set the stop as target would fail. That either returns nil or (with the fail=false argument) chooses a different stop appropriate to the index. So no feedback needed for the player or unexcplained train behavior.

2) I'm aware that trains can repath. Ideally unless the state becomes "no path" the train should keep its targeted stop. That would make the stop ID part of the trains state. Or more precise a flag saying that the current stop ID (because trains already have that info) is fixed. I guess there are situations where trains can switch stops outside of "no path"?

But I'm fine with trains switching stops assuming that generates an event (path_lost / on_path I assume). It would be easy for mods to check that the train is one they control and either reset the stop ID or handle the case otherwise. Mods have to deal with that for the "no path" problem anyway. If the player destroys the train stop or the rails to it or otherwise messes with the system the train has to go somewhere and the mod may have to notice. So mods already need to listen for events signaling trains getting redirected. Having it happen for other cases than "no path" is not really extra work.

The request is to simply have the train pick the given station as their goal now instead of searching for the closest. Any extra state for the train can be dealt with in the mod.


I'm aware of adding a temporary stop to the schedule as a way to send trains to specific stops. I mentioned that in the request. But that is far from fool prove, again as mentioned. LTN does this and I have had trains go to the rail from the wrong direction and then drive of to a different stop. I actually misuse that for double headed stations under LTN. In conclusion: a rail record is insufficient.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Tue Oct 12, 2021 4:09 pm
by curiosity
mrvn wrote:
Tue Oct 12, 2021 3:23 pm
I guess there are situations where trains can switch stops outside of "no path"?
https://wiki.factorio.com/Railway/Train ... ath_events

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Wed Oct 13, 2021 6:39 pm
by mrvn
Sending it to the rail under the train stop as mentioned doesn't always work because when the train comes from the wrong direction it will often go to a different stop after reaching the rail.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Thu Oct 14, 2021 7:07 am
by boskid
As for 1.1.42 there are only 2 ways of specifying train target: Its either a station name which expands into a (rail + rail direction) for every train stop there is under given station name, or a rail target which expands into 2 goals (one for each direction for a given rail). You can workaround this by creating a train stop on top of existing train stop (in general this is quite ugly but there are mods doing that) that would have a unique name. A more likely modding interface request would be to allow the rail target schedule record to be capable of specifying travel direction so such record would internally represent only a 1 goal.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Thu Oct 14, 2021 12:37 pm
by mrvn
boskid wrote:
Thu Oct 14, 2021 7:07 am
As for 1.1.42 there are only 2 ways of specifying train target: Its either a station name which expands into a (rail + rail direction) for every train stop there is under given station name, or a rail target which expands into 2 goals (one for each direction for a given rail). You can workaround this by creating a train stop on top of existing train stop (in general this is quite ugly but there are mods doing that) that would have a unique name. A more likely modding interface request would be to allow the rail target schedule record to be capable of specifying travel direction so such record would internally represent only a 1 goal.
Could that include an option to specify the rail target + direction by giving a train stop ID?

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Thu Oct 14, 2021 1:46 pm
by curiosity
mrvn wrote:
Thu Oct 14, 2021 12:37 pm
Could that include an option to specify the rail target + direction by giving a train stop ID?
You can easily get the connected rail from the stop entity itself.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Thu Oct 14, 2021 3:18 pm
by PFQNiet
LTN achieves this by creating a temporary stop in the train schedule, right on top of the desired real train stop. The train paths to the temporary stop, then looks for a station with the given name and finds "oh hey I'm already there, what a coincidence!"

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Fri Oct 15, 2021 2:55 pm
by mrvn
PFQNiet wrote:
Thu Oct 14, 2021 3:18 pm
LTN achieves this by creating a temporary stop in the train schedule, right on top of the desired real train stop. The train paths to the temporary stop, then looks for a station with the given name and finds "oh hey I'm already there, what a coincidence!"
As already mentioned multiple times in this thread and not working 100%.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Fri Oct 15, 2021 6:46 pm
by curiosity
mrvn wrote:
Fri Oct 15, 2021 2:55 pm
As already mentioned multiple times in this thread and not working 100%.
I don't see any prior mention of it not working. And I don't see why it won't.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Sat Oct 16, 2021 2:29 am
by mrvn
mrvn wrote:
Wed Oct 13, 2021 6:39 pm
Sending it to the rail under the train stop as mentioned doesn't always work because when the train comes from the wrong direction it will often go to a different stop after reaching the rail.
See also: viewtopic.php?f=214&t=100211

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Sat Oct 16, 2021 7:01 am
by boskid
Ok, i did some "least effort" changes to solve the core issue here - that a rail target works as a two-directional target.

Here is what will happen in 1.1.43:
Changelog for 1.1.43 wrote: Scripting:
- Added LuaEntity::connected_rail_direction read.
- Added TrainScheduleRecord::rail_direction.
LuaEntity::connected_rail_direction will just return a defines.rail_direction from a TrainStop.
When a TrainScheduleRecord with rail target will have a rail_direction, this record will only work as a single-direction target. When a rail_direction of a schedule record is not specified (equal to `nil`), that rail target will work as a two-directional target as usual.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Sat Oct 16, 2021 7:34 am
by curiosity
mrvn wrote:
Sat Oct 16, 2021 2:29 am
mrvn wrote:
Wed Oct 13, 2021 6:39 pm
Sending it to the rail under the train stop as mentioned doesn't always work because when the train comes from the wrong direction it will often go to a different stop after reaching the rail.
See also: viewtopic.php?f=214&t=100211
Which has absolutely nothing to do with the proposed solution.

Though I may have misread PFQNiet's post. To me it sounded like they were proposing the same thing as boskid in the above post.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Sat Oct 16, 2021 12:04 pm
by PFQNiet
Having only ever built one-way rail systems, I didn't realise that temporary stops could be two-directional. The fix by boskid does indeed resolve the issues with the solution I put forward.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Sat Oct 16, 2021 1:30 pm
by boskid
PFQNiet wrote:
Sat Oct 16, 2021 12:04 pm
I didn't realise that temporary stops could be two-directional.
Please do not mix rail target records with temporary records. From lua it is possible to add a temporary record that goes to a station name, and from lua it is possible to create a permanent record that goes to a rail target.

Re: add train_stop_id argument to LuaTrain::go_to_station()

Posted: Sun Oct 17, 2021 8:45 pm
by mrvn
boskid wrote:
Sat Oct 16, 2021 7:01 am
Ok, i did some "least effort" changes to solve the core issue here - that a rail target works as a two-directional target.

Here is what will happen in 1.1.43:
Changelog for 1.1.43 wrote: Scripting:
- Added LuaEntity::connected_rail_direction read.
- Added TrainScheduleRecord::rail_direction.
LuaEntity::connected_rail_direction will just return a defines.rail_direction from a TrainStop.
When a TrainScheduleRecord with rail target will have a rail_direction, this record will only work as a single-direction target. When a rail_direction of a schedule record is not specified (equal to `nil`), that rail target will work as a two-directional target as usual.
Thanks. That solves trains going to the wrong stations with a bit of scripting then.

Only thing that looks bad to me is that sending a train to a rail target record before the stop will show "going to X,Y" in the train overview. I have no idea where X,Y.

Maybe the train overview could show "going to 'Station Name' via X,Y"? As in show the next actual station plus that it is going via a waypoint. Should I make a new suggestion for that?
boskid wrote:
Sat Oct 16, 2021 1:30 pm
PFQNiet wrote:
Sat Oct 16, 2021 12:04 pm
I didn't realise that temporary stops could be two-directional.
Please do not mix rail target records with temporary records. From lua it is possible to add a temporary record that goes to a station name, and from lua it is possible to create a permanent record that goes to a rail target.
I didn't realize that. Great. That solves another problem of having bidirectional stops/waypoints. It just needs a GUI tweak to add a permanent rail target for the waypoint.