private NetworkSenderThread()
    {
        waitHandle          = new EventWaitHandle(true, EventResetMode.ManualReset);
        messageCounterTypes = new Dictionary <MessageType, ulong>();

        messageQueue = new ConcurrentQueue <OutgoingNetworkPacketContainer>();

        packetSingle = new PacketSingle();

        binaryFormatter = new BinaryFormatter();

        newPlayerQueue     = new ConcurrentQueue <CSteamID>();
        removePlayerQueue  = new ConcurrentQueue <CSteamID>();
        internalPlayerList = new List <CSteamID>();

        networkThread = new Thread(ThreadMethod);

        dumpAllExistingPlayers = false;

        networkThread.IsBackground = true;
        networkThread.Start();

        networkThread.Priority = ThreadPriority.AboveNormal;
    }
    private void ReadP2PPacket(byte[] array, uint num, uint num2, CSteamID csteamID)
    {
        MemoryStream serializationStream = new MemoryStream(array);
        Packet       packet = new BinaryFormatter().Deserialize(serializationStream) as Packet;

        if (packet.packetType == PacketType.Single)
        {
            PacketSingle packetS = packet as PacketSingle;
            switch (packetS.message.type)
            {
            case MessageType.None:
                break;

            case MessageType.LobbyInfoRequest:
                SendP2P(csteamID,
                        new Message_LobbyInfoRequest_Result(SteamFriends.GetPersonaName(),
                                                            PilotSaveManager.currentVehicle.vehicleName,
                                                            PilotSaveManager.currentScenario.scenarioName,
                                                            PilotSaveManager.currentCampaign.campaignName,
                                                            PlayerManager.players.Count.ToString()),
                        EP2PSend.k_EP2PSendReliable);
                break;

            case MessageType.LobbyInfoRequest_Result:
                Message_LobbyInfoRequest_Result result = packetS.message as Message_LobbyInfoRequest_Result;
                Multiplayer._instance.lobbyInfoText.text = result.username + "'s Game\n" + result.vehicle + "\n" + result.campaign + " " + result.scenario + "\n" + (result.playercount == "1" ? result.playercount + " Player" : result.playercount + " Players");
                break;

            case MessageType.JoinRequest:
                if (!isHost)
                {
                    Debug.LogError($"Recived Join Request when we are not the host");
                    return;
                }
                Message_JoinRequest joinRequest = packetS.message as Message_JoinRequest;
                if (players.Contains(csteamID))
                {
                    Debug.LogError("The player seemed to send two join requests");
                    return;
                }
                if (joinRequest.currentVehicle == PilotSaveManager.currentVehicle.vehicleName &&
                    joinRequest.currentScenario == PilotSaveManager.currentScenario.scenarioID &&
                    joinRequest.currentCampaign == PilotSaveManager.currentCampaign.campaignID)
                {
                    Debug.Log($"Accepting {csteamID.m_SteamID}");
                    players.Add(csteamID);
                    readyDic.Add(csteamID, false);
                    UpdateLoadingText();
                    SendP2P(csteamID, new Message_JoinRequest_Result(true), EP2PSend.k_EP2PSendReliable);
                }
                else
                {
                    string reason = "Failed to Join Player";
                    if (joinRequest.currentVehicle != PilotSaveManager.currentVehicle.vehicleName)
                    {
                        reason += "\nWrong Vehicle.";
                    }
                    if (joinRequest.currentScenario != PilotSaveManager.currentScenario.scenarioID)
                    {
                        reason += "\nWrong Scenario.";
                    }
                    if (joinRequest.currentCampaign != PilotSaveManager.currentCampaign.campaignID)
                    {
                        reason += "\nWrong Campaign.";
                    }
                    SendP2P(csteamID, new Message_JoinRequest_Result(false, reason), EP2PSend.k_EP2PSendReliable);
                    Debug.Log($"Denied {csteamID}, reason\n{reason}");
                }
                break;

            case MessageType.JoinRequest_Result:
                Message_JoinRequest_Result joinResult = packetS.message as Message_JoinRequest_Result;
                if (joinResult.canJoin)
                {
                    Debug.Log($"Joining {csteamID.m_SteamID}");
                    hostID = csteamID;
                    StartCoroutine(FlyButton());
                }
                else
                {
                    Debug.LogWarning($"We can't join {csteamID.m_SteamID} reason = \n{joinResult.reason}");
                }
                break;

            case MessageType.Ready:
                //The client has said they are ready to start, so we change it in the dictionary
                if (readyDic.ContainsKey(csteamID))
                {
                    Debug.Log($"{csteamID.m_SteamID} has said they are ready!\nHost ready state {hostReady}");
                    readyDic[csteamID] = true;
                    if (alreadyInGame)
                    {
                        //Someone is trying to join when we are already in game.
                        Debug.Log($"We are already in session, {csteamID} is joining in!");
                        SendP2P(csteamID, new Message(MessageType.Ready_Result), EP2PSend.k_EP2PSendReliable);
                        break;
                    }
                    else if (hostReady && EveryoneElseReady())
                    {
                        Debug.Log("The last client has said they are ready, starting");
                        SendGlobalP2P(new Message(MessageType.Ready_Result), EP2PSend.k_EP2PSendReliable);
                        LoadingSceneController.instance.PlayerReady();
                    }
                    UpdateLoadingText();
                }
                break;

            case MessageType.Ready_Result:
                Debug.Log("The host said everyone is ready, launching the mission");
                hostReady = true;
                LoadingSceneController.instance.PlayerReady();
                break;

            case MessageType.RequestSpawn:
                if (RequestSpawn != null)
                {
                    RequestSpawn.Invoke(packet, csteamID);
                }
                break;

            case MessageType.RequestSpawn_Result:
                if (RequestSpawn_Result != null)
                {
                    RequestSpawn_Result.Invoke(packet);
                }
                break;

            case MessageType.SpawnVehicle:
                if (SpawnVehicle != null)
                {
                    SpawnVehicle.Invoke(packet);
                }
                break;

            case MessageType.RigidbodyUpdate:
                if (RigidbodyUpdate != null)
                {
                    RigidbodyUpdate.Invoke(packet);
                }
                break;

            case MessageType.PlaneUpdate:
                if (PlaneUpdate != null)
                {
                    PlaneUpdate.Invoke(packet);
                }
                break;

            case MessageType.EngineTiltUpdate:
                if (EngineTiltUpdate != null)
                {
                    EngineTiltUpdate.Invoke(packet);
                }
                break;

            case MessageType.Disconnecting:

                if (isHost)
                {
                    if (Multiplayer.SoloTesting)
                    {
                        break;
                    }
                    players.Remove(csteamID);
                    SendGlobalP2P(packet);
                }
                else
                {
                    Message_Disconnecting messsage = ((PacketSingle)packet).message as Message_Disconnecting;
                    if (messsage.isHost)
                    {
                        //If it is the host quiting we just need to quit the mission as all networking will be lost.
                        FlightSceneManager flightSceneManager = FindObjectOfType <FlightSceneManager>();
                        if (flightSceneManager == null)
                        {
                            Debug.LogError("FlightSceneManager was null when host quit");
                        }
                        flightSceneManager.ExitScene();
                    }
                    break;
                }
                if (Disconnecting != null)
                {
                    Disconnecting.Invoke(packet);
                }
                break;

            case MessageType.WeaponsSet:
                if (WeaponSet != null)
                {
                    WeaponSet.Invoke(packet);
                }
                break;

            case MessageType.WeaponsSet_Result:
                if (WeaponSet_Result != null)
                {
                    WeaponSet_Result.Invoke(packet);
                }
                if (isHost)
                {
                    SendGlobalP2P(packet);
                }
                break;

            case MessageType.WeaponFiring:
                if (WeaponFiring != null)
                {
                    WeaponFiring.Invoke(packet);
                }
                break;

            case MessageType.WeaponStoppedFiring:
                if (WeaponStoppedFiring != null)
                {
                    WeaponStoppedFiring.Invoke(packet);
                }
                break;

            case MessageType.MissileUpdate:
                if (MissileUpdate != null)
                {
                    MissileUpdate.Invoke(packet);
                }
                break;

            case MessageType.RequestNetworkUID:
                if (RequestNetworkUID != null)
                {
                    RequestNetworkUID.Invoke(packet);
                }
                break;

            case MessageType.LoadingTextUpdate:
                if (!isHost)
                {
                    UpdateLoadingText(packet);
                }
                break;

            default:
                break;
            }
        }
    }
    /// <summary>
    /// Sends a P2P Message to another user.
    /// </summary>
    /// <param name="remoteID">The target user to send the packet to.</param>
    /// <param name="message">The message to be send to that user.</param>
    /// <param name="sendType">Specifies how you want the data to be transmitted, such as reliably, unreliable, buffered, etc.</param>
    public static void SendP2P(CSteamID remoteID, Message message, EP2PSend sendType)
    {
        PacketSingle packet = new PacketSingle(message, sendType);

        SendP2P(remoteID, packet);
    }