In Sim
In Sim
#define _ISPACKETS_H_
/////////////////////
// TCP or UDP packets can be sent in both directions, LFS reporting various
// things about its state, and the external program requesting info and
// controlling LFS with special packets, text commands or keypresses.
// NOTE : This text file was written with a TAB size equal to 4 spaces.
// 0 : practice
// 1-99 : number of laps... laps = rl
// 100-190 : 100 to 1000 laps... laps = (rl - 100) * 10 + 100
// 191-238 : 1 to 48 hours... hours = rl - 190
// InSim PACKETS
// =============
// INITIALISING InSim
// ==================
// TO START COMMUNICATION
// ======================
// TCP : Connect to LFS using a TCP connection, then send this packet :
// UDP : No connection required, just send this packet to LFS :
byte Sp0; // 0
byte Prefix; // Special host message prefix character
word Interval; // Time in ms between NLP or MCI (0 = none)
// zero : LFS sends all packets to the port of the incoming packet
// non-zero : LFS sends all packets to the specified UDPPort
// zero : LFS sends NLP / MCI packets using your TCP connection
// non-zero : LFS sends NLP / MCI packets to the specified UDPPort
// NOTE 3) Flags field (set the relevant bits to turn on the option) :
// In most cases you should not set both ISF_NLP and ISF_MCI flags
// because all IS_NLP information is included in the IS_MCI packet.
// Messages typed with this prefix will be sent to your InSim program
// on the host (in IS_MSO) and not displayed on anyone's screen.
unsigned UVal; // value (e.g. for SMALL_SSP this would be the OutSim
packet rate)
};
// VERSION REQUEST
// ===============
// CLOSING InSim
// =============
// You can send this IS_TINY to close the InSim connection to your program :
// ReqI : 0
// SubT : TINY_CLOSE (close this connection)
// You can shut down InSim completely and stop it listening at all by typing
/insim=0
// into LFS (or send a MsgTypePack to do the same thing).
// If InSim does not receive a packet for 70 seconds, it will close your
connection.
// To open it again you would need to send another InSimInit packet.
// LFS will send a blank IS_TINY packet like this every 30 seconds :
// ReqI : 0
// SubT : TINY_NONE (keep alive packet)
// ReqI : 0
// SubT : TINY_NONE (has no effect other than resetting the timeout)
// NOTE : If you want to request a reply from LFS to check the connection
// at any time, you can send this IS_TINY :
// LFS will send a StatePack any time the info in the StatePack changes.
byte QualMins;
byte RaceLaps; // see "RaceLaps" near the top of this document
byte Spare2;
byte Spare3;
// Setting states
// SCREEN MODE
// ===========
// You can send this packet to LFS to set the screen mode :
// The refresh rate actually selected by LFS will be the highest available rate
// that is less than or equal to the specified refresh rate. Refresh rate can
// be specified as zero in which case the default refresh rate will be used.
// If Width and Height are both zero, LFS will switch to windowed mode.
// You can send 64-byte text messages to LFS as if the user had typed them in.
// Messages that appear on LFS screen (up to 128 bytes) are reported to the
// external program. You can also send simulated keypresses to LFS.
char Msg[128];
};
enum
{
MSO_SYSTEM, // 0 - system message
MSO_USER, // 1 - normal visible user message
MSO_PREFIX, // 2 - hidden message starting with special prefix
(see ISI)
MSO_O, // 3 - hidden message typed on local pc with /o
command
MSO_NUM
};
// NOTE : Typing "/o MESSAGE" into LFS will send an IS_MSO with UserType = MSO_O
char Msg[64];
};
struct IS_MSX // MSg eXtended - like MST but longer (not for commands)
{
byte Size; // 100
byte Type; // ISP_MSX
byte ReqI; // 0
byte Zero;
enum
{
SND_SILENT,
SND_MESSAGE,
SND_SYSMESSAGE,
SND_INVALIDKEY,
SND_ERROR,
SND_NUM
};
// MULTIPLAYER NOTIFICATION
// ========================
// ReqI : 0
// SubT : TINY_MPE (MultiPlayerEnd)
// NOTE : If LFS is not in multiplayer mode, the host name in the ISM will be
empty.
enum
{
VOTE_NONE, // 0 - no vote
VOTE_END, // 1 - end race
VOTE_RESTART, // 2 - restart
VOTE_QUALIFY, // 3 - qualify
VOTE_NUM
};
// ReqI : 0
// SubT : TINY_VTC (VoTe Cancelled)
// ReqI : 0
// SubT : SMALL_VTA (VoTe Action)
// UVal : action (VOTE_X - Vote Action as defined above)
// ReqI : 0
// SubT : TINY_VTC (VoTe Cancel)
// RACE TRACKING
// =============
// If you are making a multiplayer InSim program, you must maintain two lists
// You should use the unique identifier UCID to identify a connection
// Each player has a unique identifier PLID from the moment he joins the race,
until he
// leaves. It's not possible for PLID and UCID to be the same thing, for two
reasons :
// 1) there may be more than one player per connection if AI drivers are used
// 2) a player can swap between connections, in the case of a driver swap (IS_TOC)
// When all players are cleared from race (e.g. /clear) LFS sends this IS_TINY
// ReqI : 0
// SubT : TINY_CLR (CLear Race)
// When a race ends (return to game setup screen) LFS sends this IS_TINY
// ReqI : 0
// SubT : TINY_REN (Race ENd)
// ReqI : 0
// SubT : TINY_VTC (VoTe Cancel)
word Flags; // race flags (must pit, can reset, etc - see below)
word NumNodes; // total number of nodes in the path
word Finish; // node index - finish line
word Split1; // node index - split 1
word Split2; // node index - split 2
word Split3; // node index - split 3
};
struct IS_NPL // New PLayer joining race (if PLID already exists, then leaving
pits)
{
byte Size; // 76
byte Type; // ISP_NPL
byte ReqI; // 0 unless this is a reply to an TINY_NPL request
byte PLID; // player's newly assigned unique id
int Spare;
byte Sp0;
byte NumP; // number in race (same when leaving pits, 1 more if new)
byte Sp2;
byte Sp3;
};
// NOTE : PType bit 0 (female) is not reported on dedicated host as humans are not
loaded
// You can use the driver model byte instead if required (and to force the use of
helmets)
struct IS_PLL // PLayer Leave race (spectate - removed from player list)
{
byte Size; // 4
byte Type; // ISP_PLL
byte ReqI; // 0
byte PLID; // player's unique id
};
byte Sp0;
byte Penalty; // current penalty value (see below)
byte NumStops; // number of pit stops
byte Sp3;
};
byte Sp0;
byte Penalty; // current penalty value (see below)
byte NumStops; // number of pit stops
byte Sp3;
struct IS_FIN // FINished race notification (not a final result - use IS_RES)
{
byte Size; // 20
byte Type; // ISP_FIN
byte ReqI; // 0
byte PLID; // player's unique id (0 = player left before result was
sent)
byte SpA;
byte NumStops; // number of pit stops
byte Confirm; // confirmation flags : disqualified etc - see below
byte SpB;
byte SpA;
byte NumStops; // number of pit stops
byte Confirm; // confirmation flags : disqualified etc - see below
byte SpB;
// LFS sends one at the start of every race or qualifying session, listing the
start order
// You can send one to LFS before a race start, to specify the starting order.
// It may be a good idea to avoid conflict by using /start=fixed (LFS setting).
// Alternatively, you can leave the LFS setting, but make sure you send your IS_REO
// AFTER you receive the IS_VTA. LFS does its default grid reordering at the same
time
// as it sends the IS_VTA (VoTe Action) and you can override this by sending an
IS_REO.
enum
{
PITLANE_EXIT, // 0 - left pit lane
PITLANE_ENTER, // 1 - entered pit lane
PITLANE_NO_PURPOSE, // 2 - entered for no purpose
PITLANE_DT, // 3 - entered for drive-through
PITLANE_SG, // 4 - entered for stop-go
PITLANE_NUM
};
enum
{
PSE_NOTHING, // bit 0 (1)
PSE_STOP, // bit 1 (2)
PSE_FR_DAM, // bit 2 (4)
PSE_FR_WHL, // etc...
PSE_LE_FR_DAM,
PSE_LE_FR_WHL,
PSE_RI_FR_DAM,
PSE_RI_FR_WHL,
PSE_RE_DAM,
PSE_RE_WHL,
PSE_LE_RE_DAM,
PSE_LE_RE_WHL,
PSE_RI_RE_DAM,
PSE_RI_RE_WHL,
PSE_BODY_MINOR,
PSE_BODY_MAJOR,
PSE_SETUP,
PSE_REFUEL,
PSE_NUM
};
// View identifiers
enum
{
VIEW_FOLLOW, // 0 - arcade
VIEW_HELI, // 1 - helicopter
VIEW_CAM, // 2 - tv camera
VIEW_DRIVER, // 3 - cockpit
VIEW_CUSTOM, // 4 - custom
VIEW_MAX
};
// Leave reasons
enum
{
LEAVR_DISCO, // 0 - disconnect
LEAVR_TIMEOUT, // 1 - timed out
LEAVR_LOSTCONN, // 2 - lost connection
LEAVR_KICKED, // 3 - kicked
LEAVR_BANNED, // 4 - banned
LEAVR_SECURITY, // 5 - OOS or cheat protection
LEAVR_NUM
};
// Penalty reasons
enum
{
PENR_UNKNOWN, // 0 - unknown or cleared penalty
PENR_ADMIN, // 1 - penalty given by admin
PENR_WRONG_WAY, // 2 - wrong way driving
PENR_FALSE_START, // 3 - starting before green light
PENR_SPEEDING, // 4 - speeding in pit lane
PENR_STOP_SHORT, // 5 - stop-go pit stop too short
PENR_STOP_LATE, // 6 - compulsory stop is too late
PENR_NUM
};
// Player flags
#define PIF_SWAPSIDE 1
#define PIF_RESERVED_2 2
#define PIF_RESERVED_4 4
#define PIF_AUTOGEARS 8
#define PIF_SHIFTER 16
#define PIF_RESERVED_32 32
#define PIF_HELP_B 64
#define PIF_AXIS_CLUTCH 128
#define PIF_INPITS 256
#define PIF_AUTOCLUTCH 512
#define PIF_MOUSE 1024
#define PIF_KB_NO_HELP 2048
#define PIF_KB_STABILISED 4096
#define PIF_CUSTOM_VIEW 8192
enum
{
TYRE_R1, // 0
TYRE_R2, // 1
TYRE_R3, // 2
TYRE_R4, // 3
TYRE_ROAD_SUPER, // 4
TYRE_ROAD_NORMAL, // 5
TYRE_HYBRID, // 6
TYRE_KNOBBLY, // 7
TYRE_NUM
};
const int NOT_CHANGED = 255;
// Confirmation flags
#define CONF_MENTIONED 1
#define CONF_CONFIRMED 2
#define CONF_PENALTY_DT 4
#define CONF_PENALTY_SG 8
#define CONF_PENALTY_30 16
#define CONF_PENALTY_45 32
#define CONF_DID_NOT_PIT 64
// Race flags
// HOSTF_CAN_VOTE 1
// HOSTF_CAN_SELECT 2
// HOSTF_MID_RACE 32
// HOSTF_MUST_PIT 64
// HOSTF_CAN_RESET 128
// HOSTF_FCV 256
// HOSTF_CRUISE 512
// Passengers byte
// bit 0 female
// bit 1 front
// bit 2 female
// bit 3 rear left
// bit 4 female
// bit 5 rear middle
// bit 6 female
// bit 7 rear right
// In each case, ReqI must be non-zero, and will be returned in the reply packet
// AUTOCROSS
// =========
// When all objects are cleared from a layout, LFS sends this IS_TINY :
// ReqI : 0
// SubT : TINY_AXC (AutoX Cleared)
// You can request information about the current layout with this IS_TINY :
// The information will be sent back in this packet (also sent when a layout is
loaded) :
char LName[32]; // the name of the layout last loaded (if loaded locally)
};
// 1) Set the Interval field in the IS_ISI (InSimInit) packet (50, 60, 70... 8000
ms)
// 2) Set one of the flags ISF_NLP or ISF_MCI in the IS_ISI packet
struct NodeLap // Car info in 6 bytes - there is an array of these in the NLP
(below)
{
word Node; // current path node
word Lap; // current lap
byte PLID; // player's unique id
byte Position; // current race position : 0 = unknown, 1 = leader, etc...
};
struct CompCar // Car info in 28 bytes - there is an array of these in the MCI
(below)
{
word Node; // current path node
word Lap; // current lap
byte PLID; // player's unique id
byte Position; // current race position : 0 = unknown, 1 = leader, etc...
byte Info; // flags and other info - see below
byte Sp3;
int X; // X map (65536 = 1 metre)
int Y; // Y map (65536 = 1 metre)
int Z; // Z alt (65536 = 1 metre)
word Speed; // speed (32768 = 100 m/s)
word Direction; // direction of car's motion : 0 = world y direction, 32768
= 180 deg
word Heading; // direction of forward axis : 0 = world y direction, 32768
= 180 deg
short AngVel; // signed, rate of change of heading : (16384 = 360
deg/s)
};
// NOTE 1) Info byte - the bits in this byte have the following meanings :
struct IS_MCI // Multi Car Info - if more than 8 in race then more than one of
these is sent
{
byte Size; // 4 + NumP * 28
byte Type; // ISP_MCI
byte ReqI; // 0 unless this is a reply to an TINY_MCI request
byte NumC; // number of valid CompCar structs in this packet
// You can change the rate of NLP or MCI after initialisation by sending this
IS_SMALL :
// ReqI : 0
// SubT : SMALL_NLI (Node Lap Interval)
// UVal : interval (0 means stop, otherwise time interval : 50, 60, 70... 8000
ms)
// CAR POSITION PACKETS (Initialising OutSim from InSim - See "OutSim" below)
// ====================
// To request Car Positions from the currently viewed car, send this IS_SMALL :
// ReqI : 0
// SubT : SMALL_SSP (Start Sending Positions)
// UVal : interval (time between updates - zero means stop sending)
// If OutSim has not been setup in cfg.txt, the SSP packet makes LFS send UDP
packets
// if in game, using the OutSim system as documented near the end of this text
file.
// You do not need to set any OutSim values in LFS cfg.txt - OutSim is fully
// initialised by the SSP packet.
// The OutSim packets will be sent to the UDP port specified in the InSimInit
packet.
// NOTE : OutSim packets are not InSim packets and don't have a 4-byte header.
// To request Dashboard Packets from the currently viewed car, send this IS_SMALL :
// ReqI : 0
// SubT : SMALL_SSG (Start Sending Gauges)
// UVal : interval (time between updates - zero means stop sending)
// If OutGauge has not been setup in cfg.txt, the SSG packet makes LFS send UDP
packets
// if in game, using the OutGauge system as documented near the end of this text
file.
// You do not need to set any OutGauge values in LFS cfg.txt - OutGauge is fully
// initialised by the SSG packet.
// The OutGauge packets will be sent to the UDP port specified in the InSimInit
packet.
// NOTE : OutGauge packets are not InSim packets and don't have a 4-byte header.
// CAMERA CONTROL
// ==============
// You can set the viewed car and selected camera directly with a special packet
// These are the states normally set in game by using the TAB and V keys
struct IS_SCC // Set Car Camera - Simplified camera packet (not SHIFT+U mode)
{
byte Size; // 8
byte Type; // ISP_SCC
byte ReqI; // 0
byte Zero;
// A Camera Position Packet can be used for LFS to report a camera position and
state.
// An InSim program can also send one to set LFS camera position in game or SHIFT+U
mode.
struct IS_CPP // Cam Pos Pack - Full camera packet (in car OR SHIFT+U mode)
{
byte Size; // 32
byte Type; // ISP_CPP
byte ReqI; // instruction : 0 / or reply : ReqI as received in the
TINY_SCP
byte Zero;
// On receiving this packet, LFS will set up the camera to match the values in the
packet,
// including switching into or out of SHIFT+U mode depending on the ISS_SHIFTU
flag.
// If ISS_VIEW_OVERRIDE is set, the in-car view Heading Pitch and Roll will be
taken
// from the values in this packet. Otherwise normal in game control will be used.
// Position vector (Vec Pos) - in SHIFT+U mode, Pos can be either relative or
absolute.
// The "Time" value in the packet is used for camera smoothing. A zero Time means
instant
// positioning. Any other value (milliseconds) will cause the camera to move
smoothly to
// the requested position in that time. This is most useful in SHIFT+U camera
modes or
// for smooth changes of internal view when using the ISS_VIEW_OVERRIDE flag.
// NOTE : You can use frequently updated camera positions with a longer Time value
than
// the update frequency. For example, sending a camera position every 100 ms, with
a
// Time value of 1000 ms. LFS will make a smooth motion from the rough inputs.
// If the requested camera mode is different from the one LFS is already in, it
cannot
// move smoothly to the new position, so in this case the "Time" value is ignored.
// TIME CONTROL
// ============
// You can Stop or Start Time in LFS and while it is stopped you can make LFS move
// in time steps in multiples of 100th of a second. Warning : unlike pausing, this
// is a "trick" to LFS and the program is unaware of time passing, so you must not
// leave it stopped because LFS is unusable in that state. You must never use this
// packet in multiplayer mode.
// ReqI : 0
// SubT : SMALL_TMS (TiMe Stop)
// UVal : stop (1 - stop / 0 - carry on)
// ReqI : 0
// SubT : SMALL_STP (STeP)
// UVal : number (number of hundredths of a second to update)
// BUTTONS
// =======
// You can make up to 240 buttons appear on the host or guests (ID = 0 to 239).
// You should set the ISF_LOCAL flag (in IS_ISI) if your program is not a host
control
// system, to make sure your buttons do not conflict with any buttons sent by the
host.
#define IS_X_MIN 0
#define IS_X_MAX 110
#define IS_Y_MIN 30
#define IS_Y_MAX 170
// If you draw buttons in this area, the area will be kept clear to
// avoid overlapping LFS buttons with your InSim program's buttons.
// Buttons outside that area will not have a space kept clear.
// You can also make buttons visible in all screens - see below.
// NOTE : BFN_REQUEST allows the user to bring up buttons with SHIFT+B or SHIFT+I
// Host buttons and local buttons are stored separately, so there is no chance of a
conflict between
// a host control system and a local system (although the buttons could overlap on
screen).
// TypeIn byte : if set, the user can click this button to type in text.
// On clicking the button, a text entry dialog will be opened, allowing the
specified number of
// characters to be typed in. The caption on the text entry dialog is optionally
customisable using
// Text in the IS_BTN packet. If the first character of IS_BTN's Text field is
zero, LFS will read
// the caption up to the second zero. The visible button text then follows that
second zero.
// Inst byte : mainly used internally by InSim but also provides some extra user
flags
// NOTE : You should not use INST_ALWAYS_ON for most buttons. This is a special
flag for buttons
// that really must be on in all screens (including the garage and options
screens). You will
// probably need to confine these buttons to the top or bottom edge of the screen,
to avoid
// overwriting LFS buttons. Most buttons should be defined without this flag, and
positioned
// in the recommended area so LFS can keep a space clear in the main screens.
// NOTE : If width or height are zero, this would normally be an invalid button.
But in that case if
// there is an existing button with the same ClickID, all the packet contents are
ignored except the
// Text field. This can be useful for updating the text in a button without
knowing its position.
// For example, you might reply to an IS_BTT using an IS_BTN with zero W and H to
update the text.
// Replies : If the user clicks on a clickable button, this packet will be sent :
struct IS_BTC // BuTton Click - sent back when user clicks a button
{
byte Size; // 8
byte Type; // ISP_BTC
byte ReqI; // ReqI as received in the IS_BTN
byte UCID; // connection that clicked the button (zero if local)
// If the TypeIn byte is set in IS_BTN the user can type text into the button
// In that case no IS_BTC is sent - an IS_BTT is sent when the user presses ENTER
struct IS_BTT // BuTton Type - sent back when user types into a text entry button
{
byte Size; // 104
byte Type; // ISP_BTT
byte ReqI; // ReqI as received in the IS_BTN
byte UCID; // connection that typed into the button (zero if local)
struct OutSimPack
{
unsigned Time; // time in milliseconds (to check order)
// NOTE 2) Motion simulators can be dangerous. The Live for Speed developers do
// not support any motion systems in particular and cannot accept responsibility
// for injuries or deaths connected with the use of such machinery.
struct OutGaugePack
{
unsigned Time; // time in milliseconds (to check order)
#define OG_SHIFTLIGHT 1
#define OG_FULLBEAM 2
#define OG_HANDBRAKE 4
#define OG_PITSPEED 8
#define OG_TC 16
#define OG_HEADLIGHTS 32
#define OG_SIGNAL_L 64
#define OG_SIGNAL_R 128
#define OG_REDLINE 256
#define OG_OILWARN 512
#define OG_1 1024
#define OG_2 2048
#define OG_3 4096
#define OG_4 8192
#define OG_KM 16384
#define OG_BAR 32768
//////
#endif