InSim
InSim es un protocolo que permite a un programa externo comunicarse con Live for Speed. Permite crear una conexión de socket con el juego y enviar y recibir paquetes de datos. El protocolo InSim describe cómo se formatea cada uno de estos paquetes, y cualquier lenguaje de programación que pueda crear una conexión de red y enviar y recibir cadenas de datos binarios puede interactuar con él.
La documentación oficial se incluye en el archivo InSim.txt, que se encuentra en la carpeta de documentos de juegos. Consiste en un archivo de encabezado C++ que contiene la definición de cada paquete, así como comentarios de Scawen sobre cómo se debe usar cada uno. La documentación aquí está destinada a ser un complemento de este archivo.
UDP vs TCP
InSim admite conexiones UDP y TCP. En el modo UDP solo se puede hacer una sola conexión, sin embargo, se pueden hacer hasta ocho conexiones al juego en TCP. Ya sea que esté conectado en TCP o UDP, es posible especificar un socket UDP separado para recibir actualizaciones de posición del automóvil, como IS_MCI e IS_NLP.
Ejemplo de InSim
Cómo crear una conexión InSim depende, por supuesto, del lenguaje de programación que esté utilizando, pero aquí hacemos un intento de documentar el proceso con algunos ejemplos del popular lenguaje de programación Python. Como se mencionó anteriormente, cualquier lenguaje capaz de hacer una conexión de socket se puede usar para interactuar con LFS, sin embargo, el principio sigue siendo el mismo.
Crear una conexión
En primer lugar debemos establecer una conexión socket con el juego, en este caso 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))
Inicializar InSim
Después de establecer la conexión, debemos inicializar el sistema InSim enviando el paquete IS_ISI. Antes de que podamos hacer esto, sin embargo, primero debemos inicializar InSim dentro de la propia LFS. Para hacer esto, inicie el juego e ingrese el comando de chat «/ insim 29999». El número de puerto utilizado puede ser cualquier puerto válido, pero 29999 generalmente tiende a ser el valor predeterminado aceptado.
Aquí está la definición para el paquete IS_ISI de 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};
Cada paquete InSim comienza con un encabezado, que consta de 4 bytes. El primer byte es el tamaño del paquete, seguido del tipo de paquete de la enumeración ISP_, y luego el ReqI (sinónimo de Request Id). Siempre que se realice una solicitud a LFS, el valor de la ReqI debe ser distinto de cero, por lo que LFS responderá con el mismo valor establecido en la ReqI del paquete solicitado. Finalmente, el cuarto byte varía dependiendo del tipo de paquete en cuestión, que en este caso está en blanco.
Como puede ver, el paquete IS_ISI contiene varias opciones y banderas que se utilizan al inicializar el sistema InSim. Debemos empaquetar estos datos en una cadena con formato binario para enviarlos 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)
Recepción de datos
Después de crear la conexión e inicializar InSim, debemos configurar el bucle de recepción de paquetes. Como los datos en modo TCP se envían como un flujo constante de datos, pueden llegar varios paquetes en una sola llamada de recepción y algunos paquetes pueden llegar incompletos. Esto significa que debemos almacenar todos los datos entrantes en un búfer y luego leer cada paquete cuando estemos seguros de que está 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()
Desempaquetar paquetes
Una vez que hemos recibido los datos del paquete como una cadena con formato binario, tenemos que desempaquetar estos datos en un formato que nos sea útil. En nuestro ejemplo anterior, cuando enviamos el paquete de inicialización IS_ISI, establecemos el ReqI a distinto de cero, lo que significa que LFS respondió con un paquete de versión IS_VER, sin embargo, no hicimos nada con él. Primero veamos la definición del paquete IS_VER de 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};
Ahora veamos cómo descomprimiríamos esos datos 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
Para mantener abierta la conexión, LFS enviará un paquete «keep alive» cada 30 segundos aproximadamente. Este paquete es un IS_TINY con un SubT (subtipo) de TINY_NONE. Debemos responder a este paquete cada vez que se recibe para evitar que la conexión con InSim se agote.
# 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)
Más ejemplos
Puede ver el ejemplo completo de este código, así como otros en la página ejemplos de InSim.
Bibliotecas InSim
Por supuesto, como dice el viejo adagio, no debe intentar reinventar la rueda (a menos que esté tratando de aprender más sobre las ruedas) y hay varias bibliotecas InSim maduras disponibles para usar en su propio código.
InSim Bibliotecas | ||||
---|---|---|---|---|
Biblioteca | de la Plataforma | Licencia | web | |
LFSLib | .NET Framework | GPL | página del proyecto | |
LFS_External | .NET Framework | Freeware | lfsforum hilo | |
JInSim | Java | Mozilla | lfsforum hilo | |
pyinsim | Python | LGPL | lfsforum hilo | |
CInSim | C/C++ | Freeware | lfsforum hilo | |
phplfs | PHP5 | Licencia Apache V2.0 | página del proyecto | |
PRISMA | PHP7 | MIT | lfsforum sección | |
InSim.NET | . NET Framework | LGPL | hilo lfsforum |
Referencia InSim
Aquí hay un intento de hacer referencia al protocolo InSim completo.
Paquete de Referencia | ||
---|---|---|
Paquete | Descripción | Tipo de |
Inicialización | ||
IS_ISI | InSim inicialización | Enseñanza |
Propósito General | ||
IS_TINY | de propósito General 4 bytes de paquete | Tanto |
IS_SMALL | de propósito General de 8 bytes de paquete | Tanto |
petición de Versión | ||
IS_VER | información de la Versión | Info |
Presentación de Informes y Solicitudes de los Estados | ||
IS_STA | Enviado cada vez que cambia el estado del juego | Info |
IS_SFP | Enviar para configurar varias opciones de estado | Instrucción |
Modo de Pantalla | ||
IS_MOD | Enviar para cambiar el modo de pantalla | Instrucción |
Mensajes de Texto y Pulsaciones de Teclas | ||
IS_MSO | Mensajes de sistema y usuario enviados desde LFS | Info |
IS_III | Mensajes de usuario para alojar InSim | Info |
IS_MST | Enviar a LFS un mensaje o comando(64 caracteres) | Instrucción |
IS_MSX | Versión extendida de IS_MST (96 caracteres), no para instrucciones de comandos | |
IS_MSL | Enviar mensaje al cliente de juego local | Instrucción |
IS_MTC | Enviar mensaje a una conexión específica o instrucción de reproductor | |
IS_SCH | Enviar un solo carácter o pulsar una tecla | Instrucción |
Notificación Multijugador | ||
IS_ISM | Enviado al iniciar o unirse a un host | Info |
IS_NCI | Se envía cuando se establece la contraseña de administrador del host, contiene datos de idioma e IP del usuario | Info |
Notificación de Votación | ||
IS_VTN | Notificar el voto del jugador (reiniciar la carrera, calificar, etc..) | Info |
la regata | ||
IS_RST | Carrera de iniciar o reanudar el | Info |
IS_NCN | Nueva conexión de unirse servidor | Info |
IS_SLC | para informar de cambios en coche de estado (en la actualidad iniciar o detener) | Info |
IS_CSC | informes de una conexión seleccionada actualmente coche | Info |
IS_CNL | Conexión de la izquierda servidor | Info |
IS_CPR | Jugador cambió de nombre | Info |
IS_NPL | Nuevo jugador de unirse a la raza, o dejando hoyos | Info |
IS_PLP | Reproductor de pozos de (ido a la pantalla garaje) | Info |
IS_PLL | Jugador a la izquierda de la raza (ido a observar) | Info |
IS_CRS | Auto reset (presiona la barra de espacio) | Info |
IS_JRR | se puede utilizar para reiniciar o iniciar un coche en una ubicación especificada | la Instrucción |
IS_LAP | tiempo de Vuelta completado | Info |
IS_SPX | Dividir vez completado | Info |
IS_PIT | parada en Boxes de introducción (en el pit box) | Info |
IS_PSF | parada en Boxes terminado | Info |
IS_PLA | Jugador entró en el pit lane (hoyo o servir de penalti) | Info |
IS_CHH | vista de la Cámara cambiado (chase view, vista personalizada etc..) | Info |
IS_PEN | Sanción o con apoyos de tracción | Info |
IS_TOC | Jugador tomado otro coche (conductor de intercambio) | Info |
IS_FLG | Reproductor muestra la bandera (amarillo o azul) | Info |
IS_PFL | Reproductor de banderas cambiado (auto-marchas automático, embrague, etc..) | Info |
IS_FIN | Jugador terminado la carrera (cruzado la meta) | Info |
IS_RES | Reproductor de resultar adjudicado, confirmó acabado | Info |
IS_REO | Reordenar parrilla de salida | Tanto |
de Autocross | ||
IS_AXI | Autocross de diseño cargado | Info |
IS_AXO | Jugador golpea de autocross objeto | Info |
IS_OCO | puede utilizarse para reemplazar específicos o todas las luces de arranque | Instrucción |
IS_UCO | envía información sobre puntos de control y círculos InSim | Info |
Seguimiento de Coches | ||
IS_NLP | Jugadores posición actual del nodo, vuelta y carrera | Info |
IS_MCI | Versión más detallada de IS_NLP, coordenadas del mundo, velocidad, ángulo y rumbo | Info |
Control de Cámara | ||
IS_SCC | Configure el automóvil visto y seleccione la cámara | Instrucción |
IS_CPP | Set completo de la posición de la cámara | Enseñanza |
Control de Reproducción | ||
IS_RIP | Carga de reproducción y pasar a destino específico | Enseñanza |
Capturas de pantalla | ||
IS_SSH | Tomar una captura de pantalla | Enseñanza |
InSim Botones | ||
IS_BFN | Eliminar un botón o todos los botones | Enseñanza |
IS_BTN | Enviar un botón a la pantalla de | la Instrucción |
IS_BTC | Enviado cuando hace clic en un botón | Info |
IS_BTT | Enviado cuando se escribe texto | Info |