raiguard / TrainGroups

A Factorio mod that eases the process of configuring train schedules.
MIT License
5 stars 0 forks source link

Group assignment lost when splitting locomotives from each other. #6

Closed robot256 closed 2 years ago

robot256 commented 2 years ago

Describe the Bug

In TrainGroups version 1.0.3. Splitting a train with a locomotive on each end will assign the group to one half but not the other.

Normally if you are only shunting manually, this is not a problem. The group gets assigned to the whole train when you couple something to the half that was assigned the group. But Multiple Unit Train Control also uncouples, deletes and replaces locomotives automatically, which causes TrainGroups to delete the data before recoupling.

When MUTC replaces a locomotive, the following events occur:

  1. MUTC decouples the target locomotive from the front and rear stock.
  2. The target locomotive becomes its own train ID and is the subject of the first on_train_created event(s) triggered by the decoupling(s), because it was the target of the "decouple" command.
  3. In the first on_train_created event, TrainGroups moves the group data from the original train ID to the target locomotive's train ID.
  4. The rest of the train ends up in either one or two remainder trains, and each piece can contain a mix of wagons and/or locomotives, triggering on_train_created a second time.
  5. In the second on_train_created event, TrainGroups does not have any data associated with the original train ID, so the remainder trains do not get assigned a group.
  6. MUTC deletes the target locomotive.
  7. TrainGroups deletes the group data that was assigned only to the target locomotive.
  8. MUTC creates the replacement locomotive and couples it to the remainder train(s).
  9. TrainGroups has no group data assigned to the remainder train(s), so there is no group assigned to the new train.

Unfortunately, there is no way to tell from on_train_created whether there was more than one train created by the same event. That's why I suggested saving it for on_tick. With careful coordination, you can subscribe when an entry is added to the checking queue and unsubscribe when the checking queue is empty.

raiguard commented 2 years ago

Aw man. I guess on_tick is necessary after all.

I used to conditionally register on_tick, but after finding a desync that would have been annoying to fix, I decided to not do that any more. So it just runs all the time.

Luckily, calling pairs() on an empty table has practically zero performance impact, so it's fine.

robot256 commented 2 years ago

Yeah, I do conditional registration in MUTC. Took some care to make sure that the event registration always matches the size of the queue. That's also what on_load is for.

robot256 commented 2 years ago

Thanks for fixing this!

raiguard commented 2 years ago

I also updated it to remove the requirement for locomotives for a train to have a group. This matches the base game's behavior. If you make a 1-1 train, decouple it, then couple a new locomotive to the cargo wagon, it will take the group from the cargo wagon.

Will this be a problem with MUTC?

robot256 commented 2 years ago

That should work well. There's no harm setting the schedule for a train with no locomotives.