InSim
InSim è un protocollo che consente a un programma esterno di comunicare con Live for Speed. Ti permette di creare una connessione socket con il gioco e di inviare e ricevere pacchetti di dati. Il protocollo InSim descrive come ciascuno di questi pacchetti è formattato e qualsiasi linguaggio di programmazione in grado di creare una connessione di rete e inviare e ricevere stringhe di dati binari può interfacciarsi con esso.
La documentazione ufficiale è inclusa nel file InSim.txt, trovato nella cartella giochi doc. Si compone di un file di intestazione C++ che contiene la definizione per ogni pacchetto, così come i commenti da Scawen su come ciascuno deve essere utilizzato. La documentazione qui è intesa come un accessorio a questo file.
UDP vs TCP
InSim supporta sia le connessioni UDP che TCP. In modalità UDP è possibile effettuare solo una singola connessione, tuttavia è possibile effettuare fino a otto connessioni al gioco in TCP. Se connesso in TCP o UDP, è possibile specificare un socket UDP separato per ricevere gli aggiornamenti della posizione dell’auto, come IS_MCI e IS_NLP.
Esempio InSim
Come si crea una connessione InSim dipende ovviamente dal linguaggio di programmazione che si sta utilizzando, ma qui si tenta di documentare il processo con alcuni esempi dal popolare linguaggio di programmazione Python. Come accennato in precedenza, qualsiasi lingua in grado di effettuare una connessione socket può essere utilizzata per interfacciarsi con LFS, tuttavia il principio rimane lo stesso indipendentemente.
Creazione di una connessione
Prima di tutto dobbiamo stabilire una connessione socket con il gioco, in questo caso 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))
Inizializzazione InSim
Dopo aver stabilito la connessione dobbiamo inizializzare il sistema InSim inviando il pacchetto IS_ISI. Prima di poter fare questo, tuttavia, dobbiamo prima intitailse InSim all’interno di LFS stessa. Per fare ciò inizia il gioco e inserisci il comando di chat “/ insim 29999”. Il numero di porta utilizzato può essere qualsiasi porta valida, ma 29999 generalmente tende ad essere l’impostazione predefinita accettata.
Ecco la definizione per il pacchetto IS_ISI da 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};
Ogni pacchetto InSim inizia con un’intestazione, composta da 4 byte. Il primo byte è la dimensione del pacchetto, seguito dal tipo di pacchetto dall’enumerazione ISP_ e quindi dal ReqI (che sta per Request Id). Ogni volta che viene fatta una richiesta a LFS, il valore del ReqI deve essere impostato su diverso da zero, per cui LFS risponderà con lo stesso valore impostato nel ReqI del pacchetto richiesto. Infine il quarto byte varia a seconda del tipo di pacchetto in questione, che in questo caso è vuoto.
Come si può vedere il pacchetto IS_ISI contiene varie opzioni e flag che vengono utilizzati quando si inizializza il sistema InSim. Dobbiamo imballare questi dati in una stringa formattata binaria per inviarlo a LFS.
# 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)
Ricezione dei dati
Dopo aver creato la connessione e inizializzato InSim dobbiamo quindi impostare il ciclo di ricezione dei pacchetti. Poiché i dati in modalità TCP vengono inviati come un flusso costante di dati, più pacchetti possono arrivare in una singola chiamata di ricezione e alcuni pacchetti possono arrivare incompleti. Ciò significa che dobbiamo memorizzare tutti i dati in arrivo in un buffer e quindi leggere ogni pacchetto quando siamo sicuri che sia completo.
# 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()
Disimballaggio dei pacchetti
Una volta che abbiamo ricevuto i dati del pacchetto come stringa formattata binaria, dobbiamo disimballare questi dati in un formato che ci è utile. Nel nostro esempio precedente quando abbiamo inviato il pacchetto di initailizzazione IS_ISI, abbiamo impostato il ReqI su diverso da zero, il che significa che LFS ha risposto con un pacchetto di versione IS_VER, tuttavia non abbiamo fatto nulla con esso. In primo luogo diamo un’occhiata alla definizione per il pacchetto IS_VER da InSim.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};
Ora diamo un’occhiata a come decomprimere quei dati in Python.
# 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
Per mantenere aperta la connessione LFS invierà un pacchetto “keep alive” ogni circa 30 secondi. Questo pacchetto è un IS_TINY con un sottotipo (sottotipo) di TINY_NONE. Dobbiamo rispondere a questo pacchetto ogni volta che viene ricevuto al fine di impedire il timeout della connessione con InSim.
# 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)
Ulteriori esempi
Puoi vedere l’esempio completo di questo codice e altri nella pagina InSim examples.
Librerie InSim
Ovviamente, come dice il vecchio adagio, non dovresti provare a reinventare la ruota (a meno che tu non stia cercando di saperne di più sulle ruote) e ci sono diverse librerie InSim mature disponibili per l’uso nel tuo codice.
InSim Librerie | ||||
---|---|---|---|---|
Libreria | Platform | Licenza | web | |
LFSLib | .NET Framework | GPL | pagina del progetto | |
LFS_External | .NET Framework | Freeware | lfsforum thread | |
JInSim | Java | Mozilla | lfsforum thread | |
pyinsim | Python | LGPL | lfsforum thread | |
CInSim | C/C++ | Freeware | lfsforum thread | |
phplfs | PHP5 | Licenza Apache V2.0 | pagina del progetto | |
PRISMA | PHP7 | MIT | lfsforum sezione | |
InSim.NET | . NET Framework | LGPL | filo lfsforum |
InSim Reference
Ecco un tentativo di fare riferimento al protocollo InSim completo.
Pacchetto di Riferimento | ||
---|---|---|
Pacchetto | Descrizione | Tipo |
Inizializzazione | ||
IS_ISI | InSim inizializzazione | Istruzione |
Scopo Generale | ||
IS_TINY | General purpose 4 byte del pacchetto | Entrambi |
IS_SMALL | General purpose 8 byte del pacchetto | Entrambi |
Versione richiesta | ||
IS_VER | informazioni sulla Versione | Info |
Stato di Reporting e Richieste | ||
IS_STA | Inviato ogni volta che il gioco cambi di stato | Info |
IS_SFP | l’Invio di impostare varie opzioni stato | Istruzione |
Modalità a Schermo | ||
IS_MOD | Invia per cambiare la modalità a schermo | Istruzione |
Messaggi di Testo e di un Tasto | ||
IS_MSO | Sistema e utente messaggi inviati da LFS | Info |
IS_III | i messaggi dell’Utente per ospitare InSim | Info |
IS_MST | Invia LFS un messaggio o comando (64 caratteri) | Istruzione |
IS_MSX | versione Estesa di IS_MST (96 caratteri), non per i comandi | Istruzione |
IS_MSL | Invia messaggio locali client di gioco | Istruzione |
IS_MTC | Invia messaggio connessione specifica o a un giocatore | Istruzione |
IS_SCH | Inviare un singolo carattere o il tasto premere il tasto | Istruzione |
il Multiplayer di Notifica | ||
IS_ISM | Inviato quando l’avvio o l’iscrizione di un host | Info |
IS_NCI | Inviato quando l’host admin password è impostata, contiene IP dell’utente e i dati di lingua | Info |
Voto Notifica | ||
IS_VTN | Notifica del giocatore con diritto di voto (riavvia gara, qualifica, etc..) | Info |
Gara di Inseguimento | ||
IS_RST | Gara di avvio o riavvio | Info |
IS_NCN | Nuova connessione entrare in server | Info |
IS_SLC | riportare le modifiche stato della vettura (attualmente start o stop) | Info |
IS_CSC | report di una connessione attualmente selezionato auto | Info |
IS_CNL | Connessione di sinistra server | Info |
IS_CPR | Giocatore ha cambiato nome | Info |
IS_NPL | Nuovo giocatore di entrare in gara, o box lasciando | Info |
IS_PLP | Lettore pozzi (andato al garage) | Info |
IS_PLL | Giocatore a sinistra di gara (andato ad assistere) | Info |
IS_CRS | Auto reset (premuto la barra spaziatrice) | Info |
IS_JRR | può essere utilizzato per ripristinare o avviare una macchina in una posizione specificata | Istruzioni |
IS_LAP | tempo sul Giro completato | Info |
IS_SPX | Dividi il tempo di completamento | Info |
IS_PIT | Pit stop ha iniziato (in box) | Info |
IS_PSF | Pit stop, finito | Info |
IS_PLA | Giocatore entrato in pit lane (a fossa o servire pena) | Info |
IS_CHH | visualizzazione della Fotocamera cambiato (chase vista, vista personalizzata etc..) | Info |
IS_PEN | Rigore dato o con incisioni | Info |
IS_TOC | Giocatore preso un’altra auto (driver swap) | Info |
IS_FLG | Giocatore bandiera (giallo e blu) | Info |
IS_PFL | Lettore di bandiere cambiato (automatico marce, auto-frizione etc..) | Info |
IS_FIN | Giocatore ha terminato la gara (attraversato il traguardo) | Info |
IS_RES | Lettore di risultato assegnati, confermato fine | Info |
IS_REO | Riordina griglia di partenza | Entrambi |
Autocross | ||
IS_AXI | Autocross layout caricato | Info |
IS_AXO | Giocatore che ha colpito autocross oggetto | Info |
IS_OCO | può essere utilizzato per sostituire specifici o tutte le luci di avvio | Istruzione |
IS_UCO | invia informazioni su InSim e di controllo e cerchi | Info |
l’Inseguimento | ||
IS_NLP | Giocatori nodo corrente, tempo sul giro e la posizione di gara | Info |
IS_MCI | versione Più dettagliata di IS_NLP tutto il mondo, le coordinate, la velocità, l’angolo e la denominazione | Info |
Controllo della Telecamera | ||
IS_SCC | Set di vista auto e selezionare fotocamera | Istruzioni |
IS_CPP | Set completo della posizione della fotocamera | Istruzione |
Controllo Replay | ||
IS_RIP | Caricare il replay e spostare a destinazione specifica | Istruzione |
Screenshot | ||
IS_SSH | screenshot | Istruzione |
InSim Pulsanti | ||
IS_BFN | Eliminare un pulsante o tutti i pulsanti | Istruzione |
IS_BTN | Invia un pulsante per lo schermo | Istruzioni |
IS_BTC | Inviato quando viene cliccato un pulsante | Info |
IS_BTT | Inviato quando viene inserito un testo | Info |