OmegaSim Wiki

OmegaSim Wiki – die Idee dazu stammt von Gnen54. Hier stehen die offenen Artikel von Nutzer Luuke42 unter der Lizenz CC BY-SA 4.0.

Mehrspieler

Stand dieses Artikels: OmegaSim 1.2.9 vom 26.10.2026 · Firmware des Autos: nicht bekannt (OmegaSim liest die Firmware-Version nicht aus)
Dieser Text wurde mithilfe von KI erstellt (Claude) und ist nicht in jedem Punkt von Menschen geprüft. Fehler bitte direkt verbessern oder auf der Diskussionsseite melden, siehe Mitmachen. Die öffentliche Fassung auf luuke42.github.io/omegasim kann älter sein als der hier beschriebene Stand.

Der Reiter WLAN Mehrspieler in OmegaSim

Mehrspieler bezeichnet in OmegaSim zwei getrennte Funktionen, mit denen mehrere Menschen gegeneinander fahren: den Mehrspieler-Modus an einem Gerät, bei dem bis zu drei Spieler mit je einem Controller und einem eigenen Carrera HYBRID-Auto an einem Telefon oder PC fahren, und den WLAN-Mehrspieler (experimentell), bei dem mehrere Geräte mit je einem Auto über ein gemeinsames Netz eine Rangliste, einen gemeinsamen Start und gleiche Renneinstellungen teilen. Im ersten Fall rechnet ein Gerät alle Autos in einem gemeinsamen Sendetakt; im zweiten rechnet jedes Gerät nur sein eigenes Auto, und ein Host vermittelt über eine kleine HTTP-Schnittstelle. Beide lassen sich mit NPCs kombinieren (siehe NPC-Fahrverhalten).

Auf einen Blick

Merkmal An einem Gerät WLAN-Mehrspieler
Menüpfad Optionen → Mehrspieler; Rollen in FAHREN → Autos → Garage; Belegung in Optionen → Controller Reiter WLAN Mehrspieler mit den Seiten Über Android-App und Über PC mit Python
Wichtigste Schalter (Standard) Mehrspieler-Modus (aus; schaltet sich mit einer Rolle Spieler 2/3 ein) · Fahrgefühl je Spieler („wie Spieler 1“) Host-Adresse, Mein Name · Renneinstellungen erzwingen (an)
Status stabil (seit dem 1.1-Abschnitt nicht mehr experimentell) experimentell
Seit Version zwei Spieler 0.6.44, drei Spieler 0.9.17, Übernehmen/Abbrechen beim Belegen 1.2.3, Fahrgefühl je Spieler 1.2.4 gemeinsamer Start 0.8.42, Bereitschaftsschirm 0.8.126, Feinabgleich und „für alle beenden“ 0.9.32
Beteiligte Quelldateien src/49-spieler.js, src/20-protocol.js, src/90-ghosts.js (Pads, Belegung, Rollen), src/50-drive.js (Cockpit), src/98-presets.js src/97-sessions.js (Client), tools/omegasim_host.py (PC-Host), android-app/…/HostServer.java, OmegaHostPlugin.java, OmegaHostService.java (Telefon-Host)

Grundlagen

Ein Gerät, mehrere Autos

Ein Telefon kann sich per Bluetooth Low Energy mit mehreren Autos zugleich verbinden. Jedes Auto bekommt etwa alle 45 ms ein Steuerpaket. Für mehrere Spieler an einem Gerät heißt das: Die App liest mehrere Gamepads, rechnet für jedes Auto ein eigenes Fahrzeugmodell und schickt alle Pakete im selben Takt. Gamepads meldet der Browser über die Gamepad-Schnittstelle; er gibt ein Pad aber erst nach dem ersten Tastendruck heraus.

Host und Client

Im WLAN-Mehrspieler ist ein Gerät der Host (Server): Es hält die gemeinsame Rangliste und den Rennplan. Alle anderen sind Clients: Sie melden ihren Stand und fragen den gemeinsamen Stand ab. Die Verbindung zu den eigenen Autos bleibt dabei auf jedem Telefon; über das WLAN gehen nur Rundenzahl, Rundenzeiten, Abgänge und für Zuschauer die Positionen.

HTTP-Abfrage statt WebSocket

Ein WebSocket ist eine dauerhaft offene Verbindung, über die beide Seiten jederzeit senden können. OmegaSim nutzt bewusst keinen, sondern einfache HTTP-Anfragen (GET zum Abfragen, POST zum Melden, Inhalt als JSON). Der Client fragt regelmäßig nach (Polling). Die Begründung im Host-Programm: Eine Rangliste ändert sich nur alle paar Sekunden, eine abgerissene HTTP-Anfrage ist ein Fehler in einer Abfrage, ein abgerissener WebSocket dagegen ein Zustand, der wieder aufgebaut werden muss.[1]

Latenz und Uhrenabgleich

Latenz ist die Zeit, die eine Nachricht unterwegs ist. Die Hin- und Rückzeit einer Anfrage heißt Round-Trip-Time (RTT). Damit alle Telefone gleichzeitig starten, braucht jedes den Versatz seiner Uhr zur Uhr des Hosts. Das Verfahren ist das von Cristian (Grundlage auch von NTP): Man notiert die eigene Uhr beim Absenden (t0) und beim Empfang (t1), der Host schickt seine Uhrzeit mit, und man nimmt an, dass der Host in der Mitte der Laufzeit geantwortet hat. Der Fehler ist dann höchstens die halbe RTT.

Secure Context und Freigaben

Browser erlauben Web Bluetooth nur in einem secure context: einer verschlüsselten Adresse (https), localhost oder einer lokalen Datei. Eine WLAN-Adresse wie 192.168.1.50:8080 über unverschlüsseltes HTTP ist keiner. Außerdem darf eine über https geladene Seite keine unverschlüsselte Adresse im WLAN abfragen, und eine Anfrage von einer fremden Herkunft braucht die Erlaubnis des Servers (CORS). Für JSON-POSTs schickt der Browser vorher eine Prüfanfrage (Preflight, Methode OPTIONS); der Host beantwortet sie mit 204 und den Kopfzeilen Access-Control-Allow-*.

Dienstsuche im WLAN

Damit niemand die Adresse abtippen muss, meldet der Host in der Android-App seinen Dienst per mDNS/DNS-SD (unter Android „NSD“) unter dem Namen _omegasim._tcp an. Andere Telefone suchen danach und bekommen Adresse und Port.

Bedienung

Mehrere Spieler an einem Gerät

  1. Alle Autos verbinden und an jedem Controller einmal einen Knopf drücken.
  2. In der Garage einem zweiten Auto die Rolle Spieler 2 und gegebenenfalls einem dritten Spieler 3 geben. Die Wahl schaltet den Mehrspieler-Modus selbst ein (Meldung „MEHRSPIELER-MODUS AN“). Alternativ Optionen → Mehrspieler → Mehrspieler-Modus (2–3 Spieler); dort steht auch, welche Pads und Autos erkannt sind.
  3. Für Spieler 2 und 3 in der Garage unter Fahrgefühl eine eigene Abstimmung wählen oder „wie Spieler 1“ lassen.
  4. Tastenbelegung je Spieler: Optionen → Controller, oben Spieler 1/2/3 wählen, Neu zuweisen, dann am richtigen Pad drücken. Mit Übernehmen (am Pad: Options eine Sekunde halten) speichern oder mit Abbrechen verwerfen.
  5. Rennen starten. Das Cockpit zeigt die Vergleichsansicht „Beide“.

WLAN-Mehrspieler mit Telefon als Host (Android-App)

  1. Auf einem Telefon im Reiter WLAN Mehrspieler → Über Android-App auf Dieses Telefon ist Host tippen.
  2. Auf den anderen Telefonen Host im WLAN suchen (oder die Adresse eintragen).
  3. Mein Name eintragen, Mitmachen.
  4. Ein Tablet oder Fernseher öffnet die Host-Adresse mit dem Zusatz /?info im Browser und wird Info-Screen; ein Telefon ohne eigenes Auto kann Als Info-Screen wählen.

WLAN-Mehrspieler mit PC als Host (Python)

  1. Auf dem PC Mehrspieler-Host starten.bat doppelklicken oder im Projektordner python tools/omegasim_host.py --port 8080 ausführen. Optional --laps 12 oder --minutes 8 für die Anzeige der Rennlänge.
  2. Die angezeigte Adresse (Form 192.168.1.50:8080) auf den Telefonen unter Host-Adresse eintragen. Alle Geräte müssen im selben WLAN sein.
  3. Für Bluetooth im Browser: einmal je Telefon in Chrome unter chrome://flags/#unsafely-treat-insecure-origin-as-secure die Host-Adresse eintragen und Chrome neu starten. Die Android-App braucht das nicht.
  4. Die Übersicht für den Fernseher liegt auf dem PC unter /mp-overview.html (über localhost, ohne Freigabe).

Gemeinsames Rennen

  1. Ein Teilnehmer tippt Rennen für alle starten (oder startet ein Rennen und wählt in der Frage „Für alle“). Auf allen Telefonen erscheint der Bereitschaftsschirm.
  2. Jeder tippt Bereit. Erst wenn alle anderen aktiven Teilnehmer bereit sind, wird der Knopf Starten beim Initiator frei.
  3. Nach dem Start läuft auf allen Telefonen dieselbe Ampel nach einem Vorlauf von 12 s.
  4. Rennen für alle beenden beendet es überall; Verlassen meldet das Gerät ab.

Einstellungen

Name in der App Bereich/Werte Standard Wirkung laut Code Schlüssel
Mehrspieler-Modus (2–3 Spieler) an/aus aus schaltet die Zusatzplätze und die Vergleichsansicht ein; eine Rolle Spieler 2/3 schaltet ihn selbst an opt-zwei-an
Rolle (Garage) Spieler 1, Spieler 2, Spieler 3, Safety Car, Reinigungsfahrzeug, NPC, Aus erstes Auto Spieler 1, weitere NPC je Rolle Spieler 1/2/3 höchstens ein Auto car.role (player, player2, player3)
Fahrgefühl (Garage, Spieler 2/3) wie Spieler 1, Arcade, Sim+, Pacejka wie Spieler 1 eigenes Preset über die kopierte Abstimmung von Spieler 1, eigene Reifenmischung omegasim-preset-spieler-2, -3
Selbstlenkung (Garage, je gesteuertem Auto) wie Optionen, aus, hält die Spur, lenkt selbst wie Optionen Fahrhilfe je Auto car.fahrhilfe
Spieler 1/2/3 (Optionen → Controller) Auswahl Spieler 1 wessen Belegung bearbeitet wird; nur im Mehrspieler-Modus sichtbar bindEditSpieler
Controller tauschen – – entfernt seit 0.10.5, verborgen und immer aus opt-zwei-tausch
Host-Adresse Text leer, dann gemerkt Adresse ohne Schema; die App setzt das Schema selbst davor mp-host
Mein Name Text leer („ohne Namen“) Name in der Rangliste, höchstens 40 Zeichen beim Host mp-name
Renneinstellungen erzwingen an/aus an das aktive Preset des Initiators geht mit dem Rennplan an alle (Tempo, Handling, Beschleunigung, Schaden, Reifenverschleiß); Controller, Tasten, Empfindlichkeit, Vibration und Ton bleiben mp-force-preset
Port (PC-Host) Zahl 8080 Port des Host-Programms --port
Rennlänge (PC-Host) Runden oder Minuten keine nur für die Übersicht --laps, --minutes

Name, Host-Adresse und eine zufällige Kennung (p + acht Zeichen) bleiben im Browser gespeichert (chc.mp.v1).

Funktionsweise

Spielerplätze: die zusatzPlatz-Registry

src/49-spieler.js verallgemeinert den früheren Zwei-Spieler-Modus auf bis zu SPIELER_MAX = 3 Spieler.[2] Spieler 1 bleibt wie er ist, weil er Wege hat, die nur er hat (Eingabe über Tastatur und Touch, Boxen-Minispiel, Windschatten, Ideallinie). Jeder weitere Spieler ist ein Zusatzplatz mit eigenem Satz:

Platz 2 ist dabei ein Satz aus Gettern und Settern auf die alten Variablennamen (playerCar2, p2Steer, tankZwei …), damit rund 300 Stellen in Prüfläufen weiter gelten; Platz 3 hat eigene Felder in derselben Form. Die Rolle player2 oder player3 ordnet ein Auto über zusatzPlatzVonRolle() seinem Platz zu, spielerNrVon(car) liefert umgekehrt 1, 2, 3 oder 0.

Feste Zuordnungen je Spieler:

Spieler Farbe Stereoseite (Pan) Rundengong
1 Grün #2ee06a 0 (Mitte bzw. links) Grundton
2 Orange #ffb02e +0,55 (rechts) × 1,5
3 Blau #4db8ff −0,25 (links) × 1,25

Ein Sendetakt für alle

Alle Zusatzplätze werden im selben 45-ms-Takt wie Spieler 1 in fester Reihenfolge bedient (spielerZweiSenden()): Für jeden Platz mit Auto wird sein Fahrzeugmodell einen Schritt gerechnet und das Paket geschrieben. Für Spieler gilt dabei die Regel „der neueste Befehl ersetzt den wartenden“, und jedes Auto hat seine eigene Schreibsperre, sodass ein langsamer Funkweg nur beim eigenen Auto einen Takt auslässt. Getrennte Sendewege waren in früheren Fassungen die Ursache für Stottern mit echtem Controller.[3] Gemessen mit 60 Takten Vollgas: 60 Pakete, kein Ausfall.

Pad-Zuordnung

padsFuerSpieler() ordnet die Gamepads zu:[4]

Jede Belegung wird zusätzlich unter der Kennung des Pads gespeichert (carrera-hybrid-gamepad-pad: + Pad-Name, höchstens 120 Zeichen). Erscheint an einem Platz ein anderes Pad, lädt padBelegungAbgleichen() dessen gemerkte Belegung. Die Belegungen je Spieler liegen außerdem unter carrera-hybrid-gamepad-bindings-v2 (Spieler 1), …-p2 und …-p3.

Abgleich-Sitzung: Übernehmen und Abbrechen (seit 1.2.3)

Das Neubelegen ist eine kleine Zustandsmaschine:[5]

Zustand Bedingung nächster Zustand
frei „Neu zuweisen“ angetippt Sitzung (Entwurf = Kopie der aktuellen Belegung)
Sitzung Eingabe am Pad des bearbeiteten Spielers, während eine Aktion wartet Sitzung (Entwurf geändert, nichts gespeichert)
Sitzung Knopf „Übernehmen“ oder Options (Taste 9) 1000 ms gehalten Sperre (Entwurf gespeichert)
Sitzung Knopf „Abbrechen“ Sperre (Entwurf verworfen)
Sperre alle Tasten aller Pads losgelassen (kein Knopf gedrückt, kein Wert über 0,3) frei

In Sitzung und Sperre reagiert das Pad auf nichts anderes. Vorher konnte eine noch gehaltene Taste nach dem Zuweisen Zurück, einen Reiterwechsel oder das Cockpit auslösen, und die Ruhelage des Sticks wurde aufgenommen, während X noch gedrückt war, sodass X sich selbst erfasste.

Fahrgefühl je Spieler (seit 1.2.4)

Jeder Zusatzmotor bekommt zuerst eine Kopie der Abstimmung von Spieler 1 (alle Werte, die Gangtabelle als eigene Objekte). Hat der Spieler in der Garage ein eigenes Fahrgefühl gewählt, legt spielerGefuehlUeberlagern() dessen Schnappschuss darüber: Die App stellt die Regler des Presets kurz ein, kopiert die entstandene Konfiguration und stellt die Regler zurück. Danach setzt sie die eigene Reifenmischung wieder ein, weil die Kopie Griff und Verschleiß von Spieler 1 mitgebracht hätte.[6] Ob ein Spieler mit Physik (Physik, Pacejka) oder als RC fährt, entscheidet sein eigenes Preset, sonst das von Spieler 1. Wählbar sind die Fahren-Presets Arcade, Sim+ und Pacejka. Globale Einstellungen wie Tankverbrauch, Schaden, Reifenverschleiß, Wetter, Höchstgeschwindigkeit und Akkuausgleich gelten für alle Autos gleich.

Was Auto 2 und 3 haben

Vorhanden Nicht vorhanden oder eingeschränkt
eigene Fahrphysik mit Gängen, Drehzahl, Tempo und Temperaturen die drei Rundenzeiten im Cockpit (sie gehören Auto 1; die anderen stehen in der Rundenübersicht)
eigene Ortung: NPCs weichen aus und wählen ihre Überholseite nach seiner Querlage, Punkt auf der Karte, Fahrhilfe und Leitplanken-Modus Makro-Aufnahme (zeichnet nur Auto 1 auf)
eigener Schaden mit Lampenausfall, Tank, Notlauf Doppler-Effekt im Ton
eigene Motorstimme auf eigener Stereoseite, eigene Knaller Boxenstopp nur per Knopf, nicht über die Boxengasse der Strecke
Rundenzählung, Rangliste, Ergebnis und CSV; die Zielflagge wartet auf alle Fahrer Boxen-Minispiel (nur ohne zweiten Spieler)
gelbe Flagge und Einführungsrunde mit eigenem Autopilot-Regler, Frühstart- und Pflichtstopp-Strafen

Die Rundenzählung kostete nichts: Sie lief schon immer je verbundenem Auto, unabhängig von der Rolle.

Cockpit und Vergleichsschirm „Beide“

OmegaSim teilt den Bildschirm nicht. Sobald Spieler 1 und Spieler 2 ein Auto in der Garage haben, zeigt der Standard-Cockpitschirm selbst die Vergleichsansicht „Beide“ (cockpitMainMalen() setzt dann data-screen="auto2"); man muss nicht mehr dorthin blättern. Die übrigen Schirme sind Box und Rennen.[7] Die Ansicht zeigt nebeneinander Tempo, Schaltlichter, Gang, Tank, Zustand, Reifen- und Bremsentemperatur und Akku, in jeder Spalte in derselben Reihenfolge, dazu je Auto einen Boxenknopf, die Wahl von Reifen und Tankmenge und einen eigenen Motor-Knopf. Hat Spieler 3 ein Auto, kommt eine dritte Spalte dazu. Der Boxenstopp eines Zusatzspielers tankt mit derselben Rate wie bei Auto 1 (22 %/s), repariert und zieht die gewählte Mischung auf; der Service beginnt erst im Stillstand. Der Ⓘ-Text der Option spricht noch von einem eigenen Schirm, zu dem man blättert; maßgeblich ist der Code.

WLAN: Schnittstelle des Hosts

Python-Host und Android-Host sprechen dieselbe Schnittstelle; wer eine ändert, muss die andere mitändern.[8]

Anfrage Inhalt Antwort und Wirkung
GET /mp/state[?zuschauer=ID] – Rangliste, Rennzustand, Host-Uhr (zeitMs), Startkennung (boot), Zahl der Zuschauer (Abruf in den letzten 5 s), Streckencode
POST /mp/report {id, name, laps, letzte, beste, abgaenge, summe, strafe, pos, strecke}, alles außer id optional legt den Fahrer an oder aktualisiert ihn; eine geänderte Rundenzahl setzt den Zeitpunkt der letzten Überfahrt
POST /mp/race {plan, phase, initiator, vorlaufMs} phase „bereit“: Bereitschaftsschirm; phase „start“: Startzeit setzen, aber nur, wenn alle aktiven Fahrer außer dem Initiator bereit sind
POST /mp/ready {id} Fahrer in die Bereit-Liste
POST /mp/race/cancel – Bereitschaftsrunde beenden, Fahrer und Wertung bleiben
POST /mp/leave {id} Fahrer entfernen
GET /mp/info – Rennlänge und eigene Adresse
GET /mp/reset – neues Rennen: alle Fahrer und der Rennplan werden gelöscht
OPTIONS – 204 mit Access-Control-Allow-Origin: * (Preflight)
alles andere – die App selbst als Dateien (Info-Screen im Browser)

Ein Bericht darf beim Python-Host höchstens 16 KiB groß sein, beim Telefon-Host 8 KiB; Namen werden auf 40, Kennungen auf 64 Zeichen gekürzt. „Aktiv“ ist ein Fahrer, der sich in den letzten 15 s gemeldet hat. Der Python-Host ermittelt seine eigene Adresse über einen UDP-Socket „zu“ einer Adresse außerhalb, ohne zu senden; so wählt das Betriebssystem die Schnittstelle, die ins Netz führt.

Takte des Clients (src/97-sessions.js):

Vorgang außerhalb des Rennens im Rennen
Stand abfragen (/mp/state) alle 1500 ms höchstens alle 3000 ms
Lebenszeichen (/mp/report) spätestens alle 5000 ms, zusätzlich nach jeder Runde ebenso
Positionen für Zuschauer alle 330 ms, nur wenn mindestens ein Zuschauer da ist höchstens alle 500 ms
Info-Screen fragt ab alle 400 ms alle 400 ms

Eine Position ist {i, f, c, k, g}: Teilnummer, Phase auf dem Teil (drei Nachkommastellen), Farbe, Kürzel (höchstens drei Zeichen) und ob es ein NPC ist; je Telefon höchstens acht Autos.

Rangliste

Sortierschlüssel = (−Runden, Zeitpunkt der letzten Rundenänderung beim Host)

Wer mehr Runden hat, führt; bei gleicher Rundenzahl, wer zuerst dort war. Die Bestzeit steht nur als Spalte daneben, weil sie „wer ist schnell“ beantwortet und nicht „wer führt“. Gezählt werden gemessene Runden: Die erste Überfahrt startet die Uhr, erst die zweite ergibt eine Zeit. Nach drei Überfahrten stehen also zwei Runden da.[9] Während eines Rennens zeichnet der Client die Tabelle erst nach dem Rennen neu.

Zeitabgleich: mp.offset

Jede Abfrage misst t0 und t1 (eigene Uhr) und liest zeitMs (Host-Uhr):[10]

// src/97-sessions.js, mpUhrProbe()
const weg = t1 - t0;                         // Hin und zurück
if (weg < 0 || weg > 300) return;            // zu langsame Proben verwerfen
mp.proben.push({ weg, off: zeitMs - (t0 + t1) / 2 });
if (mp.proben.length > 8) mp.proben.shift();
mp.offset = mp.proben.reduce((a, x) => (x.weg < a.weg ? x : a)).off;
offset  = Host_Uhr − (t0 + t1)/2          aus der Probe mit der kleinsten Laufzeit unter den letzten 8
Fehler  ≤ weg/2
lokal   = Host_Zeit − offset

Es zählt die schnellste Probe, weil bei ihr die Annahme „Antwort in der Mitte“ am wenigsten falsch sein kann.

Startzeit: startAt

  1. Der Initiator schickt /mp/race mit phase „bereit“ und dem Rennplan: Renntyp, Länge, Startwetter, Wetterwechsel, fliegender Start, Pflichtstopps, Starttank, ein vorab gewürfelter Wetterplan, eine Windrichtung, eine gemeinsame Ampelverzögerung (1000 bis 3000 ms) und, wenn „Renneinstellungen erzwingen“ an ist, das aktive Preset; in der Meisterschaft zusätzlich Event und deren Preset.
  2. Der Host setzt phase „bereit“; alle Clients zeigen beim nächsten Abruf den Bereitschaftsschirm.
  3. Sind alle aktiven Fahrer außer dem Initiator bereit, schickt der Initiator phase „start“ mit vorlaufMs = 12 000. Der Host prüft das erneut und setzt
startAt = Host_jetzt + vorlauf        vorlauf auf 6000 … 30000 ms begrenzt
erhöht die Renn-Nummer, setzt Runden und Zeiten aller Fahrer zurück und gibt startAt über /mp/state an alle.
  1. Jeder Client rechnet lokal = startAt − mp.offset. Liegt das weniger als 500 ms in der Zukunft, ignoriert er den Start. Sonst übernimmt er den Plan (Renntyp, Länge, Wetter, Preset) und startet den Countdown auf genau diese Zeit. Kennung des Rennens ist Host-Startkennung:Renn-Nummer, damit ein neu gestarteter Host mit wieder bei 1 beginnenden Nummern nicht für ein altes Rennen gehalten wird.
  2. Feinabgleich im Vorlauf: achtmal im Abstand von 300 ms eine weitere Uhrprobe; weicht die daraus berechnete Startzeit um 8 ms oder mehr von der benutzten ab, wird die Ampel entsprechend verschoben.

Zielflagge: Bei Rennen über Runden schaltet ein Client auf „letzte Runde“, sobald ein anderer aktiver Fahrer die Rundenzahl erreicht hat; die laufende Runde zählt noch. Für alle beenden sendet einen Plan mit ende: true in phase „bereit“; jeder andere Client beendet daraufhin sein Rennen, nach 4 s wird die Bereitschaftsrunde aufgehoben. Frühstart- und Pflichtstopp-Strafen gehen als summe und strafe mit zum Host; dafür sind eine neue APK beziehungsweise ein neuer Host nötig.

Host in der Android-App

Das Telefon startet einen kleinen HTTP-Server (NanoHTTPD) auf Port 8080, meldet ihn per NSD als _omegasim._tcp an und hält ihn mit einem Vordergrunddienst am Leben, damit Android ihn bei dunklem Bildschirm nicht beendet. „Host im WLAN suchen“ sucht 3500 ms lang und liefert, was in dieser Zeit gefunden und aufgelöst ist. Der Telefon-Host liefert auch die App selbst aus, sodass ein Browser im WLAN mit /?info zum Info-Screen wird. Im reinen Browser ist dieser Weg nicht möglich, weil eine Webseite keinen Server starten darf.[11]

Beispiele

Uhrenabgleich

Ein Telefon fragt um t0 = 10 000 ms (eigene Uhr) ab, die Antwort kommt um t1 = 10 060 ms, der Host meldet zeitMs = 5 000 030.

  1. weg = 60 ms (unter 300, gültig).
  2. offset = 5 000 030 − (10 000 + 10 060)/2 = 5 000 030 − 10 030 = 4 990 000 ms.
  3. Eine spätere Probe mit weg = 20 ms ergibt 4 990 012; sie ersetzt den Wert, weil sie schneller war. Der Restfehler ist höchstens 10 ms.
  4. Der Host setzt startAt = 5 012 040. Lokal: 5 012 040 − 4 990 012 = 22 028 ms auf der eigenen Uhr, also gut 12 s nach der letzten Probe.
  5. Ergibt eine Probe im Vorlauf 4 990 002, liegt die neue Startzeit 10 ms später; weil 10 ≥ 8, wird die Ampel um 10 ms verschoben.

Rangliste

Fahrer Runden letzte Rundenänderung (Host) Platz
Anna 5 100,2 s 2
Ben 5 99,8 s 1
Cem 4 98,0 s 3

Ben und Anna haben gleich viele Runden; Ben war 0,4 s früher dort und führt. Cem hat eine Runde weniger, obwohl seine letzte Überfahrt am frühesten war.

Netzlast

Vier Telefone außerhalb des Rennens: 4 × (1/1,5 s) ≈ 2,7 Abfragen je Sekunde, dazu alle 5 s ein Lebenszeichen je Telefon. Mit einem Info-Screen kommen 2,5 Abfragen je Sekunde des Info-Screens und je Telefon rund drei Positionsmeldungen je Sekunde hinzu (im Rennen zwei).

Pad-Zuordnung

Erkannt sind ein DualSense (Standardbelegung), ein Xbox-Pad (Standardbelegung) und ein USB-Pad ohne Standardbelegung, das der Browser als erstes meldet. Reihenfolge nach padsSortiert(): DualSense, Xbox, USB-Pad, also DualSense → Spieler 1, Xbox → Spieler 2, USB-Pad → Spieler 3. Hatte das Xbox-Pad früher eine eigene Belegung, wird sie beim Zuordnen für Spieler 2 geladen.

Grenzen und bekannte Probleme

Versionsgeschichte

Version Änderung
0.6.44–0.6.50 Zwei-Spieler-Modus an einem Gerät: eigene Physik, dann Ortung, Schaden, Tank, Motorstimme, Boxenstopp
0.6.19 PC-Host mit CORS-Kopfzeilen: Mitmachen auch, wenn die App nicht vom Host geladen wurde
0.8.42 gemeinsamer Start mit Startzeit in der Host-Uhr, gemeinsamer Wetterplan und Wind
0.8.126 Bereitschaftsschirm: Start erst, wenn alle bereit sind
0.9.2 Bereitschaftsrunde abbrechen, Verlassen, Host-Startkennung
0.9.17 drei Spieler über Spielerplätze (zusatzPlatz), dritte Spalte in „Beide“
0.9.32 Feinabgleich der Ampel im Vorlauf, Rennen für alle beenden
0.9.41 weniger Abfragen im Rennen (3000 ms), Tabelle erst nach dem Rennen
0.10.5 „Controller tauschen“ entfernt
1.0.12 Pflichtstopp-Strafen für alle gesteuerten Autos, Meldung von Gesamtzeit und Strafe an den Host
1.1 (Abschnitt) Spieler 2 und 3 nicht mehr experimentell; Selbstlenkung je gesteuertem Auto
1.2.3 Belegen als Entwurf mit Übernehmen (Options 1 s) und Abbrechen, Sperre bis alle Tasten los
1.2.4 Fahrgefühl je Spieler (Arcade, Sim+, Pacejka oder wie Spieler 1), eigene Reifenmischung bleibt

Einzelnachweise

  1. ↑ tools/omegasim_host.py, Kopfkommentar „Warum HTTP und kein WebSocket“.
  2. ↑ src/49-spieler.js, Kopfkommentar und zusatzPlatz().
  3. ↑ src/20-protocol.js, spielerZweiSenden(), spielerSendenVon(); CARRERA_HYBRID.md, „Zwei Spieler auf einem Handy“.
  4. ↑ src/90-ghosts.js, padsSortiert(), padsFuerSpieler().
  5. ↑ bindSitzungStarten(), bindSitzungEnde(), bindPadSitzung(), padAllesLos().
  6. ↑ src/49-spieler.js, zusatzMotorAbgleichen(), spielerGefuehlUeberlagern(); src/98-presets.js, presetSchnappschuss().
  7. ↑ src/50-drive.js, COCKPIT_SCREENS, cockpitMainMalen(), zweiSpielerAktiv().
  8. ↑ android-app/android/app/src/main/java/de/lroeseler/omegasim/HostServer.java, Kopfkommentar.
  9. ↑ tools/omegasim_host.py, zustand_lesen().
  10. ↑ src/97-sessions.js, mpUhrProbe(), mpStartFeinabgleich().
  11. ↑ OmegaHostPlugin.java, OmegaHostService.java.

Siehe auch

Quellen im Code