Revision as of 18:44, 14 June 2016

Contents

InSim

InSim is a protocol which allows an external program to communicate with Live for Speed. It allows you to create a socket connection with the game and to send and receive packets of data. The InSim protocol describes how each of these packets is formatted, and any programming language which can create a network connection and send and receive strings of binary data can interface with it.

The official documentation is included in the file InSim.txt, found in the games doc folder. It consists of a C++ header file that contains the definition for each packet, as well as comments from Scawen as to how each should be used. The documentation here is intended as an ancillary to this file.

UDP vs TCP

InSim supports both UDP and TCP connections. In UDP mode only a single connection can be made, however up to eight connections can be made to the game in TCP. Whether connected in TCP or UDP, it's possible to specify a separate UDP socket for receiving car position updates, such as IS_MCI and IS_NLP.

InSim example

How you go about creating an InSim connection is of course dependent on which programming language you are using, but here we make an attempt to document the process with some examples from the popular Python programming language. As mentioned above any language capable of making a socket connection can be used to interface with LFS, however the principle remain the same regardless.

Creating a connection

First of all we must establish a socket connection with the game, in this case in TCP.

Initialising InSim

After establishing the connection we must initialise the InSim system by sending the IS_ISI packet. Before we can do this however we must first intitailse InSim within LFS itself. To do this start the game and enter the chat command "/insim 29999". The port number used can be any valid port, but 29999 generally tends to be the accepted default.

Each InSim packet begins with a header, consisting of 4 bytes. The first byte is the size of the packet, followed by the packet type from the ISP_ enumeration, and then the ReqI (standing for Request Id). Whenever a request is made to LFS the value of the ReqI must be set to non-zero, whereby LFS will reply with the same value set in the ReqI of the requested packet. Finally the fourth byte varies depending on the type of packet in question, which in this case is blank.

As you can see the IS_ISI packet contains various options and flags that are used when initialising the InSim system. We must pack this data into a binary formatted string to send it to LFS.

Receiving Data

After creating the connection and initialising InSim we must then setup the packet receive loop. As data in TCP mode is sent as a constant stream of data, multiple packets may arrive in a single receive call and some packets may arrive incomplete. This means we must store all incoming data in a buffer and then read each packet out when we are sure it is complete.

# 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[0]):
# Copy the packet from the buffer.
packet = buffer[:ord(buffer[0])]
# Remove the packet from the buffer.
buffer = buffer[ord(buffer[0]):]
# The packet is now complete! :)
# doSomethingWithPacket(packet)
else:
break
# Release the socket.
sock.close()

Unpacking Packets

Once we have received the packet data as a binary formatted string, we then have to unpack this data into a format which is useful to us. In our previous example when we sent the IS_ISI initailisation packet, we set the ReqI to non-zero, meaning that LFS responded with an IS_VER version packet, however we didn't do anything with it. Firstly lets look at the definition for the IS_VER packet from InSim.txt.

Keep Alive

In order to keep the connection open LFS will send a "keep alive" packet every 30 or so seconds. This packet is an IS_TINY with a SubT (sub-type) of TINY_NONE. We must respond to this packet every time it is received in order to prevent the connection with InSim from timing-out.

Further examples

InSim Libraries

Of course as the old adage goes you shouldn't try to reinvent the wheel (unless you're trying to learn more about wheels) and there are several mature InSim libraries available for use in your own code.