Skip to content

API Add on rebuilding trains

Marcel1853 edited this page Oct 21, 2026 · 4 revisions

🇩🇪 Deutsche Version · ⬅ For mod authors

Add-ons: rebuilding and holding trains

Note

New in 0.0.20. train_transfer_started/train_transfer_finished exist since 0.0.10.

Rebuilding trains

Coupling or uncoupling wagons makes Factorio create new trains with new ids. Without an announcement UTL then cancels the old train's delivery ("rebuilt"). If the add-on announces the rebuild, everything moves to the new train. UTL never couples anything itself – the add-on does.

Function Effect
begin_train_change(ids) A rebuild starts: train id or list of ids that are about to disappear. Call it before coupling. Until the end UTL does not cancel their deliveries; the train's own schedule is saved.
end_train_change(old_ids, train) Rebuild done: delivery, depot entry, hold and job of the old ids move to train (LuaTrain). Returns true on success.
forget_train(train_id) Make UTL forget a train (old or new id), e.g. the uncoupled part that should stay behind. A delivery on it is cancelled.
train_transfer_started(old_id) / train_transfer_finished(old_id, train) older form with exactly one id (e.g. for mods that move trains); UTL detects the Space Exploration space elevator by itself

What end_train_change also does:

  • Schedule: if the delivery's stops are missing afterwards, UTL sets them again. If the schedule points at no stop any more, UTL sends the train to the delivery's next stop. If the train has no schedule at all, it gets back the one saved at begin_train_change.
  • Several old trains with a delivery (two loaded trains are coupled): train keeps the first, the others are cancelled.
  • Rebuilt in a depot: the train is parked again and its cargo space measured again.
  • Afterwards on_train_rebuilt comes with changing = true.
-- uncouple wagons without losing the delivery
local old_id = train.id
local front, last = train.front_stock, train.back_stock
remote.call("utl", "begin_train_change", { old_id })
front.disconnect_rolling_stock(defines.rail_direction.back)
remote.call("utl", "end_train_change", { old_id }, front.train)   -- this part carries on
remote.call("utl", "forget_train", last.train.id)                 -- the rest stays behind

If end_train_change is never called, UTL forgets the announcement after 10 minutes.

Holding trains

Function Effect
hold_train(train_id, mod) Hold a train: no dispatcher, no chained delivery, no refuelling, no cleanup, no cancelling – not even in manual mode, no "stuck" alert. A running delivery stays. Returns false if another mod already holds it or it stands free in another add-on's depot.
release_train(train_id) release it again. Standing in a depot without a delivery, it is free right away; otherwise it carries on with its schedule.
is_held(train_id) name of the mod holding it, or nil (also in get_train as held_by)
remeasure_train(train_id) measure the cargo space of a free train again when the add-on rebuilt it in the depot without the train id changing. Returns true if UTL knows the train as free.

Typical course when shunting in the middle of a delivery:

  1. hold_train – UTL leaves the train alone.
  2. Train to manual mode, shunt, couple with begin_train_change/end_train_change.
  3. Train to automatic, release_train – the delivery goes on.

A job holds the train by itself while it runs.

Clone this wiki locally