InSim
InSim est un protocole qui permet à un programme externe de communiquer avec Live pour plus de vitesse. Il vous permet de créer une connexion socket avec le jeu et d’envoyer et de recevoir des paquets de données. Le protocole InSim décrit comment chacun de ces paquets est formaté, et tout langage de programmation capable de créer une connexion réseau et d’envoyer et de recevoir des chaînes de données binaires peut s’interfacer avec lui.
La documentation officielle est incluse dans le fichier InSim.txt, trouvé dans le dossier doc des jeux. Il se compose d’un fichier d’en-tête C++ qui contient la définition de chaque paquet, ainsi que des commentaires de Scawen sur la façon dont chacun doit être utilisé. La documentation ici est conçue comme un accessoire à ce fichier.
UDP vs TCP
InSim prend en charge les connexions UDP et TCP. En mode UDP, une seule connexion peut être établie, mais jusqu’à huit connexions peuvent être effectuées au jeu en TCP. Qu’il soit connecté en TCP ou en UDP, il est possible de spécifier un socket UDP distinct pour recevoir les mises à jour de position de la voiture, telles que IS_MCI et IS_NLP.
Exemple d’InHim
La façon dont vous créez une connexion InHim dépend bien sûr du langage de programmation que vous utilisez, mais nous essayons ici de documenter le processus avec quelques exemples du langage de programmation Python populaire. Comme mentionné ci-dessus, tout langage capable d’établir une connexion socket peut être utilisé pour s’interfacer avec LFS, mais le principe reste le même malgré tout.
Création d’une connexion
Tout d’abord, il faut établir une connexion socket avec le jeu, dans ce cas en 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))
Initialisation d’InSim
Après avoir établi la connexion, nous devons initialiser le système InSim en envoyant le paquet IS_ISI. Avant de pouvoir le faire, nous devons d’abord intituler InSim au sein de l’EPA elle-même. Pour ce faire, démarrez le jeu et entrez la commande de chat « /insim 29999 ». Le numéro de port utilisé peut être n’importe quel port valide, mais 29999 a généralement tendance à être la valeur par défaut acceptée.
Voici la définition du paquet IS_ISI d’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};
Chaque paquet InSim commence par un en-tête, composé de 4 octets. Le premier octet est la taille du paquet, suivi du type de paquet de l’énumération ISP_, puis du ReqI (pour Request Id). Chaque fois qu’une demande est faite à LFS, la valeur du ReqI doit être définie sur non nulle, LFS répondra avec la même valeur définie dans le ReqI du paquet demandé. Enfin le quatrième octet varie en fonction du type de paquet considéré, qui dans ce cas est vide.
Comme vous pouvez le voir, le paquet IS_ISI contient diverses options et indicateurs utilisés lors de l’initialisation du système InSim. Nous devons emballer ces données dans une chaîne au format binaire pour les envoyer à 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)
Réception des données
Après avoir créé la connexion et initialisé InSim, nous devons ensuite configurer la boucle de réception des paquets. Comme les données en mode TCP sont envoyées sous la forme d’un flux constant de données, plusieurs paquets peuvent arriver en un seul appel de réception et certains paquets peuvent arriver incomplets. Cela signifie que nous devons stocker toutes les données entrantes dans un tampon, puis lire chaque paquet lorsque nous sommes sûrs qu’il est terminé.
# 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()
Déballage des paquets
Une fois que nous avons reçu les données du paquet sous forme de chaîne au format binaire, nous devons ensuite décompresser ces données dans un format qui nous est utile. Dans notre exemple précédent, lorsque nous avons envoyé le paquet d’initialisation IS_ISI, nous avons défini le ReqI sur non nul, ce qui signifie que LFS a répondu avec un paquet de version IS_VER, mais nous n’avons rien fait avec. Regardons d’abord la définition du paquet IS_VER d’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};
Voyons maintenant comment nous décompresserions ces données en 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
Afin de garder la connexion ouverte, LFS enverra un paquet « keep alive » toutes les 30 secondes environ. Ce paquet est un IS_TINY avec un SubT (sous-type) de TINY_NONE. Nous devons répondre à ce paquet chaque fois qu’il est reçu afin d’empêcher la connexion avec InSim de s’arrêter.
# 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)
Autres exemples
Vous pouvez voir l’exemple complet de ce code ainsi que d’autres sur la page exemples d’InSim.
Bibliothèques InSim
Bien sûr, comme le dit le vieil adage, vous ne devriez pas essayer de réinventer la roue (sauf si vous essayez d’en savoir plus sur les roues) et plusieurs bibliothèques InSim matures sont disponibles pour être utilisées dans votre propre code.
Bibliothèques InSim | ||||
---|---|---|---|---|
Bibliothèque | Plateforme | Licence | web | |
LFSLib | .NET Framework | GPL | page du projet | |
LFS_External | .NET Framework | Freeware | thread lfsforum | |
JInSim | Java | Mozilla | thread lfsforum | |
pyinsim | Python | LGPL | fil lfsforum | |
CInSim | C/C++ | Freeware | thread lfsforum | |
phplfs | PHP5 | Licence Apache V2.0 | page du projet | |
PRISME | PHP7 | MIT | section lfsforum | |
InSim.NET | .NET Framework | LGPL | thread lfsforum |
Référence InSim
Voici une tentative de référence du protocole InSim complet.
Référence de Paquet | ||
---|---|---|
Paquet | Description | Type |
Initialisation | ||
IS_ISI | Initialisation d’InSim | Instruction |
Usage Général | ||
IS_TINY | Paquet de 4 octets à usage général | Les deux |
IS_SMALL | Paquet de 8 octets à usage général | Les deux |
Demande de version | ||
IS_VER | Informations sur la version | Info |
Rapports et demandes des États | ||
IS_STA | Envoyé chaque fois que l’état du jeu change | Info |
IS_SFP | Envoyer pour définir diverses options d’état | Instruction |
Mode Écran | ||
IS_MOD | Envoyer pour changer de mode d’écran | Instruction |
Messages Texte et Pressions sur les Touches | ||
IS_MSO | Messages système et utilisateur envoyés depuis LFS | Info |
IS_III | Messages de l’utilisateur à héberger InSim | Info |
IS_MST | Envoyer un message ou une commande LFS (64 caractères) | Instruction |
IS_MSX | Version étendue d’IS_MST (96 caractères), pas pour les commandes | Instruction |
IS_MSL | Envoyer un message au client de jeu local | Instruction |
IS_MTC | Envoyer un message à une connexion ou un lecteur spécifique | Instruction |
IS_SCH | Envoyer un seul caractère ou appuyer sur une touche | Instruction |
Notification Multijoueur | ||
IS_ISM | Envoyé lors du démarrage ou de la jonction d’un hôte | Info |
IS_NCI | Envoyé lorsque le mot de passe administrateur de l’hôte est défini, contient l’adresse IP de l’utilisateur et les données de langue | Info |
Vote Notifier | ||
IS_VTN | Notifier le vote du joueur (redémarrer la course, se qualifier, etc..) | Info |
Suivi de Course | ||
IS_RST | Départ ou redémarrage de la course | Info |
IS_NCN | Nouvelle connexion serveur de connexion | Info |
IS_SLC | pour signaler les changements dans l’état de la voiture (actuellement démarrer ou arrêter) | Info |
IS_CSC | signale la voiture actuellement sélectionnée par une connexion | Info |
IS_CNL | Connexion serveur gauche | Info |
IS_CPR | Nom du joueur changé | Info |
IS_NPL | Nouveau joueur rejoignant la course ou quittant les stands | Info |
IS_PLP | Fosses des joueurs (passé à l’écran du garage) | Info |
IS_PLL | Joueur à gauche de la course (parti au spectateur) | Info |
IS_CRS | Réinitialisation de la voiture (barre d’espace enfoncée) | Info |
IS_JRR | peut être utilisé pour réinitialiser ou démarrer une voiture à un emplacement spécifié | Instruction |
IS_LAP | Temps au tour terminé | Info |
IS_SPX | Temps partiel terminé | Info |
IS_PIT | Départ de l’arrêt au stand (au stand) | Info |
IS_PSF | Arrêt au stand terminé | Info |
IS_PLA | Le joueur est entré dans la voie des stands (pour piter ou purger une pénalité) | Info |
IS_CHH | Vue de la caméra modifiée (vue de chasse, vue personnalisée, etc..) | Info |
IS_PEN | Pénalité infligée ou cadenassée | Info |
IS_TOC | Joueur repris une autre voiture (échange de conducteur) | Info |
IS_FLG | Drapeau du joueur (jaune ou bleu) | Info |
IS_PFL | Drapeaux du lecteur changés (engrenages automatiques, embrayage automatique, etc..) | Info |
IS_FIN | Course terminée par le joueur (ligne d’arrivée franchie) | Info |
IS_RES | Résultat du joueur attribué, finition confirmée | Info |
IS_REO | Réorganiser la grille de départ | Les deux |
Autocross | ||
IS_AXI | Mise en page autocross chargée | Info |
IS_AXO | Objet autocross atteint par le joueur | Info |
IS_OCO | peut être utilisé pour remplacer des tous les feux de démarrage | Instruction |
IS_UCO | envoie des informations sur les points de contrôle et les cercles InSim | Info |
Suivi De Voiture | ||
IS_NLP | Joueurs nœud actuel, tour et position de course | Info |
IS_MCI | Version plus détaillée de IS_NLP, coordonnées du monde, vitesse, angle et cap | Info |
Contrôle de la Caméra | ||
IS_SCC | Réglez la voiture vue et sélectionnez la caméra | Instruction |
IS_CPP | Régler la position complète de la caméra | Instruction |
Contrôle de Relecture | ||
IS_RIP | Charge la relecture et se déplace vers une destination spécifique | Instruction |
Captures d’écran | ||
IS_SSH | Prendre une capture d’écran | Instruction |
Boutons InSim | ||
IS_BFN | Supprimer un bouton ou tous les boutons | Instruction |
IS_BTN | Envoyer un bouton à l’écran | Instruction |
IS_BTC | Envoyé lorsqu’un bouton est cliqué | Info |
IS_BTT | Envoyé lorsque le texte est entré | Info |