Skip to content

API Add on Fahrten

Marcel1853 edited this page Oct 21, 2026 · 6 revisions

🇬🇧 English version · ⬅ Für Mod-Autoren

Add-ons: Fahrten

Note

Neu in 0.0.20.

Ein Add-on kann Züge selbst losschicken (Aufträge), normale UTL-Lieferungen anstoßen, Halte in laufende Lieferungen einfügen und bei der Zugwahl mitreden. Geplant wird im Add-on – UTL schreibt die Halte in den Fahrplan und meldet, was passiert.

Aufträge

Ein Auftrag hat nichts mit Waren zu tun: Er ist eine Liste von Halten mit beliebigen Wartebedingungen – zum Abstellgleis, in die Werkstatt, zum Umbau-Bahnhof, eine Rundfahrt …

Funktion Wirkung
send_job(train_id, mod, stops) Zug über eigene Halte schicken. Liefert die Auftrags-ID oder nil und einen Grund: "unknown-train", "bad-mod", "busy" (hat eine Lieferung oder einen Auftrag), "held-by-other", "owned-by-other", "no-stops", "bad-target", "station-full" bzw. "unreachable" (jeweils dazu die Nummer des Halts), "no-schedule".
cancel_job(id) Auftrag abbrechen; seine Halte verschwinden, der Zug fährt mit seinem Fahrplan weiter. Liefert true, wenn es ihn gab.
get_job(id) { id, mod, train_id, stops (Anzahl), started (Tick) } oder nil

Jeder Eintrag in stops ist eins davon, jeweils mit wait = Wartebedingungen (wie in LuaSchedule; ohne wait fährt der Zug durch):

Ziel Bedeutung
{ station = unit } eine UTL-Station
{ stop = Haltestelle } irgendeine Haltestelle (LuaEntity oder ihre unit_number) – auch eine ohne UTL
{ rail = Gleis, rail_direction = … } ein Gleisstück
{ position = { x, y }, surface = … } ein Wegpunkt per Position: UTL sucht das Gleis dort (Umkreis 2 Felder; Oberfläche Standard: die des Zugs)

Ohne rail_direction nimmt UTL die Richtung, in der der Zug das Gleis laut Pfadsuche erreicht. Alles davon ist freiwillig: Bei Stationen und Haltestellen setzt UTL den Wegpunkt davor selbst – eigene Wegpunkte braucht ein Add-on nur, wenn es den Weg genauer vorgeben will (z. B. über ein bestimmtes Gleis).

Mehrere Add-ons: Ein Zug gehört dem Add-on, das ihn festhält (auch während eines Auftrags) oder in dessen Depot er frei steht (own_trains). Andere Add-ons bekommen ihn nicht: send_job lehnt mit "held-by-other" bzw. "owned-by-other" ab, hold_train liefert false. Freie UTL-Züge darf jedes Add-on nehmen – sie verlassen damit UTLs Depot-Pool, bis der Auftrag fertig ist.

Getrennte Gleisnetze: UTL prüft per Pfadsuche, ob der erste Halt vom Zug aus und jeder weitere vom vorigen aus erreichbar ist (an einem Halt darf der Zug dabei wenden). Sonst "unreachable" mit der Nummer des Halts. Mit skip_path_check = true an einem Halt entfällt die Prüfung. Die Pfadsuche kostet etwas Zeit – sie läuft nur beim Anlegen eines Auftrags.

Zuglimit: Ist eine Ziel-Haltestelle voll (Zuglimit der Haltestelle oder „max. Züge“ der UTL-Station), lehnt send_job mit "station-full" und der Nummer des Halts ab – wie UTL es bei Lieferungen auch prüft. Mit ignore_limit = true an einem Halt wird das übergangen. UTL fährt Haltestellen über einen Wegpunkt davor an und merkt die Fahrt vor, damit andere Züge die Haltestelle als belegt zählen. Wird das Zuglimit erst gesetzt, wenn der Zug schon unterwegs ist, fährt er bis vor die Haltestelle und wartet dort – das fängt das Add-on selbst ab (z. B. mit cancel_job).

local job = remote.call("utl", "send_job", train_id, "meine-mod", {
  { station = abstellgleis, wait = { { type = "time", ticks = 600 } } },
  { stop = werkstatt, wait = { { type = "inactivity", ticks = 300 } } },
})

Ablauf:

  1. UTL entfernt alte temporäre UTL-Halte (z. B. den Wegpunkt ins Depot), schreibt die Halte des Auftrags hinter den aktuellen Halt und schickt den Zug los (Handbetrieb wird ausgeschaltet).
  2. Während des Auftrags ist der Zug festgehalten: kein Dispatcher, keine Anschlussfahrt, kein Tanken, kein Abbruch (Züge festhalten).
  3. An UTL-Stationen kommen on_train_arrived/on_train_departed mit job_id.
  4. Sind alle Halte abgefahren, kommt on_job_finished; der Zug ist wieder frei und fährt mit seinem eigenen Fahrplan weiter, in der Regel zurück ins Depot.

Wird der Zug umgebaut, ohne dass das Add-on es meldet, endet der Auftrag mit reason = "rebuilt"; verschwindet der Zug, mit "train-lost".

Lieferungen anstoßen

Funktion Wirkung
create_delivery{ provider, requester, type, name, quality, amount, train } eine normale UTL-Lieferung anlegen – mit Reservierungen, Ladefilter, Statistik und Ereignissen wie jede andere.
  • provider, requester = Stationen (unit); beide brauchen eine Haltestelle mit Gleis.
  • type = "item" (Standard) oder "fluid", quality Standard "normal", amount = Menge.
  • train = Zug-ID eines freien UTL-Zugs; ohne train nimmt UTL den nächsten freien Zug, der passt (Netz, Länge, Laderaum, Treibstoff).
  • Mehr als der Zug fasst, wird nicht geladen.
  • Rückgabe: Lieferungs-ID oder nil und ein Grund: "bad-spec", "bad-station", "not-enough" (Anbieter hat nicht so viel frei), "no-train", "unreachable", "schedule".

Eigene Fahrplan-Einträge

Ein Add-on darf den Fahrplan seiner Züge auch selbst ändern:

  • Feste Halte, Zuggruppen und Unterbrechungen fasst UTL nie an – es arbeitet nur mit temporären Einträgen hinter dem aktuellen Halt.
  • Eigene temporäre Einträge (an UTL vorbei mit LuaSchedule.add_record) bleiben stehen, wenn UTL aufräumt (Abbruch, neuer Auftrag, Umbau): UTL merkt sich, welche temporären Einträge es selbst geschrieben hat, und löscht nur diese.
-- Unterbrechung „bei wenig Treibstoff zur Werkstatt“ – UTL lässt sie in Ruhe
local schedule = train.get_schedule()
schedule.add_interrupt({ name = "Werkstatt", conditions = { { type = "fuel_item_count_any", condition = {
  first_signal = { type = "item", name = "coal" },
  comparator = "<", constant = 5 } } }, targets = { { station = "Werkstatt",
  wait_conditions = { { type = "time", ticks = 600 } } } }, inside_interrupt = false })

Halte in Lieferungen einfügen

Funktion Wirkung
add_delivery_stop(delivery_id, spec) Halt in eine laufende Lieferung einfügen. Liefert true oder false und einen Grund ("unknown-delivery", "bad-position", "bad-target", "unreachable", "no-schedule", "stop-not-found").

spec = Ziel wie bei Aufträgen (station, stop oder rail), wait = Wartebedingungen und where:

where erlaubt, solange die Lieferung …
"before_provider" noch zum Anbieter fährt
"after_provider" (Standard) zum Anbieter fährt oder dort lädt
"after_requester" noch nicht fertig ist

Eingefügte Halte zählen für den Ablauf der Lieferung nicht und verschwinden mit ihr, wenn sie abgebrochen wird. get_delivery zeigt ihre Anzahl in extra_stops.

Zugfilter

Funktion Wirkung
register_train_filter{ mod, interface, filter } bei der Zugwahl mitreden (in on_init und on_configuration_changed anmelden)

Nur wenn Anbieter oder Abnehmer einer Fahrt eine Add-on-Rolle haben, ruft UTL das auf – einmal je Vermittlung mit allen Kandidaten, beste zuerst, auch bei der Anschlussfahrt direkt nach einer Lieferung:

remote.add_interface("meine-mod", {
  filter = function(train_ids, info)
    -- info = { provider, requester, key, provider_role, requester_role }
    local allowed = {}
    for _, id in ipairs(train_ids) do
      if passt(id, info) then allowed[#allowed + 1] = id end
    end
    return allowed   -- leere Liste = keiner; nil = alle wie vorher
  end,
})
remote.call("utl", "register_train_filter", { mod = "meine-mod", interface = "meine-mod", filter = "filter" })

Die Reihenfolge der Rückgabe ist die Wunschreihenfolge. Lehnt der Filter alle ab, versucht UTL es beim nächsten Durchlauf wieder – den Filter also schnell halten (Leistung).

Clone this wiki locally