void CClientPacketRecorder::RecordPacket(unsigned char ucPacketID, NetBitStreamInterface& bitStream)
{
    if (m_bRecording && m_szFilename)
    {
        // Open our file
        FILE* pFile = fopen(m_szFilename, "ab+");
        if (pFile)
        {
            // Write our timestamp
            if (m_bFrameBased)
            {
                long lFrameStamp = m_lFrames - m_lRelative;
                fwrite(&lFrameStamp, sizeof(long), 1, pFile);
            }
            else
            {
                long lTimeStamp = CClientTime::GetTime() - m_lRelative;
                fwrite(&lTimeStamp, sizeof(long), 1, pFile);
            }
            //          fwrite ( &ulTimeStamp, sizeof ( unsigned long), 1, pFile );

            // Write the packet ID
            fputc(ucPacketID, pFile);

            // Write the size of the bitstream
            unsigned long ulSize = static_cast<unsigned long>(bitStream.GetNumberOfBytesUsed());
            fwrite(&ulSize, sizeof(unsigned long), 1, pFile);

            // Write the content of the bitstream to the file
            char c = 0;
            for (unsigned long i = 0; i < ulSize; i++)
            {
                bitStream.Read(c);
                fputc(c, pFile);
            }

            // Reset the readpointer so the client can use it
            bitStream.ResetReadPointer();

            // Close the file
            fclose(pFile);
        }
    }
}
bool CConnectManager::StaticProcessPacket ( unsigned char ucPacketID, NetBitStreamInterface& BitStream )
{
    // We're working on connecting?
    if ( g_pConnectManager->m_bIsConnecting )
    {
        // The packet we're expecting?
        if ( ucPacketID == PACKET_ID_MOD_NAME )
        {
            // Read out the mod to load
            char* szModName = new char [ BitStream.GetNumberOfBytesUsed () + 1 ];
            memset ( szModName, 0, BitStream.GetNumberOfBytesUsed () + 1 );
            if ( BitStream.Read ( szModName, BitStream.GetNumberOfBytesUsed () ) )
            {
                // Backward compatibly examine the bytes following the mod name
                BitStream.ResetReadPointer ();
                BitStream.Read ( szModName, strlen ( szModName ) );
                char cPad;
                BitStream.Read ( cPad );
                unsigned short usServerBitStreamVersion = 0x01;
                BitStream.Read ( usServerBitStreamVersion );    // This will silently fail for < 1.0.2 and leave the bitstream version at 0x01
                CCore::GetSingleton ().GetNetwork ()->SetServerBitStreamVersion ( usServerBitStreamVersion );

                // Limit the nick length for servers that have a problem with max length nicks
                if ( usServerBitStreamVersion < 0x06 )
                    g_pConnectManager->m_strNick = g_pConnectManager->m_strNick.substr ( 0, MAX_PLAYER_NICK_LENGTH - 1 );

                // Populate the arguments to pass it (-c host port nick)
                SString strArguments ( "%s %s", g_pConnectManager->m_strNick.c_str(), g_pConnectManager->m_strPassword.c_str() );

                // Hide the messagebox we're currently showing
                CCore::GetSingleton ().RemoveMessageBox ();

                // If we connected from quick-connect, get rid of it
                CQuickConnect * pQuickConnect = CCore::GetSingleton ().GetLocalGUI ()->GetMainMenu ()->GetQuickConnectWindow ();
                if ( pQuickConnect->IsVisible () )
                    pQuickConnect->SetVisible ( false );

                // Save the connection details into the config
                CVARS_SET ( "host",     g_pConnectManager->m_strHost );
                CVARS_SET ( "port",     g_pConnectManager->m_usPort );
                CVARS_SET ( "password", g_pConnectManager->m_strPassword );

                //Conver the Address to an unsigned long
                unsigned long ulAddr = inet_addr( g_pConnectManager->m_strHost.c_str() );

                //Create an instance of the in_addr structure to store the address
                in_addr Address;
                //Set the address to the unsigned long we just created
                Address.S_un.S_addr = ulAddr;
                //Set the current server info and Add the ASE Offset to the Query port)
                CCore::GetSingleton().SetCurrentServer ( Address, g_pConnectManager->m_usPort + 123 );

                // Kevuwk: Forced the config to save here so that the IP/Port isn't lost on crash
                CCore::GetSingleton ().SaveConfig ();

                // Reset our variables
                g_pConnectManager->m_strNick = "";
                g_pConnectManager->m_strHost = "";
                g_pConnectManager->m_strPassword = "";

                g_pConnectManager->m_usPort = 0;
                g_pConnectManager->m_bIsConnecting = false;
                g_pConnectManager->m_tConnectStarted = 0;

                // Load the mod
                if ( !CModManager::GetSingleton ().Load ( szModName, strArguments ) )
                {
                    // Failed loading the mod
                    strArguments.Format ( "No such mod installed (%s)", szModName );
                    CCore::GetSingleton ().ShowMessageBox ( "Error", strArguments, MB_BUTTON_OK | MB_ICON_ERROR );
                    g_pConnectManager->Abort ();
                }
            }
            else
            {
                // Show failed message and abort the attempt
                CCore::GetSingleton ().ShowMessageBox ( "Error", "Bad server response (2)", MB_BUTTON_OK | MB_ICON_ERROR );
                g_pConnectManager->Abort ();
            }

            delete [] szModName;
        }
        else
        {
            // Not the player joined packet?
            if ( ucPacketID != PACKET_ID_SERVER_JOIN && ucPacketID != PACKET_ID_SERVER_JOIN_DATA )
            {
                // Show failed message and abort the attempt
                CCore::GetSingleton ().ShowMessageBox ( "Error", "Bad server response (1)", MB_BUTTON_OK | MB_ICON_ERROR );
                g_pConnectManager->Abort ();
            }
        }

        return true;
    }

    return false;
}
///////////////////////////////////////////////////////////////
//
// CLatentReceiver::OnReceive
//
//
//
///////////////////////////////////////////////////////////////
void CLatentReceiver::OnReceive ( NetBitStreamInterface* pBitStream )
{
    //
    // Read header
    //
    ushort usId = 0;
    bool bIsHead = false;
    bool bIsTail = false;
    bool bIsCancel = false;
    ushort usCategory = 0;
    ushort usResourceNetId = 0xFFFF;
    uint uiFinalSize = 0;
    uint uiRate = 0;

    pBitStream->ReadBits ( &usId, 15 );
    if ( pBitStream->ReadBit () )
    {
        // Special type
        uchar ucSpecialFlag;
        pBitStream->Read ( ucSpecialFlag );
        if ( ucSpecialFlag == FLAG_HEAD )
        {
            bIsHead = true;
            pBitStream->Read ( usCategory );
            pBitStream->Read ( uiFinalSize );
            pBitStream->Read ( uiRate );
            if ( pBitStream->Version () >= 0x31 )
                pBitStream->Read ( usResourceNetId );
        }
        else
        if ( ucSpecialFlag == FLAG_TAIL )
        {
            bIsTail = true;
        }
        else
        if ( ucSpecialFlag == FLAG_CANCEL )
        {
            bIsCancel = true;
        }
        else
        {
            return OnReceiveError ( "Invalid special type" );
        }
    }

    pBitStream->AlignReadToByteBoundary ();
    ushort usSizeSent = 0;
    pBitStream->Read ( usSizeSent );

    //
    // Process header
    //
    if ( bIsHead )
    {
        // If head, check no previous transfer
        if ( activeRx.bReceiveStarted )
            return OnReceiveError ( "bIsHead && activeRx.bReceiveActive" );
        if ( uiFinalSize > 100 * 1024 * 1024 )
            return OnReceiveError ( "uiFinalSize too large" );

        activeRx.usId = usId;
        activeRx.bReceiveStarted = true;
        activeRx.usCategory = usCategory;
        activeRx.uiRate = uiRate;
        activeRx.usResourceNetId = usResourceNetId;
        activeRx.buffer.SetSize ( uiFinalSize );
        activeRx.uiWritePosition = 0;
    }

    if ( activeRx.usId != usId )
        return OnReceiveError ( "usId wrong" );

    if ( bIsCancel )
    {
        // Reset for next receive
        activeRx = SReceiveItem ();
        return;
    }


    //
    // Read body
    //
    if ( activeRx.uiWritePosition + usSizeSent > activeRx.buffer.GetSize () )
        return OnReceiveError ( "Buffer would overflow" );

    if ( bIsTail && activeRx.uiWritePosition + usSizeSent != activeRx.buffer.GetSize () )
        return OnReceiveError ( "Buffer size wrong" );

    pBitStream->Read ( activeRx.buffer.GetData () + activeRx.uiWritePosition, usSizeSent );
    activeRx.uiWritePosition += usSizeSent;


    //
    // Process tail
    //
    if ( bIsTail )
    {
        if ( activeRx.usCategory == CATEGORY_PACKET )
        {
            // Recreate the packet data
            NetBitStreamInterface* pBitStream = DoAllocateNetBitStream ( m_RemoteId, m_usBitStreamVersion );
            uchar ucPacketId = 0;
            uint uiBitStreamBitsUsed = 0;

            CBufferReadStream stream ( activeRx.buffer );
            stream.Read ( ucPacketId );
            stream.Read ( uiBitStreamBitsUsed );
            uint uiBitStreamBytesUsed = ( uiBitStreamBitsUsed + 7 ) >> 3;

            if ( uiBitStreamBytesUsed != activeRx.buffer.GetSize () - 5 )
                return OnReceiveError ( "Buffer size mismatch" );

            pBitStream->WriteBits ( activeRx.buffer.GetData () + 5, uiBitStreamBitsUsed );
            pBitStream->ResetReadPointer ();

            DoStaticProcessPacket ( ucPacketId, m_RemoteId, pBitStream, activeRx.usResourceNetId );
            DoDeallocateNetBitStream ( pBitStream );
        }
        else
        {
bool CConnectManager::StaticProcessPacket ( unsigned char ucPacketID, NetBitStreamInterface& BitStream )
{
    // We're working on connecting?
    if ( g_pConnectManager->m_bIsConnecting )
    {
        // The packet we're expecting?
        if ( ucPacketID == PACKET_ID_MOD_NAME )
        {
            // Read out the mod to load
            char* szModName = new char [ BitStream.GetNumberOfBytesUsed () + 1 ];
            memset ( szModName, 0, BitStream.GetNumberOfBytesUsed () + 1 );
            if ( BitStream.Read ( szModName, BitStream.GetNumberOfBytesUsed () ) )
            {
                // Backward compatibly examine the bytes following the mod name
                BitStream.ResetReadPointer ();
                BitStream.Read ( szModName, strlen ( szModName ) );
                char cPad;
                BitStream.Read ( cPad );
                unsigned short usServerBitStreamVersion = 0x01;
                BitStream.Read ( usServerBitStreamVersion );    // This will silently fail for < 1.0.2 and leave the bitstream version at 0x01
                CCore::GetSingleton ().GetNetwork ()->SetServerBitStreamVersion ( usServerBitStreamVersion );

                // Populate the arguments to pass it (-c host port nick)
                SString strArguments ( "%s %s", g_pConnectManager->m_strNick.c_str(), g_pConnectManager->m_strPassword.c_str() );

                // Hide the messagebox we're currently showing
                CCore::GetSingleton ().RemoveMessageBox ();

                // If we connected from quick-connect, get rid of it
                CQuickConnect * pQuickConnect = CCore::GetSingleton ().GetLocalGUI ()->GetMainMenu ()->GetQuickConnectWindow ();
                if ( pQuickConnect->IsVisible () )
                    pQuickConnect->SetVisible ( false );

                // Save the connection details into the config
                CVARS_SET ( "host",     g_pConnectManager->m_strHost );
                CVARS_SET ( "port",     g_pConnectManager->m_usPort );
                CVARS_SET ( "password", g_pConnectManager->m_strPassword );


                // Save the connection details into the recently played servers list
                in_addr Address;
                if ( CServerListItem::Parse ( g_pConnectManager->m_strHost.c_str (), Address ) )
                {
                    CServerBrowser* pServerBrowser = CCore::GetSingleton ().GetLocalGUI ()->GetMainMenu ()->GetServerBrowser ();
                    CServerList* pRecentList = pServerBrowser->GetRecentList ();
                    CServerListItem RecentServer ( Address, g_pConnectManager->m_usPort + SERVER_LIST_QUERY_PORT_OFFSET );
                    if ( !pRecentList->Exists ( RecentServer ) )
                    {
                        pRecentList->Add ( RecentServer );
                    }

                    // Set as our current server for xfire
                    if ( XfireIsLoaded () )
                    {
                        const char *szKey[2], *szValue[2];
                        szKey[0] = "Gamemode";
                        szValue[0] = RecentServer.strType.c_str();

                        szKey[1] = "Map";
                        szValue[1] = RecentServer.strMap.c_str();

                        XfireSetCustomGameData ( 2, szKey, szValue ); 
                    }
                }

                // Kevuwk: Forced the config to save here so that the IP/Port isn't lost on crash
                CCore::GetSingleton ().SaveConfig ();

                // Reset our variables
                g_pConnectManager->m_strNick = "";
                g_pConnectManager->m_strHost = "";
                g_pConnectManager->m_strPassword = "";

                g_pConnectManager->m_usPort = 0;
                g_pConnectManager->m_bIsConnecting = false;
                g_pConnectManager->m_tConnectStarted = 0;

                // Load the mod
                if ( !CModManager::GetSingleton ().Load ( szModName, strArguments ) )
                {
                    // Failed loading the mod
                    strArguments.Format ( "No such mod installed (%s)", szModName );
                    CCore::GetSingleton ().ShowMessageBox ( "Error", strArguments, MB_BUTTON_OK | MB_ICON_ERROR );
					g_pConnectManager->Abort ();
                }
            }
            else
            {
                // Show failed message and abort the attempt
                CCore::GetSingleton ().ShowMessageBox ( "Error", "Bad server response (2)", MB_BUTTON_OK | MB_ICON_ERROR );
                g_pConnectManager->Abort ();
            }

            delete [] szModName;
        }
        else
        {
            // Not the player joined packet?
            if ( ucPacketID != PACKET_ID_SERVER_JOIN && ucPacketID != PACKET_ID_SERVER_JOIN_DATA )
            {
                // Show failed message and abort the attempt
                CCore::GetSingleton ().ShowMessageBox ( "Error", "Bad server response (1)", MB_BUTTON_OK | MB_ICON_ERROR );
                g_pConnectManager->Abort ();
            }
        }

        return true;
    }

    return false;
}