// // InSim4.cs // // Author: // Robert BRACCAGNI alias Gai-Luron // // Copyright (c) 2010 Gai-Luron // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #define MONO using System; using System.Collections; using System.Threading; namespace InSim { public enum tyre { 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, TYRE_NO_CHANGE, }; enum vtn { VOTE_NONE, // 0 - no vote VOTE_END, // 1 - end race VOTE_RESTART, // 2 - restart VOTE_QUALIFY, // 3 - qualify VOTE_NUM }; enum bfn { BFN_DEL_BTN, // 0 - instruction : delete one button (must set ClickID) BFN_CLEAR, // 1 - instruction : clear all buttons made by this insim instance BFN_USER_CLEAR, // 2 - info : user cleared this insim instance's buttons BFN_REQUEST, // 3 - user request : SHIFT+B or SHIFT+I - request for buttons }; enum pen { PENALTY_NONE, // 0 PENALTY_DT, // 1 PENALTY_DT_VALID, // 2 PENALTY_SG, // 3 PENALTY_SG_VALID, // 4 PENALTY_30, // 5 PENALTY_45, // 6 PENALTY_NUM } enum penr { 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 }; enum obh { OBH_LAYOUT, //1 // an added object OBH_CAN_MOVE, //2 // a movable object OBH_WAS_MOVING, //4 // was moving before this hit OBH_ON_SPOT //8 // object in original position }; enum uco { UCO_CIRCLE_ENTER, //1 entered a circle UCO_CIRCLE_LEAVE, //2 left a circle UCO_CP_FWD, //4 crossed cp in forward direction UCO_CP_REV, //8 crossed cp in reverse direction }; enum PMOAction { PMO_LOADING_FILE, // 0 - sent by the layout loading system only PMO_ADD_OBJECTS, // 1 - adding objects (from InSim or editor) PMO_DEL_OBJECTS, // 2 - delete objects (from InSim or editor) PMO_CLEAR_ALL, // 3 - clear all objects (NumO must be zero) PMO_TINY_AXM, // 4 - a reply to a TINY_AXM request PMO_TTC_SEL, // 5 - a reply to a TTC_SEL request PMO_SELECTION, // 6 - set a connection's layout editor selection PMO_POSITION, // 7 - user pressed O without anything selected PMO_GET_Z, // 8 - request Z values / reply with Z values PMO_NUM }; enum mode { CIM_NORMAL, // 0 - not in a special mode CIM_OPTIONS, // 1 CIM_HOST_OPTIONS, // 2 CIM_GARAGE, // 3 CIM_CAR_SELECT, // 4 CIM_TRACK_SELECT, // 5 CIM_SHIFTU, // 6 - free view mode CIM_NUM }; enum SubMode { FVM_PLAIN, // 1no buttons displayed FVM_BUTTONS, // 2buttons displayed (not editing) FVM_SP2, // 3reserved FVM_SP3, // 4reserved FVM_EDIT_CHALK, // 5 FVM_EDIT_CONES, // 6 FVM_EDIT_TYRES, // 7 FVM_EDIT_MARKERS, // 8 FVM_EDIT_OTHER, // 9 FVM_EDIT_CONCRETE, // 10 FVM_EDIT_CONTROL, // 11 FVM_EDIT_MARSH, // 12 FVM_NUM // 13 }; enum BTN_style { ISB_C1 = 1, ISB_C2 = 2, ISB_C4 = 4, ISB_CLICK = 8, ISB_LIGHT = 16, ISB_DARK = 32, ISB_LEFT = 64, ISB_RIGHT = 128 }; enum PIT_work { PSE_NOTHING = 0, // bit 0 (1) PSE_STOP = 2, // bit 1 (2) PSE_FR_DAM = 4, // bit 2 (4) PSE_FR_WHL = 8, // etc... PSE_LE_FR_DAM = 16, PSE_LE_FR_WHL = 32, PSE_RI_FR_DAM = 64, PSE_RI_FR_WHL = 128, PSE_RE_DAM = 256, PSE_RE_WHL = 512, PSE_LE_RE_DAM = 1024, PSE_LE_RE_WHL = 2048, PSE_RI_RE_DAM = 4096, PSE_RI_RE_WHL = 8192, PSE_BODY_MINOR = 16384, PSE_BODY_MAJOR = 32768, PSE_SETUP = 65536, PSE_REFUEL = 131072, }; enum confirm { CONF_MENTIONED = 1, CONF_CONFIRMED = 2, CONF_PENALTY_DT = 4, CONF_PENALTY_SG = 8, CONF_PENALTY_30 = 16, CONF_PENALTY_45 = 32, CONF_DID_NOT_PIT = 64 } enum ISF { RES_0 = 1, RES_1 = 2, // bit 1 : spare LOCAL = 4, // bit 2 : spare MSO_COLS = 8, // bit 3 : spare NLP = 16, // bit 4 : set to receive NLP packets MCI = 32, // bit 5 : set to receive MCI packets CON = 64, // bit 6 : set to receive CON packets OBH = 128, // bit 7 : set to receive OBH packets HLV = 256, // bit 8 : receive HLV packets AXM_LOAD = 512, // bit 9 : receive AXM when loading a layout AXM_EDIT = 1024, // bit 10 : receive AXM when changing objects REQ_JOIN = 2048 // bit 11 : process join requests } enum TypePack { ISP_NONE, // 0 : not used ISP_ISI, // 1 - instruction : insim initialise ISP_VER, // 2 - info : version info ISP_TINY, // 3 - both ways : multi purpose ISP_SMALL, // 4 - both ways : multi purpose ISP_STA, // 5 - info : state info ISP_SCH, // 6 - instruction : single character ISP_SFP, // 7 - instruction : state flags pack ISP_SCC, // 8 - instruction : set car camera ISP_CPP, // 9 - both ways : cam pos pack ISP_ISM, // 10 - info : start multiplayer ISP_MSO, // 11 - info : message out ISP_III, // 12 - info : hidden /i message ISP_MST, // 13 - instruction : type message or /command ISP_MTC, // 14 - instruction : message to a connection ISP_MOD, // 15 - instruction : set screen mode ISP_VTN, // 16 - info : vote notification ISP_RST, // 17 - info : race start ISP_NCN, // 18 - info : new connection ISP_CNL, // 19 - info : connection left ISP_CPR, // 20 - info : connection renamed ISP_NPL, // 21 - info : new player (joined race) ISP_PLP, // 22 - info : player pit (keeps slot in race) ISP_PLL, // 23 - info : player leave (spectate - loses slot) ISP_LAP, // 24 - info : lap time ISP_SPX, // 25 - info : split x time ISP_PIT, // 26 - info : pit stop start ISP_PSF, // 27 - info : pit stop finish ISP_PLA, // 28 - info : pit lane enter / leave ISP_CCH, // 29 - info : camera changed ISP_PEN, // 30 - info : penalty given or cleared ISP_TOC, // 31 - info : take over car ISP_FLG, // 32 - info : flag (yellow or blue) ISP_PFL, // 33 - info : player flags (help flags) ISP_FIN, // 34 - info : finished race ISP_RES, // 35 - info : result confirmed ISP_REO, // 36 - both ways : reorder (info or instruction) ISP_NLP, // 37 - info : node and lap packet ISP_MCI, // 38 - info : multi car info ISP_MSX, // 39 - instruction : type message ISP_MSL, // 40 - instruction : message to local computer ISP_CRS, // 41 - info : car reset ISP_BFN, // 42 - both ways : delete buttons / receive button requests ISP_AXI, // 43 - info : autocross layout information ISP_AXO, // 44 - info : hit an autocross object ISP_BTN, // 45 - instruction : show a button on local or remote screen ISP_BTC, // 46 - info : sent when a user clicks a button ISP_BTT, // 47 - info : sent after typing into a button ISP_RIP, // 48 - both ways : replay information packet ISP_SSH, // 49 - both ways : screenshot ISP_CON, // 50 - info : contact between cars (collision report) ISP_OBH, // 51 - info : contact car + object (collision report) ISP_HLV, // 52 - info : report incidents that would violate HLVC ISP_PLC, // 53 - instruction : player cars ISP_AXM, // 54 - both ways : autocross multiple objects ISP_ACR, // 55 - info : admin command report ISP_HCP, // 56 - instruction : car handicaps ISP_NCI, // 57 - info : new connection - extra info for host ISP_JRR, // 58 - instruction : reply to a join request (allow / disallow) ISP_UCO, // 59 - info : report InSim checkpoint / InSim circle ISP_OCO, // 60 - instruction : object control (currently used for lights) ISP_TTC, // 61 - instruction : multi purpose - target to connection ISP_SLC, // 62 - info : connection selected a car ISP_CSC, // 63 - info : car state changed ISP_CIM, // 64 - info : connection's interface mode }; enum TypeTiny { TINY_NONE, // 0 - keep alive : see "maintaining the connection" TINY_VER, // 1 - info request : get version TINY_CLOSE, // 2 - instruction : close insim TINY_PING, // 3 - ping request : external progam requesting a reply TINY_REPLY, // 4 - ping reply : reply to a ping request TINY_VTC, // 5 - both ways : game vote cancel (info or request) TINY_SCP, // 6 - info request : send camera pos TINY_SST, // 7 - info request : send state info TINY_GTH, // 8 - info request : get time in hundredths (i.e. SMALL_RTP) TINY_MPE, // 9 - info : multi player end TINY_ISM, // 10 - info request : get multiplayer info (i.e. ISP_ISM) TINY_REN, // 11 - info : race end (return to race setup screen) TINY_CLR, // 12 - info : all players cleared from race TINY_NCN, // 13 - info request : get NCN for all connections TINY_NPL, // 14 - info request : get all players TINY_RES, // 15 - info request : get all results TINY_NLP, // 16 - info request : send an IS_NLP TINY_MCI, // 17 - info request : send an IS_MCI TINY_REO, // 18 - info request : send an IS_REO TINY_RST, // 19 - info request : send an IS_RST TINY_AXI, // 20 - info request : send an IS_AXI - AutoX Info TINY_AXC, // 21 - info : autocross cleared TINY_RIP, // 22 - info request : send an IS_RIP - Replay Information Packet TINY_NCI, // 23 - info request : get NCI for all guests (on host only) TINY_ALC, // 24 - info request : send a SMALL_ALC (allowed cars) TINY_AXM, // 25 - info request : send IS_AXM packets for the entire layout TINY_SLC, // 26 - info request : send IS_SLC packets for all connections }; enum TypeSmall // the fourth byte of IS_SMALL packets is one of these { SMALL_NONE, // 0 : not used SMALL_SSP, // 1 - instruction : start sending positions SMALL_SSG, // 2 - instruction : start sending gauges SMALL_VTA, // 3 - report : vote action SMALL_TMS, // 4 - instruction : time stop SMALL_STP, // 5 - instruction : time step SMALL_RTP, // 6 - info : race time packet (reply to GTH) SMALL_NLI, // 7 - instruction : set node lap interval SMALL_ALC, // 8 - both ways : set or get allowed cars (TINY_ALC) SMALL_LCS, // 9 - instruction : set local car switches (lights, horn, siren) }; enum TypeTTC // the fourth byte of IS_SMALL packets is one of these { TTC_NONE, // 0 : not used TTC_SEL, // 1 - info request : send IS_AXM for a layout editor selection TTC_SEL_START, // 2 - info request : send IS_AXM every time the selection changes TTC_SEL_STOP, // 3 - instruction : switch off IS_AXM requested by TTC_SEL_START }; public class Connect { public class ConnectException : Exception { public ConnectException(string message) : base(message) { } public ConnectException(string message, Exception innerException) : base(message, innerException) { } } public class objPacket { public DateTime dateReceived; public byte[] recvPacket; public objPacket(byte[] precvPacket) { recvPacket = precvPacket; dateReceived = DateTime.Now; } } public bool connected = false; public string Product; public string Version; public string HostName; public int PakSize; public int InSimVersion; private System.Net.Sockets.UdpClient uc; private TcpConnection.Connection tc; private bool TCPmode; bool waitReceiveLow = true; public bool waitReceive = true; private Encoder myEncoder = new Encoder(); private bool Local; private string Host; private int Port; private GLDebug.Debug myDebug; public Queue InsimPacks = new Queue(500); public Thread TInsimReceive = null; System.Net.IPEndPoint remoteEP = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0); public Connect(GLDebug.Debug pmyDebug) { this.myDebug = pmyDebug; } /// /// /// /// /// /// /// /// /// /// /// /// public void insimConnect(string host, int port, string adminPassword, string mode, string nameApp, bool isLocal, bool TCPmode, int receiveJoinReq, int disableAIcars) { this.TCPmode = TCPmode; this.Host = host; this.Port = port; this.Local = isLocal; if (this.TCPmode) insimConnectTCP(host, port, adminPassword, mode, nameApp, isLocal, receiveJoinReq, disableAIcars); else insimConnectUDP(host, port, adminPassword, mode, nameApp, isLocal, receiveJoinReq, disableAIcars); // Start Thread Receiving packet // Why a thread, because of Lagging option TInsimReceive = new Thread(new ThreadStart(this.TInSimReceive)); TInsimReceive.Start(); } public void insimConnectTCP(string host, int port, string adminPassword, string mode, string nameApp, bool isLocal, int receiveJoinReq, int disableAIcars) { int nbTry = 0; int maxTry = 2; tc = new TcpConnection.Connection(host, port); myDebug.Write("mss", "Connecting to: [" + host + " / " + port + "]"); retryConnect: try { tc.Connect(); } catch { if (nbTry > maxTry) { myDebug.printDateOnEachLine = false; myDebug.WriteLine("mss", "Ko"); myDebug.printDateOnEachLine = true; throw new ConnectException("Lapper Instance [" + host + "/" + port + "] failed connecting with TCP connection!"); } else { Console.WriteLine("Lapper Instance [" + host + "/" + port + "] failed connecting!"); //System.Threading.Thread.Sleep(200); myDebug.printDateOnEachLine = false; myDebug.Write("mss", "."); myDebug.printDateOnEachLine = true; goto retryConnect; } } if (adminPassword.Length > 16) { Console.WriteLine("Wrong length adminPassword! :'" + adminPassword + "' max 16 characters"); myDebug.WriteLine("mss", "[" + host + " / " + port + "] Connection failed: Wrong length adminpass in Lapper!!"); } myDebug.printDateOnEachLine = false; myDebug.WriteLine("mss", ""); myDebug.printDateOnEachLine = true; byte[] inSimInit = myEncoder.ISI(adminPassword, 0, 0, nameApp, isLocal, receiveJoinReq, disableAIcars); try { this.Send(inSimInit, inSimInit.Length); } catch (Exception e) { throw e; } byte[] recvPacket; this.waitReceiveLow = true; recvPacket = this.ReceivePack(); myDebug.WriteLine("mss", "Instance [" + host + " / " + port + "] successfully connected "); try { InSim.Decoder.VER ver = new InSim.Decoder.VER(recvPacket); this.connected = true; this.Product = ver.Product; this.Version = ver.Version; this.InSimVersion = ver.InSimVersion; } catch { myDebug.WriteLine("mss", "[" + host + " / " + port + "] Connection failed: Lapper Password does not match with the server admin password!!"); Console.WriteLine("Lapper password does not match with the server admin password!! restart LFSLapper"); Console.ReadLine(); } } public void insimConnectUDP(string host, int port, string adminPassword, string mode, string nameApp, bool isLocal, int receiveJoinReq, int disableAIcars) { int nbTry = 0; int maxTry = 2; myDebug.Write("mss", "Connecting to: [" + host + " / " + port + "]"); retryConnect: try { uc = new System.Net.Sockets.UdpClient(host, port); } catch (Exception e) { myDebug.printDateOnEachLine = false; myDebug.WriteLine("mss", ""); myDebug.printDateOnEachLine = true; throw e; } #if MONO int localport = 0; //for mono #else int localport = ((System.Net.IPEndPoint)uc.Client.LocalEndPoint).Port;//for .NET #endif byte[] inSimInit = myEncoder.ISI(adminPassword, localport, 0, nameApp, isLocal, receiveJoinReq, disableAIcars); try { this.Send(inSimInit, inSimInit.Length); } catch (Exception e) { myDebug.printDateOnEachLine = false; myDebug.WriteLine("mss", ""); myDebug.printDateOnEachLine = true; throw e; } byte[] recvPacket; try { this.waitReceiveLow = true; recvPacket = this.ReceivePack(); } catch { if (nbTry++ > maxTry) { myDebug.printDateOnEachLine = false; myDebug.WriteLine("mss", ""); myDebug.printDateOnEachLine = true; throw (new Exception("Can't Receive reply of ISI Packet")); } else { //System.Threading.Thread.Sleep(200); myDebug.printDateOnEachLine = false; myDebug.Write("mss", "."); myDebug.printDateOnEachLine = true; goto retryConnect; } } myDebug.printDateOnEachLine = false; myDebug.WriteLine("mss", ""); myDebug.WriteLine("mss", "Instance [" + host + " / " + port + "] successfully connected"); myDebug.printDateOnEachLine = true; InSim.Decoder.VER ver = new InSim.Decoder.VER(recvPacket); this.connected = true; this.Product = ver.Product; this.Version = ver.Version; this.InSimVersion = ver.InSimVersion; } public void TInSimReceive() // Thread of reception { myDebug.WriteLine("mss", "InSImReceive Thread Started..."); while (true) { byte[] recvPacket; this.waitReceiveLow = true; try { recvPacket = this.ReceivePack(); } catch { //System.Threading.Thread.Sleep(500); continue; } Monitor.Enter(InsimPacks); InsimPacks.Enqueue(new objPacket(recvPacket)); Monitor.Exit(InsimPacks); } } public objPacket Receive() { objPacket recvPacket; while (true) { Monitor.Enter(InsimPacks); if (InsimPacks.Count != 0) { // Console.WriteLine(InsimPacks.Count); recvPacket = (objPacket)InsimPacks.Dequeue(); } else { recvPacket = null; } Monitor.Exit(InsimPacks); if (waitReceive == false) break; } return recvPacket; } public void Send(byte[] outMsg, int Length) { if (this.TCPmode) { this.SendTCP(outMsg, Length); } else this.SendUDP(outMsg, Length); } public void SendTCP(byte[] outMsg, int Length) { try { tc.SendToServer(outMsg, Length); } catch { throw new ConnectException("Insim TCP Connection Lost on " + Host + " / " + Port); } } public void SendUDP(byte[] outMsg, int Length) { try { uc.Send(outMsg, Length); } catch { throw new ConnectException("Insim UDP Connection Lost on " + Host + " / " + Port); } } public byte[] ReceivePack() { if (this.TCPmode) return ReceiveTCP(); else return ReceiveUDP(); } public byte[] ReceiveTCP() { if (tc.Available || waitReceiveLow) return tc.GetPackFromInsimServer(); else return null; } public byte[] ReceiveUDP() { try { if (uc.Available != 0 || waitReceiveLow) { return uc.Receive(ref remoteEP); } else return null; } catch { throw new ConnectException("Insim UDP Connection Lost on " + Host + " / " + Port); } } public void Close() { if (this.TCPmode) CloseTCP(); else CloseUDP(); if (TInsimReceive != null) { TInsimReceive.Abort(); TInsimReceive.Join(); } } public void CloseTCP() { tc.Disconnect(); } public void CloseUDP() { uc.Close(); } public string packetHead(byte[] packet) { string packetHead; packetHead = Enum.GetName(typeof(TypePack), packet[1]); if (packetHead == null) packetHead = "ISP_" + packet[1].ToString(); packetHead = packetHead.Remove(0, 4); return packetHead; } public uint verifyID(byte[] packet) { return (uint)0; } } public class Encoder { #region Send TINY insimpackets /// /// Request Insimpacket to LFS for information /// /// public byte[] TINY_NONE() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_NONE); } public byte[] TINY_PING() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_PING); } public byte[] VER() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_VER); } public byte[] VTC() { return IS_TINY((byte)TypePack.ISP_TINY, 0, (byte)TypeTiny.TINY_VTC); } public byte[] NCN() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_NCN); } public byte[] ISM() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_ISM); } public byte[] NPL() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_NPL); } public byte[] AXI() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_AXI); } public byte[] AXM() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_AXM); } public byte[] GTH() // Request RaceTimer { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_GTH); } public byte[] ALC() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_ALC); } public byte[] NCI() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_NCI); } public byte[] RST() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_RST); } public byte[] REO(int ReqI) { return IS_TINY((byte)TypePack.ISP_TINY, (byte)ReqI, (byte)TypeTiny.TINY_REO); } public byte[] SST() { return IS_TINY((byte)TypePack.ISP_TINY, 10, (byte)TypeTiny.TINY_SST); } public byte[] ISC() { return IS_TINY((byte)TypePack.ISP_TINY, 1, (byte)TypeTiny.TINY_CLOSE); } public byte[] NLI(int interval) { return IS_SMALL((byte)TypePack.ISP_SMALL, 0, (byte)TypeSmall.SMALL_NLI, (uint)interval); } public byte[] ALC(int allowedcars) { return IS_SMALL((byte)TypePack.ISP_SMALL, 0, (byte)TypeSmall.SMALL_ALC, (uint)allowedcars); } public byte[] LCS(int Switches) { return IS_SMALL((byte)TypePack.ISP_SMALL, 0, (byte)TypeSmall.SMALL_LCS, (uint)Switches); } #endregion public byte[] IS_TINY(byte Type, byte ReqI, byte SubT) { byte[] packet = new byte[4]; packet[0] = (byte)(4 / 4); packet[1] = Type; packet[2] = ReqI; packet[3] = SubT; return packet; } public byte[] IS_SMALL(byte Type, byte ReqI, byte SubT, uint Uval) { byte[] packet = new byte[8]; packet[0] = (byte)(8 / 4); packet[1] = Type; packet[2] = ReqI; packet[3] = SubT; packet[4] = (byte)(Uval & 0xff); packet[5] = (byte)((Uval >> 8) & 0xff); packet[6] = (byte)((Uval >> 16) & 0xff); packet[7] = (byte)((Uval >> 24) & 0xff); return packet; } /// /// Sent TTC (target to connection) info to LFS /// public byte[] TTC(byte ReqI, byte UCID) { byte[] packet = new byte[8]; packet[0] = (byte)(8 / 4); packet[1] = (byte)TypePack.ISP_TTC; packet[2] = ReqI; // ReqI - 0 unless it is an info request or a reply to an info request packet[3] = 1; // subtype, from TTC_ enumeration (e.g. TTC_SEL) >> 1 = TTC_SEL packet[4] = UCID; // connection's unique id (0 = local) packet[5] = 0; // B1, B2, B3 may be used in various ways depending on SubT packet[6] = 0; // packet[7] = 0; // return packet; // send packet to lfs } /// /// Sent MST (command messages) to LFS /// public byte[] MST(string msg) { int msgLen = msg.Length > 63 ? 63 : msg.Length; byte[] buffer = new byte[63]; //Encode string int length = LfsEncoding.Current.GetBytes(msg, buffer, 0, 63); // Get the packet size byte[] packet = new byte[68]; packet[0] = (byte)(68 / 4); packet[1] = (byte)TypePack.ISP_MST; packet[2] = 0; packet[3] = 0; for (int i = 0; i < 63; i++) { packet[i + 4] = buffer[i]; } return packet; } public byte[] MST(byte[] msg) { byte[] packet = new byte[68]; packet[0] = (byte)(68 / 4); packet[1] = (byte)TypePack.ISP_MST; packet[2] = 0; packet[3] = 0; System.Array.Copy(msg, 0, packet, 4, System.Math.Min(63, msg.Length)); return packet; } /// /// Sent MSX (Player messages) to LFS /// public byte[] MSX(string msg) { //int msgLen = msg.Length > 96 ? 96 : msg.Length; byte[] buffer = new byte[96]; //Encode string int length = LfsEncoding.Current.GetBytes(msg, buffer, 0, 96); // Get the packet size byte[] packet = new byte[100]; packet[0] = (byte)(100 / 4); packet[1] = (byte)TypePack.ISP_MSX; packet[2] = 0; packet[3] = 0; //InSim.CodePage.GetBytes(msg, 0, msgLen, packet, 4); //Encode string for (int i = 0; i < length; i++) { packet[i + 4] = buffer[i]; } return packet; } public byte[] MSX(byte[] msg) { byte[] packet = new byte[100]; packet[0] = (byte)(100 / 4); packet[1] = (byte)TypePack.ISP_MSX; packet[2] = 0; packet[3] = 0; System.Array.Copy(msg, 0, packet, 4, System.Math.Min(96, msg.Length)); return packet; } public byte[] MTC(int UCID, int PLID, string msg, int Sound) { byte[] buffer = new byte[128]; //Encode string int length = LfsEncoding.Current.GetBytes(msg, buffer, 0, 128); // Get the packet size (MTC needs trailing zero). int PacketSize = (byte)(Math.Min(length + (4 - (length % 4)), 128)); if (PacketSize > 128) { PacketSize = 128; } //MTC LAPPER INSIM PACKET byte[] packet = new byte[8 + PacketSize]; packet[0] = (byte)((8 + PacketSize) / 4); packet[1] = (byte)TypePack.ISP_MTC; packet[2] = 0; packet[3] = (byte)Sound; packet[4] = (byte)UCID; packet[5] = (byte)PLID; packet[6] = 0; packet[7] = 0; for (int i = 0; i < length; i++) { packet[i + 8] = buffer[i]; } //Test //Console.WriteLine("ISP_MTC: TEXTLENGTH::" + length + "SIZE::" + (8 + PacketSize) + " bytes UCID::" + UCID + " TEXT:: " + msg); return packet; } /// /// InSim Initialization Request Encoder /// /// Administrator password. /// Port number. 0 for same port as output. /// Seconds between MCI packets. 0 to disable. /// // OK in VERSION 4 public byte[] ISI(string adminPass, int portNum, byte mciSeconds, string nameApp, bool local, int receiveJoinReq, int disableAIcars) { byte[] packet = new byte[44]; packet[0] = (byte)(44 / 4); packet[1] = (byte)TypePack.ISP_ISI; packet[2] = 1; packet[3] = 0; // Port packet[4] = (byte)(portNum % 256); // LSB packet[5] = (byte)(portNum / 256); // MSB if (local) { if (receiveJoinReq == 1 || disableAIcars == 1) // if ReceiveJoinRequest or DisableAI is set to 1 in main LPR script - set REQ_JOIN flag { packet[6] = (byte)ISF.MCI | (byte)ISF.LOCAL | (byte)ISF.OBH | (byte)ISF.CON | (UInt16)ISF.HLV & 255 | (UInt16)ISF.AXM_EDIT & 255 | (UInt16)ISF.AXM_LOAD & 255; // LSB packet[7] = (UInt16)ISF.HLV >> 8 | (UInt16)ISF.AXM_EDIT >> 8 | (UInt16)ISF.AXM_LOAD >> 8 | (UInt16)ISF.REQ_JOIN >> 8; // MSB } else { packet[6] = (byte)ISF.MCI | (byte)ISF.LOCAL | (byte)ISF.OBH | (byte)ISF.CON | (UInt16)ISF.HLV & 255 | (UInt16)ISF.AXM_EDIT & 255 | (UInt16)ISF.AXM_LOAD & 255; // LSB packet[7] = (UInt16)ISF.HLV >> 8 | (UInt16)ISF.AXM_EDIT >> 8 | (UInt16)ISF.AXM_LOAD >> 8; // MSB } } else { if (receiveJoinReq == 1 || disableAIcars == 1) // if ReceiveJoinRequest or DisableAI is set to 1 in main LPR script - set REQ_JOIN flag { packet[6] = (byte)ISF.MCI | (byte)ISF.OBH | (byte)ISF.CON | (UInt16)ISF.HLV & 255 | (UInt16)ISF.AXM_EDIT & 255 | (UInt16)ISF.AXM_LOAD & 255 | (UInt16)ISF.REQ_JOIN & 255; // LSB packet[7] = (UInt16)ISF.HLV >> 8 | (UInt16)ISF.AXM_EDIT >> 8 | (UInt16)ISF.AXM_LOAD >> 8 | (UInt16)ISF.REQ_JOIN >> 8; // MSB } else { packet[6] = (byte)ISF.MCI | (byte)ISF.OBH | (byte)ISF.CON | (UInt16)ISF.HLV & 255 | (UInt16)ISF.AXM_EDIT & 255 | (UInt16)ISF.AXM_LOAD & 255 | (UInt16)ISF.REQ_JOIN & 255; // LSB packet[7] = (UInt16)ISF.HLV >> 8 | (UInt16)ISF.AXM_EDIT >> 8 | (UInt16)ISF.AXM_LOAD >> 8; // MSB } } packet[8] = 9; //Insim Version packet[9] = (byte)'!'; // Number of milli seconds between NLP or MCI packets (0=none) packet[10] = 40; // LSB packet[11] = 0; // MSB System.Text.Encoding.ASCII.GetBytes(adminPass, 0, Math.Min(adminPass.Length, 16), packet, 12); System.Text.Encoding.ASCII.GetBytes(nameApp, 0, Math.Min(nameApp.Length, 16), packet, 28); return packet; } /// /// ISP_BFN ( Clicked Button) /// public byte[] BFN(byte ReqI, int SubT, int UCID, int ClickID) { byte[] packet = new byte[8]; packet[0] = (byte)(8 / 4); packet[1] = (byte)TypePack.ISP_BFN; packet[2] = ReqI; packet[3] = (byte)SubT; packet[4] = (byte)UCID; packet[5] = (byte)ClickID; packet[6] = 0; packet[7] = 0; return packet; } /// /// Sent BTN (Button) info to LFS /// /// public byte[] BTN(byte ReqI, int L, int T, int W, int H, int UCID, int ClickID, int style, int TypeIn, string Caption, string Text) { //Calculate packetsize int PacketSize = 0; byte[] buffer = new byte[240]; int poke = Caption.Length; string allText; if (poke > 0) allText = " " + Caption + " " + Text; else allText = Text; while (allText.Length % 4 != 0) allText += " "; if (allText.Length > 240) allText = allText.Substring(0, 240); //Calculate packetsize (Text) int length = LfsEncoding.Current.GetBytes(allText, buffer, 0, 240); if (length > 0) { PacketSize = (byte)(Math.Min(length + (4 - (length % 4)), 240)); } else { PacketSize = 0; } byte[] packet = new byte[(12 + PacketSize)]; packet[0] = (byte)((12 + PacketSize) / 4); packet[1] = (byte)TypePack.ISP_BTN; packet[2] = ReqI; packet[3] = (byte)UCID; packet[4] = (byte)ClickID; packet[5] = 0; packet[6] = (byte)style; packet[7] = (byte)TypeIn; packet[8] = (byte)L; packet[9] = (byte)T; packet[10] = (byte)W; packet[11] = (byte)H; for (int i = 0; i < length; i++) { packet[i + 12] = (byte)buffer[i]; if (poke != 0) { packet[12] = 0; packet[12 + poke + 1] = 0; } int l = allText.Length; for (int a = 12 + allText.Length - 1; a > 12; a--) { if (packet[a] == ' ') packet[a] = 0; else break; } } return packet; } /// /// Sent REO (Grid reorder) request to LFS /// public byte[] REO(byte ReqI, int nbPlayer, byte[] arPLID) { byte[] packet = new byte[36]; packet[0] = (byte)(36 / 4); packet[1] = (byte)TypePack.ISP_REO; packet[2] = ReqI; packet[3] = (byte)nbPlayer; for (int i = 0; i < 32; i++) packet[i + 4] = (byte)arPLID[i]; return packet; } /// /// Sent OCO (StartLight Control) info to LFS /// public byte[] OCO(byte OCOAction, byte Index, byte Identifier, byte Data) { byte[] packet = new byte[8]; packet[0] = (byte)(8 / 4); packet[1] = (byte)TypePack.ISP_OCO; packet[2] = 0; packet[3] = 0; packet[4] = OCOAction; packet[5] = Index; packet[6] = Identifier; packet[7] = Data; return packet; } /// /// Sent HCP Car Handicap info to LFS /// public byte[] HCP(byte Car,byte H_Mass, byte H_Tres) { byte[] packet = new byte[68]; packet[0] = (byte)(68 / 4); packet[1] = (byte)TypePack.ISP_HCP; packet[2] = 0; packet[3] = 0; packet[4 + (Car * 2)] = H_Mass; packet[5 + (Car * 2)] = H_Tres; return packet; } //4 + (1 1) /// /// Sent AXM (Objects) info to LFS /// public byte[] AXM(byte NumO, byte UCID, byte PMOAction, byte PMOFlags, short[] X, short[] Y, byte[] Z, byte[] Flags, byte[] Index, byte[] Heading) { byte[] packet = new byte[(8 + (NumO * 8))]; packet[0] = (byte)((8 + (NumO * 8)) / 4); packet[1] = (byte)TypePack.ISP_AXM; packet[2] = 0; packet[3] = NumO; packet[4] = UCID; packet[5] = PMOAction; packet[6] = PMOFlags; packet[7] = 0; byte a = 0; for (byte i = 0; i < NumO; i++) { //Convert Short X into 2 bytes packet[8 + (i * 8)] = (byte)(X[a] & 255); packet[9 + (i * 8)] = (byte)(X[a] >> 8); //Shift by 8 bits //Convert Short Y into 2 bytes packet[10 + (i * 8)] = (byte)(Y[a] & 255); packet[11 + (i * 8)] = (byte)(Y[a] >> 8); //Shift by 8 bits packet[12 + (i * 8)] = Z[a]; packet[13 + (i * 8)] = Flags[a]; packet[14 + (i * 8)] = Index[a]; packet[15 + (i * 8)] = Heading[a]; a++; } return packet; } /// /// Sent PLC (Objects) Playerallowed cars info to LFS /// public byte[] PLC(byte UCID, int Cars) { byte[] packet = new byte[12]; packet[0] = (byte)(12 / 4); packet[1] = (byte)TypePack.ISP_PLC; packet[2] = 0; packet[3] = 0; packet[4] = UCID; packet[5] = 0; packet[6] = 0; packet[7] = 0; //CARS packet[8] = (byte)((Cars) & 255); packet[9] = (byte)((Cars) >> 8); packet[10] = (byte)((Cars) >> 16); packet[11] = (byte)((Cars) >> 24); return packet; } /// /// Sent JRR (join Request) info to LFS /// Join Request Reply - send one of these back to LFS in response to a join request /// public byte[] JRR(short X, short Y, byte Zbyte, byte Flags, byte Heading, byte UCID, byte PLID, byte JRRAction) { byte[] packet = new byte[16]; packet[0] = (byte)(16 / 4); packet[1] = (byte)TypePack.ISP_JRR; packet[2] = 0; packet[3] = PLID; packet[4] = UCID; packet[5] = JRRAction; packet[6] = 0; packet[7] = 0; //Convert Short X into 2 bytes packet[8] = (byte)(X & 255); packet[9] = (byte)(X >> 8); //Shift by 8 bits //Convert Short Y into 2 bytes packet[10] = (byte)(Y & 255); packet[11] = (byte)(Y >> 8); //Shift by 8 bits packet[12] = Zbyte; packet[13] = Flags; packet[14] = 0; packet[15] = Heading; return packet; } } /// /// Decoder Convert datatypes /// Version packet decoder /// public class Decoder { static int pakGetByte(byte[] pak, int first) { return (int)pak[first]; } static string pakGetString(byte[] pak, int first, int len) { // return InSim.CodePage.GetString(pak, first, len); return LfsEncoding.Current.GetString(pak, first, len); } static int pakGetWord(byte[] pak, int first) { return (int)System.BitConverter.ToUInt16(pak, first); } static int pakGetShort(byte[] pak, int first) { return (int)System.BitConverter.ToInt16(pak, first); } static long pakGetUnsigned(byte[] pak, int first) { return (long)System.BitConverter.ToUInt32(pak, first); } static int pakGetInt(byte[] pak, int first) { return (int)System.BitConverter.ToInt32(pak, first); } static float pakGetFloat(byte[] pak, int first) { return (float)System.BitConverter.ToSingle(pak, first); } static bool pakGetBoolean(byte[] pak, int first) { return (Boolean)System.BitConverter.ToBoolean(pak, first); } public class TINY { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly string SubT; public TINY(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); SubT = Enum.GetName(typeof(TypeTiny), packet[3]); } } public class SMALL { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly string SubT; public long uval; public SMALL(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); SubT = Enum.GetName(typeof(TypeSmall), packet[3]); uval = pakGetUnsigned(packet, 4); } } public class TTC { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly string SubT; public readonly int UCID; public readonly int B1; public readonly int B2; public readonly int B3; public long uval; public TTC(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); SubT = Enum.GetName(typeof(TypeTTC), packet[3]); UCID = pakGetByte(packet, 4); B1 = pakGetByte(packet, 5); B2 = pakGetByte(packet, 6); B3 = pakGetByte(packet, 7); } } public class VER // 20 Bytes { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly string Version; public readonly string Product; public readonly int InSimVersion; public readonly int Spare; public VER(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); Zero = pakGetByte(packet, 3); Version = pakGetString(packet, 4, 8); Product = pakGetString(packet, 12, 6); InSimVersion = pakGetWord(packet, 18); Spare = pakGetByte(packet, 19); } } public class ISM { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly int Host; public readonly int Spare1; public readonly int Spare2; public readonly int Spare3; public readonly string HName; public ISM(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); Zero = pakGetByte(packet, 3); Host = pakGetByte(packet, 4); Spare1 = pakGetByte(packet, 5); Spare2 = pakGetByte(packet, 6); Spare3 = pakGetByte(packet, 7); HName = pakGetString(packet, 8, 32); } } // Ok for Insim 4 public class DefCompCar { public int node; public int lap; public int PLID; public int Position; public int Infos; public int x; public int y; public int z; public int speed; public int direction; public int heading; public int angvel; } public class MCI { public int numOfPlayers; public DefCompCar[] compCar = new DefCompCar[16]; public MCI(byte[] packet) { numOfPlayers = pakGetByte(packet, 3); int offsetStartPlayer = 4; int lengthPlayer = 28; for (int i = 0; i < System.Math.Min(8, numOfPlayers); i++) { compCar[i] = new DefCompCar(); compCar[i].node = pakGetWord(packet, offsetStartPlayer + i * lengthPlayer + 0); compCar[i].lap = pakGetWord(packet, offsetStartPlayer + i * lengthPlayer + 2); compCar[i].PLID = pakGetByte(packet, offsetStartPlayer + i * lengthPlayer + 4); compCar[i].Position = pakGetByte(packet, offsetStartPlayer + i * lengthPlayer + 5); compCar[i].Infos = pakGetByte(packet, offsetStartPlayer + i * lengthPlayer + 6); compCar[i].x = pakGetInt(packet, offsetStartPlayer + i * lengthPlayer + 8); compCar[i].y = pakGetInt(packet, offsetStartPlayer + i * lengthPlayer + 12); compCar[i].z = pakGetInt(packet, offsetStartPlayer + i * lengthPlayer + 16); compCar[i].speed = pakGetWord(packet, offsetStartPlayer + i * lengthPlayer + 20); compCar[i].direction = pakGetWord(packet, offsetStartPlayer + i * lengthPlayer + 22); compCar[i].heading = pakGetWord(packet, offsetStartPlayer + i * lengthPlayer + 24); compCar[i].angvel = pakGetShort(packet, offsetStartPlayer + i * lengthPlayer + 26); } } } // Ok for Insim 4 public class NLP { public NLP(byte[] packet) { } } // OK For Insim 7 //Admin Command Report ( added @ 16-10-2017) public class ACR // Size 12, 16, 20... 72 depending on Text { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly int UCID; public readonly int Admin; public readonly int Result; public readonly int Sp3; public readonly string Text; public ACR(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); Zero = pakGetByte(packet, 3); UCID = pakGetByte(packet, 4); Admin = pakGetByte(packet, 5); Result = pakGetByte(packet, 6); Sp3 = pakGetByte(packet, 7); Text = pakGetString(packet, 8, 64); } } public class SLC // Player Select a car in garage { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly string Car; public SLC(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); ReqI = pakGetByte(packet, 3); UCID = pakGetByte(packet, 4); Car = pakGetString(packet, 5, 4); } } public class NCI { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly int Language; public readonly int Sp1; public readonly int Sp2; public readonly int Sp3; public readonly long UserID; public readonly long IP; public string IPAddress; public NCI(byte[] packet) //Packetsize 16 Bytes { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); UCID = pakGetByte(packet, 3); Language = pakGetByte(packet, 4); Sp1 = pakGetByte(packet, 4); Sp2 = pakGetByte(packet, 5); Sp3 = pakGetByte(packet, 6); UserID = pakGetUnsigned(packet, 7); IP = pakGetUnsigned(packet, 12); //Convert Decimal number into dotted decimal IPadress byte[] IPPacket = new byte[4]; IPPacket[0] = (byte)((IP) & 255); IPPacket[1] = (byte)((IP) >> 8); IPPacket[2] = (byte)((IP) >> 16); IPPacket[3] = (byte)((IP) >> 24); IPAddress = "" + IPPacket[0] + "." + IPPacket[1] + "." + IPPacket[2] + "." + IPPacket[3]; } } // OK For Insim 7 public class CarContact // 8 bytes : car in a contact with an object { public int PLID; public int Info; // like Info byte in CompCar (CCI_BLUE / CCI_YELLOW / CCI_LAG) public int Sp2; // spare public int Steer; // front wheel steer in degrees (right positive) public int ThrBrk; // high 4 bits : throttle / low 4 bits : brake (0 to 15) public int CluHan; // high 4 bits : clutch / low 4 bits : handbrake (0 to 15) public int GearSp; // high 4 bits : gear (15=R) / low 4 bits : spare public int Speed; // m/s public int Direction; // car's motion if Speed > 0 : 0 = world y direction, 128 = 180 deg public int Heading; // direction of forward axis : 0 = world y direction, 128 = 180 deg public int AccelF; // m/s^2 longitudinal acceleration (forward positive) public int AccelR; // m/s^2 lateral acceleration (right positive) public int X; // position (1 metre = 16) public int Y; // position (1 metre = 16) } // OK For Insim 7 public class CON { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly int SpClose; public readonly int Time; public CarContact PlayerA = new CarContact(); public CarContact PlayerB = new CarContact(); public CON(byte[] packet) // Size 40 bytes { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); Zero = pakGetByte(packet, 3); SpClose = pakGetWord(packet, 4); Time = pakGetWord(packet, 6); //Player A PlayerA.PLID = pakGetByte(packet, 8); //1 Byte // player's unique id PlayerA.Info = pakGetByte(packet, 9); //1 Byte // like Info byte in CompCar (CCI_BLUE / CCI_YELLOW / CCI_LAG) PlayerA.Sp2 = pakGetByte(packet, 10); //1 Byte // spare PlayerA.Steer = pakGetByte(packet, 11); //1 Byte // front wheel steer in degrees (right positive) PlayerA.ThrBrk = pakGetByte(packet, 12); //1 Byte // high 4 bits : throttle / low 4 bits : brake (0 to 15) PlayerA.CluHan = pakGetByte(packet, 13); //1 Byte // high 4 bits : clutch / low 4 bits : handbrake (0 to 15) PlayerA.GearSp = pakGetByte(packet, 14); //1 Byte // high 4 bits : gear (15=R) / low 4 bits : spare PlayerA.Speed = pakGetByte(packet, 15); //1 Byte // m/s PlayerA.Direction = pakGetByte(packet, 16); //1 Byte // car's motion if Speed > 0 : 0 = world y direction, 128 = 180 deg PlayerA.Heading = pakGetByte(packet, 17); //1 Byte // direction of forward axis : 0 = world y direction, 128 = 180 deg PlayerA.AccelF = pakGetByte(packet, 18); //1 Byte // m/s^2 longitudinal acceleration (forward positive) PlayerA.AccelR = pakGetByte(packet, 19); //1 Byte // m/s^2 lateral acceleration (right positive) PlayerA.X = pakGetShort(packet, 20); //2 Byte // position (1 metre = 16) PlayerA.Y = pakGetShort(packet, 22); //2 Byte // position (1 metre = 16) //Player B PlayerB.PLID = pakGetByte(packet, 24); //1 Byte PlayerB.Info = pakGetByte(packet, 25); //1 Byte // like Info byte in CompCar (CCI_BLUE / CCI_YELLOW / CCI_LAG) PlayerB.Sp2 = pakGetByte(packet, 26); //1 Byte // spare PlayerB.Steer = pakGetByte(packet, 27); //1 Byte // front wheel steer in degrees (right positive) PlayerB.ThrBrk = pakGetByte(packet, 28); //1 Byte // high 4 bits : throttle / low 4 bits : brake (0 to 15) PlayerB.CluHan = pakGetByte(packet, 29); //1 Byte // high 4 bits : clutch / low 4 bits : handbrake (0 to 15) PlayerB.GearSp = pakGetByte(packet, 30); //1 Byte // high 4 bits : gear (15=R) / low 4 bits : spare PlayerB.Speed = pakGetByte(packet, 31); //1 Byte // m/s PlayerB.Direction = pakGetByte(packet, 32); //1 Byte // car's motion if Speed > 0 : 0 = world y direction, 128 = 180 deg PlayerB.Heading = pakGetByte(packet, 33); //1 Byte // direction of forward axis : 0 = world y direction, 128 = 180 deg PlayerB.AccelF = pakGetByte(packet, 34); //1 Byte // m/s^2 longitudinal acceleration (forward positive) PlayerB.AccelR = pakGetByte(packet, 35); //1 Byte // m/s^2 lateral acceleration (right positive) PlayerB.X = pakGetShort(packet, 36); //2 Bytes // position (1 metre = 16) PlayerB.Y = pakGetShort(packet, 38); //2 Bytes // position (1 metre = 16) } } public class ObjectInfo // Info about a single object - explained in the layout file format { public int X; public int Y; public int Z; public int Flags; public int Index; public int Heading; } public class CarContOBJ // 8 bytes : car in a contact with an object { public int Direction; public int Heading; public int Speed; public int PlayerPosZ; public int PlayerPosX; public int PlayerPosY; } public class OBH // 24 Byte size Object Collision between Car > Object { public CarContOBJ CarCont = new CarContOBJ(); public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int SpClose; public readonly int ObjectHitTime; public readonly int ObjectPosX; public readonly int ObjectPosY; public readonly int ObjectPosZ; public readonly int Sp1; public readonly int Index; public readonly int OBHFlags; public OBH(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); PLID = pakGetByte(packet, 3); SpClose = pakGetWord(packet, 4); ObjectHitTime = pakGetWord(packet, 6); CarCont.Direction = pakGetByte(packet, 8); CarCont.Heading = pakGetByte(packet, 9); CarCont.Speed = pakGetByte(packet, 10); CarCont.PlayerPosZ = pakGetByte(packet, 11); CarCont.PlayerPosX = pakGetShort(packet, 12); CarCont.PlayerPosY = pakGetShort(packet, 14); ObjectPosX = pakGetShort(packet, 16); ObjectPosY = pakGetShort(packet, 18); ObjectPosZ = pakGetByte(packet, 20); Sp1 = pakGetByte(packet, 21); Index = pakGetByte(packet, 22); OBHFlags = pakGetByte(packet, 23); } } // OK For Insim 7 public class HLV // Size 16 Bytes: Hot Lap Validity - off track / hit wall / speeding in pits / out of bounds { public CarContOBJ CarCont = new CarContOBJ(); public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int HVLC; public readonly int Spare01; public readonly int Time; public HLV(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); PLID = pakGetByte(packet, 3); HVLC = pakGetByte(packet, 4); Spare01 = pakGetWord(packet, 5); Time = pakGetWord(packet, 6); CarCont.Direction = pakGetByte(packet, 8); CarCont.Heading = pakGetByte(packet, 9); CarCont.Speed = pakGetByte(packet, 10); CarCont.PlayerPosZ = pakGetByte(packet, 11); CarCont.PlayerPosX = pakGetShort(packet, 12); CarCont.PlayerPosY = pakGetShort(packet, 14); } } // OK For Insim 7 public class UCO // Size 28 Bytes: report InSim checkpoint / InSim circle { public CarContOBJ C = new CarContOBJ(); public ObjectInfo OBJInfo = new ObjectInfo(); public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int Sp0; public readonly int UCOAction; public readonly int Sp2; public readonly int Sp3; public readonly int Time; public UCO(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); PLID = pakGetByte(packet, 3); Sp0 = pakGetByte(packet, 4); UCOAction = pakGetByte(packet, 5); Sp2 = pakGetByte(packet, 6); Sp3 = pakGetByte(packet, 7); Time = pakGetInt(packet, 8); C.Direction = pakGetByte(packet, 12); C.Heading = pakGetByte(packet, 13); C.Speed = pakGetByte(packet, 14); C.PlayerPosZ = pakGetByte(packet, 15); C.PlayerPosX = pakGetShort(packet, 16); C.PlayerPosY = pakGetShort(packet, 18); OBJInfo.X = pakGetShort(packet, 20); OBJInfo.Y = pakGetShort(packet, 22); OBJInfo.Z = pakGetByte(packet, 24); OBJInfo.Flags = pakGetByte(packet, 25); OBJInfo.Index = pakGetByte(packet, 26); OBJInfo.Heading = pakGetByte(packet, 27); } } // OK For Insim 7 public class AXM // Size 16 Bytes: Info about objects { public ObjectInfo[] OBJInfo = new ObjectInfo[30]; public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int NumO; public readonly int UCID; public readonly int PMOAction; public readonly int PMOFlags; public readonly int Sp3; public AXM(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); NumO = pakGetByte(packet, 3); UCID = pakGetByte(packet, 4); PMOAction = pakGetByte(packet, 5); PMOFlags = pakGetByte(packet, 6); Sp3 = pakGetByte(packet, 7); for (byte i = 0; i < NumO; i++) { OBJInfo[i] = new ObjectInfo(); OBJInfo[i].X = pakGetShort(packet, 8 + (i * 8)); OBJInfo[i].Y = pakGetShort(packet, 10 + (i * 8)); OBJInfo[i].Z = pakGetByte(packet, 12 + (i * 8)); OBJInfo[i].Flags = pakGetByte(packet, 13 + (i * 8)); OBJInfo[i].Index = pakGetByte(packet, 14 + (i * 8)); OBJInfo[i].Heading = pakGetByte(packet, 15 + (i * 8)); } } } public class CSC // Cars State Changed { public CarContOBJ CarCont = new CarContOBJ(); public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public int PLID; public int Sp0; public int CSCAction; public int Sp2; public int Sp3; public int Time; public CSC(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); PLID = pakGetByte(packet, 3); Sp0 = pakGetByte(packet, 4); CSCAction = pakGetByte(packet, 5); Sp2 = pakGetByte(packet, 6); Sp3 = pakGetByte(packet, 7); Time = pakGetInt(packet, 8); CarCont.Direction = pakGetByte(packet, 12); CarCont.Heading = pakGetByte(packet, 13); CarCont.Speed = pakGetByte(packet, 14); CarCont.PlayerPosZ = pakGetByte(packet, 15); CarCont.PlayerPosX = pakGetShort(packet, 16); CarCont.PlayerPosY = pakGetShort(packet, 18); } } public class AXI //40 bytes// AutoX Info { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly int AXStart; public readonly int NumCP; public readonly int NumO; public string LayoutName; public AXI(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); Zero = pakGetByte(packet, 3); AXStart = pakGetByte(packet, 4); NumCP = pakGetByte(packet, 5); NumO = pakGetWord(packet, 6); LayoutName = pakGetString(packet, 8, 32); } } /// /// State pack decoder /// LFS will send a StatePack any time the info in the StatePack changes. /// // OK For Insim 4 public class STA { /// /// Short Track Name. /// /// public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly float ReplaySpeed = 0; public readonly int Flags = 0; public readonly int InGameCam = 0; public readonly int ViewPlayer = 0; public readonly int NumP = 0; public readonly int NumConns = 0; public readonly int NumFinished = 0; public readonly int RaceInProg = 0; public readonly int QualMins = 0; public readonly int RaceLaps = 0; public string ShortTrackName = "NOT SET"; public readonly int Weather = 0; public readonly int Wind = 0; public STA() { } public STA(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); Zero = pakGetByte(packet, 3); ReplaySpeed = pakGetFloat(packet, 4); Flags = pakGetWord(packet, 8); InGameCam = pakGetByte(packet, 10); ViewPlayer = pakGetByte(packet, 11); NumP = pakGetByte(packet, 12); NumConns = pakGetByte(packet, 13); NumFinished = pakGetByte(packet, 14); RaceInProg = pakGetByte(packet, 15); QualMins = pakGetByte(packet, 16); RaceLaps = pakGetByte(packet, 17); ShortTrackName = pakGetString(packet, 20, 6); Weather = pakGetByte(packet, 26); Wind = pakGetByte(packet, 27); } } public class REO { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int NumP; public byte[] PLID = new byte[32]; public REO(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); NumP = pakGetByte(packet, 3); Array.ConstrainedCopy(packet, 4, PLID, 0, 32); } } public class RES { /// /// Short Track Name. /// public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly string userName; public readonly string nickName; public readonly string Plate; public readonly string CName; public readonly long TTime; public readonly long BTime; public readonly int NumStops; public readonly int Confirm; public readonly int LapDone; public readonly int Flags; public readonly int ResultNum; public readonly int NumRes; public RES(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); PLID = pakGetByte(packet, 3); userName = pakGetString(packet, 4, 24); nickName = pakGetString(packet, 28, 24); Plate = pakGetString(packet, 52, 8); CName = pakGetString(packet, 60, 4); TTime = pakGetUnsigned(packet, 64); BTime = pakGetUnsigned(packet, 68); NumStops = pakGetByte(packet, 73); Confirm = pakGetByte(packet, 74); LapDone = pakGetWord(packet, 76); Flags = pakGetWord(packet, 78); ResultNum = pakGetByte(packet, 80); NumRes = pakGetByte(packet, 81); } } public class FIN { /// /// Short Track Name. /// public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly long TTime; public readonly long BTime; public readonly int NumStops; public readonly int Confirm; public readonly int LapDone; public readonly int Flags; public FIN(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); PLID = pakGetByte(packet, 3); TTime = pakGetUnsigned(packet, 4); BTime = pakGetUnsigned(packet, 8); NumStops = pakGetByte(packet, 13); Confirm = pakGetByte(packet, 14); LapDone = pakGetWord(packet, 16); Flags = pakGetWord(packet, 18); } } public enum fact { 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, } public class PLA { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int NumP; public int PLID; public fact fact; public PLA(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); fact = (fact)pakGetByte(pak, 4); } } public class MSO { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly int PLID; public readonly int UserType; public readonly int TextStart; public readonly string message; public readonly string completeMessage; public MSO(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); UCID = pakGetByte(packet, 4); PLID = pakGetByte(packet, 5); UserType = pakGetByte(packet, 6); TextStart = pakGetByte(packet, 7); message = pakGetString(packet, 8 + TextStart, 128 - TextStart); completeMessage = pakGetString(packet, 8, 128); } } public class NPL { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int UCID; public readonly int PType; public readonly int Flags; public readonly string nickName; public readonly string Plate; public readonly string CName; public readonly string SName; public readonly tyre TyreRearLeft; public readonly tyre TyreRearRight; public readonly tyre TyreFrontLeft; public readonly tyre TyreFrontRight; public readonly int H_Mass; public readonly int H_TRes; public readonly int Pass; public readonly int RWAdj; // low 4 bits: tyre width reduction (rear) public readonly int FWAdj; // low 4 bits: tyre width reduction (front) public readonly int sp2; public readonly int sp3; public readonly int SetF; public readonly int NumP; public readonly int CarConfig; public readonly int Fuel; // public readonly PlayerFlags flags; public enum PlayerFlags : ushort { SwapSide = 1, // If Swapside -> pilote à gauche Reserved_2 = 2, Reserved_4 = 4, AutoGears = 8, Shifter = 16, Reserved_32 = 32, HelpBrake = 64, AxisClutch = 128, InPits = 256, AutoClutch = 512, Mouse = 1024, KbNoHelp = 2048, KbStabilised = 4096, CustomView = 8192 } public NPL(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); UCID = pakGetByte(pak, 4); PType = pakGetByte(pak, 5); Flags = pakGetWord(pak, 6); nickName = pakGetString(pak, 8, 24); Plate = pakGetString(pak, 32, 8); CName = pakGetString(pak, 40, 4); SName = pakGetString(pak, 44, 16); TyreRearLeft = (tyre)pakGetByte(pak, 60); TyreRearRight = (tyre)pakGetByte(pak, 61); TyreFrontLeft = (tyre)pakGetByte(pak, 62); TyreFrontRight = (tyre)pakGetByte(pak, 63); H_Mass = pakGetByte(pak, 64); H_TRes = pakGetByte(pak, 65); Pass = pakGetByte(pak, 67); RWAdj = pakGetByte(pak, 68); FWAdj = pakGetByte(pak, 69); SetF = pakGetByte(pak, 72); NumP = pakGetByte(pak, 73); CarConfig = pakGetByte(pak, 74); Fuel = pakGetByte(pak, 75); } } // Ok For insim 4 public class PIT { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int LapsDone; public readonly int Flags; public readonly int FuelAdd; public readonly int Penalty; public readonly int NumStop; public readonly tyre TyreRearLeft; public readonly tyre TyreRearRight; public readonly tyre TyreFrontLeft; public readonly tyre TyreFrontRight; public readonly long Work; public readonly string sWork; public PIT(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); LapsDone = pakGetWord(pak, 4); Flags = pakGetWord(pak, 6); FuelAdd = pakGetByte(pak, 8); Penalty = pakGetByte(pak, 9); NumStop = pakGetByte(pak, 10); TyreRearLeft = (tyre)pakGetByte(pak, 12); TyreRearRight = (tyre)pakGetByte(pak, 13); TyreFrontLeft = (tyre)pakGetByte(pak, 14); TyreFrontRight = (tyre)pakGetByte(pak, 15); Work = pakGetUnsigned(pak, 16); sWork = ""; string virg = ""; if ( (Work & (long)PIT_work.PSE_FR_DAM) != 0 || (Work & (long)PIT_work.PSE_RE_DAM) != 0 || (Work & (long)PIT_work.PSE_LE_FR_DAM) != 0 || (Work & (long)PIT_work.PSE_RI_FR_DAM) != 0 || (Work & (long)PIT_work.PSE_LE_RE_DAM) != 0 || (Work & (long)PIT_work.PSE_RI_RE_DAM) != 0 ) { sWork = sWork + virg + "Mechanical Damage"; virg = ", "; } if ((Work & (long)PIT_work.PSE_BODY_MINOR) != 0) { sWork = sWork + virg + "Minor Damage"; virg = ", "; } if ((Work & (long)PIT_work.PSE_BODY_MAJOR) != 0) { sWork = sWork + virg + "Major Damage"; virg = ", "; } if ((Work & (long)PIT_work.PSE_REFUEL) != 0) { sWork = sWork + virg + "Refuelling"; virg = ", "; } if ((Work & (long)PIT_work.PSE_SETUP) != 0) { sWork = sWork + virg + "Setup"; virg = ", "; } if ( (Work & (long)PIT_work.PSE_FR_WHL) != 0 || (Work & (long)PIT_work.PSE_LE_FR_WHL) != 0 || (Work & (long)PIT_work.PSE_RI_FR_WHL) != 0 || (Work & (long)PIT_work.PSE_RE_WHL) != 0 || (Work & (long)PIT_work.PSE_LE_RE_WHL) != 0 || (Work & (long)PIT_work.PSE_RI_RE_WHL) != 0 ) { sWork = sWork + virg + "Wheels"; virg = ", "; } } } // Ok For insim 4 public class PSF { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly long STime; public PSF(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); STime = pakGetUnsigned(pak, 4); } } // LAP OK for insim 8 public class LAP { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly long LTime; public readonly long ETime; public readonly int LapsDone; public readonly int Flags; public readonly int Penalty; public readonly int NumStop; public readonly int Fuel200; public LAP(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); LTime = pakGetUnsigned(pak, 4); ETime = pakGetUnsigned(pak, 8); LapsDone = pakGetWord(pak, 12); Flags = pakGetWord(pak, 14); Penalty = pakGetByte(pak, 17); NumStop = pakGetByte(pak, 18); Fuel200 = pakGetByte(pak, 19); } } /// /// Split X time decoder /// // LAP OK for insim 8 public class SPX { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly long STime; public readonly long ETime; public readonly int Split; public readonly int Penalty; public readonly int NumStop; public readonly int Fuel200; public SPX(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); STime = pakGetUnsigned(pak, 4); ETime = pakGetUnsigned(pak, 8); Split = pakGetByte(pak, 12); Penalty = pakGetByte(pak, 13); NumStop = pakGetByte(pak, 14); Fuel200 = pakGetByte(pak, 15); } } // Race Restart Ok for Insim 7 public class RST { /// /// Gets time for qualifications in minutes. If zero, race started. /// public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly int RaceLaps; public readonly int QualMins; public readonly int NumP; public readonly int Timing; public readonly string Track; public readonly int Weather; public readonly int Wind; public readonly int Flags; public readonly int NumNodes; public readonly int Finish; public readonly int Split1; public readonly int Split2; public readonly int Split3; public RST(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); Zero = pakGetByte(pak, 3); RaceLaps = pakGetByte(pak, 4); QualMins = pakGetByte(pak, 5); NumP = pakGetByte(pak, 6); Timing = pakGetByte(pak, 7); Track = pakGetString(pak, 8, 6); Weather = pakGetByte(pak, 14); Wind = pakGetByte(pak, 15); Flags = pakGetWord(pak, 16); NumNodes = pakGetWord(pak, 18); Finish = pakGetWord(pak, 20); Split1 = pakGetWord(pak, 22); Split2 = pakGetWord(pak, 24); Split3 = pakGetWord(pak, 26); } } // Ok for Insim 7 public class NCN { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly string userName; public readonly string nickName; public readonly int Admin; public readonly int Total; public readonly int Flags; public NCN(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); UCID = pakGetByte(pak, 3); userName = pakGetString(pak, 4, 24); nickName = pakGetString(pak, 28, 24); Admin = pakGetByte(pak, 52); Total = pakGetByte(pak, 53); Flags = pakGetByte(pak, 54); } } // Ok For insim 4 public class CNL { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly int Reason; public readonly int Total; public CNL(byte[] pak) { PacketSize = pakGetByte(pak, 0); Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); UCID = pakGetByte(pak, 3); Reason = pakGetByte(pak, 4); Total = pakGetByte(pak, 5); } } // Ok For insim 4 public class CPR { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly string newNickName; public readonly string Plate; public CPR(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); UCID = pakGetByte(pak, 3); newNickName = pakGetString(pak, 4, 24); Plate = pakGetString(pak, 28, 8); } } // Ok for Insim 4 /// /// PLayer Pits /// public class PLP { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public PLP(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); } } // Ok for Insim 4 /// /// PLayer Leave race /// public class PLL { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public PLL(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); } } // Ok For insim 4 public class FLG { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int OffOn; public readonly int Flag; public readonly int CarBehind; public FLG(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); OffOn = pakGetByte(pak, 4); Flag = pakGetByte(pak, 5); CarBehind = pakGetByte(pak, 6); } } public class PEN { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int OldPen; public readonly int NewPen; public readonly int Reason; public PEN(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); OldPen = pakGetByte(pak, 4); NewPen = pakGetByte(pak, 5); Reason = pakGetByte(pak, 6); } } public class BFN { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int SubT; public readonly int UCID; public readonly int ClickID; public BFN(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); SubT = pakGetByte(pak, 3); UCID = pakGetByte(pak, 4); ClickID = pakGetByte(pak, 5); } } public class BTC { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly int ClickID; public readonly int CFlags; public BTC(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); UCID = pakGetByte(pak, 3); ClickID = pakGetByte(pak, 4); CFlags = pakGetByte(pak, 6); } } public class BTT { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly int ClickID; public readonly int TypIn; public string Text; public BTT(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); UCID = pakGetByte(pak, 3); ClickID = pakGetByte(pak, 4); TypIn = pakGetByte(pak, 6); Text = pakGetString(pak, 8, 96); } } public class TOC { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int OldUCID; public readonly int NewUCID; public TOC(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); OldUCID = pakGetByte(pak, 4); NewUCID = pakGetByte(pak, 5); } } public class VTN { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int Zero; public readonly int UCID; public readonly int Action; public VTN(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); Zero = pakGetByte(pak, 3); UCID = pakGetByte(pak, 4); Action = pakGetByte(pak, 5); } } public class PFL { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public readonly int Flags; public PFL(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); Flags = pakGetWord(pak, 4); } } public class CRS { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int PLID; public CRS(byte[] pak) { PacketSize = pakGetByte(pak, 0) * 4; Type = pakGetByte(pak, 1); ReqI = pakGetByte(pak, 2); PLID = pakGetByte(pak, 3); } } // OK For Insim 7 //Admin Command Report ( added @ 16-10-2017) public class CIM // Size 8 Bytes { public readonly int PacketSize; public readonly int Type; public readonly int ReqI; public readonly int UCID; public readonly int Mode; public readonly int SubMode; public readonly int SelType; public readonly int Sp3; public CIM(byte[] packet) { PacketSize = pakGetByte(packet, 0) * 4; Type = pakGetByte(packet, 1); ReqI = pakGetByte(packet, 2); UCID = pakGetByte(packet, 3); Mode = pakGetByte(packet, 4); SubMode = pakGetByte(packet, 5); SelType = pakGetByte(packet, 6); Sp3 = pakGetByte(packet, 7); } } } }