Files
Viano-Core/doc/clientless/transport-tools.md
T
Nico 1164a72ea3 Implement clientless transports, Lua reload and same-map portals
Add native transport recording and execution with grid lifecycle handling, clientless teleport acknowledgements, and regression tests. Support targeted same-map portal imports and preserve disabled taxi nodes. Document live transport and portal verification and the remaining portal inventory.
2026-10-26 11:27:56 +01:00

331 lines
14 KiB
Markdown

# Clientless Transport: Aufnahme und Test
Die Integration verwendet reguläre Trinity-Transporte (`TransportBase`). Eine
Haltestelle hat genau einen TravelGraph-Node für Ein- und Ausstieg. Der Übergang
auf das Fahrzeug wird getrennt von den Groundkanten aufgenommen. Es werden
keine Schiffe, Aufzüge oder Bahnen teleportiert oder für den Bot angehalten.
## Datenbank
Die zusätzliche Migration liegt unter
`sql/custom/world/2026_10_25_00_clientless_transport.sql`. Sie wird ausdrücklich
auf die Test-Weltdatenbank angewendet. Die drei neuen Tabellen sind:
- `vcore_clientless_transport_stop`: Haltestelle, Fahrzeug-Entry, Spawn und Dockpose.
- `vcore_clientless_transport_point`: geordnete Übergangspunkte mit Welt-/Transportbezug.
- `vcore_clientless_transport_stand`: benannte Stehplätze relativ zum Fahrzeugmodell.
Bestehende Nodes und Groundkanten bleiben erhalten. Neue Fahrtverbindungen
werden in `vcore_clientless_travel_edge` gespeichert. Ohne zwei gültige,
kompatible Aufnahmen wird eine Transportkante vom Graphen nicht geladen.
Ein Reload kopiert keine Änderungen in eine bereits laufende Fahrt hinein.
## 1. Haltestelle und Fahrzeug bestimmen
Schiffe und Zeppeline können unabhängig vom Aufenthaltsort des GM über die
nativen Routendaten untersucht werden:
```text
.clientless transport services
.clientless transport services 7
```
Die Liste zeigt Spawn, Entry, Modellname, Umlaufzeit, Zahl der geplanten Halte
und Pfadabschnitte. Mit Spawn-ID werden zusätzlich die tatsächlichen
Dockpositionen, Karten, Ankunftszeitpunkte im Umlauf und Haltezeiten ausgegeben.
Diese Daten stammen aus den geladenen Transportpfaden, nicht aus möglicherweise
veralteten `transports.name`-Beschreibungen. Die Dockposition bezeichnet den
Fahrzeugursprung; den Haltestellen-Node weiterhin auf begehbarem festen Boden
am tatsächlichen Land-Deck-Übergang aufnehmen. Reine Patrouillen ohne planmäßige
Halte sind keine automatisch geeigneten Passagierverbindungen.
Beide Befehle sind auch ohne eingeloggten Bot in der Konsole verfügbar.
Die Spawn-ID bleibt auf beiden Karten dieselbe, obwohl der Core beim
Kartenwechsel eine andere Transportkopie verwendet. Diese kopiert der Recorder
nicht als zweites Fahrzeug in den Graphen.
Mit dem GM auf festem Boden direkt vor der gewünschten Einstiegsstelle stehen:
```text
.clientless node add lift_lower elevator
.clientless transport near 30
```
Für andere Verkehrsmittel den Nodetyp `tram`, `ship` oder `zeppelin` verwenden.
`near` zeigt unter anderem Entry, Spawn-ID, Weltposition, `stopped`, Periode,
Fortschritt und verbleibende Haltezeit. Die **Spawn-ID**, nicht die Entry-ID,
bindet die Aufnahme an das konkrete Fahrzeug bzw. den konkreten Wagen.
```text
.clientless transport inspect 204666
```
In der Konsole wird ein online befindlicher CPC-Player als Beobachter angegeben:
```text
clientless transport inspect 204666 26
clientless transport near 30 26
```
Die vom Transportrecorder verwendeten Node-Koordinaten können auch über die
Konsole geprüft werden:
```text
clientless transport node tram_sw
clientless transport node tram_if
```
Das Objekt muss auf der Map des Beobachters geladen sein. `remainingPause` wird
in Millisekunden ausgegeben; `4294967295` bezeichnet einen Halt ohne bekannte
zeitliche Begrenzung. Ein GoState allein wird nicht als Ankunft interpretiert.
## 2. Geeigneten Stehplatz speichern (optional vorab)
Normal an Bord gehen, einen sicheren, ebenen Platz wählen und dort stehen:
```text
.clientless transport stand add center
.clientless transport stand list
```
Stehplätze sind lokal zum Transportmodell gespeichert und bleiben bei Bewegung
und Kartenwechseln an derselben Stelle des Fahrzeugs. Sie können auch während
der Fahrt aufgenommen werden. Nicht fliegen oder fallen. Derselbe Name wird
nicht still überschrieben. Andere Namen erlauben weitere Standorte.
```text
.clientless transport stand list 4170
.clientless transport stand remove 4170 unused_name
```
`list <entry>` und `remove <entry> <name>` sind konsolenfähig. Ein von einer
Haltestelle verwendeter Standname kann nicht entfernt werden, bevor deren
Aufnahme ausdrücklich entfernt wurde.
## 3. Land -> Deck aufnehmen
Wieder am gemeinsamen Haltestellen-Node auf festem Boden stehen. Auf die nächste
Ankunft warten, damit ein vollständiges Haltefenster verfügbar ist:
```text
.clientless transport record start lift_lower 204666
```
Nun normal zum Fahrzeug gehen, es betreten und bis zum gewünschten Stehplatz
laufen. Die Aufnahme erfolgt automatisch alle 100 ms mit mindestens 0,75 Yards
Punktabstand. Der Wechsel vom Land zum Passenger wird automatisch markiert.
```text
.clientless transport record mark
.clientless transport record info
.clientless transport record stop center
```
`mark` ist optional und erzwingt einen zusätzlichen Punkt. `stop center`
speichert den Übergang und legt bei Bedarf den Stand `center` an. Existiert er
bereits, muss der GM höchstens 1,5 Yards davon entfernt stehen.
Die Aufnahme muss während desselben Halts beendet werden. Abfahrt,
Transportwechsel, Verlassen des Fahrzeugs nach bereits erfolgtem Einstieg,
Positionssprünge über 8 Yards, Flug oder ein Übergang über 60 Yards machen sie
ungültig. Vorhandene Aufnahmen werden nicht still überschrieben.
```text
.clientless transport record cancel
```
Bei einem Fehler bleibt die Diagnose über `record info` sichtbar. Erst mit
`cancel` verwerfen und beim nächsten Halt neu beginnen. Jeder GM hat einen
eigenen Aufnahmebuffer; Logout verwirft nur dessen ungespeicherte Aufnahme.
## 4. Gegenhaltestelle aufnehmen
Mit genau demselben Fahrzeug/Wagen zur Gegenhaltestelle fahren. Aussteigen und
auf festem Boden den gemeinsamen Node anlegen:
```text
.clientless node add lift_upper elevator
```
Bei einer folgenden Ankunft von diesem Node erneut an Bord zum gleichen lokalen
Stand laufen und aufnehmen:
```text
.clientless transport record start lift_upper 204666
.clientless transport record stop center
.clientless transport stops
```
Die Deck-Endpunkte beider Übergänge dürfen höchstens 3 Yards auseinanderliegen.
Damit wird keine unbekannte längere Querung des Decks zwischen zwei verschiedenen
Standorten benötigt. Der aufgezeichnete Übergang wird beim Ausstieg umgekehrt.
Deshalb einen Weg aufnehmen, der in beiden Laufrichtungen begehbar ist.
Bei einer Tiefenbahnaufnahme denselben Wagen an beiden Bahnhöfen verwenden.
Die sechs Wagen haben Entries 176080..176085 und Spawn-IDs 18802..18807.
Die Haltefenster betragen ungefähr 11..14 Sekunden; kurze Rampenwege sind
entsprechend wichtig. Ein anderer Wagen ist eine andere Aufnahmeverbindung.
## 5. Fahrtkante anlegen
```text
.clientless transport link lift_lower lift_upper elevator 100 both
```
Der Kostenwert ist ein positiver **Graphkostenwert**, keine automatisch mit
Groundlängen vergleichbare Sekundenzahl. Zum ersten isolierten Funktionstest
ist der genaue Wert unkritisch; konkurrierende Fernrouten benötigen später eine
gemeinsame Kostenkalibrierung. `both` ist optional und erzeugt eine bidirektionale
Kante. Es darf nur verwendet werden, wenn das reale Verkehrsmittel beide
Richtungen bedient. Ohne `both` entsteht nur die angegebene Fahrtrichtung.
Die Kante wird erst nach Prüfung beider Haltestellen angelegt. Gleicher Entry,
gleicher Spawn, verschiedene Dockpositionen/Maps und kompatible Stehplätze sind
notwendig. Die Typen `tram`/`elevator` gehören zu GameObjects des Typs 11,
`ship`/`zeppelin` zu Typ 15.
Die Haltestellen benötigen wie andere Nodes eine Verbindung zum übrigen Netz:
aufgenommene Groundkanten oder zulässige, vollständig geprüfte MMAP-Anschlüsse.
## 6. Botfahrt testen
Arthoran zunächst an der Abfahrt positionieren und clientlos einloggen. Das
bestehende Login-Lua-Skript kann bereits andere Aufträge starten; für einen
isolierten Transporttest dieses Skript vorher entsprechend einstellen, z.B.:
```lua
queue_action("travel_to_node", {
node = "lift_upper",
hard_destination = true
})
```
Alternativ bei einem untätigen CPC-Player über Konsole oder Spielchat:
```text
clientless transport travel 26 lift_upper
clientless transport status 26
clientless actioninfo 26
```
`travel` hängt einen Auftrag an die reguläre CPC-Aktionswarteschlange an; es
unterbricht keine bereits laufende andere Aktion. Die Zustände sind `Waiting`,
`Boarding`, `Riding`, `Leaving`, `Arrived`, `Failed`. Während der Mitfahrt wird
keine Groundnavigation gestartet. Native Kartenwechsel werden für CPC ohne
Client-ACK abgeschlossen. Der nächste Graphschritt beginnt erst nach dem
Aussteigen und Erreichen des gemeinsamen Zielnodes auf Land.
```text
clientless transport cancel 26
```
Abbruch auf Land stoppt die Fahrt. An Bord bleibt der Bot Passenger und steigt
an einer sicheren aufgezeichneten Haltestelle aus, statt in der Luft oder im
Wasser abgehängt zu werden. Ein harter Timeout meldet `Failed` und lässt eine
noch vorhandene Passenger-Zuordnung bestehen; die Diagnose bleibt erhalten.
Alle Transport-Zustandswechsel und Aufnahmefehler stehen in
`adventurebot-navigation.log`. `.clientless`-Spielchatbefehle und deren Antworten
werden dort ebenfalls protokolliert; Konsolenantworten sind über tmux lesbar.
## Pflege
```text
.clientless transport reload
.clientless transport forget lift_lower
```
`forget` entfernt nur die Übergangsaufnahme. Node, Groundkanten und benannte
Stehplätze bleiben bestehen. Nach Verschieben des Nodes dessen Aufnahme neu
anlegen. Fahrtkanten mit unvollständigen Daten werden nicht geplant.
## Verifikation und Grenzen
Automatisierte Zustands-/Recorder-Tests:
```text
python3 tests/clientless/test_transport.py
```
Diese verwenden die tatsächlichen Produktionsmethoden mit deterministischen
Weltobjekt-Doubles. Sie prüfen unter anderem Haltefenster, Koordinatenrahmen,
Warteverhalten, Passenger-Zuordnung, Ausstieg und Abbruch/Timeout. Sie beweisen
keine Kollisionsfreiheit eines konkreten Decks und keine erfolgreiche Fahrt
auf einem realen GameObject.
Nach dem Tiefenbahntest folgen ein Schiff mit Kartenwechsel und ein Zeppelin;
Fahrstühle werden anschließend behandelt. Je Verbindung beide Fahrtrichtungen,
verpasste Halte, Ein-/Ausstieg und Fortsetzung einer Groundroute prüfen. Logout/Serverneustart
während einer Typ-11-Fahrt ist noch separat zu verifizieren; der bestehende
Trinity-Loginpfad stellt vorrangig die Typ-15-Transportzuordnung wieder her.
Die Recorder setzen einen normalen GM-Client für die echte Bewegung voraus;
sie erzeugen keine synthetischen Deckpfade.
## Live-Test Sturmwind → Eisenschmiede, 26.10.2026
Arthoran (GUID 26) fuhr über Kante 1741 von `tram_sw` nach `tram_if` auf
Wagen 18803. Navigationlog: Boarding 00:37:34, Riding mit `passenger=1`
00:37:35, Leaving 00:38:38, Arrived mit `passenger=0` 00:38:42.
Die Konsole meldete anschließend `travel-route-complete`. Das belegt die
serverseitige Durchführung einer Richtung; Gegenrichtung und visuelle
Ingame-Abnahme sind damit noch nicht bestätigt.
Vorbedingung/noch offener Fehler: Beim ersten Start ausschließlich an der
Sturmwindseite war Spawn 18803 nicht geladen. Seine Datenbank-Spawnposition
liegt auf der Eisenschmiedeseite (4.528, 8.435, 7.011). Ein kurzer Diagnose-Login
Arthorans an `tram_if` lud das Spawn-Grid; danach war der aktive Wagen auch von
Sturmwind aus verfügbar. Für den eigentlichen Fahrtest wurde Arthoran offline
wieder an `tram_sw` positioniert. Während der Fahrt wurden keine Positionen per
Datenbank oder Teleport verändert. Automatisches Laden des entfernten
Transport-Spawn-Grids muss vor autonomem Betrieb ergänzt werden; der erfolgreiche
Fahrtest nach manuellem Vorladen behebt diese Einschränkung nicht.
Testskript und vorherige Charakterposition gesichert unter
`/tmp/vcore-tram-ride.1i65g2dm`.
Nachtrag: Der oben beschriebene Spawn-Grid-Fehler wurde anschließend im
allgemeinen Map-Lifecycle behoben und mit einem frischen Prozess ausschließlich
von Sturmwind aus geprüft. Alle sechs Wagen waren verfügbar und bewegten sich.
Details und verbleibende Befunde: [transport-grid-lifecycle.md](transport-grid-lifecycle.md).
## Nächste Verbindungen: Schiff und Zeppelin
Aktuelle Nutzerauswahl: zuerst **Schiff ab Sturmwind**. Die konkrete Aufnahme
für Spawn 2 und der Testablauf stehen in
[ship-stormwind-ruttheran.md](ship-stormwind-ruttheran.md).
Geeignete erste Kandidaten aus der Testdatenbank:
- Spawn 7, Entry 20808, `The Maiden's Fancy`: Küstenschiff; tatsächliche Häfen
über `services 7` prüfen. Der Kartenwechsel zwischen Kalimdor und den östlichen
Königreichen prüft die Passenger-Übergabe zwischen Transportkopien.
- Spawn 20, Entry 190549, `The Zephyr`: Zeppelin auf Kalimdor. Die vorhandene
Transport-/SmartAI bleibt erhalten. Die Fahrt ergänzt den Lufttransport-Test
ohne Kartenwechsel.
Die Recorder- und Link-Befehle bleiben dieselben. Beispiele mit nach Prüfung
der Anlegestellen manuell aufgenommenen Nodes:
```text
.clientless node add ship_ratchet ship
.clientless transport record start ship_ratchet 7
.clientless transport record stop maiden_center
.clientless node add ship_booty_bay ship
.clientless transport record start ship_booty_bay 7
.clientless transport record stop maiden_center
.clientless transport link ship_ratchet ship_booty_bay ship 100 both
```
Den ersten Stehplatz an der Gegenhaltestelle wieder exakt aufsuchen. Zwischen
den beiden Node-Aufnahmen mit demselben Schiff mitfahren. `record start` beginnt
jeweils auf festem Boden, `record stop` endet an Bord während desselben Halts.
Pro physischer Anlegestelle weiterhin nur einen gemeinsamen Node verwenden;
Landverbindungen zum übrigen TravelGraph getrennt als Groundkante erfassen.
Für den Zeppelin analog eigene Haltestellen-Keys, Fahrzeug-Spawn 20 und
Kantentyp `zeppelin` verwenden. Schiffs- und Zeppelin-Verbindungen erst nach
einer echten Fahrt als verifiziert betrachten. Die automatisierten Tests
simulieren den nativen Kartenwechsel; sie ersetzen keinen echten Worldport-
und Kollisions-/Sichtbarkeitstest.