InSim
InSim ist ein Protokoll, das es einem externen Programm ermöglicht, mit Live for Speed zu kommunizieren. Es ermöglicht Ihnen, eine Socket-Verbindung mit dem Spiel herzustellen und Datenpakete zu senden und zu empfangen. Das InSim-Protokoll beschreibt, wie jedes dieser Pakete formatiert ist, und jede Programmiersprache, die eine Netzwerkverbindung herstellen und Zeichenfolgen von Binärdaten senden und empfangen kann, kann eine Schnittstelle dazu herstellen.
Die offizielle Dokumentation ist in der Datei InSim enthalten.txt, gefunden im Ordner games doc. Es besteht aus einer C ++ – Header-Datei, die die Definition für jedes Paket sowie Kommentare von Scawen enthält, wie jedes Paket verwendet werden soll. Die Dokumentation hier ist als Ergänzung zu dieser Datei gedacht.
UDP vs TCP
InSim unterstützt sowohl UDP- als auch TCP-Verbindungen. Im UDP-Modus kann nur eine einzige Verbindung hergestellt werden, in TCP können jedoch bis zu acht Verbindungen zum Spiel hergestellt werden. Unabhängig davon, ob Sie über TCP oder UDP verbunden sind, können Sie einen separaten UDP-Socket für den Empfang von Fahrzeugpositionsaktualisierungen angeben, z. B. IS_MCI und IS_NLP.
InSim-Beispiel
Wie Sie eine InSim-Verbindung erstellen, hängt natürlich davon ab, welche Programmiersprache Sie verwenden, aber hier versuchen wir, den Prozess mit einigen Beispielen aus der beliebten Programmiersprache Python zu dokumentieren. Wie oben erwähnt, kann jede Sprache, die eine Socket-Verbindung herstellen kann, als Schnittstelle zu LFS verwendet werden, das Prinzip bleibt jedoch unabhängig davon gleich.
Erstellen einer Verbindung
Zunächst müssen wir eine Socket-Verbindung mit dem Spiel herstellen, in diesem Fall in TCP.
# Import Python's socket module.import socket# Initialise the socket in TCP mode. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# Connect to LFS.sock.connect(('localhost', 29999))
Initialisierung von InSim
Nach dem Aufbau der Verbindung müssen wir das InSim-System initialisieren, indem wir das IS_ISI-Paket senden. Bevor wir dies jedoch tun können, müssen wir zuerst intitailse InSim innerhalb LFS selbst. Starten Sie dazu das Spiel und geben Sie den Chat-Befehl „/ insim 29999“ ein. Die verwendete Portnummer kann jeder gültige Port sein, aber 29999 ist im Allgemeinen der akzeptierte Standard.
Hier ist die Definition für das IS_ISI-Paket von InSim.txt.
struct IS_ISI // InSim Init - packet to initialise the InSim system{byteSize;// 44byteType;// ISP_ISIbyteReqI;// If non-zero LFS will send an IS_VER packetbyteZero;// 0wordUDPPort;// Port for UDP replies from LFS (0 to 65535)wordFlags;// Bit flags for options (see below)byteSp0;// 0bytePrefix;// Special host message prefix characterwordInterval;// Time in ms between NLP or MCI (0 = none)charAdmin;// Admin password (if set in LFS)charIName;// A short name for your program};
Jedes InSim-Paket beginnt mit einem Header, der aus 4 Bytes besteht. Das erste Byte ist die Größe des Pakets, gefolgt vom Pakettyp aus der ISP_-Enumeration und dann dem ReqI (steht für Request Id). Immer wenn eine Anfrage an LFS gestellt wird, muss der Wert des ReqI auf ungleich Null gesetzt werden, wobei LFS mit dem gleichen Wert antwortet, der im ReqI des angeforderten Pakets festgelegt ist. Schließlich variiert das vierte Byte in Abhängigkeit von der Art des betreffenden Pakets, das in diesem Fall leer ist.
Wie Sie sehen können, enthält das IS_ISI-Paket verschiedene Optionen und Flags, die bei der Initialisierung des InSim-Systems verwendet werden. Wir müssen diese Daten in eine binär formatierte Zeichenfolge packen, um sie an LFS zu senden.
# Import Python's struct module, which allows us to pack and unpack strings.import struct# Pack the IS_ISI data into a string.isi = struct.pack('BBBBHHBcH16s16s', 44, # Size 1, # Type 1, # ReqI 0, # Zero 0, # UDPPort 0, # Flags 0, # Sp0 ' ', # Prefix 0, # Interval 'password', # Admin 'MyProgram',) # IName# Send the string to InSimsock.send(isi)
Empfangen von Daten
Nach dem Herstellen der Verbindung und der Initialisierung von InSim müssen wir die Paketempfangsschleife einrichten. Da Daten im TCP-Modus als konstanter Datenstrom gesendet werden, können mehrere Pakete in einem einzigen Empfangsaufruf eintreffen und einige Pakete können unvollständig eintreffen. Dies bedeutet, dass wir alle eingehenden Daten in einem Puffer speichern und dann jedes Paket auslesen müssen, wenn wir sicher sind, dass es vollständig ist.
# We use a string as the buffer.buffer = ''while True: # Receive up to 1024 bytes of data. data = sock.recv(1024) # If no data is received the connection has closed. if data: # Append received data onto the buffer. buffer += data # Loop through each completed packet in the buffer. The first byte of # each packet is the packet size, so check that the length of the # buffer is at least the size of the first packet. while len(buffer) > 0 and len(buffer) > ord(buffer): # Copy the packet from the buffer. packet = buffer)] # Remove the packet from the buffer. buffer = buffer):] # The packet is now complete! :) # doSomethingWithPacket(packet) else: break# Release the socket.sock.close()
Pakete auspacken
Sobald wir die Paketdaten als binär formatierte Zeichenfolge erhalten haben, müssen wir diese Daten in ein für uns nützliches Format entpacken. In unserem vorherigen Beispiel, als wir das IS_VER-Initailization-Paket gesendet haben, haben wir den ReqI auf ungleich Null gesetzt, was bedeutet, dass LFS mit einem IS_VER-Versionspaket geantwortet hat, aber wir haben nichts damit gemacht. Schauen wir uns zunächst die Definition für das IS_VER-Paket von InSim an.txt.
struct IS_VER // VERsion{byteSize;// 20byteType;// ISP_VERSIONbyteReqI;// ReqI as received in the request packetbyteZero;charVersion;// LFS version, e.g. 0.3GcharProduct;// Product : DEMO or S1wordInSimVer;// InSim Version : increased when InSim packets change};
Schauen wir uns nun an, wie wir diese Daten in Python entpacken würden.
# Import Python's struct module.import struct# Unpack the binary formatted packet data into the values we need.size, type, reqi, zero, version, product, insimver = struct.unpack('BBBB8s6sH', packet)# Check the InSim version.if insimver != 4: print 'Invalid InSim version!' sock.close()
Keep Alive
Um die Verbindung offen zu halten, sendet LFS alle 30 Sekunden ein „Keep Alive“ -Paket. Dieses Paket ist ein IS_TINY mit einem SubT (Subtyp) von TINY_NONE. Wir müssen jedes Mal auf dieses Paket antworten, wenn es empfangen wird, um ein Timeout der Verbindung mit InSim zu verhindern.
# Some constants.ISP_TINY = 3TINY_NONE = 0# Check the packet type.if ord(packet) == ISP_TINY: # Unpack the packet data. tiny = struct.unpack('BBBB', packet) # Check the SubT. if tiny == TINY_NONE: # Send the keep alive packet back to LFS. sock.send(packet)
Weitere Beispiele
Sie können das vollständige Beispiel dieses Codes sowie andere auf der Seite InSim examples sehen.
InSim-Bibliotheken
Natürlich sollten Sie, wie das alte Sprichwort sagt, nicht versuchen, das Rad neu zu erfinden (es sei denn, Sie möchten mehr über Räder erfahren), und es gibt mehrere ausgereifte InSim-Bibliotheken, die in Ihrem eigenen Code verwendet werden können.
InSim Bibliotheken | ||||
---|---|---|---|---|
Bibliothek | Plattform | Lizenz | web | |
LFSLib | .NET Framework | GPL | Projektseite | |
LFS_External | .NET Framework | Freeware | lfsforum Thema | |
JInSim | Java | Mozilla | lfsforum Thema | |
pyinsim | Python | LGPL | lfsforum Thema | |
CInSim | C/C++ | Freeware | lfsforum Thema | |
phplfs | PHP5 | Apache License V2.0 | Projektseite | |
PRISM | PHP7 | MIT | lfsforum Sektion | |
In Englisch.NET | .NET Framework | LGPL | lfsforum Thema |
InSim-Referenz
Hier wird versucht, auf das vollständige InSim-Protokoll zu verweisen.
Paket Referenz | ||
---|---|---|
Paket | Beschreibung | Typ |
Initialisierung | ||
IS_ISI | InSim Initialisierung | Anweisung |
Allgemeiner Zweck | ||
IS_TINY | Allgemeines 4-Byte-Paket | Beide |
IS_SMALL | Allgemeines 8-Byte-Paket | Beide |
Versionsanfrage | ||
IS_VER | Versionsinformationen | Infos |
Staatliche Berichterstattung und Anfragen | ||
IS_STA | Wird gesendet, wenn sich der Spielstatus ändert | Info |
IS_SFP | Senden, um verschiedene Statusoptionen festzulegen | Anweisung |
Bildschirm Modus | ||
IS_MOD | Senden, um den Bildschirmmodus zu ändern | Anweisung |
Textnachrichten und Tastendrücke | ||
IS_MSO | Von LFS gesendete System- und Anwendermeldungen | Info |
IST_III | Benutzermeldungen an Host InSim | Info |
IS_MST | LFS eine Nachricht oder einen Befehl senden (64 Zeichen) | Anweisung |
IS_MSX | Erweiterte Version von IS_MST (96 Zeichen), nicht für Befehle | Anweisung |
IS_MSL | Nachricht an lokalen Spielclient senden | Anweisung |
IS_MTC | Nachricht an bestimmte Verbindung oder Player senden | Anweisung |
IS_SCH | Einzelnes Zeichen oder Tastendruck senden | Anleitung |
Multiplayer-Benachrichtigung | ||
IS_ISM | Wird beim Starten oder Verbinden eines Hosts gesendet | Info |
IS_NCI | Wird gesendet, wenn das Host-Administratorkennwort festgelegt ist, enthält Benutzer-IP- und Sprachdaten | Info |
Abstimmung benachrichtigen | ||
IS_VTN | Benachrichtigung über die Spielerabstimmung (Rennen neu starten, qualifizieren usw..) | Infos |
Rennverfolgung | ||
IS_RST | Start oder Neustart des Rennens | Info |
IS_NCN | Neue Verbindung zum Server | Info |
IS_SLC | zum Melden von Änderungen des Fahrzeugzustands (derzeit Start oder Stopp) | Info |
IS_CSC | meldet das aktuell ausgewählte Auto einer Verbindung | Info |
IS_CNL | Verbindung zum Server | Info |
IST_CPR | Name des Spielers geändert | Info |
IS_NPL | Neuer Spieler tritt dem Rennen bei oder verlässt die Box | Info |
IS_PLP | Spielergruben (zum Garagenbildschirm gegangen) | Info |
IS_PLL | Spieler links Rennen (gone to spectate) | Info |
IS_CRS | Auto Reset (Leertaste gedrückt) | Info |
IS_JRR | kann verwendet werden, um reset oder starten ein auto an einem bestimmten ort | Anweisung |
IS_LAP | Rundenzeit beendet | Info |
IS_SPX | Zwischenzeitlich abgeschlossen | Info |
IS_PIT | Boxenstopp gestartet (an der Box) | Info |
IS_PSF | Boxenstopp beendet | Info |
IS_PLA | Spieler trat in die Boxengasse ein (um eine Strafe zu verhängen) | Info |
IS_CHH | Kameraansicht geändert (Chase-Ansicht, benutzerdefinierte Ansicht usw..) | Infos |
IS_PEN | Strafe gegeben oder gestemmt | Info |
IS_TOC | Spieler hat ein anderes Auto übernommen (Fahrerwechsel) | Info |
IS_FLG | Spieler angezeigte Flagge (gelb oder blau) | Info |
IS_PFL | Spielerflaggen geändert (automatische Gänge, automatische Kupplung usw..) | Infos |
IS_FIN | Spieler beendet Rennen (Ziellinie überschritten) | Info |
IS_RES | Spielerergebnis vergeben, Finish bestätigt | Info |
IS_REO | Startaufstellung neu anordnen | Beide |
Autocross | ||
IS_AXI | Autocross Layout geladen | Info |
IS_AXO | Spieler Treffer autocross Objekt | Info |
IS_OCO | kann verwendet werden, um bestimmte oder alle start lichter | Anweisung |
IS_UCO | sendet Informationen über InSim Checkpoints und Kreise | Info |
Autoverfolgung | ||
IS_NLP | Aktuelle Knoten-, Runden- und Rennposition des Spielers | Info |
IS_MCI | Detailliertere Version von IS_NLP, Welt-Koordinaten, Geschwindigkeit, Winkel und Kurs | Info |
Kamerasteuerung | ||
IS_SCC | Set gesehen auto und wählen kamera | Anweisung |
IS_CPP | Volle Kameraposition einstellen | Anweisung |
Replay-Steuerung | ||
IS_RIP | Wiedergabe laden und zu einem bestimmten Ziel verschieben | Anweisung |
Bildschirmfotos | ||
IS_SSH | Machen Sie einen Screenshot | Anweisung |
InSim Tasten | ||
IS_BFN | Löschen einer Taste oder aller Tasten | Anweisung |
IS_BTN | Senden Sie eine Taste an den Bildschirm | Anweisung |
IS_BTC | Wird gesendet, wenn auf eine Schaltfläche geklickt wird | Info |
IS_BTT | Wird gesendet, wenn Text eingegeben wird | Info |