//  
//  managePacket.cs
//  
//  Author:
//       Robert BRACCAGNI alias Gai-Luron <lfsgailuron@free.fr>
// 
//  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 <http://www.gnu.org/licenses/>.


namespace LFSLapper
{
    using System;
    using UTILS;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Collections;
    using Configurator;
    using LapperThreads;

    partial class LFSClient
    {
        System.Collections.ArrayList PLIDChangePos = new System.Collections.ArrayList();
        bool flagFirstInState = true;
        bool ExecuteEvent = false; //Object Hit Execute event
        int MCIPlayerFlagCounterTwo = 0;
        int RST_packet_From_NPL = 0;
        string PlayerOfObject = "";


        private string Objects(int ObjectIndex)
        {
            string[] Object = new string[256]; //195 object positions in LFS (lyt format)
            Object[0] = "Trackside Object"; //TrackSide Object (Movable objects that belong to the track)
            Object[1] = "";
            Object[2] = "";
            Object[3] = "";
            Object[4] = "Long Chalk Line"; Object[5] = "Short Chalk Line"; //Chalk Lines
            Object[6] = "Short Ahead Arrow"; Object[7] = "Long Ahead Arrow"; // Ahead Arrows
            Object[8] = "Short Left Curve Arrow"; Object[9] = "Left Turn Arrow"; Object[10] = "Long Left Curve Arrow"; // Left Arrows
            Object[11] = "Short Right Curve Arrow"; Object[12] = "Right Turn Arrow"; Object[13] = "Long Right Curve Arrow"; // Right Arrows
            Object[14] = "";
            Object[15] = "";
            Object[16] = "";
            Object[17] = "";
            Object[18] = "";
            Object[19] = "";
            Object[20] = "Red/White Cone"; Object[21] = "Red Cone"; Object[22] = "Striped Cone"; // Types of Red Cones
            Object[23] = "Striped Blue Cone"; Object[24] = "Blue Cone"; // Types of Blue Cones 
            Object[25] = "Striped Green Cone"; Object[26] = "Green Cone"; // Types of Green Cones
            Object[27] = "Orange Cone"; Object[28] = "White Cone"; // Types of White Cones
            Object[29] = "Striped Yellow Cone"; Object[30] = "Yellow Cone"; // Types of Yellow Cones
            Object[31] = "";
            Object[32] = "";
            Object[33] = "";
            Object[34] = "";
            Object[35] = "";
            Object[36] = "";
            Object[37] = "";
            Object[38] = "";
            Object[39] = "";
            Object[40] = "Red Cone Pointer"; Object[41] = "Blue Cone Pointer"; Object[42] = "Green Cone Pointer"; Object[43] = "Yellow Cone Pointer"; //Pointer Cones
            Object[44] = "";
            Object[45] = "";
            Object[46] = "";
            Object[47] = "";
            Object[48] = "Small Single Tyre"; Object[49] = "Small 2 Stack Tyre"; Object[50] = "Small 3 Stack Tyre"; Object[51] = "Small 4 Stack Tyre"; // Small Tirestacks
            Object[52] = "Big Single Tyre"; Object[53] = "Big 2 Stack Tyre"; Object[54] = "Big 3 Stack Tyre"; Object[55] = "Big 4 Stack Tyre"; //Big Tirestacks
            Object[56] = "";
            Object[57] = "";
            Object[58] = "";
            Object[59] = "";
            Object[60] = "";
            Object[61] = "";
            Object[62] = "";
            Object[63] = "";
            Object[64] = "Left Curve Marker"; Object[65] = "Right Curve Marker";
            Object[66] = "Left Turn Marker"; Object[67] = "Right Turn Marker";
            Object[68] = "Hard Left Turn Marker"; Object[69] = "Hard Right Turn Marker";
            Object[70] = "Left-Right Turn Marker"; Object[71] = "Right-Left Turn Marker";
            Object[72] = "U-Turn >> Right Turn Marker"; Object[73] = "U-Turn >> Left Turn Marker";
            Object[74] = "Left Winding Turn Marker"; Object[75] = "Right Winding Turn Marker";
            Object[76] = "Left U-Turn Marker"; Object[77] = "Right U-Turn Marker";
            Object[78] = "";
            Object[79] = "";
            Object[80] = "";
            Object[81] = "";
            Object[82] = "";
            Object[83] = "";
            Object[84] = "25m Sign"; Object[85] = "50m Sign";
            Object[86] = "75m Sign"; Object[87] = "100m Sign"; Object[88] = "125m Sign";
            Object[89] = "150m Sign"; Object[90] = "200m Sign"; Object[91] = "250m Sign";
            Object[92] = "";
            Object[93] = "";
            Object[94] = "";
            Object[95] = "";
            Object[96] = "Short Armco"; Object[97] = "Medium Armco"; Object[98] = "Long Armco"; // Not moveable Armco
            Object[99] = "";
            Object[100] = "";
            Object[101] = "";
            Object[102] = "";
            Object[103] = "";
            Object[104] = "Long Barrier"; Object[105] = "Short Barrier Red"; Object[106] = "Short Barrier White"; //Barriers
            Object[107] = "";
            Object[108] = "";
            Object[109] = "";
            Object[110] = "";
            Object[111] = "";
            Object[112] = "Banner"; Object[113] = "Banner"; // 2 Banners
            Object[114] = "";
            Object[115] = "";
            Object[116] = "";
            Object[117] = "";
            Object[118] = "";
            Object[119] = "";
            Object[120] = "Small Ramp"; Object[121] = "Big Ramp";// Ramps
            Object[122] = "";
            Object[123] = "";
            Object[124] = "";
            Object[125] = "";
            Object[126] = "";
            Object[127] = "";
            Object[128] = "Speed Hump"; Object[129] = "Speed Hump"; // Speedhumbs
            Object[130] = "";
            Object[131] = "";
            Object[132] = "";
            Object[133] = "";
            Object[134] = "";
            Object[135] = "";
            Object[136] = "Green Post"; Object[137] = "Orange Post"; Object[138] = "Red Post"; Object[139] = "White Post"; // Post Objects
            Object[140] = "";
            Object[141] = "";
            Object[142] = "";
            Object[143] = "";
            Object[144] = "Bale";
            Object[145] = "";
            Object[146] = "";
            Object[147] = "";
            Object[148] = "Railing";
            Object[149] = "StartLight";
            Object[150] = "";
            Object[151] = "";
            Object[152] = "";
            Object[153] = "";
            Object[154] = "";
            Object[155] = "";
            Object[156] = "";
            Object[157] = "";
            Object[158] = "";
            Object[159] = "";
            Object[160] = "Keep Left Sign"; Object[161] = "Keep Right Sign"; //Keep side Signs
            Object[162] = "";
            Object[163] = "";
            Object[164] = "";
            Object[165] = "";
            Object[166] = "";
            Object[167] = "";
            Object[168] = "80 km/h Sign"; Object[169] = "50 km/h Sign"; //Speed Signs
            Object[170] = "";
            Object[171] = "";
            Object[172] = "Concrete Slab"; Object[173] = "Concrete Ramp"; Object[174] = "Concrete Wall"; Object[175] = "Concrete Pillar";
            Object[176] = "Concrete Slab Wall"; Object[177] = "Concrete Ramp Wall";
            Object[178] = "Concrete Short Slab Wall";
            Object[179] = "Concrete Wedge";
            Object[180] = "";
            Object[181] = "";
            Object[182] = "";
            Object[183] = "";
            Object[184] = "Start Position";
            Object[185] = "Pit Start Point"; Object[186] = "Pit Stop Box"; // Pit Objects
            Object[187] = "";
            Object[188] = "";
            Object[189] = "";
            Object[190] = "";
            Object[191] = "";
            Object[192] = "";
            Object[252] = "Checkpoint";
            Object[253] = "Checker";
            Object[254] = "Restricted area";
            Object[255] = "Route Checker";
            return Object[ObjectIndex];
        }//List with objects

        void managePacket(InSim.Decoder.TINY tiny)
        {
            // Keep alive connection
            //            Console.WriteLine(tiny.SubT);
            switch (tiny.SubT)
            {
                case "TINY_NONE":
                    byte[] stiny = myEncoder.TINY_NONE();
                    insimConnection.Send(stiny, stiny.Length);
                    break;
                case "TINY_CLR": // "CLear Race - all players removed from race in one go"
                    if (newCfg.varsLapper.AutoRestartRaceSec > 0)
                    {
                        currRace.nextRestart = DateTime.Now.AddSeconds((double)newCfg.varsLapper.AutoRestartRaceSec);
                        currRace.autoRestartOn = true;
                    }
                    break;
                case "TINY_REN": // "Race ENd - return to game setup screen"
                    newCfg.executeFunction("OnRaceEnd", null, null);
                    break;
            }
        }
        void managePacket(InSim.Decoder.NCN newConnection)
        {
            infoPlayer currInfoPlayer;

            listOfPlayers.newPlayer(objPubStatUser, newCfg, newConnection.UCID, newConnection.userName, newConnection.nickName, newConnection.Flags, insimConnection.Product);
            currInfoPlayer = listOfPlayers.getPlayerByUCID(newConnection.UCID);
            createPlayerSetOfVars(currInfoPlayer); // Creation of player set of Vars

            byte[] nci = myEncoder.NCI();
            insimConnection.Send(nci, nci.Length);

            if (currInfoPlayer == null)
                return;
            cfu.retreive(currInfoPlayer);
            if (currInfoPlayer.CName == "")
            {
                string[] ar_CNAME = newCfg.varsLapper.DefaultTopCar.Split('+');
                if (ar_CNAME.Length != 0)
                    currInfoPlayer.CName = ar_CNAME[0].Trim();
                else
                    currInfoPlayer.CName = "XFG";
            }

            gripSqlDbs.retreiveRow(currInfoPlayer, currState.ShortTrackName);
            driftSqlDbs.retreiveRow(currInfoPlayer, currState.ShortTrackName);

            string testExclude = "," + newCfg.varsLapper.IdleExclude.ToLower() + ",";
            if (testExclude.IndexOf("," + currInfoPlayer.userName.ToLower() + ",") != -1)
                currInfoPlayer.allowIdleOnTrack = true;
            else
                currInfoPlayer.allowIdleOnTrack = false;
            // Set the admin flag if the player is a server  admin
            if (newConnection.Admin == 1)
            {
                currInfoPlayer.isServerAdmin = true;
                uGroup.addUser("superUsers", currInfoPlayer.userName);
            }
            byte[] alc = myEncoder.ALC();
            insimConnection.Send(alc, alc.Length);
            string[] args = new string[1];
            args[0] = currInfoPlayer.userName;
            newCfg.executeFunction("OnConnect", currInfoPlayer, args);

        }
        void managePacket(InSim.Decoder.CNL lostConnection)
        {
            infoPlayer currInfoPlayer;

            currInfoPlayer = listOfPlayers.getPlayerByUCID(lostConnection.UCID);
            if (currInfoPlayer == null)
                return;
            if (currInfoPlayer.isConfigPlayerChanged) // On disconnect of player, save config file
                cfu.update(currInfoPlayer);
            string[] args = new string[2];
            args[0] = currInfoPlayer.userName;
            args[1] = lostConnection.Reason.ToString();
            newCfg.executeFunction("OnDisConnect", null, args);
            listOfPlayers.removePlayer(newCfg, lostConnection.UCID);
        }

        void managePacket(InSim.Decoder.NPL newPlayer)
        {
            ////////////////// DisableAI using join request //////////////////
            if (newPlayer.NumP == 0)                            // If this is a join request 
            {
                if (newCfg.varsLapper.DisableAI == 1)           // If DisableAI is enabled
                {
                    if ((newPlayer.PType & 2) == 2)             // If this is an AI
                    {
                        // Reject AI's join request
                        // JRR( X, Y, Zbyte, Flags, Heading, UCID, PLID, JRRAction)
                        byte[] jrr = myEncoder.JRR(0, 0, 0, 0, 0, (byte)newPlayer.UCID, 0, 0);
                        insimConnection.Send(jrr, jrr.Length);
                        return;     // we are done here, no need to continue
                    }
                    else if (newCfg.varsLapper.ReceiveJoinRequest == -1)      // If not an AI then allow the join request (to avoid LFS keep waiting for the response), but only if OnNewJoinRequest event is disabled!!!
                    {
                        // Allow Player's join request
                        // JRR( X, Y, Zbyte, Flags, Heading, UCID, PLID, JRRAction)
                        byte[] jrr = myEncoder.JRR(0, 0, 0, 0, 0, (byte)newPlayer.UCID, 0, 1);
                        insimConnection.Send(jrr, jrr.Length);
                    }
                }
                else if ((newPlayer.PType & 2) == 2)        // else if this is a join request for AI but DisableAI is disabled, allow AI's join request (to avoid LFS keep waiting for the response)
                {
                    // Allow AI's join request
                    // JRR( X, Y, Zbyte, Flags, Heading, UCID, PLID, JRRAction)
                    byte[] jrr = myEncoder.JRR(0, 0, 0, 0, 0, (byte)newPlayer.UCID, 0, 1);
                    insimConnection.Send(jrr, jrr.Length);
                }
            }
            // check if DisableAI is enabled and if so, spectate AI cars that are already on track (this is NOT a join request)
            if (newCfg.varsLapper.DisableAI == 1 && (newPlayer.PType & 2) == 2)     // If DisableAI is enabled and if this is actually an AI
            {
                SendMsg("/msg ^3AI drivers are not allowed. ^8" + newPlayer.nickName + "^3 was spectated.");
                SendMsg("/spec " + newPlayer.nickName);
            }
            ///////////////////// End of DisableAI script /////////////////////

            int FL_Changed = 0;
            int FR_Changed = 0;
            int RL_Changed = 0;
            int RR_Changed = 0;

            if ((newPlayer.PType & 2) != 0) // Exclude AI players
                return;

            infoPlayer currInfoPlayer;

            currInfoPlayer = listOfPlayers.getPlayerByUCID(newPlayer.UCID);
            if (currInfoPlayer == null)
                return;
            currInfoPlayer.OnTrack = true;

            currInfoPlayer.LastCrossedFinishLine = System.DateTime.Now;
            currInfoPlayer.MaxLapTime1Reached = false;
            currInfoPlayer.MaxLapTime2Reached = false;
            currInfoPlayer.MaxLapTime = trackInfo.getMaxLapTime(currState.ShortTrackName, newPlayer.CName);
            listOfPlayers.majIndexPLID(newPlayer.UCID, newPlayer.PLID);

            // If player change car, Clear session
            if (currInfoPlayer.CName != newPlayer.CName)
            {
                currInfoPlayer.clearSessionInfo();
                currInfoPlayer.CName = newPlayer.CName;
            }

            currInfoPlayer.SkinName = newPlayer.SName;  //SkinName without Car/Skin ID
            currInfoPlayer.Plate = newPlayer.Plate; // Set the license plate
            currInfoPlayer.CarConfig = newPlayer.CarConfig; // CarConfiguration

            //Display fuel of the current player
            if (newPlayer.Fuel == 255)
                currInfoPlayer.FuelValue = -1;
            else
                currInfoPlayer.FuelValue = newPlayer.Fuel; // Display Fuel

            gripSqlDbs.retreiveRow(currInfoPlayer, currState.ShortTrackName);
            driftSqlDbs.retreiveRow(currInfoPlayer, currState.ShortTrackName);


            #region Handicap User
            // If indication of Handicap of current player
            currInfoPlayer.P_Mass = newPlayer.H_Mass;
            currInfoPlayer.P_TRes = newPlayer.H_TRes;
            int cumH_Mass = 0;
            int cumH_Tres = 0;
            // Handicap priority
            // Player, CarTrack, Car
            // Car handicap

            if (newCfg.varsLapper.RefreshHandicapUsers)
                UpdateHandicapUsers(newCfg.varsLapper.HandicapUsers);

            if (carHandicap.ContainsKey(currInfoPlayer.CName.ToLower()))
            {
                cumH_Mass = (carHandicap[currInfoPlayer.CName.ToLower()] as infoHandicap).H_Mass;
                cumH_Tres = (carHandicap[currInfoPlayer.CName.ToLower()] as infoHandicap).H_TRes;
            }
            // Car/Track handicap
            string carTrack = currInfoPlayer.CName.ToLower() + "/" + currState.ShortTrackName.ToLower();
            if (carTrackHandicap.ContainsKey(carTrack))
            {
                cumH_Mass = (carTrackHandicap[carTrack] as infoHandicap).H_Mass;
                cumH_Tres = (carTrackHandicap[carTrack] as infoHandicap).H_TRes;
            }
            // Player handicap
            if (playerHandicap.ContainsKey(currInfoPlayer.userName.ToLower()))
            {
                cumH_Mass = (playerHandicap[currInfoPlayer.userName.ToLower()] as infoHandicap).H_Mass;
                cumH_Tres = (playerHandicap[currInfoPlayer.userName.ToLower()] as infoHandicap).H_TRes;
            }
            currInfoPlayer.H_Mass = cumH_Mass;
            currInfoPlayer.H_TRes = cumH_Tres;
            if (newPlayer.H_Mass < cumH_Mass || newPlayer.H_TRes < cumH_Tres)
            {
                string[] args = new string[1];
                args[0] = currInfoPlayer.userName;
                newCfg.executeFunction("OnToLowHandicap", currInfoPlayer, args);
            }
            #endregion

            if (currInfoPlayer.oldTyreRearLeft == InSim.tyre.TYRE_NUM)
                currInfoPlayer.oldTyreRearLeft = newPlayer.TyreRearLeft;
            if (currInfoPlayer.oldTyreRearRight == InSim.tyre.TYRE_NUM)
                currInfoPlayer.oldTyreRearRight = newPlayer.TyreRearRight;
            if (currInfoPlayer.oldTyreFrontLeft == InSim.tyre.TYRE_NUM)
                currInfoPlayer.oldTyreFrontLeft = newPlayer.TyreFrontLeft;
            if (currInfoPlayer.oldTyreFrontRight == InSim.tyre.TYRE_NUM)
                currInfoPlayer.oldTyreFrontRight = newPlayer.TyreFrontRight;

            currInfoPlayer.tyreRearLeft = newPlayer.TyreRearLeft;
            currInfoPlayer.tyreRearRight = newPlayer.TyreRearRight;
            currInfoPlayer.tyreFrontLeft = newPlayer.TyreFrontLeft;
            currInfoPlayer.tyreFrontRight = newPlayer.TyreFrontRight;
            currInfoPlayer.RearWheelsAdj = newPlayer.RWAdj;
            currInfoPlayer.FrontWheelsAdj = newPlayer.FWAdj;

            if (currInfoPlayer.oldTyreRearLeft != currInfoPlayer.tyreRearLeft)
                RL_Changed = 1;
            if (currInfoPlayer.oldTyreRearRight != currInfoPlayer.tyreRearRight)
                RR_Changed = 1;
            if (currInfoPlayer.oldTyreFrontLeft != currInfoPlayer.tyreFrontLeft)
                FL_Changed = 1;
            if (currInfoPlayer.oldTyreFrontRight != currInfoPlayer.tyreFrontRight)
                FR_Changed = 1;

            if (FL_Changed != 0 || FR_Changed != 0 || RL_Changed != 0 || RR_Changed != 0)
            {
                string[] args = new string[5];
                args[0] = currInfoPlayer.userName;
                args[1] = FL_Changed.ToString();
                args[2] = FR_Changed.ToString();
                args[3] = RL_Changed.ToString();
                args[4] = RR_Changed.ToString();
                newCfg.executeFunction("OnChangeTyres", currInfoPlayer, args);
            }


            #region Authorization for this player to join race
            // Player Authorisation

            if (listOfPlayers.countPlayer() > newCfg.varsLapper.AuthMinPlayer)
            {
                if (isAllowedPlayer(currInfoPlayer))
                {
                    if (SystemAuth.AllowAllPlayer == false)
                    {
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnAuthAllowed", currInfoPlayer, args);
                    }
                }
                else
                {
                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction("OnAuthNotAllowed", currInfoPlayer, args);
                }
            }
            #endregion

            #region flags for this player
            //actionPlayerFlags(newPlayer.Flags, currInfoPlayer, true);
            #endregion
            {
                #region Request Packets
                RST_packet_From_NPL = 1;

                //Get AllowedCars from LFS
                byte[] alc = myEncoder.ALC();
                insimConnection.Send(alc, alc.Length);
                //request state packet
                byte[] sst = myEncoder.SST();
                insimConnection.Send(sst, sst.Length);
                //request RaceInfo packet
                byte[] rst = myEncoder.RST();
                insimConnection.Send(rst, rst.Length);
                #endregion

                if (newPlayer.NumP == 0 && newCfg.varsLapper.ReceiveJoinRequest == 1)    // If this is a join request and $ReceiveJoinRequest is enabled - execute OnNewJoinRequest event
                {
                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction("OnNewJoinRequest", currInfoPlayer, args);
                }
                else                        // If not a join request - execute OnNewPlayerJoin event
                {

                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction("OnNewPlayerJoin", currInfoPlayer, args);
                }
            }
        }

        void managePacket(InSim.Decoder.CRS crs)
        {
            // Krayy car reset code
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(crs.PLID);
            if (currInfoPlayer == null)
                return;
            string[] args = new string[1];
            if (currRace.inRace)
            {
                if (newCfg.varsLapper.MaxCarResets > 0) //Keep 0 to execute OnCarReset everytime the player reset their car
                {
                    currInfoPlayer.NumCarResets++;
                    args[0] = currInfoPlayer.userName;
                    if (currInfoPlayer.NumCarResets >= newCfg.varsLapper.MaxCarResets)
                    {
                        newCfg.executeFunction("OnMaxCarResets", currInfoPlayer, args);
                    }
                    else
                    {
                        newCfg.executeFunction("OnCarReset", currInfoPlayer, args);
                    }
                }
                else
                {
                    newCfg.executeFunction("OnCarReset", currInfoPlayer, args);
                }
            }
            else
            {
                //nothing yet
            }
        }
        void managePacket(InSim.Decoder.PLP plp)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(plp.PLID);
            if (currInfoPlayer == null)
                return;
            currInfoPlayer.OnPit = false;
            currInfoPlayer.OnTrack = false;
            currInfoPlayer.idCurrZone = "NONE";
            currInfoPlayer.old_x = 0;
            currInfoPlayer.old_y = 0;
            currInfoPlayer.old_z = 0;
            currInfoPlayer.oldTyreRearLeft = currInfoPlayer.tyreRearLeft;
            currInfoPlayer.oldTyreRearRight = currInfoPlayer.tyreRearRight;
            currInfoPlayer.oldTyreFrontLeft = currInfoPlayer.tyreFrontLeft;
            currInfoPlayer.oldTyreFrontRight = currInfoPlayer.tyreFrontRight;
            currInfoPlayer.currVote = (int)InSim.vtn.VOTE_NONE;

            string[] args = new string[1];
            args[0] = currInfoPlayer.userName;
            newCfg.executeFunction("OnPit", currInfoPlayer, args);

        }
        void managePacket(InSim.Decoder.PLL pll)
        {
            //send request to get LFSCARS
            byte[] alc = myEncoder.ALC();
            insimConnection.Send(alc, alc.Length);

            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(pll.PLID);
            if (currInfoPlayer == null)
                return;

            //Check if Player entered a zone. Same Code as in MCI packet
            
            if(currInfoPlayer.CurrentIDTask != "")
            {
                string cmdZone = listOfZoneEvent.getCommandZoneLeave(currState.ShortTrackName, currInfoPlayer.LastZone, currInfoPlayer.CurrentIDTask);
                if (cmdZone != "")
                {
                    string getidTask = listOfZoneEvent.getCommandIDTask(currState.ShortTrackName, currInfoPlayer.LastZone);
                    if (getidTask == "")
                    {
                        getidTask = "unknown";
                    }
                    currInfoPlayer.CurrentIDTask = "";
                    string[] argss = new string[2];
                    argss[0] = currInfoPlayer.userName;
                    argss[1] = getidTask;
                    newCfg.executeFunction(cmdZone, currInfoPlayer, argss);
                }
            }
            
            currInfoPlayer.OnTrack = false;
            currInfoPlayer.idCurrZone = "NONE";
            currInfoPlayer.CurrentIDTask = "";
            currInfoPlayer.instantSpeed = 0;   //reset speed
            currInfoPlayer.AngVel = 0;         //reset players carangle
            currInfoPlayer.stuntticks = 0;     //reset stuntticks
            currInfoPlayer.x = -1;
            currInfoPlayer.y = -1;
            currInfoPlayer.CurrLap = -1;
            currInfoPlayer.CurrZone = -1;
            currInfoPlayer.LastZone = -1;
            currInfoPlayer.CurrNode = -1;
            currInfoPlayer.LastNode = -1;
            currInfoPlayer.old_x = 0;
            currInfoPlayer.old_y = 0;
            currInfoPlayer.old_z = 0;
            currInfoPlayer.OnPit = false;
            currInfoPlayer.currVote = (int)InSim.vtn.VOTE_NONE;
            currInfoPlayer.showButton = 0;
            //ClearButton(currInfoPlayer);
            string[] args = new string[1];
            args[0] = currInfoPlayer.userName;
            newCfg.executeFunction("OnLeaveRace", currInfoPlayer, args);
            listOfPlayers.removeIndexPLID(pll.PLID);
        }
        void managePacket(InSim.Decoder.CPR cpr)
        {
            infoPlayer currInfoPlayer;


            currInfoPlayer = listOfPlayers.getPlayerByUCID(cpr.UCID);
            if (currInfoPlayer == null)
                return;
            // For make bug programm to test object debug
            /*
                                        currInfoPlayer = listOfPlayers.getPlayerByUCID(300);
                                        currInfoPlayer.CName = "";
            */

            string oldNickName = currInfoPlayer.nickName;
            currInfoPlayer.Rename(cpr.newNickName);
            currInfoPlayer.Plate = cpr.Plate;

            // Sometime LFS send a CPR with same oldNickname and newNickname, maybe a new uniqueID
            // if you do .Remove of Var the programm crash because the ref of var are same and the program crash;
            // Update user database & execute OnNameChange function
            string[] par = new string[3];
            par[0] = currInfoPlayer.userName;
            par[1] = oldNickName;
            par[2] = cpr.newNickName;
            newCfg.executeFunction("OnNameChange", currInfoPlayer, par);


        }
        void managePacket(InSim.Decoder.LAP lapDec)
        {
            infoPlayer currInfoPlayer;

            currInfoPlayer = listOfPlayers.getPlayerByPLID(lapDec.PLID);
            if (currInfoPlayer == null)
                return;

            // Set Fuel remaining
            currInfoPlayer.FuelValue = lapDec.Fuel200 / 2;

            if (currRace.inRace == true)
            {
                // Calculate reminaing race time each time a racer passes the start/finish line if this is a timed race - between 1 and 48 hours
                if (currRace.raceLaps >= 191)
                {
                    currRace.raceMins = (int)(((currRace.raceLaps - 190) * 60) - (lapDec.ETime / 60000));
                    // Set RaceLapsLeft to 1 if there is less than 5 mins of the race remaining
                    if (currRace.raceMins <= 30)
                    {
                        currRace.raceLapsLeft = 1;
                    }
                }
                // If this racer is the race leader...
                if (lapDec.LapsDone > currRace.lapsDone)
                {
                    currRace.lapsDone = lapDec.LapsDone;
                    // Set raceLapsLeft based on LAP.RaceLaps
                    if (currRace.raceLaps < 100)
                    {
                        // Short race - less than 100 laps
                        currRace.raceLapsLeft = currRace.raceLaps - lapDec.LapsDone;
                    }
                    else if (currRace.raceLaps < 191)
                    {
                        // Long race - between 100 and 1000 laps
                        currRace.raceLapsLeft = (((currRace.raceLaps - 100) * 10) + 100) - lapDec.LapsDone;
                    }
                }
            }

            #region test flags for this player
            actionPlayerFlags(lapDec.Flags, currInfoPlayer, false);
            #endregion

            if (lapDec.LTime == unitConv.HMSToLong(60, 0, 0))
                goto endOfLap;

            #region Drift scores
            if (currInfoPlayer.totaldriftscore >= newCfg.varsLapper.MinimumDriftScore)
            {
                currInfoPlayer.updateLapDriftScore(currState.ShortTrackName);
                if (currInfoPlayer.isNewBestdriftScore)
                {
                    driftSqlDbs.updateRow(true, currInfoPlayer, currState.ShortTrackName);
                    //                    driftSqlDbs.updateRow(true, currInfoPlayer, currentTrackName, modeSync, newCfg.varsLapper.SyncID, newCfg.varsLapper.SyncDir, SyncIDsToSync);
                    try
                    {
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnDriftPB", currInfoPlayer, args);
                    }
                    catch (Exception ex)
                    {
                        myDebug.WriteLine("err", "Error OnDriftPb " + ex.ToString());
                    }
                }
                else
                {
                    try
                    {
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnDriftLap", currInfoPlayer, args);
                    }
                    catch (Exception ex)
                    {
                        myDebug.WriteLine("err", "Error OnDriftLap " + ex.ToString());
                    }
                }
            }
            else
            {
                try
                {
                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction("OnDriftTooLow", currInfoPlayer, args);
                }
                catch (Exception ex)
                {
                    myDebug.WriteLine("err", "Error OnDriftTooLow " + ex.ToString());
                }
            }
            #endregion

            // For non drifting Update row of DB Every Laps
            currInfoPlayer.updateLap(currWr, lapDec, trackInfo.getMaxLapTime(currState.ShortTrackName, currInfoPlayer.CName), currState.ShortTrackName, newCfg.varsLapper.LapTimeUsedForPb);
            listOfPlayers.updateGap(lapDec.PLID, (int)paramLapper.maxSplit, newCfg, false);
            //            gripSqlDbs.updateRow(currInfoPlayer.isNewPBLtime | currInfoPlayer.isNewPBLap, currInfoPlayer, currentTrackName, modeSync, newCfg.varsLapper.SyncID, newCfg.varsLapper.SyncDir, SyncIDsToSync);
            string levels1 = "";
            string levels2 = "";
            bool newPB = currInfoPlayer.isNewPBLtime;
            if (newPB)
            {
                levels1 = StringLevelsAllowedPlayer(currInfoPlayer, false);
            }
            gripSqlDbs.updateRow(currInfoPlayer.isNewPBLtime | currInfoPlayer.isNewPBLap, currInfoPlayer, currState.ShortTrackName);
            if (newPB)
            {
                levels2 = StringLevelsAllowedPlayer(currInfoPlayer, false);

                for (int i = 0; i < levels2.Length; i++)
                {
                    if (levels2[i] != ',' && levels1.IndexOf(levels2[i]) == -1)
                    {
                        string[] par = new string[2];
                        try
                        {
                            int idxLevel = (int.Parse(levels2[i].ToString()));
                            par[0] = currInfoPlayer.userName;
                            par[1] = SystemAuth.LibelLevel[idxLevel];
                            newCfg.executeFunction("OnAuthReached", currInfoPlayer, par);
                        }
                        catch
                        {
                            myDebug.WriteLine("err", "Error on auth level");
                        }
                    }
                }
            }

            // On new Split
            #region Show splitting
            currInfoPlayer.lastSector = currInfoPlayer.currSector;
            currInfoPlayer.currSector = 1;
            if (newCfg.varsLapper.ShowSplitPB && currInfoPlayer.showSplitPB)
            {
                string[] args = new string[1];
                args[0] = currInfoPlayer.userName;
                newCfg.executeFunction("OnSpbLast", currInfoPlayer, args);
            }

            {
                string[] args = new string[1];
                args[0] = currInfoPlayer.userName;
                newCfg.executeFunction("OnLap", currInfoPlayer, args);
            }
            #endregion

            #region Message relative to time do by player ( good time, incerdible time, etc... )
            string lapTimeAction = trackInfo.getLapAction(currState.ShortTrackName, currInfoPlayer.CName, lapDec.LTime);
            if (lapTimeAction != "")
            {
                string[] args = new string[1];
                args[0] = currInfoPlayer.userName;
                newCfg.executeFunction(lapTimeAction, currInfoPlayer, args);
            }
            #endregion

            #region Show if new PB
            if (currInfoPlayer.isNewPBLtime)
            {
                string CurAction = "";
                try
                {
                    if (playerFilter.ContainsKey(currInfoPlayer.userName.ToLower()))
                        CurAction = "OnPBQual";
                    else
                        CurAction = "OnPB";
                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction(CurAction, currInfoPlayer, args);
                }
                catch (Exception ex)
                {
                    myDebug.WriteLine("err", "Error " + CurAction + " " + ex.ToString());
                }
            }
            #endregion

            #region Max session laps
            if (currInfoPlayer.sessLaps >= newCfg.varsLapper.MaxSessionLaps)
            {
                string[] args = new string[1];
                args[0] = currInfoPlayer.userName;
                newCfg.executeFunction("OnMaxSessionLaps", currInfoPlayer, args);
            }
            #endregion

            #region pit windows open and close
            if (newCfg.varsLapper.PitWindowStop != 0 && currRace.inRace)
            {
                if ((currInfoPlayer.lapsDone + 1) == newCfg.varsLapper.PitWindowStart)
                {
                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction("OnBeginPitWindow", currInfoPlayer, args);
                }
                if (currInfoPlayer.lapsDone == newCfg.varsLapper.PitWindowStop)
                {
                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction("OnEndPitWindow", currInfoPlayer, args);
                }
            }

        #endregion
        endOfLap:
            currInfoPlayer.totaldriftscore = 0;//reset score to 0
            currInfoPlayer.maxLapSpeed = 0;//reset maxlapspeed to 0
            currInfoPlayer.bestSpeed = (double)0;
            //			currInfoPlayer.currSector = currInfoPlayer.currSector + 1;

        }

        void managePacket(InSim.Decoder.SPX splitdec)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(splitdec.PLID);
            if (currInfoPlayer == null)
                return;
            if (splitdec.STime == unitConv.HMSToLong(60, 0, 0))
                return;

            // Set Fuel remaining
            currInfoPlayer.FuelValue = splitdec.Fuel200 / 2;

            currInfoPlayer.updateSplit(currWr, splitdec, currState.ShortTrackName);
            listOfPlayers.updateGap(splitdec.PLID, splitdec.Split - 1, newCfg, false);
            // Allow idle after firts split when a race is started
            if (currRace.inRace)
                currRace.allowIdleOnTrack = false;
            // If new splitting on PB file, save value and query save delayed DB
            if (currInfoPlayer.newPBBestSplit)
            {
                //                gripSqlDbs.updateRow(true, currInfoPlayer, currentTrackName, modeSync, newCfg.varsLapper.SyncID, newCfg.varsLapper.SyncDir, SyncIDsToSync);
                gripSqlDbs.updateRow(true, currInfoPlayer, currState.ShortTrackName);
            }

            SplitNotify(currInfoPlayer, splitdec);
        }

        void managePacket(InSim.Decoder.RST rst) // (Re)start a Race
        {
            //When RaceInfo packet is sent by NewPLayer packet and race is not busy. Else Reset RST_packet_From_NPL tp 0;
            //Otherwise this event will be executed everytime when a player joined the server.
            if (RST_packet_From_NPL != 1)
            {
                currRace.lapsDone = 0;
                if (newCfg.varsLapper.EnableRotation)
                    currRace.racesDone++;

                currRace.started = DateTime.Now;
                currRace.allowIdleOnTrack = true;
                if (newCfg.varsLapper.AutoRestartRaceSec > 0)
                { // When a player finish a race, next race is n minute after his finish
                    currRace.nextRestart = DateTime.Now.AddDays(365); // Next restart after 365 Day, ie no restart
                    currRace.autoRestartOn = false;
                }
                //Raz of idle on start
                listOfPlayers.raceRestart();
                currRace.timing = rst.Timing;
                currRace.raceFlags = rst.Flags;
                currRace.raceLaps = 0;
                currRace.raceMins = 0;
                currRace.qualMins = 0;
                if (rst.QualMins == 0 && rst.RaceLaps == 0)  // In practice session
                {
                    currRace.isRaceRunning = false;

                    string[] par = new string[1];
                    par[0] = rst.NumP.ToString();
                    newCfg.executeFunction("OnPracStart", null, par);
                }
                else if (rst.QualMins == 0) // In Race Start
                {
                    currRace.isRaceRunning = true;

                    string[] par = new string[1];
                    par[0] = rst.NumP.ToString();
                    currRace.raceLaps = rst.RaceLaps;
                    // Set raceLapsLeft based on LAP.RaceLaps
                    if (currRace.raceLaps < 100)
                    {
                        // Short race - less than 100 laps
                        currRace.raceLapsLeft = currRace.raceLaps;
                    }
                    else if (currRace.raceLaps < 191)
                    {
                        // Long race - between 100 and 1000 laps
                        currRace.raceLapsLeft = (((currRace.raceLaps - 100) * 10) + 100);
                    }
                    else
                    {
                        // Timed race - 1 to 48 hours
                        currRace.raceMins = ((currRace.raceLaps - 190) * 60); // Use raceMins to store race time
                        currRace.raceLapsLeft = 99;
                    }
                    newCfg.executeFunction("OnRaceStart", null, par);
                }
                else if (rst.RaceLaps == 0) // In Qualification
                {
                    currRace.isRaceRunning = false;

                    string[] par = new string[1];
                    currRace.qualMins = rst.QualMins;
                    par[0] = rst.NumP.ToString();
                    newCfg.executeFunction("OnQualStart", null, par);
                }
                byte[] sstreq = myEncoder.SST(); // Request State
                insimConnection.Send(sstreq, sstreq.Length);
            }
            //Reset Requested value from New Player packet;
            else
            {
                currRace.raceFlags = rst.Flags;
                currRace.qualMins = rst.QualMins;
                currRace.raceLaps = rst.RaceLaps;
                currRace.timing = rst.Timing;
                RST_packet_From_NPL = 0;
            }
        }
        void managePacket(InSim.Decoder.FIN fin) // FINished race notification (not a final result - use IS_RES)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(fin.PLID);
            if (currInfoPlayer == null)
                return;
            currInfoPlayer.allowIdleOnTrack = true;
            currInfoPlayer.finishedPLID = fin.PLID;

            string[] par = new string[1];
            par[0] = currInfoPlayer.userName;
            newCfg.executeFunction("OnFinish", currInfoPlayer, par);


        }
        void managePacket(InSim.Decoder.RES res) // RESult (qualify or confirmed finish)
        {
            if (newCfg.varsLapper.AutoRestartRaceSec > 0 && (currRace.autoRestartOn == false || newCfg.varsLapper.AutoRestartOnFirstFinished == false))
            { // When a player finish a race or qualify, next race is n minute after his finish
                currRace.nextRestart = DateTime.Now.AddSeconds((double)newCfg.varsLapper.AutoRestartRaceSec);
                currRace.autoRestartOn = true;
            }
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByFinishedPLID(res.PLID);
            if (currInfoPlayer == null)
                return;

            currInfoPlayer.finishedPos = res.ResultNum + 1;
            currInfoPlayer.racePBTime = res.BTime;
            currInfoPlayer.raceTotalTime = res.TTime;
            string[] par = new string[2];
            par[0] = currInfoPlayer.userName;
            par[1] = res.Confirm.ToString();
            newCfg.executeFunction("OnResult", currInfoPlayer, par);

        }

        void managePacket(InSim.Decoder.REO reo)
        {
            //            Console.WriteLine("Receive an ISP_REO");
            //            Console.WriteLine("ReqI " + reo.ReqI);
            //            Console.WriteLine("NumP " + reo.NumP);
            gridInfo.LfsOrder = reo.PLID;
            string tmpStr = gridInfo.PLIDsToString(reo.PLID);
            string[] par = new string[3];
            par[0] = reo.NumP.ToString();
            par[1] = reo.ReqI.ToString();
            par[2] = tmpStr;
            newCfg.executeFunction("OnREO", null, par);
            //            infoPlayer currInfoPlayer;
        }

        void managePacket(InSim.Decoder.STA newState)
        {
            if (currState == null || currState.ShortTrackName != newState.ShortTrackName)
            {
                listOfPlayers.changeTrack(newState.ShortTrackName, gripSqlDbs, driftSqlDbs);
            }
            currState = newState;

            // Check whether the track is a Free Roaming one
            if (currState.ShortTrackName.Trim().EndsWith("X") || currState.ShortTrackName.Trim().EndsWith("Y"))
                currRace.isFreeRoaming = true;
            else
                currRace.isFreeRoaming = false;

            if (newState.RaceInProg == 1 && newState.RaceLaps > 0)
                currRace.inRace = true;
            else
                currRace.inRace = false;
            if (flagFirstInState == true && (newState.Flags & 512) == 512)
            {
                flagFirstInState = false;

                byte[] sism = myEncoder.ISM();
                insimConnection.Send(sism, sism.Length);
            }
            //send request to get LFSCARS
            byte[] alc = myEncoder.ALC();
            insimConnection.Send(alc, alc.Length);
        }
        void managePacket(InSim.Decoder.MSO mso)
        {
            infoPlayer currInfoPlayer;

            currInfoPlayer = listOfPlayers.getPlayerByUCID(mso.UCID);
            if (currInfoPlayer == null)
                return;
            //            Console.WriteLine(mso.completeMessage);

            string nicknamewithoutcolors = currInfoPlayer.nickName;
            if (mso.UserType == 1)
            {
                if (swearWordObj.findSwearWords(mso.message)) // On swear word
                {
                    currInfoPlayer.swearWordsCount++;
                    string tmpStr;
                    if (currInfoPlayer.swearWordsCount >= newCfg.varsLapper.SwearWordsMax)
                    {
                        tmpStr = "OnSwearWords2";
                        currInfoPlayer.swearWordsCount = 0;
                    }
                    else
                    {
                        tmpStr = "OnSwearWords1";
                    }
                    string[] par = new string[1];
                    par[0] = currInfoPlayer.userName;
                    newCfg.executeFunction(tmpStr, currInfoPlayer, par);
                }
                CheckForFlooding(currInfoPlayer);

            }

            //Added 07-11-2017
            //Execute event when the Host or System is sending a message
            if (((mso.UserType == 0) || (mso.UserType > 2)) && (mso.message != "")) // Host/System Messages
            {
                string[] par = new string[2];
                par[0] = mso.message;
                par[1] = utils.quote(System.DateTime.Now.ToString(newCfg.varsLapper.LongTimeFormat));
                newCfg.executeFunction("OnHostMSO", currInfoPlayer, par);
            }


            if (mso.UserType == 1 || mso.UserType == 2)
            {
                if (mso.message.ToLower() == "!status")
                {
                    SendMsgToConnection(currInfoPlayer.UCID, "LFSLapper in working mode", 0);
                }
                else if (mso.message.ToLower() == "!start")
                {
                    SendMsgToConnection(currInfoPlayer.UCID, "LFSLapper is already working", 0);
                }
                else if (mso.message.ToLower() == "!stop")
                {
                    userGroups ugroup = new userGroups(myDebug);
                    ugroup.addUserFromFile("superUsers", newCfg.varsLapper.WorkingDir + "/" + newCfg.varsLapper.superUsers);
                    if (ugroup.userExist("superUsers", currInfoPlayer.userName.ToLower()) || (currInfoPlayer.UCID == 0))
                    {
                        this.TermProg = true;
                        SendMsgToConnection(currInfoPlayer.UCID, "Go to stand by mode!", 0);
                    }
                    else
                    {
                        SendMsgToConnection(currInfoPlayer.UCID, "^1Only for Lapper admins!", 0);
                    }

                }
                else
                {
                    string[] par = new string[2];
                    par[0] = currInfoPlayer.userName;
                    par[1] = mso.message;
                    newCfg.executeFunction("OnMSO", currInfoPlayer, par);
                }
            }
        }
        void managePacket(InSim.Decoder.FLG flg)
        {
            String usernamebehind = "None";
            infoPlayer currInfoPlayer;
            infoPlayer currInfoPlayer_CarBehind;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(flg.PLID);
            if (currInfoPlayer == null)
                return;
            //Blueflag
            if (flg.Flag == 1)
            {
                currInfoPlayer_CarBehind = listOfPlayers.getPlayerByPLID(flg.CarBehind);
                if (currInfoPlayer_CarBehind == null)
                    return;
                usernamebehind = currInfoPlayer_CarBehind.userName;

                string[] args = new string[3];
                args[0] = currInfoPlayer.userName;
                args[1] = usernamebehind; //returns uname of car behind
                args[2] = utils.quote(System.DateTime.Now.ToString(newCfg.varsLapper.ShortTimeFormat));
                newCfg.executeFunction("OnBlueFlag", currInfoPlayer, args);
            }

            //Yellowflag 
            if (flg.Flag == 2)
            {
                string[] args = new string[3];
                args[0] = currInfoPlayer.userName;
                args[1] = flg.OffOn.ToString();
                args[2] = utils.quote(System.DateTime.Now.ToString(newCfg.varsLapper.ShortTimeFormat));
                newCfg.executeFunction("OnYellowFlag", currInfoPlayer, args);
            }
        }

        void managePacket(DateTime datRecvPacket, InSim.Decoder.MCI mci)
        {
            infoPlayer currInfoPlayer;
            bool LastCar = false;

            #region Update stat of each player
            double xm = 0;
            double ym = 0;
            double zm = 0;
            int x = 0;
            int y = 0;
            int z = 0;

            for (int i = 0; i < System.Math.Min(16, mci.numOfPlayers); i++)
            {
                xm = mci.compCar[i].x / 65536d;
                ym = mci.compCar[i].y / 65536d;
                zm = mci.compCar[i].z / 65536d;

                x = (int)xm;
                y = (int)ym;
                z = (int)zm;

                double spm = mci.compCar[i].speed / 327.68 * 3.6; // kmh
                double dirm = mci.compCar[i].direction * 180 / 32768d;
                double headm = mci.compCar[i].heading * 180 / 32768d;

                if (headm > 180)
                    headm -= 360;

                double angm = mci.compCar[i].angvel * 180 / 8192d;
                int currPos = mci.compCar[i].Position;
                int currLap = mci.compCar[i].lap;

                currInfoPlayer = listOfPlayers.getPlayerByPLID(mci.compCar[i].PLID);
                if (currInfoPlayer != null)
                {
                    double accStart;
                    double accStop;
                    double accStart2;
                    double accStop2;

                    if (currInfoPlayer.unitSpeedKmh)
                    {
                        accStart = newCfg.varsLapper.AccelerationStartSpeed;
                        accStop = newCfg.varsLapper.AccelerationEndSpeed;
                        accStart2 = newCfg.varsLapper.AccelerationStartSpeed2;
                        accStop2 = newCfg.varsLapper.AccelerationEndSpeed2;
                    }
                    else
                    {
                        accStart = newCfg.varsLapper.AccelerationStartSpeedMph * 1.609344;
                        accStop = newCfg.varsLapper.AccelerationEndSpeedMph * 1.609344;
                        accStart2 = newCfg.varsLapper.AccelerationStartSpeedMph2 * 1.609344;
                        accStop2 = newCfg.varsLapper.AccelerationEndSpeedMph2 * 1.609344;
                    }
                    {
                        int zone = currInfoPlayer.LastZone;
                        string idZone = currInfoPlayer.idCurrZone;
                        //Streetcode Yisc[NL]
                        int street = currInfoPlayer.LastStreet;
                        string idStreet = currInfoPlayer.idCurrStreet;


                        if (x != currInfoPlayer.x || y != currInfoPlayer.y)
                        {
                            zone = listOfZoneEvent.getMyZone(currState.ShortTrackName, x, y);
                            idZone = listOfZoneEvent.idZoneByIdxZone(currState.ShortTrackName, zone);

                            //Streetcode Yisc[NL]
                            street = listOfStreetEvent.getMyStreet(currState.ShortTrackName, x, y);
                            idStreet = listOfStreetEvent.idStreetByIdxStreet(currState.ShortTrackName, street);
                        }

                        double x_double = Math.Round(xm, 2); //double X
                        double y_double = Math.Round(ym, 2); //double Y
                        double z_double = Math.Round(zm, 2); //double Z

                        currInfoPlayer.UpdateState(currPos, currLap, mci.compCar[i].node, zone, idZone, street, idStreet, x_double, y_double, z_double, spm, dirm, headm, angm, newCfg.varsLapper.RealTimeDriftScore, newCfg.varsLapper.MinimumDriftSpeed, newCfg.varsLapper.MinimumDriftAngle, newCfg.varsLapper.MaximumDriftAngle, newCfg.varsLapper.MinAngleVelocity, accStart, accStop, accStart2, accStop2, currInfoPlayer.OnTrack);

                        if (currInfoPlayer.lastPos != currInfoPlayer.currPos)
                        {
                            PLIDChangePos.Add(currInfoPlayer);
                        }
                    }
                    #endregion
                }
                {
                    if ((mci.compCar[i].Infos & 128) != 0) // iterator'sbyte the Last packet
                    {

                        for (int idx = 0; idx < PLIDChangePos.Count; idx++)
                        {
                            infoPlayer tmpCurrInfoPlayer = (infoPlayer)PLIDChangePos[idx];
                            listOfPlayers.updateGap(tmpCurrInfoPlayer.PLID, tmpCurrInfoPlayer.lastIdxSplit, newCfg, true);
                            string[] args = new string[3];
                            args[0] = tmpCurrInfoPlayer.userName;
                            args[1] = tmpCurrInfoPlayer.lastPos.ToString();
                            args[2] = tmpCurrInfoPlayer.currPos.ToString();
                            newCfg.executeFunction("OnChangePos", tmpCurrInfoPlayer, args);
                        }
                        PLIDChangePos.Clear();
                        LastCar = true; // Reached the last car of a set of MCI
                    }
                }

            }

            #region Action to do when you receive the last packet for set car
            if (LastCar)
            {
                LastCar = false;

                foreach (System.Collections.DictionaryEntry de in listOfPlayers.playersUCID)
                {
                    currInfoPlayer = (infoPlayer)de.Value;
                    //PlayerDetection


                    //STREETEVENT CODE
                    #region street Event Yisc[NL] 
                    if (currInfoPlayer.CurrStreet != currInfoPlayer.LastStreet)
                    {
                        //LEAVE STREET
                        if (currInfoPlayer.LastStreet != -1)
                        {
                            try
                            {
                                string cmdStreetLeave = listOfStreetEvent.getCommandStreetLeave(currState.ShortTrackName, currInfoPlayer.LastStreet, currInfoPlayer.CurrentStreetIDTask);
                                if (cmdStreetLeave != "")
                                {
                                    string getstreetidTask = listOfStreetEvent.getCommandStreetIDTask(currState.ShortTrackName, currInfoPlayer.LastStreet);
                                    if (getstreetidTask == "")
                                    {
                                        getstreetidTask = "unknown";
                                    }
                                    currInfoPlayer.CurrentStreetIDTask = "";
                                    //1 argument (UserName)
                                    string[] args = new string[1];
                                    args[0] = currInfoPlayer.userName;
                                    newCfg.executeFunction(cmdStreetLeave, currInfoPlayer, args);
                                }
                            }
                            catch
                            {

                            }
                        }

                        //ENTER STREET
                        currInfoPlayer.LastStreet = currInfoPlayer.CurrStreet;
                        if (currInfoPlayer.CurrStreet != -1)
                        {
                            string cmdStreetEnter = listOfStreetEvent.getCommandStreetEnter(currState.ShortTrackName, currInfoPlayer.CurrStreet);
                            if (cmdStreetEnter != "")
                            {
                                string getstreetidTask = listOfStreetEvent.getCommandStreetIDTask(currState.ShortTrackName, currInfoPlayer.CurrStreet);
                                if (getstreetidTask == "")
                                {
                                    getstreetidTask = "unknown";
                                }
                                //1 argument (UserName)
                                currInfoPlayer.CurrentStreetIDTask = getstreetidTask;
                                string[] args = new string[1];
                                args[0] = currInfoPlayer.userName;
                                newCfg.executeFunction(cmdStreetEnter, currInfoPlayer, args);
                            }
                        }
                    }

                    #endregion

                    #region check for instunt time player
                    if (currInfoPlayer.stuntticks == newCfg.varsLapper.MaxNbInStunt)
                    {
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnMaxNbInStunt", currInfoPlayer, args);
                    }
                    else if (currInfoPlayer.stuntticks == 1)
                    {
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnAngleVelocity", currInfoPlayer, args);
                    }
                    #endregion

                    #region check for idle time
                    {
                        if (currRace.allowIdleOnTrack == true || currInfoPlayer.allowIdleOnTrack == true || currRace.inRace == false || currInfoPlayer.OnPit == true || currInfoPlayer.OnTrack == false)
                        { // if not in race, Force IdleTick for each player to 0
                            currInfoPlayer.idleticks = 0;
                        }
                    }
                    if (currInfoPlayer.idleticks > (newCfg.varsLapper.OnIdleTimeout2 * 10))
                    {
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnIdle2", currInfoPlayer, args);
                        currInfoPlayer.idleticks = 0;
                        currInfoPlayer.OnIdleAction1Sended = false;
                    }
                    if ((currInfoPlayer.idleticks > (newCfg.varsLapper.OnIdleTimeout1 * 10)) && (currInfoPlayer.OnIdleAction1Sended == false))
                    {
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnIdle1", currInfoPlayer, args);
                        currInfoPlayer.OnIdleAction1Sended = true;
                    }
                    #endregion

                    #region DriftScoring (Realtime or Show Driftscore after each drift
                    if (newCfg.varsLapper.RealTimeDriftScore == -1)
                    {
                        if (currInfoPlayer.driftticks == 0 && currInfoPlayer.totaldriftscore > 0 && currInfoPlayer.lastdriftscore > 0)
                        {
                            {
                                string[] args = new string[1];
                                args[0] = currInfoPlayer.userName;
                                newCfg.executeFunction("OnDriftScore", currInfoPlayer, args);
                            }

                            if (currInfoPlayer.lastdriftscore >= newCfg.varsLapper.GoodDriftScore)
                            {
                                string[] args = new string[1];
                                args[0] = currInfoPlayer.userName;
                                newCfg.executeFunction("OnGoodDrift", currInfoPlayer, args);
                            }

                            currInfoPlayer.lastdriftscore = 0;
                        }
                    }
                    else if (newCfg.varsLapper.RealTimeDriftScore == 1)
                    {
                        if (MCIPlayerFlagCounterTwo > 1)
                        {
                            if (currInfoPlayer.driftticks > 0 && currInfoPlayer.totaldriftscore > 0) //NEW (Realtime driftscoring)
                            {
                                {
                                    string[] args = new string[1];
                                    args[0] = currInfoPlayer.userName;
                                    newCfg.executeFunction("OnDriftScore", currInfoPlayer, args);
                                }
                                //Stop spamming gooddrift event 
                                if (currInfoPlayer.lastdriftscore >= newCfg.varsLapper.GoodDriftScore)
                                {
                                    if (currInfoPlayer.showedgooddriftscore == false)  //IF event isnt executed yet then execute event. 
                                    {
                                        string[] args = new string[1];
                                        args[0] = currInfoPlayer.userName;
                                        currInfoPlayer.showedgooddriftscore = true;
                                        newCfg.executeFunction("OnGoodDrift", currInfoPlayer, args);
                                    }
                                }
                                else
                                {
                                    currInfoPlayer.showedgooddriftscore = false;
                                }
                            }
                            MCIPlayerFlagCounterTwo = 0;
                        }
                        MCIPlayerFlagCounterTwo++;
                    }

                    if (currInfoPlayer.isDriftReset) // Drift score reset due to low speed
                    {
                        {
                            string[] args = new string[1];
                            args[0] = currInfoPlayer.userName;
                            newCfg.executeFunction("OnDriftResetScore", currInfoPlayer, args);
                        }
                    }

                    #endregion
                    #region acceleration1 0-100 & acceleration2 100-160
                    if ((currInfoPlayer.accelerationTimeValid && currInfoPlayer.accelerationTime.TotalSeconds <= newCfg.varsLapper.AccelerationPrivateMaxTime))
                    {
                        currInfoPlayer.accelerationTimeValid = false;
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnAcceleration", currInfoPlayer, args);
                    }

                    if (currInfoPlayer.accelerationTimeValid2 && currInfoPlayer.accelerationTime2.TotalSeconds <= newCfg.varsLapper.AccelerationPrivateMaxTime2)
                    {
                        currInfoPlayer.accelerationTimeValid2 = false;
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnAcceleration2", currInfoPlayer, args);
                    }
                    #endregion

                    #region Action if player is to slow to complete a lap
                    if (currRace.inRace && currInfoPlayer.OnTrack)
                    {
                        if (newCfg.varsLapper.MaxAllowedLapTime1 != -1)
                        {
                            long second = (long)(((double)newCfg.varsLapper.MaxAllowedLapTime1 / 100) * ((double)currInfoPlayer.MaxLapTime / 1000));
                            if (!currInfoPlayer.MaxLapTime1Reached && currInfoPlayer.LastCrossedFinishLine.AddSeconds((double)second) < DateTime.Now)
                            {
                                string[] args = new string[1];
                                args[0] = currInfoPlayer.userName;
                                newCfg.executeFunction("OnMaxAllowedLapTime1", currInfoPlayer, args);
                                currInfoPlayer.MaxLapTime1Reached = true;
                            }
                        }
                        if (newCfg.varsLapper.MaxAllowedLapTime2 != -1)
                        {
                            long second = (long)(((double)newCfg.varsLapper.MaxAllowedLapTime2 / 100) * ((double)currInfoPlayer.MaxLapTime / 1000));
                            if (!currInfoPlayer.MaxLapTime2Reached && currInfoPlayer.LastCrossedFinishLine.AddSeconds((double)second) < DateTime.Now)
                            {
                                string[] args = new string[1];
                                args[0] = currInfoPlayer.userName;
                                newCfg.executeFunction("OnMaxAllowedLapTime2", currInfoPlayer, args);
                                currInfoPlayer.MaxLapTime2Reached = true;
                            }
                        }
                    }
                    #endregion
                    //Updated 09/12/2016
                    #region speedTrap Node Event
                    if (currInfoPlayer.CurrNode != currInfoPlayer.LastNode)
                    {
                        if (currInfoPlayer.LastNode != -1)
                        {
                            string cmdNode = listOfNodeEvent.getCommandNodeLeave(currState.ShortTrackName, currInfoPlayer.LastNode);
                            if (cmdNode != "")
                            {
                                string getidTask = listOfNodeEvent.getCommandIDTask(currState.ShortTrackName, currInfoPlayer.LastNode);
                                if (getidTask == "")
                                {
                                    getidTask = "unknown";
                                }
                                string[] args = new string[2];
                                args[0] = currInfoPlayer.userName;
                                args[1] = getidTask;
                                newCfg.executeFunction(cmdNode, currInfoPlayer, args);
                            }
                        }
                        currInfoPlayer.LastNode = currInfoPlayer.CurrNode;
                        {
                            string cmdNode = listOfNodeEvent.getCommandNodeEnter(currState.ShortTrackName, currInfoPlayer.CurrNode);
                            if (cmdNode != "")
                            {
                                string getidTask = listOfNodeEvent.getCommandIDTask(currState.ShortTrackName, currInfoPlayer.LastNode);
                                if (getidTask == "")
                                {
                                    getidTask = "unknown";
                                }
                                string[] args = new string[2];
                                args[0] = currInfoPlayer.userName;
                                args[1] = getidTask;
                                newCfg.executeFunction(cmdNode, currInfoPlayer, args);
                            }
                        }
                    }
                    #endregion
                    //Updated 09/12/2016
                    #region speedTrap Zone Event

                    if (currInfoPlayer.CurrZone != currInfoPlayer.LastZone)
                    {
                        //Leave Zone
                        if (currInfoPlayer.LastZone != -1)
                        {
                            string cmdZone = listOfZoneEvent.getCommandZoneLeave(currState.ShortTrackName, currInfoPlayer.LastZone, currInfoPlayer.CurrentIDTask);
                            if (cmdZone != "")
                            {
                                string getidTask = listOfZoneEvent.getCommandIDTask(currState.ShortTrackName, currInfoPlayer.LastZone);
                                if (getidTask == "")
                                {
                                    getidTask = "unknown";
                                }
                                currInfoPlayer.CurrentIDTask = "";
                                string[] args = new string[2];
                                args[0] = currInfoPlayer.userName;
                                args[1] = getidTask;
                                newCfg.executeFunction(cmdZone, currInfoPlayer, args);
                            }
                        }

                        //Enter Zone
                        currInfoPlayer.LastZone = currInfoPlayer.CurrZone;
                        if (currInfoPlayer.CurrZone != -1)
                        {
                            string cmdZone = listOfZoneEvent.getCommandZoneEnter(currState.ShortTrackName, currInfoPlayer.CurrZone);
                            if (cmdZone != "")
                            {
                                string getidTask = listOfZoneEvent.getCommandIDTask(currState.ShortTrackName, currInfoPlayer.CurrZone);
                                if (getidTask == "")
                                {
                                    getidTask = "unknown";
                                }
                                currInfoPlayer.CurrentIDTask = getidTask;
                                string[] args = new string[2];
                                args[0] = currInfoPlayer.userName;
                                args[1] = getidTask;
                                newCfg.executeFunction(cmdZone, currInfoPlayer, args);
                            }
                        }
                    }
                    #endregion

                    #region check for player have done disToDo
                    if (newCfg.varsLapper.distToDo != -1 && currInfoPlayer.totDistMeter > currInfoPlayer.lastTotDistMeter + newCfg.varsLapper.distToDo)
                    {
                        currInfoPlayer.lastTotDistMeter += newCfg.varsLapper.distToDo;
                        string[] args = new string[1];
                        args[0] = currInfoPlayer.userName;
                        newCfg.executeFunction("OnDistDone", currInfoPlayer, args);
                    }
                    #endregion
                }
            }
            #endregion

        }

        void managePacket(InSim.Decoder.ISM ism)
        {
            currentHName = ism.HName;

            Console.WriteLine("LFSLapper connected to: " + utils.stripLFSColor(ism.HName) + " [" + connectName + "/" + connectIP + ":" + connectPort + "]");
            Console.WriteLine("----------------------------------------------------------------------------------");
            if (newCfg.varsLapper.EnableRegisterWeb)
            {
                objregisterWeb.HName = ism.HName;
                objregisterWeb.Ver = LFSLapper.getShortVersion(4);
                objregisterWeb.URL = newCfg.varsLapper.RegisterWebsite;
            }
            HName = ism.HName;
            // Get All Connections
            //System.Threading.Thread.Sleep(100);
            byte[] ismncn = myEncoder.NCN();
            insimConnection.Send(ismncn, ismncn.Length);
            // Get All Players
            //System.Threading.Thread.Sleep(100);
            byte[] ismnpl = myEncoder.NPL();
            insimConnection.Send(ismnpl, ismnpl.Length);

        }

        void managePacket(InSim.Decoder.PEN pen)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(pen.PLID);
            if (currInfoPlayer == null)
                return;
            currInfoPlayer.PenaltyNew = pen.NewPen;
            if (currRace.isRaceRunning)
            {
                OnPenalties(currInfoPlayer, pen);
            }
        }

        void managePacket(InSim.Decoder.BFN bfn)
        {
            infoPlayer currInfoPlayer;

            currInfoPlayer = listOfPlayers.getPlayerByUCID(bfn.UCID);
            if (currInfoPlayer == null)
                return;

            if (bfn.SubT == (int)InSim.bfn.BFN_USER_CLEAR)
                currInfoPlayer.playerBox.deleteAllButton(currInfoPlayer, newCfg);
            {
                string[] args = new string[2];
                args[0] = currInfoPlayer.userName;
                args[1] = bfn.SubT.ToString();
                newCfg.executeFunction("OnButtonFunction", currInfoPlayer, args);
            }
        }

        void managePacket(InSim.Decoder.BTC btc)
        {
            infoPlayer currInfoPlayer;

            currInfoPlayer = listOfPlayers.getPlayerByUCID(btc.UCID);
            if (currInfoPlayer == null)
                return;
            string[] par = new string[2];
            par[0] = btc.CFlags.ToString();
            par[1] = currInfoPlayer.playerBox.getId(btc.ClickID, btc.UCID);
            string doAct = currInfoPlayer.playerBox.doAction(btc.ClickID, btc.UCID);
            ISMB.executeButtonFunction exeFunc = currInfoPlayer.playerBox.doActionBC(btc.ClickID, btc.UCID);
            if (doAct != "")
                newCfg.executeFunction(doAct, currInfoPlayer, par);
            if (exeFunc != null)
                exeFunc(ISMB.typExeFunc.TYPE_BUTTON, currInfoPlayer, btc.CFlags, par[1].ToString());
        }

        void managePacket(InSim.Decoder.BTT btt)
        {
            infoPlayer currInfoPlayer;

            currInfoPlayer = listOfPlayers.getPlayerByUCID(btt.UCID);
            if (currInfoPlayer == null)
                return;
            string[] par = new string[2];
            par[0] = currInfoPlayer.playerBox.getId(btt.ClickID, btt.UCID);
            par[1] = btt.Text.Trim();
            string doAct = currInfoPlayer.playerBox.doAction(btt.ClickID, btt.UCID);
            ISMB.executeButtonFunction exeFunc = currInfoPlayer.playerBox.doActionBC(btt.ClickID, btt.UCID);
            if (doAct != "")
                newCfg.executeFunction(doAct, currInfoPlayer, par);
            if (exeFunc != null)
                exeFunc(ISMB.typExeFunc.TYPE_TEXT, currInfoPlayer, 0, par[0].ToString());
        }

        void managePacket(InSim.Decoder.TOC toc)
        {
            infoPlayer currInfoPlayer;

            infoPlayer oldCurrInfoPlayer = listOfPlayers.getPlayerByPLID(toc.PLID);
            if (oldCurrInfoPlayer == null)
                return;



            listOfPlayers.removeIndexPLID(toc.PLID); // Remove PLID OF oldPlayer
            listOfPlayers.majIndexPLID(toc.NewUCID, toc.PLID); // Attach PLID to new player

            currInfoPlayer = listOfPlayers.getPlayerByPLID(toc.PLID);
            currInfoPlayer.P_Mass = oldCurrInfoPlayer.P_Mass;
            currInfoPlayer.P_TRes = oldCurrInfoPlayer.P_TRes;
            currInfoPlayer.CName = oldCurrInfoPlayer.CName;
            // Retreive Info of this Player in DBS

            gripSqlDbs.retreiveRow(currInfoPlayer, currState.ShortTrackName);
            driftSqlDbs.retreiveRow(currInfoPlayer, currState.ShortTrackName);

            currInfoPlayer.OnTrack = true;

            currInfoPlayer.LastCrossedFinishLine = DateTime.Now;
            currInfoPlayer.MaxLapTime1Reached = false;
            currInfoPlayer.MaxLapTime2Reached = false;

            //Get info about the Oldplayer and the new player (who take over the car)
            infoPlayer OldPlayer_info = listOfPlayers.getPlayerByUCID(toc.OldUCID);
            infoPlayer NewPlayer_info = listOfPlayers.getPlayerByUCID(toc.NewUCID);

            if (OldPlayer_info == null || NewPlayer_info == null)
                return;

            string[] args = new string[3];
            args[0] = OldPlayer_info.userName;
            args[1] = NewPlayer_info.userName;
            args[2] = OldPlayer_info.CName;
            newCfg.executeFunction("OnTakeOverCar", currInfoPlayer, args);
        }

        void managePacket(InSim.Decoder.PIT pit)
        {
            infoPlayer currInfoPlayer;
            int FL_Changed = 0;
            int FR_Changed = 0;
            int RL_Changed = 0;
            int RR_Changed = 0;


            currInfoPlayer = listOfPlayers.getPlayerByPLID(pit.PLID);
            if (currInfoPlayer == null)
                return;
            currInfoPlayer.OnPit = true;
            currInfoPlayer.instantSpeed = 0;

            if (pit.FuelAdd == 255)
            {
                currInfoPlayer.PitFuel = -1;
            }
            else
            {
                currInfoPlayer.PitFuel = pit.FuelAdd;
            }

            currInfoPlayer.pitWork = pit.sWork;
            if ((pit.Work & (long)InSim.PIT_work.PSE_LE_FR_WHL) != 0)
                FL_Changed = 1;
            if ((pit.Work & (long)InSim.PIT_work.PSE_RI_FR_WHL) != 0)
                FR_Changed = 1;
            if ((pit.Work & (long)InSim.PIT_work.PSE_LE_RE_WHL) != 0)
                RL_Changed = 1;
            if ((pit.Work & (long)InSim.PIT_work.PSE_RI_RE_WHL) != 0)
                RR_Changed = 1;
            currInfoPlayer.tyreFrontLeft = currInfoPlayer.oldTyreFrontLeft;
            currInfoPlayer.tyreFrontRight = currInfoPlayer.oldTyreFrontRight;
            currInfoPlayer.tyreRearLeft = currInfoPlayer.oldTyreRearLeft;
            currInfoPlayer.tyreRearRight = currInfoPlayer.oldTyreRearRight;

            if ((int)pit.TyreRearLeft != 255)
                currInfoPlayer.tyreRearLeft = pit.TyreRearLeft;
            if ((int)pit.TyreRearRight != 255)
                currInfoPlayer.tyreRearRight = pit.TyreRearRight;
            if ((int)pit.TyreFrontLeft != 255)
                currInfoPlayer.tyreFrontLeft = pit.TyreFrontLeft;
            if ((int)pit.TyreFrontRight != 255)
                currInfoPlayer.tyreFrontRight = pit.TyreFrontRight;
            {
                string[] args = new string[1];
                args[0] = currInfoPlayer.userName;
                newCfg.executeFunction("OnBeginPit", currInfoPlayer, args);
            }

            if (newCfg.varsLapper.PitWindowStop != 0 && currRace.inRace)
            {
                if ((currInfoPlayer.lapsDone + 1) < newCfg.varsLapper.PitWindowStart || (currInfoPlayer.lapsDone + 1) > newCfg.varsLapper.PitWindowStop)
                {
                    string[] args = new string[1];
                    args[0] = currInfoPlayer.userName;
                    newCfg.executeFunction("OnNotPitWindow", currInfoPlayer, args);
                }
            }
            {
                //                if (FL_Changed != 0 || FR_Changed != 0 || RL_Changed != 0 || RR_Changed != 0)
                //                {
                string[] args = new string[5];
                args[0] = currInfoPlayer.userName;
                args[1] = FL_Changed.ToString();
                args[2] = FR_Changed.ToString();
                args[3] = RL_Changed.ToString();
                args[4] = RR_Changed.ToString();
                newCfg.executeFunction("OnChangeTyres", currInfoPlayer, args);
                //                }
            }


        }

        void managePacket(InSim.Decoder.PSF psf)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(psf.PLID);
            if (currInfoPlayer == null)
                return;
            currInfoPlayer.OnPit = false;
            currInfoPlayer.totalPitTime += psf.STime;
            currInfoPlayer.pitTime = psf.STime;
            currInfoPlayer.pitStops++;

            string[] args = new string[1];
            args[0] = currInfoPlayer.userName;
            newCfg.executeFunction("OnEndPit", currInfoPlayer, args);

        }

        void managePacket(InSim.Decoder.SMALL small)
        {
            //            Console.WriteLine("ReqI " + small.ReqI);
            switch (small.SubT)
            {
                case "SMALL_VTA":
                    if (small.uval == (long)InSim.vtn.VOTE_RESTART)
                    {
                        if (currVotation.allowRestart)
                        {
                            currVotation.allowRestart = false;
                            //                            Console.WriteLine("Send a new ISP_REO"); 
                            //                            setReorder(newCfg.varsLapper.ReorderGrid); // Set the reorder relative TO PB
                            // Send the reordered list
                            /*
                                                        byte[] reo = myEncoder.REO(1, currState.NumP, gridInfo.LapperOrder);
                                                        insimConnection.Send(reo, reo.Length);
                            */
                        }
                        else
                        {
                            if (newCfg.varsLapper.VoteRestart != -1)
                            {
                                byte[] vtc = myEncoder.VTC();
                                insimConnection.Send(vtc, vtc.Length);
                                return;
                            }
                        }
                    }
                    else if (small.uval == (long)InSim.vtn.VOTE_QUALIFY)
                    {
                        if (currVotation.allowQualify)
                        {
                            currVotation.allowQualify = false;
                        }
                        else
                        {
                            if (newCfg.varsLapper.VoteQualify != -1)
                            {
                                byte[] vtc = myEncoder.VTC();
                                insimConnection.Send(vtc, vtc.Length);
                                return;
                            }
                        }
                    }
                    else if (small.uval == (long)InSim.vtn.VOTE_END)
                    {
                        if (currVotation.allowEnd)
                        {
                            currVotation.allowEnd = false;
                        }
                        else
                        {
                            if (newCfg.varsLapper.VoteEnd != -1)
                            {
                                byte[] vtc = myEncoder.VTC();
                                insimConnection.Send(vtc, vtc.Length);
                                return;
                            }
                        }
                    }
                    listOfPlayers.voteClear();
                    break;

                //Get allowed cars from LFS SMALL_ALC packet

                case "SMALL_ALC":
                    {
                        //long CarsLeft = small.uval;
                        //GetAllowedcarsFromLFS(CarsLeft);
                    }
                    break;
            }
        }

        public void GetAllowedcarsFromLFS(long CarsLeft)
        {
            /*
            //send request packet to LFS , receive SMALL_ALC packet

            //Putt allowed cars in a array
            string[] LFSCars = { "UF1", "XFG", "XRG", "LX4", "LX6", "RB4", "FXO", "XRT", "RAC", "FZ5", "UFR", "XFR", "FXR", "XRR", "FZR", "MRT", "FBM", "FOX", "F08", "BF1" };
            string[] CarsAllowed = new string[20];
            string carstring = "";
            //Clear Array and lappervar before filling.
            newCfg.varsLapper.AllowedCars = "";
            Array.Clear(CarsAllowed, 0, CarsAllowed.Length);

            int count = 0;
            while (CarsLeft > 0 && count < 21)
            {
                #region calculate cars
                //FBM
                if (CarsLeft >= 524288)
                {
                    CarsLeft = CarsLeft - 524288;
                    CarsAllowed[count] = "FBM";
                    count++;
                }
                //BF1
                if ((CarsLeft < 524288) && (CarsLeft >= 262144))
                {
                    CarsLeft = CarsLeft - 262144;
                    CarsAllowed[count] = "BF1";
                    count++;
                }
                //FZR
                if ((CarsLeft < 262144) && (CarsLeft >= 131072))
                {
                    CarsLeft = CarsLeft - 131072;
                    CarsAllowed[count] = "FZR";
                    count++;
                }
                //XRR
                if ((CarsLeft < 131072) && (CarsLeft >= 65536))
                {
                    CarsLeft = CarsLeft - 65536;
                    CarsAllowed[count] = "XRR";
                    count++;
                }
                //FXR
                if ((CarsLeft < 65536) && (CarsLeft >= 32768))
                {
                    CarsLeft = CarsLeft - 32768;
                    CarsAllowed[count] = "FXR";
                    count++;
                }
                //F08
                if ((CarsLeft < 32768) && (CarsLeft >= 16384))
                {
                    CarsLeft = CarsLeft - 16384;
                    CarsAllowed[count] = "F08";
                    count++;
                }
                //UFR
                if ((CarsLeft < 16384) && (CarsLeft >= 8192))
                {
                    CarsLeft = CarsLeft - 8192;
                    CarsAllowed[count] = "UFR";
                    count++;
                }
                //XFR
                if ((CarsLeft < 8192) && (CarsLeft >= 4096))
                {
                    CarsLeft = CarsLeft - 4096;
                    CarsAllowed[count] = "XFR";
                    count++;
                }
                //FOX
                if ((CarsLeft < 4096) && (CarsLeft >= 2048))
                {
                    CarsLeft = CarsLeft - 2048;
                    CarsAllowed[count] = "FOX";
                    count++;
                }
                //FZ5
                if ((CarsLeft < 2048) && (CarsLeft >= 1024))
                {
                    CarsLeft = CarsLeft - 1024;
                    CarsAllowed[count] = "FZ5";
                    count++;
                }
                //RAC
                if ((CarsLeft < 1024) && (CarsLeft >= 512))
                {
                    CarsLeft = CarsLeft - 512;
                    CarsAllowed[count] = "RAC";
                    count++;
                }
                //Uf1
                if ((CarsLeft < 512) && (CarsLeft >= 256))
                {
                    CarsLeft = CarsLeft - 256;
                    CarsAllowed[count] = "UF1";
                    count++;
                }
                //MRT
                if ((CarsLeft < 256) && (CarsLeft >= 128))
                {
                    CarsLeft = CarsLeft - 128;
                    CarsAllowed[count] = "MRT";
                    count++;
                }
                //LX6
                if ((CarsLeft < 128) && (CarsLeft >= 64))
                {
                    CarsLeft = CarsLeft - 64;
                    CarsAllowed[count] = "LX6";
                    count++;
                }
                //LX4
                if ((CarsLeft < 64) && (CarsLeft >= 32))
                {
                    CarsLeft = CarsLeft - 32;
                    CarsAllowed[count] = "LX4";
                    count++;
                }
                //FXO
                if ((CarsLeft < 32) && (CarsLeft >= 16))
                {
                    CarsLeft = CarsLeft - 16;
                    CarsAllowed[count] = "FXO";
                    count++;
                }
                //RB4
                if ((CarsLeft < 16) && (CarsLeft >= 8))
                {
                    CarsLeft = CarsLeft - 8;
                    CarsAllowed[count] = "RB4";
                    count++;
                }
                //XRT
                if ((CarsLeft < 8) && (CarsLeft >= 4))
                {
                    CarsLeft = CarsLeft - 4;
                    CarsAllowed[count] = "XRT";
                    count++;
                }
                //XRG
                if ((CarsLeft < 4) && (CarsLeft >= 2))
                {
                    CarsLeft = CarsLeft - 2;
                    CarsAllowed[count] = "XRG";
                    count++;
                }
                //XFG
                if ((CarsLeft < 2) && (CarsLeft >= 1))
                {
                    CarsLeft = CarsLeft - 1;
                    CarsAllowed[count] = "XFG";
                    count++;
                }
                #endregion
            }

            for (int i = 0; i < 20; i++)
            {
                for (int a = 0; a < CarsAllowed.Length; a++)
                {
                    if (CarsAllowed[a] == LFSCars[i])
                    {
                        carstring = carstring + "+" + CarsAllowed[a];
                        newCfg.varsLapper.AllowedCars = carstring.Substring(1); //remove 1st char "+"
                    }
                }
            }
            */
        }

        void managePacket(InSim.Decoder.VTN vtn)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByUCID(vtn.UCID);
            if (currInfoPlayer == null)
                return;
            //            Console.WriteLine("Votation FROM " + currInfoPlayer.nickName);
            // Ignore votation from admin, but do action
            if (vtn.UCID == 0)
            {
                if (vtn.Action == (int)InSim.vtn.VOTE_END)
                    currVotation.allowEnd = true;
                if (vtn.Action == (int)InSim.vtn.VOTE_RESTART)
                    currVotation.allowRestart = true;
                if (vtn.Action == (int)InSim.vtn.VOTE_QUALIFY)
                    currVotation.allowQualify = true;
            }
            else
            {
                if (currRace.inRace == false || (currRace.inRace && currRace.lapsDone >= InRaceLapsVoteMin && currRace.lapsDone <= InRaceLapsVoteMax && InRaceLapsVoteMax != 0))
                {
                    currInfoPlayer.currVote = vtn.Action;
                    currInfoPlayer.expireVote = DateTime.Now.AddSeconds(newCfg.varsLapper.VoteLifeSec);
                }
                else
                {
                    currInfoPlayer.currVote = (int)InSim.vtn.VOTE_NONE;
                    currInfoPlayer.expireVote = DateTime.Now.AddSeconds(newCfg.varsLapper.VoteLifeSec);
                }
            }

        }

        void managePacket(InSim.Decoder.PFL pfl)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(pfl.PLID);
            if (currInfoPlayer == null)
                return;
            if (currInfoPlayer.OnTrack)
                actionPlayerFlags(pfl.Flags, currInfoPlayer, true);

        }

        void managePacket(InSim.Decoder.PLA pla)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(pla.PLID);
            if (currInfoPlayer == null)
                return;
            if (pla.fact == InSim.fact.PITLANE_EXIT)
            {
                string[] args = new string[1];
                args[0] = currInfoPlayer.userName;
                newCfg.executeFunction("OnExitPitLane", currInfoPlayer, args);
            }
            else
            {
                string[] args = new string[2];
                string fact = "";
                try
                {
                    fact = Enum.GetName(typeof(InSim.fact), pla.fact);
                }
                catch
                {
                }
                if (fact == "")
                    fact = "UNKNOWN";
                fact = fact.Remove(0, 8);

                args[0] = currInfoPlayer.userName;
                args[1] = fact;
                newCfg.executeFunction("OnEnterPitLane", currInfoPlayer, args);
            }
        }

        void managePacket(InSim.Decoder.CON con)//CarContact
        {
            infoPlayer currInfoPlayer_PlayerA;
            infoPlayer currInfoPlayer_PlayerB;
            currInfoPlayer_PlayerA = listOfPlayers.getPlayerByPLID(con.PlayerA.PLID);
            currInfoPlayer_PlayerB = listOfPlayers.getPlayerByPLID(con.PlayerB.PLID);

            if ((currInfoPlayer_PlayerA == null) || (currInfoPlayer_PlayerB == null))
            {
                return;
            }

            double PlayerASpeed = con.PlayerA.Speed * 3.6; //km/h
            double PlayerBSpeed = con.PlayerB.Speed * 3.6; //km/h

            double PlayerA_X = con.PlayerA.X / 16;
            double PlayerA_Y = con.PlayerA.Y / 16;
            double PlayerB_X = con.PlayerB.X / 16;
            double PlayerB_Y = con.PlayerB.Y / 16;

            string[] args = new string[8];
            args[0] = currInfoPlayer_PlayerA.userName;
            args[1] = currInfoPlayer_PlayerB.userName;
            args[2] = PlayerASpeed.ToString();
            args[3] = PlayerBSpeed.ToString();
            args[4] = PlayerA_X.ToString();
            args[5] = PlayerB_X.ToString();
            args[6] = PlayerA_Y.ToString();
            args[7] = PlayerB_Y.ToString();
            newCfg.executeFunction("OnCarContact", currInfoPlayer_PlayerA, args);
        }

        void managePacket(InSim.Decoder.UCO uco) //Insim Checker/Checkpoint
        {
            try
            {
                infoPlayer currInfoPlayer;
                currInfoPlayer = listOfPlayers.getPlayerByPLID(uco.PLID);
                if (currInfoPlayer == null)
                {
                    return;
                }

                string objectHit;
                double Speed;
                int CircleIndex;
                int TypeCheckpoint = 0;


                objectHit = Objects(uco.OBJInfo.Index);

                if (currInfoPlayer.unitSpeedKmh)
                {
                    Speed = uco.C.Speed * 3.6; // MS >> KMH
                }
                else
                {
                    Speed = Math.Round(uco.C.Speed * 2.236936, 1);// MS >> MPH
                }

                if (uco.OBJInfo.Index == 253)
                {
                    CircleIndex = uco.OBJInfo.Heading;
                }
                else
                {
                    CircleIndex = uco.OBJInfo.Index;
                    TypeCheckpoint = uco.OBJInfo.Flags % 4;
                    if (TypeCheckpoint == 1)
                    {
                        objectHit = "1st checkpoint";
                    }
                    if (TypeCheckpoint == 2)
                    {
                        objectHit = "2nd checkpoint";
                    }
                    if (TypeCheckpoint == 3)
                    {
                        objectHit = "3rd checkpoint";
                    }
                    if (TypeCheckpoint == 0)
                    {
                        objectHit = "Finish line";
                    }
                }
                int Time = uco.Time * 10;
                string[] args = new string[6];
                args[0] = currInfoPlayer.userName;
                args[1] = uco.UCOAction.ToString();
                args[2] = unitConv.LongToHMS(long.Parse(Time.ToString()));
                args[3] = objectHit.ToString();
                args[4] = Speed.ToString();
                args[5] = CircleIndex.ToString();
                newCfg.executeFunction("OnCrossingChecker", currInfoPlayer, args);
            }
            catch
            {
                myDebug.WriteLine("err", "Something went wrong with the UCO insimpacket");
            }
        }

        void managePacket(InSim.Decoder.OBH obh)//ObjectHit
        {
            #region Detect Type of object detection value
            if (newCfg.varsLapper.DetectHitObject != "")
            {
                if (newCfg.varsLapper.DetectHitObject.Contains("All_Tires") && (obh.Index > 47 && obh.Index < 56))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("All_Cones") && ((obh.Index > 19 && obh.Index < 31) || (obh.Index > 39 && obh.Index < 44)))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("All_TurnMarkers") && (obh.Index > 63 && obh.Index < 78))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("All_DistMarkers") && (obh.Index > 83 && obh.Index < 91))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("All_Armco") && (obh.Index > 95 && obh.Index < 99))
                {
                    ExecuteEvent = true;
                }
                #region Concrete Objects
                if (newCfg.varsLapper.DetectHitObject.Contains("All_Concrete") && (obh.Index > 171 && obh.Index < 180))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_Slabs") && (obh.Index == 172))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_Ramps") && (obh.Index == 173))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_Walls") && (obh.Index == 174))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_Pillars") && (obh.Index == 175))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_SlabWalls") && (obh.Index == 176))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_RampWalls") && (obh.Index == 177))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_ShortSlabWalls") && (obh.Index == 178))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Concrete_Wedges") && (obh.Index == 179))
                {
                    ExecuteEvent = true;
                }
                #endregion


                if (newCfg.varsLapper.DetectHitObject.Contains("Banners") && (obh.Index > 111 && obh.Index < 114))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("SpeedBumps") && (obh.Index > 127 && obh.Index < 130))
                {
                    ExecuteEvent = true;
                }
                #region BarrierObjects
                if (newCfg.varsLapper.DetectHitObject.Contains("All_Barriers") && (obh.Index > 103 && obh.Index < 107))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Long_Barrier") && (obh.Index == 104))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Red_Barrier") && (obh.Index == 105))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("White_Barrier") && (obh.Index == 106))
                {
                    ExecuteEvent = true;
                }
                #endregion
                #region PostObjects
                if (newCfg.varsLapper.DetectHitObject.Contains("All_Post") && (obh.Index > 135 && obh.Index < 140))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Green_Post") && (obh.Index == 136))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Orange_Post") && (obh.Index == 137))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Red_Post") && (obh.Index == 138))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("White_Post") && (obh.Index == 139))
                {
                    ExecuteEvent = true;
                }
                #endregion

                if (newCfg.varsLapper.DetectHitObject.Contains("KeepSigns") && (obh.Index > 159 && obh.Index < 162))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("SpeedSigns") && (obh.Index > 167 && obh.Index < 170))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Bale") && (obh.Index == 144))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("Railing") && (obh.Index == 148))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("TrackSide_Objects") && (obh.Index == 0))
                {
                    ExecuteEvent = true;
                }
                if (newCfg.varsLapper.DetectHitObject.Contains("All_Objects"))
                {
                    ExecuteEvent = true;
                }
            }
            else
            {
                ExecuteEvent = false;
            }
            #endregion

            if (ExecuteEvent == true)
            {
                string objectHit;
                infoPlayer currInfoPlayer;
                currInfoPlayer = listOfPlayers.getPlayerByPLID(obh.PLID);
                if (currInfoPlayer == null)
                    return;
                objectHit = Objects(obh.Index);

                if (currInfoPlayer.unitSpeedKmh)
                {
                    currInfoPlayer.ObjectContactSpeed = obh.CarCont.Speed; //KMH
                }
                else
                {
                    currInfoPlayer.ObjectContactSpeed = Math.Round(obh.CarCont.Speed * 0.62137, 1);//KMH >> MPH
                }
                currInfoPlayer.ObjectContactDir = obh.CarCont.Direction;
                currInfoPlayer.ObjectContactHead = obh.CarCont.Heading;
                int ObjectX = obh.ObjectPosX / 16;
                int ObjectY = obh.ObjectPosY / 16;
                int ObjectZ = obh.ObjectPosZ;
                int Time = obh.ObjectHitTime * 10;


                string[] args = new string[9];
                args[0] = currInfoPlayer.userName;
                args[1] = obh.OBHFlags.ToString();
                args[2] = Time.ToString();
                args[3] = ObjectX.ToString();
                args[4] = ObjectY.ToString();
                args[5] = ObjectZ.ToString();
                args[6] = objectHit.ToString();
                args[7] = obh.Index.ToString();
                args[8] = currInfoPlayer.ObjectContactSpeed.ToString();
                newCfg.executeFunction("OnObjectHit", currInfoPlayer, args);
                ExecuteEvent = false; // Event is executed
            }
        }

        void managePacket(InSim.Decoder.AXM axm)//Layout information
        {
            if (newCfg.varsLapper.DisplayObjectInfo != -1)
            {
                infoPlayer currInfoPlayer;
                infoPlayer NewPlayerInfo;
                currInfoPlayer = listOfPlayers.getPlayerByUCID(axm.UCID);

                if (PlayerOfObject == "")
                {
                    if (currInfoPlayer != null)
                    {
                        PlayerOfObject = currInfoPlayer.userName;
                    }
                    else
                    {
                        PlayerOfObject = "Insim/Host";
                    }
                }
                NewPlayerInfo = listOfPlayers.getPlayerByUserName(PlayerOfObject);

                double[] ObjectX = new double[axm.NumO];
                double[] ObjectY = new double[axm.NumO];
                int[] ObjectZ = new int[axm.NumO];
                int[] ObjectHeading = new int[axm.NumO];
                int[] ObjectFlag = new int[axm.NumO];
                int[] ObjectIndex = new int[axm.NumO];
                string[] ObjectType = new string[axm.NumO];

                for (int i = 0; i < axm.NumO; i++)
                {
                    ObjectX[i] = Math.Round((double)axm.OBJInfo[i].X / 16, 2);
                    ObjectY[i] = Math.Round((double)axm.OBJInfo[i].Y / 16, 2);
                    ObjectZ[i] = axm.OBJInfo[i].Z;
                    ObjectHeading[i] = axm.OBJInfo[i].Heading;
                    ObjectFlag[i] = axm.OBJInfo[i].Flags;
                    ObjectIndex[i] = axm.OBJInfo[i].Index;
                    ObjectType[i] = Objects(axm.OBJInfo[i].Index);
                }

                string[] args = new string[4];
                args[0] = PlayerOfObject;
                args[1] = axm.NumO.ToString();
                args[2] = axm.PMOAction.ToString();

                for (int i = 0; i < axm.NumO; i++)
                {
                    if (i != 0)
                    {
                        args[3] = args[3] + "|" + ObjectX[i] + ":" + ObjectY[i] + ":" + ObjectZ[i] + ":" + ObjectHeading[i] + ":" + ObjectFlag[i] + ":" + ObjectIndex[i] + ":" + ObjectType[i];
                    }
                    else
                    {
                        args[3] = ObjectX[i].ToString() + ":" + ObjectY[i].ToString() + ":" + ObjectZ[i].ToString() + ":" + ObjectHeading[i].ToString() + ":" + ObjectFlag[i].ToString() + ":" + ObjectIndex[i].ToString() + ":" + ObjectType[i].ToString();
                    }
                }
                newCfg.executeFunction("OnObjectInfo", NewPlayerInfo, args);
                PlayerOfObject = "";
            }
        }

        void managePacket(InSim.Decoder.AXI axi) //Layout information
        {
            if (axi.NumO > 1)
            {

                SendMsgToConnection(PlayerLayoutInfoRequest, "^7==========Layout Information==========", 0);
                SendMsgToConnection(PlayerLayoutInfoRequest, "^7Number of Objects: ^8" + axi.NumO, 0);
                SendMsgToConnection(PlayerLayoutInfoRequest, "^7Number of Checkpoints: ^8" + axi.NumCP, 0);
                SendMsgToConnection(PlayerLayoutInfoRequest, "^7Number of Startarrows: ^8" + axi.AXStart, 0);
                if (axi.LayoutName != "")
                {
                    SendMsgToConnection(PlayerLayoutInfoRequest, "Layoutname: ^8" + axi.LayoutName, 0);
                }
                SendMsgToConnection(PlayerLayoutInfoRequest, "^7====================================", 0);
            }
            else
            {
                SendMsgToConnection(PlayerLayoutInfoRequest, "^7No Layout detected!", 0);
            }
        }

        void managePacket(InSim.Decoder.NCI nci)// New Conn Info - sent on host only if an admin password has been set
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByUCID(nci.UCID);

            switch (nci.Language)
            {
                case 0: currInfoPlayer.LFS_Language = "ENGLISH"; break;
                case 1: currInfoPlayer.LFS_Language = "DEUTSCH"; break;
                case 2: currInfoPlayer.LFS_Language = "PORTUGUESE"; break;
                case 3: currInfoPlayer.LFS_Language = "FRENCH"; break;
                case 4: currInfoPlayer.LFS_Language = "SUOMI"; break;
                case 5: currInfoPlayer.LFS_Language = "NORSK"; break;
                case 6: currInfoPlayer.LFS_Language = "NEDERLANDS"; break;
                case 7: currInfoPlayer.LFS_Language = "CATALAN"; break;
                case 8: currInfoPlayer.LFS_Language = "TURKISH"; break;
                case 9: currInfoPlayer.LFS_Language = "CASTELLANO"; break;
                case 10: currInfoPlayer.LFS_Language = "ITALIANO"; break;
                case 11: currInfoPlayer.LFS_Language = "DANSK"; break;
                case 12: currInfoPlayer.LFS_Language = "CZECH"; break;
                case 13: currInfoPlayer.LFS_Language = "RUSSIAN"; break;
                case 14: currInfoPlayer.LFS_Language = "ESTONIAN"; break;
                case 15: currInfoPlayer.LFS_Language = "SERBIAN"; break;
                case 16: currInfoPlayer.LFS_Language = "GREEK"; break;
                case 17: currInfoPlayer.LFS_Language = "POLSKI"; break;
                case 18: currInfoPlayer.LFS_Language = "CROATIAN"; break;
                case 19: currInfoPlayer.LFS_Language = "HUNGARIAN"; break;
                case 20: currInfoPlayer.LFS_Language = "BRAZILIAN"; break;
                case 21: currInfoPlayer.LFS_Language = "SWEDISH"; break;
                case 22: currInfoPlayer.LFS_Language = "SLOVAK"; break;
                case 23: currInfoPlayer.LFS_Language = "GALEGO"; break;
                case 24: currInfoPlayer.LFS_Language = "SLOVENSKI"; break;
                case 25: currInfoPlayer.LFS_Language = "BELARUSSIAN"; break;
                case 26: currInfoPlayer.LFS_Language = "LATVIAN"; break;
                case 27: currInfoPlayer.LFS_Language = "LITHUANIAN"; break;
                case 28: currInfoPlayer.LFS_Language = "TRADITIONAL_CHINESE"; break;
                case 29: currInfoPlayer.LFS_Language = "SIMPLIFIED_CHINESE"; break;
                case 30: currInfoPlayer.LFS_Language = "JAPANESE"; break;
                case 31: currInfoPlayer.LFS_Language = "KOREAN"; break;
                case 32: currInfoPlayer.LFS_Language = "BULGARIAN"; break;
                case 33: currInfoPlayer.LFS_Language = "LATINO"; break;
                case 34: currInfoPlayer.LFS_Language = "UKRAINIAN"; break;
                case 35: currInfoPlayer.LFS_Language = "INDONESIAN"; break;
                case 36: currInfoPlayer.LFS_Language = "ROMANIAN"; break;
                case 37: currInfoPlayer.LFS_Language = "NUM_LANG"; break;
            }
            currInfoPlayer.LFS_UserID = Convert.ToUInt32(nci.UserID);
            currInfoPlayer.DecimalIPAddress = Convert.ToUInt32(nci.IP);
            currInfoPlayer.IPAddress = nci.IPAddress.ToString();
        }

        void managePacket(InSim.Decoder.CSC csc)//Car State Changed (Idling/Driving)
        {
            infoPlayer currInfoPlayer;
            currInfoPlayer = listOfPlayers.getPlayerByPLID(csc.PLID);
            string[] args = new string[2];

            if (currInfoPlayer == null)
                return;

            args[0] = currInfoPlayer.userName;
            args[1] = csc.CSCAction.ToString();
            newCfg.executeFunction("OnCarStateChanged", currInfoPlayer, args);
        }

        void managePacket(InSim.Decoder.ACR acr)//Admin Command Report
        {
            infoPlayer Player;
            Player = listOfPlayers.getPlayerByUCID(acr.UCID);
            string[] args = new string[5];

            //Is player doesnt exist or is a host
            if ((Player == null) || (acr.UCID == 0))
                return;

            args[0] = Player.userName;
            args[1] = acr.Admin.ToString();
            args[2] = acr.Result.ToString();
            args[3] = acr.Text.ToString();
            args[4] = utils.quote(System.DateTime.Now.ToString(newCfg.varsLapper.LongTimeFormat));
            newCfg.executeFunction("OnAdminCommandReport", Player, args);
        }

        void managePacket(InSim.Decoder.SLC slc)//Player select car
        {
            infoPlayer Player;
            Player = listOfPlayers.getPlayerByUCID(slc.UCID);

            //Is player doesnt exist or is a host
            if ((Player == null) || (slc.UCID == 0))
                return;

            string[] args = new string[3];
            args[0] = Player.userName;
            args[1] = slc.CName.ToString();
            args[2] = utils.quote(System.DateTime.Now.ToString(newCfg.varsLapper.LongTimeFormat));
            newCfg.executeFunction("OnPlayerSelectCar", Player, args);
        }

        void managePacket(InSim.Decoder.HLV hlv)//HotLap Validation
        {
            infoPlayer Player;
            Player = listOfPlayers.getPlayerByPLID(hlv.PLID);
            string[] args = new string[3];

            //Is player doesnt exist or is a host
            if (Player == null)
                return;

            args[0] = Player.userName;
            args[1] = hlv.HVLC.ToString();
            args[2] = utils.quote(System.DateTime.Now.ToString(newCfg.varsLapper.LongTimeFormat));
            newCfg.executeFunction("OnLapValidation", Player, args);
        }

        void managePacket(InSim.Decoder.CIM cim)//Menu selecting
        {
            infoPlayer Player;
            Player = listOfPlayers.getPlayerByUCID(cim.UCID);
            string[] args = new string[5];

            //Is player doesnt exist or is a host
            if (Player == null)
                return;

            args[0] = Player.userName;
            args[1] = cim.Mode.ToString();
            args[2] = cim.SubMode.ToString();
            args[3] = cim.SelType.ToString();
            args[4] = utils.quote(System.DateTime.Now.ToString(newCfg.varsLapper.LongTimeFormat));
            newCfg.executeFunction("OnInterfaceMode", Player, args);
        }

        void managePacket(InSim.Decoder.MAL mal)//Get Selected mods.
        {
            newCfg.varsLapper.AmountofModdedCars = mal.NumM;
            newCfg.ListOfAllowedModdedCars.Clear();
            newCfg.ListOfAllowedModdedCars.AddRange(mal.SkinIDHex);

        }

        void managePacket(InSim.Decoder.IPB ipb)//Get list of banned IP's.
        {
            newCfg.varsLapper.AmountofIPBans = ipb.NumB;
            newCfg.ListOfIPBans.Clear();
            newCfg.ListOfIPBans.AddRange(ipb.IPBans);
        }

        void managePacket(InSim.Decoder.PLH plh)//Get list of players with Handicaps.
        {
            infoPlayer Player;
            string[] args = new string[4];

            string[] UserName = new string[plh.NumP];
            int[] Flags = new int[plh.NumP];
            int[] H_Mass = new int[plh.NumP];
            int[] H_Tres = new int[plh.NumP];

            for (int i = 0; i < plh.NumP; i++)
            {
                Player = listOfPlayers.getPlayerByPLID(plh.Ply_HCap[i].PLID);
                UserName[i] = Player.userName;
                Flags[i] = plh.Ply_HCap[i].Flags;
                H_Mass[i] = plh.Ply_HCap[i].H_Mass;
                H_Tres[i] = plh.Ply_HCap[i].H_Tres;

                args[0] = UserName[i].ToString();
                args[1] = Flags[i].ToString();
                args[2] = H_Mass[i].ToString();
                args[3] = H_Tres[i].ToString();

                newCfg.executeFunction("OnPlayerHandicap", Player, args);
            }
        }
    }

}
