Open robot256 opened 2 years ago
First question for feedback:
Which routing scheme would be best?
Second question: How much user input should be required to configure the inter-surface links?
for question number one :
Looking at these options I personally would go for option 2 as it gives the most flexibility especially in something like SE, where there are many different ressources and some of them are frequently needed in combination.
for question number two:
I think I would prefer a manual approach for this question, as it shouldn't be to hard to generate the gui and I think having a override for the automatic one would be really practical too. so I think nothing would be lost by going for this one first. (also it means less performance overhead as we don't need to check for new connections between surfaces)
Thanks for the feedback! I am very glad to have someone critique my ideas.
I added another concern to the readme, to make the learning curve manageable for players who haven't used complicated train routing before. I don't want to replicate 100% of the features of LTN. Reducing the total number of trains is not the goal, only reducing the number elevator transits.
For dispatching method: Option 2 is the most complicated to implement, and learn to use. I'm a little hesitant to sign up for this amount of code and maintenance unless it's absolutely necessary. I also don't like the number of empty trips it causes in general. There are some tricks we could do to limit the number of empty trains making transits, like giving priority to storing empties in a depot on the current surface unless the other surface has not enough empties. But that ends up making it even more complicated than LTN.
For multiple-resource providers, option 1 would work with the method of filtering wagon slots to carry multiple items. With the train dedicated to that set of resources, the schedule, and potentially circuits can be set to travel whenever any one of the resources is needed. It's cumbersome but doable. But would also result in extra transits if only half the train's contents was actually requested, and the train would always have to return.
Option 3 can be done with multi-resource providers either with filtered wagons, or if each resource has a separate waiting area station they load up, and circuits to tell which resource should be loaded. Though I might be recalling how I combined the Train Supply Manager, Dispatcher, and Automatic Coupling System mods into a frankenstein's monster of a network.
With option 1, there are also vanilla ways to manually pair up-going resources with down-going resources, so that return trips would not be completely empty. That comes down to whether we want the user to make a complicated vanilla-like setup, or learn how to use the LTN system and thereafter have a potentially simpler system.
In my opinion, the strength of option 1 is that it allows all the vanilla techniques to be reused, and also several other train mods like Dispatcher and Automatic Coupling System. Even if we implement option 2 eventually, I am leaning toward implementing option 1 first, as a separate mod, for that purpose.
For network discovery: Agreed that manual configuration is the most transparent and least performance cost. I do worry it would confuse people if they forget to add a route or it gets misconfigured for some reason. And it rules out the possibility of automatically routing through Train Tunnels, or using two space elevators to cross a planet's ocean, for example. If you have to manually specify which elevator stops to use for each station pair, then it's no different from scheduling the elevator transits manually.
I guess I don't see how automatic route discovery would be a problem gameplay wise. We already have to segregate trains that are on the same surface, by using different stop names or different LTN network IDs. With a sufficient path cost, there is no risk that a train would path up-down-up-down unless something was really wrong with the rest of your network.
The hybrid link system is what I tried on my personal LTN hacking session, before I knew you could rename elevators at all, and it was very annoying even with every elevator as the default name.
about dispatch method:
I do agree that 2 is the most code intensive one and therefore the hardest. I'm just not sure if 1 would really be a good first step, or if it would more be a side-step. because I see a big difference in how it operates, from a mod level. as it basically needs to modify existing schedules to create the train limits. while both 2 and 3 will create schedules from only the internal data. of course this could also be avoided by doing 1 in a different way, namely a read schedule -> store schedule internally -> delete schedule -> modify internal schedule -> write new schedule**. this way a lot of code could be transferred into the other mod. I also see the appeal of a type 1 mod for people going more vanilla. and still wanting inter surface train limits.
**I thought of the following other two options to do this but there are probably even better ones: i) turn train to manual if it shouldn't drive. (can cause a lot of confusion.) ii) insert fake station that either has a exceeded limit or is impossible to reach.
for tunnels a automatic configuration would be nice. connecting stuff automatically through elevators I see no problem with. The part where I would see manual configuration to be nice is at the transfer penalty side, how much should the mod avoid to move items through the elevator. but the connection between the surfaces could be done automatic, even we would give the options to configure that manually.
I looked at the Factorio API again, and I am not as excited about automatic connection finding now. There are only two ways to find what stops can be pathed to from where: Create a train and tell it to find a path, or duplicate the entire Factorio rail network connection and pathing logic in the mod. I suppose creating an invisible dummy train and asking it to path to/from the surface entrance/exit could work to determine which ones are linked, but that is still a lot of work and has to be redone every time the rail network changes.
I don't think the above process will ever make sense to replace a valid vanilla train path with a multi-surface path, so the only trains that should be modified are ones that cannot already get to a station on their own surface. That means the schedule would only be modified if the train is already stuck in the state of "destination full" or "no path" and an open station exists on a linked surface. I don't see the need to make manual scheduling of elevator stops unnecessary in every single instance. Unusual ones like bridging oceans do not need to be handled.
I think for vanilla-like scheduling, this mod's behavior does not have to be completely invisible to the user. As long as the mod behavior can be triggered with a specific, relatively simple network design, that will be good enough.
The Train Tunnels mod is still very buggy and I think I will not try to support it right now. I think it has been sufficiently demonstrated that without Factorio support for interdimensional train portals, mod-teleporting trains is very slow and inefficient.
Dispatcher saves the schedule and replaces it with a blank one, and this has caused me a lot of headaches when the saved schedule is not properly restored. Limiting schedule adjustment to when the train is already stuck should solve this.
Concurrent Train Restriction does exactly (ii), creating a fake station and assigning it to trains that are "paused".
I did another test of the train-stuck behavior. A train will pause its schedule if all stops of the target name on that surface are closed by the train limit, OR if all stops of the target name on that surface are inaccessible. If there are no stops of the target name on the surface (i.e. it only exists on the linked surface) then the train will skip that stop. There is no event when the nonexistent schedule entry is skipped.
That means for my simple method to work, you need dummy stops on the origin surface in order to trigger mod routing to the other surface. This could be handled by invisible stops created by a mod GUI, or a requirement of the user to place dummy stops manually in order to specify which stops are accessible from the other surface.
If a stop on the same surface is both inaccessible and full (or limit=0), the train pathing to it will say "destination full" rather than "no path".
If there are two stops on the same surface, one accessible but full and the other one available but inaccessible, the train will say "no path" as it is trying to get to the inaccessible one. If the accessible one becomes available, the train will not repath to it.
If there are two available stops on the same surface, one accessible and the other inaccessible, the train will reserve the accessible one even if it is farther away. This is good, because it means the relative location of the inaccessible dummy stop is not important. Real stops on the same surface will always take priority over selecting a dummy stop that requests a transit to another surface.
More notes:
Use this thread to provide comments and suggestions for the initial development.