Exemple #1
0
bool CMapInfoPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Write the map weather
    BitStream.Write ( m_ucWeather );
    BitStream.Write ( m_ucWeatherBlendingTo );
    BitStream.Write ( m_ucBlendedWeatherHour );

    BitStream.WriteBit ( m_bHasSkyGradient );
    if ( m_bHasSkyGradient )
    {
        BitStream.Write ( m_ucSkyGradientTR );
        BitStream.Write ( m_ucSkyGradientTG );
        BitStream.Write ( m_ucSkyGradientTB );
        BitStream.Write ( m_ucSkyGradientBR );
        BitStream.Write ( m_ucSkyGradientBG );
        BitStream.Write ( m_ucSkyGradientBB );
    }

    // Write the map hour
    BitStream.Write ( m_ucClockHour );
    BitStream.Write ( m_ucClockMin );

    BitStream.WriteCompressed ( m_ulMinuteDuration );

    // Write the map flags
    SMapInfoFlagsSync flags;
    flags.data.bShowNametags  = m_bShowNametags;
    flags.data.bShowRadar     = m_bShowRadar;
    flags.data.bCloudsEnabled = m_bCloudsEnabled;
    BitStream.Write ( &flags );

    // Write any other world conditions
    BitStream.Write ( m_fGravity );
    if ( m_fGameSpeed == 1.0f )
        BitStream.WriteBit ( true );
    else
    {
        BitStream.WriteBit ( false );
        BitStream.Write ( m_fGameSpeed );
    }
    BitStream.Write ( m_fWaveHeight );
    BitStream.Write ( m_fWaterLevel );

    BitStream.WriteCompressed ( m_usFPSLimit );

    // Write the garage states
    for ( unsigned char i = 0 ; i < MAX_GARAGES ; i++ )
    {
        BitStream.WriteBit( static_cast < unsigned char > ( m_pbGarageStates[i] ) );
    }

    // Write the fun bugs state
    SFunBugsStateSync funBugs;
    funBugs.data.bQuickReload = g_pGame->IsGlitchEnabled ( CGame::GLITCH_QUICKRELOAD );
    funBugs.data.bFastFire    = g_pGame->IsGlitchEnabled ( CGame::GLITCH_FASTFIRE );
    funBugs.data.bFastMove    = g_pGame->IsGlitchEnabled ( CGame::GLITCH_FASTMOVE );
    BitStream.Write ( &funBugs );

    return true;
}
bool CLightsyncPacket::Write(NetBitStreamInterface& BitStream) const
{
    bool bSyncPosition;

    if (Count() == 0)
        return false;

    for (std::vector<CPlayer*>::const_iterator iter = m_players.begin(); iter != m_players.end(); ++iter)
    {
        CPlayer*                       pPlayer = *iter;
        CPlayer::SLightweightSyncData& data = pPlayer->GetLightweightSyncData();
        CVehicle*                      pVehicle = pPlayer->GetOccupiedVehicle();

        // Find the difference between now and the time the position last changed for the player
        long long llTicksDifference = GetTickCount64_() - pPlayer->GetPositionLastChanged();

        // Right we need to sync the position if there is no vehicle or he's in a vehicle and the difference between setPosition is less than or equal to the
        // slow sync rate i.e. make sure his position has been updated more than 0.001f in the last 1500ms plus a small margin for error (probably not needed).
        // This will ensure we only send positions when the position has changed.
        bSyncPosition = (!pVehicle || pPlayer->GetOccupiedVehicleSeat() == 0) && llTicksDifference <= g_TickRateSettings.iLightSync + 100;

        BitStream.Write(pPlayer->GetID());
        BitStream.Write((unsigned char)pPlayer->GetSyncTimeContext());

        unsigned short usLatency = pPlayer->GetPing();
        BitStream.WriteCompressed(usLatency);

        BitStream.WriteBit(data.health.bSync);
        if (data.health.bSync)
        {
            SPlayerHealthSync health;
            health.data.fValue = pPlayer->GetHealth();
            BitStream.Write(&health);

            SPlayerArmorSync armor;
            armor.data.fValue = pPlayer->GetArmor();
            BitStream.Write(&armor);
        }

        BitStream.WriteBit(bSyncPosition);
        if (bSyncPosition)
        {
            SLowPrecisionPositionSync pos;
            pos.data.vecPosition = pPlayer->GetPosition();
            BitStream.Write(&pos);

            bool bSyncVehicleHealth = data.vehicleHealth.bSync && pVehicle;
            BitStream.WriteBit(bSyncVehicleHealth);
            if (bSyncVehicleHealth)
            {
                SLowPrecisionVehicleHealthSync health;
                health.data.fValue = pVehicle->GetHealth();
                BitStream.Write(&health);
            }
        }
    }

    return true;
}
 void CPositionRotationAnimation::ToBitStream( NetBitStreamInterface& a_rBitStream, bool a_bResumeMode ) const
 {
     a_rBitStream.WriteBit ( a_bResumeMode );
     if ( a_bResumeMode )
     {
        unsigned long ulNow = _GetTime ();
        unsigned long ulElaspedTime = ulNow - m_ulStartTime;
        unsigned long ulTimeLeft = 0;
        if ( m_ulEndTime > ulNow )
        {
            ulTimeLeft = m_ulEndTime - ulNow;
        }
        a_rBitStream.WriteCompressed ( ulElaspedTime );
        a_rBitStream.WriteCompressed ( ulTimeLeft );
     }
     else
     {
         a_rBitStream.WriteCompressed ( m_ulDuration );
     }

     SPositionSync positionSync;
     positionSync.data.vecPosition = m_SourceValue.m_vecPosition;
     a_rBitStream.Write ( &positionSync );

     SRotationRadiansSync rotationSync ( true ); //RPC function used floats when join time packet didn't, let's go for float
     rotationSync.data.vecRotation = m_SourceValue.m_vecRotation;
     a_rBitStream.Write ( &rotationSync );
    
     positionSync.data.vecPosition = m_TargetValue.m_vecPosition;
     a_rBitStream.Write ( &positionSync );

     a_rBitStream.WriteBit ( m_bDeltaRotationMode );
     if ( m_bDeltaRotationMode )
     {
        rotationSync.data.vecRotation = m_DeltaValue.m_vecRotation; //We serialize DELTA
     }
     else
     {
         rotationSync.data.vecRotation = m_TargetValue.m_vecRotation;
     }
     a_rBitStream.Write ( &rotationSync );

     ////We write the string directly to allow new types without changing netcode (since integer values of enum might change)
     a_rBitStream.WriteString ( CEasingCurve::GetStringFromEasingType( m_easingCurve.GetType() ) );
     double fEasingPeriod, fEasingAmplitude, fEasingOvershoot;
     m_easingCurve.GetParams ( fEasingPeriod, fEasingAmplitude, fEasingOvershoot );
     a_rBitStream.Write ( fEasingPeriod );
     a_rBitStream.Write ( fEasingAmplitude );
     a_rBitStream.Write ( fEasingOvershoot );
 }
///////////////////////////////////////////////////////////////
//
// CLatentSendQueue::SendCancelNotification
//
// Tell remote an in-progress transfer is cancelled
//
///////////////////////////////////////////////////////////////
void CLatentSendQueue::SendCancelNotification ( SSendItem& activeTx )
{
    assert ( activeTx.bSendStarted && !activeTx.bSendFinishing );
    NetBitStreamInterface* pBitStream = DoAllocateNetBitStream ( m_RemoteId, m_usBitStreamVersion );
    pBitStream->WriteBits ( &activeTx.uiId, 15 );
    pBitStream->WriteBit ( 1 );
    pBitStream->Write ( (uchar)FLAG_CANCEL );
    DoSendPacket ( PACKET_ID_LATENT_TRANSFER, m_RemoteId, pBitStream, PACKET_PRIORITY_LOW, PACKET_RELIABILITY_RELIABLE_ORDERED, PACKET_ORDERING_DATA_TRANSFER );
    DoDeallocateNetBitStream ( pBitStream );
}
bool CPickupHitConfirmPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // unsigned short   (2)     - pickup id
    // bool                     - hide it?

    // Got a pickup to send?
    if ( m_pPickup )
    {
        // Write the pickup id and visibily state
        BitStream.Write ( m_pPickup->GetID () );

        // WRite the flags
        BitStream.WriteBit ( m_pPickup->IsVisible () );
        BitStream.WriteBit ( m_bPlaySound );

        return true;
    }

    return false;
}
bool CPlayerJoinCompletePacket::Write ( NetBitStreamInterface& BitStream ) const
{
    BitStream.Write ( m_PlayerID );
    BitStream.Write ( m_ucNumberOfPlayers );
    BitStream.Write ( m_RootElementID );

    // Transmit server requirement for the client to check settings
    BitStream.Write ( m_iEnableClientChecks );

    // Transmit whether or not the Voice is enabled
    BitStream.WriteBit ( m_bVoiceEnabled );

    // Transmit the sample rate for voice
    SIntegerSync < unsigned char, 2 > sampleRate ( m_ucSampleRate );
    BitStream.Write ( &sampleRate );

    // Transmit the quality for voice
    SIntegerSync < unsigned char, 4 > voiceQuality ( m_ucQuality );
    BitStream.Write ( &voiceQuality );

    // Transmit the max bitrate for voice
    BitStream.WriteCompressed ( m_uiBitrate );

    // Tellclient about maybe throttling back http client requests
    BitStream.Write ( m_iHTTPMaxConnectionsPerClient );

    BitStream.Write ( static_cast < unsigned char > ( m_ucHTTPDownloadType ) );

    switch ( m_ucHTTPDownloadType )
    {
    case HTTP_DOWNLOAD_ENABLED_PORT:
        {
            BitStream.Write ( m_usHTTPDownloadPort );
        }

        break;
    case HTTP_DOWNLOAD_ENABLED_URL:
        {
            // Internal http server port
            if ( BitStream.Version() >= 0x48 )
                BitStream.Write( m_usHTTPDownloadPort );

            // External http server URL
            BitStream.WriteString ( m_strHTTPDownloadURL );
        }

        break;
    default:
        break;
    }

    return true;
}
bool CExplosionSyncPacket::Write(NetBitStreamInterface& BitStream) const
{
    // Write the source player and latency if any. Otherwize 0
    if (m_pSourceElement)
    {
        BitStream.WriteBit(true);
        ElementID ID = m_pSourceElement->GetID();
        BitStream.Write(ID);

        unsigned short usLatency = static_cast<CPlayer*>(m_pSourceElement)->GetPing();
        BitStream.WriteCompressed(usLatency);
    }
    else
    {
        BitStream.WriteBit(false);
    }

    if (m_OriginID != INVALID_ELEMENT_ID)
    {
        BitStream.WriteBit(true);
        BitStream.Write(m_OriginID);
    }
    else
        BitStream.WriteBit(false);

    // Write position and type
    SPositionSync position(false);
    position.data.vecPosition = m_vecPosition;
    BitStream.Write(&position);

    SExplosionTypeSync explosionType;
    explosionType.data.uiType = m_ucType;
    BitStream.Write(&explosionType);

    return true;
}
bool CVehicleTrailerPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    BitStream.Write ( m_Vehicle );
    BitStream.Write ( m_AttachedVehicle );
    BitStream.WriteBit ( m_bAttached );

    if ( m_bAttached )
    {
        SPositionSync position ( false );
        position.data.vecPosition = m_vecPosition;
        BitStream.Write ( &position );

        SRotationDegreesSync rotation ( false );
        rotation.data.vecRotation = m_vecRotationDegrees;
        BitStream.Write ( &rotation );

        SVelocitySync turn;
        turn.data.vecVelocity = m_vecTurnSpeed;
        BitStream.Write ( &turn );
    }

    return true;
}
bool CServerTextItemPacket::Write ( NetBitStreamInterface &BitStream  ) const
{
    BitStream.WriteCompressed ( m_ulUniqueId );

    // Write the flag byte
    BitStream.WriteBit ( m_bDeletable );

    // Not deleting this?
    if ( !m_bDeletable )
    {
        BitStream.Write ( m_fX );
        BitStream.Write ( m_fY );
        BitStream.Write ( m_fScale );
        BitStream.Write ( m_red );
        BitStream.Write ( m_green );
        BitStream.Write ( m_blue );
        BitStream.Write ( m_alpha );
        BitStream.Write ( m_ucFormat );

        // Grab the text length
        size_t sizeText = strlen ( m_szText );
        if ( sizeText > 1024 )
        {
            sizeText = 1024;
        }

        // Write the text
        BitStream.WriteCompressed ( static_cast < unsigned short > ( sizeText ) );
        if ( sizeText )
        {
            BitStream.Write ( m_szText, sizeText );
        }
    }

    return true;
}
Exemple #10
0
bool CLuaArgument::WriteToBitStream ( NetBitStreamInterface& bitStream, std::map < CLuaArguments*, unsigned long > * pKnownTables ) const
{
    SLuaTypeSync type;

    switch ( GetType () )
    {
        // Nil type
        case LUA_TNIL:
        {
            type.data.ucType = LUA_TNIL;
            bitStream.Write ( &type );
            break;
        }

        // Boolean type
        case LUA_TBOOLEAN:
        {
            type.data.ucType = LUA_TBOOLEAN;
			bitStream.Write ( &type );

            // Write the boolean to it
            bitStream.WriteBit ( GetBoolean () );
            break;
        }

        // Table argument
        case LUA_TTABLE:
        {
            if ( pKnownTables && pKnownTables->find ( m_pTableData ) != pKnownTables->end () )
            {
                // Self-referencing table
                type.data.ucType = LUA_TTABLEREF;
                bitStream.Write ( &type );
                bitStream.WriteCompressed ( pKnownTables->find ( m_pTableData )->second );
            }
            else
            {
                type.data.ucType = LUA_TTABLE;
                bitStream.Write ( &type );

                // Write the subtable to the bitstream
                m_pTableData->WriteToBitStream ( bitStream, pKnownTables );
            }
            break;
        }

        // Number argument?
        case LUA_TNUMBER:
        {
            type.data.ucType = LUA_TNUMBER;
            bitStream.Write ( &type );
            float fNumber = static_cast < float > ( GetNumber () );
            long lNumber = static_cast < long > ( fNumber );
            float fNumberInteger = static_cast < float > ( lNumber );

            // Check if the number is an integer and can fit a long datatype
            if ( fabs ( fNumber ) > fabs ( fNumberInteger + 1 ) ||
                 fabs ( fNumber - fNumberInteger ) >= FLOAT_EPSILON )
            {
                bitStream.WriteBit ( true );
                bitStream.Write ( fNumber );
            }
            else
            {
                bitStream.WriteBit ( false );
                bitStream.WriteCompressed ( lNumber );
            }
            break;
        }

        // String argument
        case LUA_TSTRING:
        {           
            // Grab the string and its length. Is it short enough to be sendable?
            const char* szTemp = m_strString.c_str ();
            size_t sizeTemp = strlen ( szTemp );
            unsigned short usLength = static_cast < unsigned short > ( sizeTemp );
			if ( sizeTemp == usLength )
			{
                // This is a string argument
                type.data.ucType = LUA_TSTRING;
			    bitStream.Write ( &type );

                // Write its length
				bitStream.WriteCompressed ( usLength );

                // Write the content too if it's not empty
                if ( usLength > 0 )
                {
				    bitStream.Write ( const_cast < char* > ( szTemp ), usLength );
                }
			}
			else
			{
                // Too long string
                LogUnableToPacketize ( "Couldn't packetize argument list. Invalid string specified, limit is 65535 characters." );

                // Write a nil though so other side won't get out of sync
                type.data.ucType = LUA_TNIL;
                bitStream.Write ( &type );
                return false;
			}
            break;
        }

        // Element argument
        case LUA_TLIGHTUSERDATA:
        {
            // Grab the element from this userdata pointer. Valid and has a synced element ID?
			CElement* pElement = GetElement ();
			if ( pElement && pElement->GetID () != INVALID_ELEMENT_ID )
			{
                // Write its ID
                type.data.ucType = LUA_TLIGHTUSERDATA;
				bitStream.Write ( &type );
				bitStream.WriteCompressed ( static_cast < ElementID > ( pElement->GetID () ) );
			}
			else
			{
                // Jax: this just spams the script debugger, it's not really neccesary
                // LogUnableToPacketize ( "Couldn't packetize argument list, invalid element specified." );

                // Write a nil though so other side won't get out of sync
                type.data.ucType = LUA_TNIL;
                bitStream.Write ( &type );
				return false;
			}

            break;
        }

        // Unpacketizable type.
		default:
		{
            // Unpacketizable
			LogUnableToPacketize ( "Couldn't packetize argument list, unknown type specified." );

            // Write a nil though so other side won't get out of sync
            type.data.ucType = LUA_TNIL;
            bitStream.Write ( &type );
			return false;
		}
    }

    // Success
    return true;
}
bool CVehiclePuresyncPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Got a player to send?
    if ( m_pSourceElement )
    {
        CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement );

        // Player is in a vehicle and is the driver?
        CVehicle* pVehicle = pSourcePlayer->GetOccupiedVehicle ();
        if ( pVehicle )
        {
            // Player ID
            ElementID PlayerID = pSourcePlayer->GetID ();
            BitStream.Write ( PlayerID );

            // Write the time context of that player
            BitStream.Write ( pSourcePlayer->GetSyncTimeContext () );

            // Write his ping divided with 2 plus a small number so the client can find out when this packet was sent
            unsigned short usLatency = pSourcePlayer->GetPing ();
            BitStream.WriteCompressed ( usLatency );

            // Write the keysync data
            CControllerState ControllerState = pSourcePlayer->GetPad ()->GetCurrentControllerState ();
            WriteFullKeysync ( ControllerState, BitStream );

            // Write the vehicle matrix only if he's the driver
            CVector vecTemp;
            unsigned int uiSeat = pSourcePlayer->GetOccupiedVehicleSeat ();
            if ( uiSeat == 0 )
            {
                // Vehicle position
                SPositionSync position ( false );
                position.data.vecPosition = pVehicle->GetPosition ();
                BitStream.Write ( &position );

                // Vehicle rotation
                SRotationDegreesSync rotation;
                pVehicle->GetRotationDegrees ( rotation.data.vecRotation );
                BitStream.Write ( &rotation );

                // Move speed vector
                SVelocitySync velocity;
                velocity.data.vecVelocity = pVehicle->GetVelocity ();
                BitStream.Write ( &velocity );

                // Turn speed vector
                SVelocitySync turnSpeed;
                turnSpeed.data.vecVelocity = pVehicle->GetTurnSpeed ();
                BitStream.Write ( &turnSpeed );

                // Health
                SVehicleHealthSync health;
                health.data.fValue = pVehicle->GetHealth ();
                BitStream.Write ( &health );
            }

            // Player health and armor
            SPlayerHealthSync health;
            health.data.fValue = pSourcePlayer->GetHealth ();
            BitStream.Write ( &health );

            SPlayerArmorSync armor;
            armor.data.fValue = pSourcePlayer->GetArmor ();
            BitStream.Write ( &armor );

            // Weapon
            unsigned char ucWeaponType = pSourcePlayer->GetWeaponType ();

            // Flags
            SVehiclePuresyncFlags flags;
            flags.data.bIsWearingGoggles     = pSourcePlayer->IsWearingGoggles ();
            flags.data.bIsDoingGangDriveby   = pSourcePlayer->IsDoingGangDriveby ();
            flags.data.bIsSirenOrAlarmActive = pVehicle->IsSirenActive ();
            flags.data.bIsSmokeTrailEnabled  = pVehicle->IsSmokeTrailEnabled ();
            flags.data.bIsLandingGearDown    = pVehicle->IsLandingGearDown ();
            flags.data.bIsOnGround           = pVehicle->IsOnGround ();
            flags.data.bIsInWater            = pVehicle->IsInWater ();
            flags.data.bIsDerailed           = pVehicle->IsDerailed ();
            flags.data.bIsAircraft           = ( pVehicle->GetVehicleType () == VEHICLE_PLANE ||
                                                 pVehicle->GetVehicleType () == VEHICLE_HELI );
            flags.data.bHasAWeapon           = ( ucWeaponType != 0 );
            flags.data.bIsHeliSearchLightVisible = pVehicle->IsHeliSearchLightVisible ();
            BitStream.Write ( &flags );

            // Write the weapon stuff
            if ( flags.data.bHasAWeapon )
            {
                // Write the weapon slot
                SWeaponSlotSync slot;
                slot.data.uiSlot = pSourcePlayer->GetWeaponSlot ();
                BitStream.Write ( &slot );

                if ( flags.data.bIsDoingGangDriveby && CWeaponNames::DoesSlotHaveAmmo ( slot.data.uiSlot ) )
                {
                    // Write the ammo states
                    SWeaponAmmoSync ammo ( ucWeaponType, false, true );
                    ammo.data.usAmmoInClip = pSourcePlayer->GetWeaponAmmoInClip ();
                    BitStream.Write ( &ammo );

                    // Sync aim data
                    SWeaponAimSync aim ( 0.0f, true );
                    aim.data.vecOrigin = pSourcePlayer->GetSniperSourceVector ();
                    pSourcePlayer->GetTargettingVector ( aim.data.vecTarget );
                    aim.data.fArm = pSourcePlayer->GetAimDirection ();
                    BitStream.Write ( &aim );

                    // Sync driveby direction
                    SDrivebyDirectionSync driveby;
                    driveby.data.ucDirection = pSourcePlayer->GetDriveByDirection ();
                    BitStream.Write ( &driveby );
                }
            }

            // Vehicle specific data only if he's the driver
            if ( uiSeat == 0 )
            {
                WriteVehicleSpecific ( pVehicle, BitStream );
            }

            // Write vehicle_look_left and vehicle_look_right control states when
            // it's an aircraft.
            if ( flags.data.bIsAircraft )
            {
                BitStream.WriteBit ( ControllerState.LeftShoulder2 != 0 );
                BitStream.WriteBit ( ControllerState.RightShoulder2 != 0 );
            }

            // Success
            return true;
        }
    }

    return false;
}
bool CResourceStartPacket::Write(NetBitStreamInterface& BitStream) const
{
    if (!m_strResourceName.empty())
    {
        // Write the resource name
        unsigned char sizeResourceName = static_cast<unsigned char>(m_strResourceName.size());
        BitStream.Write(sizeResourceName);
        if (sizeResourceName > 0)
        {
            BitStream.Write(m_strResourceName.c_str(), sizeResourceName);
        }

        // Write the resource id
        BitStream.Write(m_pResource->GetNetID());

        // Write the resource element id
        BitStream.Write(m_pResource->GetResourceRootElement()->GetID());

        // Write the resource dynamic element id
        BitStream.Write(m_pResource->GetDynamicElementRoot()->GetID());

        // Count the amount of 'no client cache' scripts
        unsigned short usNoClientCacheScriptCount = 0;
        if (m_pResource->IsClientScriptsOn() == true)
        {
            list<CResourceFile*>::iterator iter = m_pResource->IterBegin();
            for (; iter != m_pResource->IterEnd(); ++iter)
            {
                if ((*iter)->GetType() == CResourceScriptItem::RESOURCE_FILE_TYPE_CLIENT_SCRIPT &&
                    static_cast<CResourceClientScriptItem*>(*iter)->IsNoClientCache() == true)
                {
                    ++usNoClientCacheScriptCount;
                }
            }
        }
        BitStream.Write(usNoClientCacheScriptCount);

        // Write the declared min client version for this resource
        if (BitStream.Version() >= 0x32)
        {
            BitStream.WriteString(m_pResource->GetMinServerReqFromMetaXml());
            BitStream.WriteString(m_pResource->GetMinClientReqFromMetaXml());
        }
        if (BitStream.Version() >= 0x45)
        {
            BitStream.WriteBit(m_pResource->IsOOPEnabledInMetaXml());
        }

        if (BitStream.Version() >= 0x62)
        {
            BitStream.Write(m_pResource->GetDownloadPriorityGroup());
        }

        // Send the resource files info
        list<CResourceFile*>::iterator iter = m_pResource->IterBegin();
        for (; iter != m_pResource->IterEnd(); iter++)
        {
            if (((*iter)->GetType() == CResourceScriptItem::RESOURCE_FILE_TYPE_CLIENT_CONFIG && m_pResource->IsClientConfigsOn()) ||
                ((*iter)->GetType() == CResourceScriptItem::RESOURCE_FILE_TYPE_CLIENT_SCRIPT && m_pResource->IsClientScriptsOn() &&
                 static_cast<CResourceClientScriptItem*>(*iter)->IsNoClientCache() == false) ||
                ((*iter)->GetType() == CResourceScriptItem::RESOURCE_FILE_TYPE_CLIENT_FILE && m_pResource->IsClientFilesOn()))
            {
                // Write the Type of chunk to read (F - File, E - Exported Function)
                BitStream.Write(static_cast<unsigned char>('F'));

                // Write the map name
                const char* szFileName = (*iter)->GetWindowsName();
                size_t      sizeFileName = strlen(szFileName);

                // Make sure we don't have any backslashes in the name
                char* szCleanedFilename = new char[sizeFileName + 1];
                strcpy(szCleanedFilename, szFileName);
                for (unsigned int i = 0; i < sizeFileName; i++)
                {
                    if (szCleanedFilename[i] == '\\')
                        szCleanedFilename[i] = '/';
                }

                BitStream.Write(static_cast<unsigned char>(sizeFileName));
                if (sizeFileName > 0)
                {
                    BitStream.Write(szCleanedFilename, sizeFileName);
                }

                // ChrML: Don't forget this...
                delete[] szCleanedFilename;

                BitStream.Write(static_cast<unsigned char>((*iter)->GetType()));
                CChecksum checksum = (*iter)->GetLastChecksum();
                BitStream.Write(checksum.ulCRC);
                BitStream.Write((const char*)checksum.md5.data, sizeof(checksum.md5.data));
                BitStream.Write((*iter)->GetApproxSize());
                if ((*iter)->GetType() == CResourceScriptItem::RESOURCE_FILE_TYPE_CLIENT_FILE)
                {
                    CResourceClientFileItem* pRCFItem = reinterpret_cast<CResourceClientFileItem*>(*iter);
                    // write bool whether to download or not
                    BitStream.WriteBit(pRCFItem->IsAutoDownload());
                }
            }
        }

        // Loop through the exported functions
        list<CExportedFunction>::iterator iterExportedFunction = m_pResource->IterBeginExportedFunctions();
        for (; iterExportedFunction != m_pResource->IterEndExportedFunctions(); iterExportedFunction++)
        {
            // Check to see if the exported function is 'client'
            if (iterExportedFunction->GetType() == CExportedFunction::EXPORTED_FUNCTION_TYPE_CLIENT)
            {
                // Write the Type of chunk to read (F - File, E - Exported Function)
                BitStream.Write(static_cast<unsigned char>('E'));

                // Write the exported function
                std::string strFunctionName = iterExportedFunction->GetFunctionName();
                size_t      sizeFunctionName = strFunctionName.length();

                BitStream.Write(static_cast<unsigned char>(sizeFunctionName));
                if (sizeFunctionName > 0)
                {
                    BitStream.Write(strFunctionName.c_str(), sizeFunctionName);
                }
            }
        }

        return true;
    }

    return false;
}
bool CEntityAddPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    SPositionSync position ( false );

    // Check that we have any entities
    if ( m_Entities.size () > 0 )
    {
        // Write the number of entities
        unsigned int NumElements = m_Entities.size ();
        BitStream.WriteCompressed ( NumElements );

        // For each entity ...
        CVector vecTemp;
        vector < CElement* > ::const_iterator iter = m_Entities.begin ();
        for ( ; iter != m_Entities.end (); iter++ )
        {
            // Entity id
            CElement* pElement = *iter;
            BitStream.Write ( pElement->GetID () );

            // Entity type id
            unsigned char ucEntityTypeID = static_cast < unsigned char > ( pElement->GetType () );
            BitStream.Write ( ucEntityTypeID );

            // Entity parent
            CElement* pParent = pElement->GetParentEntity ();
            ElementID ParentID = INVALID_ELEMENT_ID;
            if ( pParent )
                ParentID = pParent->GetID ();
            BitStream.Write ( ParentID );

            // Entity interior
            BitStream.Write ( pElement->GetInterior () );

            // Entity dimension
            BitStream.WriteCompressed ( pElement->GetDimension () );

            // Entity attached to
            CElement* pElementAttachedTo = pElement->GetAttachedToElement ();
            if ( pElementAttachedTo )
            {
                BitStream.WriteBit ( true );
                BitStream.Write ( pElementAttachedTo->GetID () );

                // Attached position and rotation
                SPositionSync attachedPosition ( false );
                SRotationDegreesSync attachedRotation ( false );
                pElement->GetAttachedOffsets ( attachedPosition.data.vecPosition,
                                               attachedRotation.data.vecRotation );
                BitStream.Write ( &attachedPosition );
                BitStream.Write ( &attachedRotation );
            }
            else
                BitStream.WriteBit ( false );

            // Entity collisions enabled
            bool bCollisionsEnabled = true;

            switch ( pElement->GetType() )
            {
                case CElement::VEHICLE:
                {
                    CVehicle* pVehicle = static_cast < CVehicle* > ( pElement );
                    bCollisionsEnabled = pVehicle->GetCollisionEnabled ( );
                    break;
                }
                case CElement::OBJECT:
                {
                    CObject* pObject = static_cast < CObject* > ( pElement );
                    bCollisionsEnabled = pObject->GetCollisionEnabled ( );
                    break;
                }
                case CElement::PED:
                case CElement::PLAYER:
                {
                    CPed* pPed = static_cast < CPed* > ( pElement );
                    bCollisionsEnabled = pPed->GetCollisionEnabled ( );
                    break;
                }
            }

            BitStream.WriteBit ( bCollisionsEnabled );
            
            // Write custom data
            CCustomData* pCustomData = pElement->GetCustomDataPointer ();
            assert ( pCustomData );
            BitStream.WriteCompressed ( pCustomData->CountOnlySynchronized () );
            map < string, SCustomData > :: const_iterator iter = pCustomData->IterBegin ();
            for ( ; iter != pCustomData->IterEnd (); iter++ )
            {
                const char* szName = iter->first.c_str ();
                const CLuaArgument* pArgument = &iter->second.Variable;
                bool bSynchronized = iter->second.bSynchronized;

                if ( bSynchronized )
                {
                    unsigned char ucNameLength = static_cast < unsigned char > ( strlen ( szName ) );
                    BitStream.Write ( ucNameLength );
                    BitStream.Write ( szName, ucNameLength );
                    pArgument->WriteToBitStream ( BitStream );
                }
            }

            // Grab its name
            char szEmpty [1];
            szEmpty [0] = 0;
            const char* szName = pElement->GetName ().c_str ();
            if ( !szName )
                szName = szEmpty;

            // Write the name. It can be empty.
            unsigned short usNameLength = static_cast < unsigned short > ( strlen ( szName ) );
            BitStream.WriteCompressed ( usNameLength );
            if ( usNameLength > 0 )
            {
                BitStream.Write ( const_cast < char * > ( szName ), usNameLength );    
            }

            // Write the sync time context
            BitStream.Write ( pElement->GetSyncTimeContext () );

            // Write the rest depending on the type
            switch ( ucEntityTypeID )
            {
                case CElement::OBJECT:
                {
                    CObject* pObject = static_cast < CObject* > ( pElement );

                    // Position
                    position.data.vecPosition = pObject->GetPosition ();
                    BitStream.Write ( &position );

                    // Rotation
                    SRotationRadiansSync rotationRadians ( false );
                    pObject->GetRotation ( rotationRadians.data.vecRotation );
                    BitStream.Write ( &rotationRadians );

                    // Object id
                    BitStream.WriteCompressed ( pObject->GetModel () );

                    // Alpha
                    SEntityAlphaSync alpha;
                    alpha.data.ucAlpha = pObject->GetAlpha ();
                    BitStream.Write ( &alpha );

                    // Double sided
                    bool bIsDoubleSided = pObject->IsDoubleSided ();
                    BitStream.WriteBit ( bIsDoubleSided );

                    // Moving
                    const CPositionRotationAnimation* pMoveAnimation = pObject->GetMoveAnimation ();
                    if ( pMoveAnimation )
                    {
                         BitStream.WriteBit ( true );
                         pMoveAnimation->ToBitStream ( BitStream, true );
                    }
                    else
                    {
                        BitStream.WriteBit ( false );
                    }

                    // Scale
                    float fScale = pObject->GetScale ();
                    BitStream.Write ( fScale );

                    // Static
                    bool bStatic = pObject->IsStatic ();
                    BitStream.WriteBit ( bStatic );

                    // Health
                    SObjectHealthSync health;
                    health.data.fValue = pObject->GetHealth ();
                    BitStream.Write ( &health );

                    break;
                }

                case CElement::PICKUP:
                {
                    CPickup* pPickup = static_cast < CPickup* > ( pElement );

                    // Position
                    position.data.vecPosition = pPickup->GetPosition ();
                    BitStream.Write ( &position );

                    // Grab the model and write it
                    unsigned short usModel = pPickup->GetModel ();
                    BitStream.WriteCompressed ( usModel );

                    // Write if it's visible
                    bool bVisible = pPickup->IsVisible ();
                    BitStream.WriteBit ( bVisible );

                    // Write the type
                    SPickupTypeSync pickupType;
                    pickupType.data.ucType = pPickup->GetPickupType ();
                    BitStream.Write ( &pickupType );

                    switch ( pPickup->GetPickupType () )
                    {
                        case CPickup::ARMOR:
                        {
                            SPlayerArmorSync armor;
                            armor.data.fValue = pPickup->GetAmount ();
                            BitStream.Write ( &armor );
                            break;
                        }
                        case CPickup::HEALTH:
                        {
                            SPlayerHealthSync health;
                            health.data.fValue = pPickup->GetAmount ();
                            BitStream.Write ( &health );
                            break;
                        }
                        case CPickup::WEAPON:
                        {
                            SWeaponTypeSync weaponType;
                            weaponType.data.ucWeaponType = pPickup->GetWeaponType ();
                            BitStream.Write ( &weaponType );

                            SWeaponAmmoSync ammo ( weaponType.data.ucWeaponType, true, false );
                            ammo.data.usTotalAmmo = pPickup->GetAmmo ();
                            BitStream.Write ( &ammo );
                            break;
                        }
                        default: break;
                    }

                    break;
                }

                case CElement::VEHICLE:
                {
                    CVehicle* pVehicle = static_cast < CVehicle* > ( pElement );

                    // Write the vehicle position and rotation
                    position.data.vecPosition = pVehicle->GetPosition ();
                    SRotationDegreesSync rotationDegrees ( false );
                    pVehicle->GetRotationDegrees ( rotationDegrees.data.vecRotation );

                    // Write it
                    BitStream.Write ( &position );
                    BitStream.Write ( &rotationDegrees );

                    // Vehicle id as a char
                    // I'm assuming the "-400" is for adjustment so that all car values can
                    // fit into a char?  Why doesn't someone document this?
                    //
                    // --slush
                    BitStream.Write ( static_cast < unsigned char > ( pVehicle->GetModel () - 400 ) );

                    // Health
                    SVehicleHealthSync health;
                    health.data.fValue = pVehicle->GetHealth ();
                    BitStream.Write ( &health );

                    // Color
                    CVehicleColor& vehColor = pVehicle->GetColor ();
                    uchar ucNumColors = vehColor.GetNumColorsUsed () - 1;
                    BitStream.WriteBits ( &ucNumColors, 2 );
                    for ( uint i = 0 ; i <= ucNumColors ; i++ )
                    {
                        SColor RGBColor = vehColor.GetRGBColor ( i );
                        BitStream.Write ( RGBColor.R );
                        BitStream.Write ( RGBColor.G );
                        BitStream.Write ( RGBColor.B );
                    }

                    // Paintjob
                    SPaintjobSync paintjob;
                    paintjob.data.ucPaintjob = pVehicle->GetPaintjob ();
                    BitStream.Write ( &paintjob );

                    // Write the damage model
                    SVehicleDamageSync damage ( true, true, true, true, false );
                    memcpy ( damage.data.ucDoorStates,  pVehicle->m_ucDoorStates,  MAX_DOORS );
                    memcpy ( damage.data.ucWheelStates, pVehicle->m_ucWheelStates, MAX_WHEELS );
                    memcpy ( damage.data.ucPanelStates, pVehicle->m_ucPanelStates, MAX_PANELS );
                    memcpy ( damage.data.ucLightStates, pVehicle->m_ucLightStates, MAX_LIGHTS );
                    BitStream.Write ( &damage );

                    // If the vehicle has a turret, send its position too
                    unsigned short usModel = pVehicle->GetModel ();
                    if ( CVehicleManager::HasTurret ( usModel ) )
                    {
                        SVehicleTurretSync specific;
                        specific.data.fTurretX = pVehicle->GetTurretPositionX ();
                        specific.data.fTurretY = pVehicle->GetTurretPositionY ();
                        BitStream.Write ( &specific );
                    }

                    // If the vehicle has an adjustable property send its value
                    if ( CVehicleManager::HasAdjustableProperty ( usModel ) )
                    {
                        BitStream.WriteCompressed ( pVehicle->GetAdjustableProperty () );
                    }

                    // If the vehicle has doors, sync their open angle ratios.
                    if ( CVehicleManager::HasDoors ( usModel ) )
                    {
                        SDoorOpenRatioSync door;
                        for ( unsigned char i = 0; i < 6; ++i )
                        {
                            door.data.fRatio = pVehicle->GetDoorOpenRatio ( i );
                            BitStream.Write ( &door );
                        }
                    }

                    // Write all the upgrades
                    CVehicleUpgrades* pUpgrades = pVehicle->GetUpgrades ();
                    unsigned char ucNumUpgrades = pUpgrades->Count ();
                    unsigned short* usSlotStates = pUpgrades->GetSlotStates ();
                    BitStream.Write ( ucNumUpgrades );

                    if ( ucNumUpgrades > 0 )
                    {
                        unsigned char ucSlot = 0;
                        for ( ; ucSlot < VEHICLE_UPGRADE_SLOTS ; ucSlot++ )
                        {
                            unsigned short usUpgrade = usSlotStates [ ucSlot ];

                            /*
                            * This is another retarded modification in an attempt to save
                            * a byte.  We're apparently subtracting 1000 so we can store the
                            * information in a single byte instead of two.  This only gives us
                            * a maximum of 256 vehicle slots.
                            *
                            * --slush
                            * -- ChrML: Ehm, GTA only has 17 upgrade slots... This is a valid optimization.
                            */
                            if ( usUpgrade )
                                BitStream.Write ( static_cast < unsigned char > ( usSlotStates [ ucSlot ] - 1000 ) );
                        }
                    }

                    // Get the vehicle's reg plate as 8 bytes of chars with the not used bytes
                    // nulled.
                    const char* cszRegPlate = pVehicle->GetRegPlate ();
                    BitStream.Write ( cszRegPlate, 8 );

                    // Light override
                    SOverrideLightsSync overrideLights;
                    overrideLights.data.ucOverride = pVehicle->GetOverrideLights ();
                    BitStream.Write ( &overrideLights );

                    // Grab various vehicle flags
                    BitStream.WriteBit ( pVehicle->IsLandingGearDown () );
                    BitStream.WriteBit ( pVehicle->IsSirenActive () );
                    BitStream.WriteBit ( pVehicle->IsFuelTankExplodable () );
                    BitStream.WriteBit ( pVehicle->IsEngineOn () );
                    BitStream.WriteBit ( pVehicle->IsLocked () );
                    BitStream.WriteBit ( pVehicle->AreDoorsUndamageable () );
                    BitStream.WriteBit ( pVehicle->IsDamageProof () );
                    BitStream.WriteBit ( pVehicle->IsFrozen () );
                    BitStream.WriteBit ( pVehicle->IsDerailed () );
                    BitStream.WriteBit ( pVehicle->IsDerailable () );
                    BitStream.WriteBit ( pVehicle->GetTrainDirection () );
                    BitStream.WriteBit ( pVehicle->IsTaxiLightOn () );

                    // Write alpha
                    SEntityAlphaSync alpha;
                    alpha.data.ucAlpha = pVehicle->GetAlpha ();
                    BitStream.Write ( &alpha ); 

                    // Write headlight color
                    SColor color = pVehicle->GetHeadLightColor ();
                    if ( color.R != 255 || color.G != 255 || color.B != 255 )
                    {
                        BitStream.WriteBit ( true );
                        BitStream.Write ( color.R );
                        BitStream.Write ( color.G );
                        BitStream.Write ( color.B );
                    }
                    else
                        BitStream.WriteBit ( false );

                    // Write handling
                    if ( g_pGame->GetHandlingManager()->HasModelHandlingChanged ( static_cast < eVehicleTypes > ( pVehicle->GetModel() ) )
                        || pVehicle->HasHandlingChanged() )
                    {
                        BitStream.WriteBit ( true );
                        SVehicleHandlingSync handling;
                        CHandlingEntry* pEntry = pVehicle->GetHandlingData ();

                        handling.data.fMass                         = pEntry->GetMass ();
                        handling.data.fTurnMass                     = pEntry->GetTurnMass ();
                        handling.data.fDragCoeff                    = pEntry->GetDragCoeff ();
                        handling.data.vecCenterOfMass               = pEntry->GetCenterOfMass ();
                        handling.data.ucPercentSubmerged            = pEntry->GetPercentSubmerged ();
                        handling.data.fTractionMultiplier           = pEntry->GetTractionMultiplier ();
                        handling.data.ucDriveType                   = pEntry->GetCarDriveType ();
                        handling.data.ucEngineType                  = pEntry->GetCarEngineType ();
                        handling.data.ucNumberOfGears               = pEntry->GetNumberOfGears ();
                        handling.data.fEngineAcceleration           = pEntry->GetEngineAcceleration ();
                        handling.data.fEngineInertia                = pEntry->GetEngineInertia ();
                        handling.data.fMaxVelocity                  = pEntry->GetMaxVelocity ();
                        handling.data.fBrakeDeceleration            = pEntry->GetBrakeDeceleration ();
                        handling.data.fBrakeBias                    = pEntry->GetBrakeBias ();
                        handling.data.bABS                          = pEntry->GetABS ();
                        handling.data.fSteeringLock                 = pEntry->GetSteeringLock ();
                        handling.data.fTractionLoss                 = pEntry->GetTractionLoss ();
                        handling.data.fTractionBias                 = pEntry->GetTractionBias ();
                        handling.data.fSuspensionForceLevel         = pEntry->GetSuspensionForceLevel ();
                        handling.data.fSuspensionDamping            = pEntry->GetSuspensionDamping ();
                        handling.data.fSuspensionHighSpdDamping     = pEntry->GetSuspensionHighSpeedDamping ();
                        handling.data.fSuspensionUpperLimit         = pEntry->GetSuspensionUpperLimit ();
                        handling.data.fSuspensionLowerLimit         = pEntry->GetSuspensionLowerLimit ();
                        handling.data.fSuspensionFrontRearBias      = pEntry->GetSuspensionFrontRearBias ();
                        handling.data.fSuspensionAntiDiveMultiplier = pEntry->GetSuspensionAntiDiveMultiplier ();
                        handling.data.fCollisionDamageMultiplier    = pEntry->GetCollisionDamageMultiplier ();
                        handling.data.uiModelFlags                  = pEntry->GetModelFlags ();
                        handling.data.uiHandlingFlags               = pEntry->GetHandlingFlags ();
                        handling.data.fSeatOffsetDistance           = pEntry->GetSeatOffsetDistance ();
                        //handling.data.uiMonetary                    = pEntry->GetMonetary ();
                        //handling.data.ucHeadLight                   = pEntry->GetHeadLight ();
                        //handling.data.ucTailLight                   = pEntry->GetTailLight ();
                        handling.data.ucAnimGroup                   = pEntry->GetAnimGroup ();
                        BitStream.Write ( &handling );
                    }
                    else
                        BitStream.WriteBit ( false );

                    break;
                }                

                case CElement::MARKER:
                {
                    CMarker* pMarker = static_cast < CMarker* > ( pElement );

                    // Position
                    position.data.vecPosition = pMarker->GetPosition ();
                    BitStream.Write ( &position );

                    // Type
                    SMarkerTypeSync markerType;
                    markerType.data.ucType = pMarker->GetMarkerType ();
                    BitStream.Write ( &markerType );

                    // Size
                    float fSize = pMarker->GetSize ();
                    BitStream.Write ( fSize );

                    // Colour
                    SColorSync color;
                    color = pMarker->GetColor ();
                    BitStream.Write ( &color );

                    // Write the target position vector eventually
                    if ( markerType.data.ucType == CMarker::TYPE_CHECKPOINT ||
                         markerType.data.ucType == CMarker::TYPE_RING )
                    {
                        if ( pMarker->HasTarget () )
                        {
                            BitStream.WriteBit ( true );

                            position.data.vecPosition = pMarker->GetTarget ();
                            BitStream.Write ( &position );
                        }
                        else
                            BitStream.WriteBit ( false );
                    }

                    break;
                }

                case CElement::BLIP:
                {
                    CBlip* pBlip = static_cast < CBlip* > ( pElement );

                    // Grab the blip position
                    position.data.vecPosition = pBlip->GetPosition ();
                    BitStream.Write ( &position );

                    // Write the ordering id
                    BitStream.WriteCompressed ( pBlip->m_sOrdering );

                    // Write the visible distance
                    SIntegerSync < unsigned short, 14 > visibleDistance ( pBlip->m_usVisibleDistance );
                    BitStream.Write ( &visibleDistance );

                    // Write the icon
                    SIntegerSync < unsigned char, 6 > icon ( pBlip->m_ucIcon );
                    BitStream.Write ( &icon );
                    if ( pBlip->m_ucIcon == 0 )
                    {
                        // Write the size
                        SIntegerSync < unsigned char, 5 > size ( pBlip->m_ucSize );
                        BitStream.Write ( &size );

                        // Write the color
                        SColorSync color;
                        color = pBlip->GetColor ();
                        BitStream.Write ( &color );
                    }                    

                    break;
                }

                case CElement::RADAR_AREA:
                {
                    CRadarArea* pArea = static_cast < CRadarArea* > ( pElement );

                    // Write the position
                    SPosition2DSync position2D ( false );
                    position2D.data.vecPosition = pArea->GetPosition ();
                    BitStream.Write ( &position2D );

                    // Write the size
                    SPosition2DSync size2D ( false );
                    size2D.data.vecPosition = pArea->GetSize ();
                    BitStream.Write ( &size2D );

                    // And the color
                    SColor color = pArea->GetColor ();
                    BitStream.Write ( color.R );
                    BitStream.Write ( color.G );
                    BitStream.Write ( color.B );
                    BitStream.Write ( color.A );

                    // Write whether it is flashing
                    bool bIsFlashing = pArea->IsFlashing ();
                    BitStream.WriteBit ( bIsFlashing );

                    break;
                }

                case CElement::WORLD_MESH:
                {
                    /*
                    CWorldMesh* pMesh = static_cast < CWorldMesh* > ( pElement );

                    // Write the name
                    char* szName = pMesh->GetName ();
                    unsigned short usNameLength = static_cast < unsigned short > ( strlen ( szName ) );
                    BitStream.Write ( usNameLength );
                    BitStream.Write ( szName, static_cast < int > ( usNameLength ) );

                    // Write the position and rotation
                    CVector vecTemp = pMesh->GetPosition ();
                    BitStream.Write ( vecTemp.fX );
                    BitStream.Write ( vecTemp.fY );
                    BitStream.Write ( vecTemp.fZ );
                    
                    vecTemp = pMesh->GetRotation ();
                    BitStream.Write ( vecTemp.fX );
                    BitStream.Write ( vecTemp.fY );
                    BitStream.Write ( vecTemp.fZ );
                    */

                    break;
                }

                case CElement::TEAM:
                {
                    CTeam* pTeam = static_cast < CTeam* > ( pElement );

                    // Write the name
                    char* szTeamName = pTeam->GetTeamName ();
                    unsigned short usNameLength = static_cast < unsigned short > ( strlen ( szTeamName ) );
                    unsigned char ucRed, ucGreen, ucBlue;
                    pTeam->GetColor ( ucRed, ucGreen, ucBlue );
                    bool bFriendlyFire = pTeam->GetFriendlyFire ();
                    BitStream.WriteCompressed ( usNameLength );
                    BitStream.Write ( szTeamName, usNameLength );                    
                    BitStream.Write ( ucRed );
                    BitStream.Write ( ucGreen );
                    BitStream.Write ( ucBlue );
                    BitStream.WriteBit ( bFriendlyFire );

                    break;
                }

                case CElement::PED:
                {
                    CPed* pPed = static_cast < CPed* > ( pElement );

                    // position
                    position.data.vecPosition = pPed->GetPosition ();
                    BitStream.Write ( &position );

                    // model
                    unsigned short usModel = pPed->GetModel ();
                    BitStream.WriteCompressed ( usModel );

                    // rotation
                    SPedRotationSync pedRotation;
                    pedRotation.data.fRotation = pPed->GetRotation ();
                    BitStream.Write ( &pedRotation );

                    // health
                    SPlayerHealthSync health;
                    health.data.fValue = pPed->GetHealth ();
                    BitStream.Write ( &health );

                    // Armor
                    SPlayerArmorSync armor;
                    armor.data.fValue = pPed->GetArmor ();
                    BitStream.Write ( &armor );
                    
                    // vehicle
                    CVehicle * pVehicle = pPed->GetOccupiedVehicle ();
                    if ( pVehicle )
                    {
                        BitStream.WriteBit ( true );
                        BitStream.Write ( pVehicle->GetID () );

                        SOccupiedSeatSync seat;
                        seat.data.ucSeat = pPed->GetOccupiedVehicleSeat ();
                        BitStream.Write ( &seat );
                    }
                    else
                        BitStream.WriteBit ( false );

                    // flags
                    BitStream.WriteBit ( pPed->HasJetPack () );
                    BitStream.WriteBit ( pPed->IsSyncable () );
                    BitStream.WriteBit ( pPed->IsHeadless () );
                    BitStream.WriteBit ( pPed->IsFrozen () );

                    // alpha
                    SEntityAlphaSync alpha;
                    alpha.data.ucAlpha = pPed->GetAlpha ();
                    BitStream.Write ( &alpha );

                    // clothes
                    unsigned char ucNumClothes = 0;
                    CPlayerClothes* pClothes = pPed->GetClothes ( );
                    for ( unsigned char ucType = 0 ; ucType < PLAYER_CLOTHING_SLOTS ; ucType++ )
                    {
                        SPlayerClothing* pClothing = pClothes->GetClothing ( ucType );
                        if ( pClothing )
                        {
                            ucNumClothes++;
                        }
                    }
                    BitStream.Write ( ucNumClothes );
                    for ( unsigned char ucType = 0 ; ucType < PLAYER_CLOTHING_SLOTS ; ucType++ )
                    {
                        SPlayerClothing* pClothing = pClothes->GetClothing ( ucType );
                        if ( pClothing )
                        {
                            unsigned char ucTextureLength = strlen ( pClothing->szTexture );
                            unsigned char ucModelLength = strlen ( pClothing->szModel );

                            BitStream.Write ( ucTextureLength );
                            BitStream.Write ( pClothing->szTexture, ucTextureLength );
                            BitStream.Write ( ucModelLength );
                            BitStream.Write ( pClothing->szModel, ucModelLength );
                            BitStream.Write ( ucType );
                        }
                    }
                    break;
                }

                case CElement::DUMMY:
                {
                    CDummy* pDummy = static_cast < CDummy* > ( pElement );
                    
                    // Type Name
                    const char* szTypeName = pDummy->GetTypeName ().c_str ();
                    unsigned short usTypeNameLength = static_cast < unsigned short > ( strlen ( szTypeName ) );
                    BitStream.WriteCompressed ( usTypeNameLength );
                    BitStream.Write ( const_cast < char* > ( szTypeName ), usTypeNameLength );                      

                    // Position
                    position.data.vecPosition = pDummy->GetPosition();
                    if ( position.data.vecPosition != CVector ( 0.0f, 0.0f, 0.0f ) )
                    {
                        BitStream.WriteBit ( true );
                        BitStream.Write ( &position );
                    }
                    else
                        BitStream.WriteBit ( false );

                    break;
                }

                case CElement::PLAYER:
                {
                    break;
                }

                case CElement::SCRIPTFILE:
                {
                    // No extra data
                    break;
                }

                case CElement::COLSHAPE:
                {
                    CColShape* pColShape = static_cast < CColShape* > ( pElement );
                    if ( !pColShape->GetParentEntity () )
                    {
                        // Jax: i'm pretty sure this is f*****g up our packet somehow..
                        // all valid col-shapes should have a parent!
                        assert ( false );
                    }

                    // Type
                    SColshapeTypeSync colType;
                    colType.data.ucType = static_cast < unsigned char > ( pColShape->GetShapeType () );
                    BitStream.Write ( &colType );

                    // Position
                    position.data.vecPosition = pColShape->GetPosition ();
                    BitStream.Write ( &position );
                    
                    // Enabled
                    BitStream.WriteBit ( pColShape->IsEnabled () );

                    // Auto Call Event
                    BitStream.WriteBit ( pColShape->GetAutoCallEvent () );

                    switch ( pColShape->GetShapeType () )
                    {
                        case COLSHAPE_CIRCLE:
                        {
                            BitStream.Write ( static_cast < CColCircle* > ( pColShape )->GetRadius () );
                            break;
                        }
                        case COLSHAPE_CUBOID:
                        {
                            SPositionSync size ( false );
                            size.data.vecPosition = static_cast < CColCuboid* > ( pColShape )->GetSize ();
                            BitStream.Write ( &size );
                            break;
                        }
                        case COLSHAPE_SPHERE:
                        {
                            BitStream.Write ( static_cast < CColSphere* > ( pColShape )->GetRadius () );
                            break;
                        }
                        case COLSHAPE_RECTANGLE:
                        {
                            SPosition2DSync size ( false );
                            size.data.vecPosition = static_cast < CColRectangle* > ( pColShape )->GetSize ();
                            BitStream.Write ( &size );
                            break;
                        }
                        case COLSHAPE_TUBE:
                        {
                            BitStream.Write ( static_cast < CColTube* > ( pColShape )->GetRadius () );
                            BitStream.Write ( static_cast < CColTube* > ( pColShape )->GetHeight () );
                            break;
                        }
                        case COLSHAPE_POLYGON:
                        {
                            CColPolygon* pPolygon = static_cast < CColPolygon* > ( pColShape );
                            BitStream.WriteCompressed ( pPolygon->CountPoints() );
                            std::vector < CVector2D > ::const_iterator iter = pPolygon->IterBegin();
                            for ( ; iter != pPolygon->IterEnd () ; iter++ )
                            {
                                SPosition2DSync vertex ( false );
                                vertex.data.vecPosition = *iter;
                                BitStream.Write ( &vertex );
                            }
                            break;
                        }
                        default: break;
                    }
                    break;
                }

                case CElement::WATER:
                {
                    CWater* pWater = static_cast < CWater* > ( pElement );
                    unsigned char ucNumVertices = (unsigned char)pWater->GetNumVertices ();
                    BitStream.Write ( ucNumVertices );
                    CVector vecVertex;
                    for ( int i = 0; i < ucNumVertices; i++ )
                    {
                        pWater->GetVertex ( i, vecVertex );
                        BitStream.Write ( (short)vecVertex.fX );
                        BitStream.Write ( (short)vecVertex.fY );
                        BitStream.Write ( vecVertex.fZ );
                    }
                    break;
                }

                default:
                {
                    assert ( 0 );
                    CLogger::LogPrintf ( "not sending this element - id: %i\n", pElement->GetType () );
                }
            }
        }

        // Success
        return true;
    }

    return false;
}
Exemple #14
0
// Can't use bitStream.Version() here as it is sometimes not set
bool CLuaArgument::WriteToBitStream(NetBitStreamInterface& bitStream, CFastHashMap<CLuaArguments*, unsigned long>* pKnownTables) const
{
    SLuaTypeSync type;

    switch (GetType())
    {
        // Nil type
        case LUA_TNIL:
        {
            type.data.ucType = LUA_TNIL;
            bitStream.Write(&type);
            break;
        }

        // Boolean type
        case LUA_TBOOLEAN:
        {
            type.data.ucType = LUA_TBOOLEAN;
            bitStream.Write(&type);

            // Write the boolean to it
            bitStream.WriteBit(GetBoolean());
            break;
        }

        // Table argument
        case LUA_TTABLE:
        {
            ulong* pThingy;
            if (pKnownTables && (pThingy = MapFind(*pKnownTables, m_pTableData)))
            {
                // Self-referencing table
                type.data.ucType = LUA_TTABLEREF;
                bitStream.Write(&type);
                bitStream.WriteCompressed(*pThingy);
            }
            else
            {
                type.data.ucType = LUA_TTABLE;
                bitStream.Write(&type);

                // Write the subtable to the bitstream
                m_pTableData->WriteToBitStream(bitStream, pKnownTables);
            }
            break;
        }

        // Number argument?
        case LUA_TNUMBER:
        {
            type.data.ucType = LUA_TNUMBER;
            bitStream.Write(&type);

            int       iNumber;
            float     fNumber;
            double    dNumber;
            EDataType dataType = GetDataTypeToUse(GetNumber(), &iNumber, &fNumber, &dNumber);
            if (dataType == DATA_TYPE_INT)
            {
                bitStream.WriteBit(false);
                bitStream.WriteCompressed(iNumber);
            }
            else if (dataType == DATA_TYPE_FLOAT)
            {
                bitStream.WriteBit(true);
                bitStream.WriteBit(false);
                bitStream.Write(fNumber);
            }
            else
            {
                bitStream.WriteBit(true);
                bitStream.WriteBit(true);
                bitStream.Write(dNumber);
            }
            break;
        }

        // String argument
        case LUA_TSTRING:
        {
            // Grab the string and its length. Is it short enough to be sendable?
            const char*    szTemp = m_strString.c_str();
            size_t         sizeTemp = m_strString.length();
            unsigned short usLength = static_cast<unsigned short>(sizeTemp);
            if (sizeTemp == usLength)
            {
                // This is a string argument
                type.data.ucType = LUA_TSTRING;
                bitStream.Write(&type);

                // Write its length
                bitStream.WriteCompressed(usLength);

                // Write the content too if it's not empty
                if (usLength > 0)
                {
                    bitStream.Write(szTemp, usLength);
                }
            }
            else
            {
                // This is a long string argument
                type.data.ucType = LUA_TSTRING_LONG;
                bitStream.Write(&type);

                // Write its length
                uint uiLength = sizeTemp;
                bitStream.WriteCompressed(uiLength);

                // Write the content too if it's not empty
                if (uiLength > 0)
                {
                    bitStream.AlignWriteToByteBoundary();
                    bitStream.Write(szTemp, uiLength);
                }
            }
            break;
        }

        // Element argument
        case LUA_TLIGHTUSERDATA:
        case LUA_TUSERDATA:
        {
            // Grab the element from this userdata pointer. Valid and has a synced element ID?
            CElement* pElement = GetElement();
            if (pElement && pElement->GetID() != INVALID_ELEMENT_ID)
            {
                // Write its ID
                type.data.ucType = LUA_TUSERDATA;
                bitStream.Write(&type);
                bitStream.Write(pElement->GetID());
            }
            else
            {
                // Jax: this just spams the script debugger, it's not really neccesary
                // LogUnableToPacketize ( "Couldn't packetize argument list, invalid element specified." );

                // Write a nil though so other side won't get out of sync
                type.data.ucType = LUA_TNIL;
                bitStream.Write(&type);
                return false;
            }

            break;
        }

        // Unpacketizable type.
        default:
        {
            // Unpacketizable
            LogUnableToPacketize("Couldn't packetize argument list, unknown type specified.");

            // Write a nil though so other side won't get out of sync
            type.data.ucType = LUA_TNIL;
            bitStream.Write(&type);
            return false;
        }
    }

    // Success
    return true;
}
//
// Should do the same this as what CKeysyncPacket::Write() does
//
bool CSimKeysyncPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Write the source player id
    BitStream.Write ( m_PlayerID );

    // Write the keysync data
    WriteSmallKeysync ( m_sharedControllerState, BitStream );

    // Write the rotations
    SKeysyncRotation rotation;
    rotation.data.fPlayerRotation = m_Cache.fPlayerRotation;
    rotation.data.fCameraRotation = m_Cache.fCameraRotation;
    BitStream.Write ( &rotation );

    // Write the flags
    BitStream.Write ( &m_Cache.flags );

    // If he's shooting or aiming
    if ( m_sharedControllerState.ButtonCircle || ( m_sharedControllerState.RightShoulder1 ) )
    {
        // Write his current weapon slot
        unsigned int uiSlot = m_Cache.ucWeaponSlot;   // check m_Cache.bWeaponCorrect ! 
        SWeaponSlotSync slot;
        slot.data.uiSlot = uiSlot;
        BitStream.Write ( &slot );

        if ( CWeaponNames::DoesSlotHaveAmmo ( uiSlot ) )
        {
            // Write his ammo in clip
            SWeaponAmmoSync ammo ( m_ucPlayerGotWeaponType, false, true );
            ammo.data.usAmmoInClip = m_Cache.usAmmoInClip;
            BitStream.Write ( &ammo );

            // Write the weapon aim data
            SWeaponAimSync aim ( 0.0f );
            aim.data.vecOrigin = m_Cache.vecSniperSource;
            aim.data.vecTarget = m_Cache.vecTargetting;
            aim.data.fArm = m_Cache.fAimDirection;
            BitStream.Write ( &aim );

            // Write the driveby aim directoin
            BitStream.Write ( m_Cache.ucDriveByDirection );
        }
    }

    // If he's in a vehicle, read out the small vehicle specific data
    if ( m_bPlayerHasOccupiedVehicle && m_Cache.flags.data.bSyncingVehicle )
    {
        if ( CVehicleManager::HasTurret ( m_usVehicleGotModel ) )
            BitStream.Write ( &m_Cache.turretSync );

        if ( m_bVehicleHasHydraulics )
        {
            BitStream.Write ( m_sharedControllerState.RightStickX );
            BitStream.Write ( m_sharedControllerState.RightStickY );
        }

        if ( m_bVehicleIsPlaneOrHeli )
        {
            BitStream.WriteBit ( m_sharedControllerState.LeftShoulder2 != 0);
            BitStream.WriteBit ( m_sharedControllerState.RightShoulder2 != 0);
        }
    }

    return true;
}
bool CPlayerListPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // bool                  - show the "X has joined the game" messages?
    // [ following repeats <number of players joined> times ]
    // unsigned char  (1)    - assigned player id
    // unsigned char  (1)    - player nick length
    // unsigned char  (X)    - player nick (X = player nick length)
    // bool                  - is he dead?
    // bool                  - spawned? (following data only if this is TRUE)
    // unsigned char  (1)    - model id
    // unsigned char  (1)    - team id
    // bool                  - in a vehicle?
    // unsigned short (2)    - vehicle id (if vehicle)
    // unsigned char  (1)    - vehicle seat (if vehicle)
    // CVector        (12)   - position (if player)
    // float          (4)    - rotation (if player)
    // bool                  - has a jetpack?
    // unsigned short (2)    - dimension

    // Write the global flags
    BitStream.WriteBit ( m_bShowInChat );

    CPlayer* pPlayer = NULL;
    // Put each player in our list into the packet
    list < CPlayer* > ::const_iterator iter = m_List.begin ();
    for ( ; iter != m_List.end (); ++iter )
    {
        // Grab the real pointer
        pPlayer = *iter;

        // Write the player ID
        ElementID PlayerID = pPlayer->GetID ();
        BitStream.Write ( PlayerID );

        // Time sync context
        BitStream.Write ( pPlayer->GetSyncTimeContext () );

        // Write the nick length
        const char* szNickPointer = pPlayer->GetNick ();
        unsigned char ucNickLength = static_cast < unsigned char > ( strlen ( szNickPointer ) );
        if ( ucNickLength < MIN_NICK_LENGTH || ucNickLength > MAX_NICK_LENGTH )
        {
            BitStream.Write ( static_cast < unsigned char > ( 3 ) );
            BitStream.Write ( "???", 3 );
        }
        else
        {
            BitStream.Write ( ucNickLength );
            BitStream.Write ( szNickPointer, ucNickLength );
        }

        // Version info
        if ( BitStream.Version () >= 0x34 )
        {
            BitStream.Write ( pPlayer->GetBitStreamVersion () );
            SString strBuild = pPlayer->GetPlayerVersion ().SubStr ( 8 );
            uint uiBuildNumber = atoi ( strBuild );
            BitStream.Write ( uiBuildNumber );
        }

        // Flags
        bool bInVehicle = ( pPlayer->GetOccupiedVehicle () != NULL );
        BitStream.WriteBit ( pPlayer->IsDead () );  // Currently unused by the client
        BitStream.WriteBit ( true );                // (Was IsSpawned) Used by the client to determine if extra info was sent (in this packet)
        BitStream.WriteBit ( bInVehicle );
        BitStream.WriteBit ( pPlayer->HasJetPack () );
        BitStream.WriteBit ( pPlayer->IsNametagShowing () );
        BitStream.WriteBit ( pPlayer->IsNametagColorOverridden () );
        BitStream.WriteBit ( pPlayer->IsHeadless() );
        BitStream.WriteBit ( pPlayer->IsFrozen() );

        // Nametag stuff
        unsigned char ucNametagTextLength = 0;
        char* szNametagText = pPlayer->GetNametagText ();
        if ( szNametagText )
            ucNametagTextLength = static_cast < unsigned char > ( strlen ( szNametagText ) );

        BitStream.Write ( ucNametagTextLength );
        if ( ucNametagTextLength > 0 )
            BitStream.Write ( szNametagText, ucNametagTextLength );

        // Write nametag color if it's overridden
        if ( pPlayer->IsNametagColorOverridden () )
        {
            unsigned char ucR, ucG, ucB;
            pPlayer->GetNametagColor ( ucR, ucG, ucB );
            BitStream.Write ( ucR );
            BitStream.Write ( ucG );
            BitStream.Write ( ucB );
        }

        // Move anim
        if ( BitStream.Version() > 0x4B )
        {
            uchar ucMoveAnim = pPlayer->GetMoveAnim();
            BitStream.Write ( ucMoveAnim );
        }

        // Always send extra info (Was: "Write spawn info if he's spawned")
        if ( true )
        {
            // Player model ID
            BitStream.WriteCompressed ( pPlayer->GetModel () );

            // Team id
            CTeam* pTeam = pPlayer->GetTeam ();
            if ( pTeam )
            {
                BitStream.WriteBit ( true );
                BitStream.Write ( pTeam->GetID () );
            }
            else
                BitStream.WriteBit ( false );

            if ( bInVehicle )
            {
                // Grab the occupied vehicle
                CVehicle* pVehicle = pPlayer->GetOccupiedVehicle ();

                // Vehicle ID and seat
                BitStream.Write ( pVehicle->GetID () );

                SOccupiedSeatSync seat;
                seat.data.ucSeat = pPlayer->GetOccupiedVehicleSeat ();
                BitStream.Write ( &seat );
            }
            else
            {
                // Player position
                SPositionSync position ( false );
                position.data.vecPosition = pPlayer->GetPosition ();
                BitStream.Write ( &position );

                // Player rotation
                SPedRotationSync rotation;
                rotation.data.fRotation = pPlayer->GetRotation ();
                BitStream.Write ( &rotation );
            }

            BitStream.WriteCompressed ( pPlayer->GetDimension () );
            BitStream.Write ( pPlayer->GetFightingStyle () );

            SEntityAlphaSync alpha;
            alpha.data.ucAlpha = pPlayer->GetAlpha ();
            BitStream.Write ( &alpha );

            BitStream.Write ( pPlayer->GetInterior () );

            // Write the weapons of the player weapon slots
            for ( unsigned int i = 0; i < 16; ++i )
            {
                CWeapon* pWeapon = pPlayer->GetWeapon ( i );
                if ( pWeapon && pWeapon->ucType != 0 )
                {
                    BitStream.WriteBit ( true );
                    SWeaponTypeSync weaponType;
                    weaponType.data.ucWeaponType = pWeapon->ucType;
                    BitStream.Write ( &weaponType );
                }
                else
                    BitStream.WriteBit ( false );
            }
        }
    }

    return true;
}
Exemple #17
0
bool CMapInfoPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Write the map weather
    BitStream.Write ( m_ucWeather );
    BitStream.Write ( m_ucWeatherBlendingTo );
    BitStream.Write ( m_ucBlendedWeatherHour );

    BitStream.WriteBit ( m_bHasSkyGradient );
    if ( m_bHasSkyGradient )
    {
        BitStream.Write ( m_ucSkyGradientTR );
        BitStream.Write ( m_ucSkyGradientTG );
        BitStream.Write ( m_ucSkyGradientTB );
        BitStream.Write ( m_ucSkyGradientBR );
        BitStream.Write ( m_ucSkyGradientBG );
        BitStream.Write ( m_ucSkyGradientBB );
    }

    // Write heat haze
    BitStream.WriteBit ( m_bHasHeatHaze );
    if ( m_bHasHeatHaze )
    {
        SHeatHazeSync heatHaze ( m_HeatHazeSettings );
        BitStream.Write ( &heatHaze );
    }

    // Write the map hour
    BitStream.Write ( m_ucClockHour );
    BitStream.Write ( m_ucClockMin );

    BitStream.WriteCompressed ( m_ulMinuteDuration );

    // Write the map flags
    SMapInfoFlagsSync flags;
    flags.data.bShowNametags  = m_bShowNametags;
    flags.data.bShowRadar     = m_bShowRadar;
    flags.data.bCloudsEnabled = m_bCloudsEnabled;
    BitStream.Write ( &flags );

    // Write any other world conditions
    BitStream.Write ( m_fGravity );
    if ( m_fGameSpeed == 1.0f )
        BitStream.WriteBit ( true );
    else
    {
        BitStream.WriteBit ( false );
        BitStream.Write ( m_fGameSpeed );
    }
    BitStream.Write ( m_fWaveHeight );
    // Write world water level
    BitStream.Write ( m_WorldWaterLevelInfo.fSeaLevel );
    BitStream.WriteBit ( m_WorldWaterLevelInfo.bNonSeaLevelSet );
    if ( m_WorldWaterLevelInfo.bNonSeaLevelSet )
        BitStream.Write ( m_WorldWaterLevelInfo.fNonSeaLevel );

    BitStream.WriteCompressed ( m_usFPSLimit );

    // Write the garage states
    for ( unsigned char i = 0 ; i < MAX_GARAGES ; i++ )
    {
        BitStream.WriteBit( static_cast < unsigned char > ( m_pbGarageStates[i] ) );
    }

    // Write the fun bugs state
    SFunBugsStateSync funBugs;
    funBugs.data.bQuickReload = g_pGame->IsGlitchEnabled ( CGame::GLITCH_QUICKRELOAD );
    funBugs.data.bFastFire    = g_pGame->IsGlitchEnabled ( CGame::GLITCH_FASTFIRE );
    funBugs.data.bFastMove    = g_pGame->IsGlitchEnabled ( CGame::GLITCH_FASTMOVE );
    funBugs.data.bCrouchBug   = g_pGame->IsGlitchEnabled ( CGame::GLITCH_CROUCHBUG );
    funBugs.data.bCloseRangeDamage = g_pGame->IsGlitchEnabled ( CGame::GLITCH_CLOSEDAMAGE );
    BitStream.Write ( &funBugs );

    BitStream.Write ( m_fJetpackMaxHeight );

    BitStream.WriteBit ( m_bOverrideWaterColor );
    if ( m_bOverrideWaterColor )
    {
        BitStream.Write ( m_ucWaterRed );
        BitStream.Write ( m_ucWaterGreen );
        BitStream.Write ( m_ucWaterBlue );
        BitStream.Write ( m_ucWaterAlpha );
    }

    // Interior sounds
    BitStream.WriteBit ( m_bInteriorSoundsEnabled );

    // Rain level
    BitStream.WriteBit ( m_bOverrideRainLevel );
    if ( m_bOverrideRainLevel )
    {
        BitStream.Write ( m_fRainLevel );
    }

    // Sun size
    BitStream.WriteBit ( m_bOverrideSunSize );
    if ( m_bOverrideSunSize )
    {
        BitStream.Write ( m_fSunSize );
    }

    // Sun color
    BitStream.WriteBit ( m_bOverrideSunColor );
    if ( m_bOverrideSunColor )
    {
        BitStream.Write ( m_ucSunCoreR );
        BitStream.Write ( m_ucSunCoreG );
        BitStream.Write ( m_ucSunCoreB );
        BitStream.Write ( m_ucSunCoronaR );
        BitStream.Write ( m_ucSunCoronaG );
        BitStream.Write ( m_ucSunCoronaB );
    }

    // Wind velocity
    BitStream.WriteBit ( m_bOverrideWindVelocity );
    if ( m_bOverrideWindVelocity )
    {
        BitStream.Write ( m_fWindVelX );
        BitStream.Write ( m_fWindVelY );
        BitStream.Write ( m_fWindVelZ );
    }

    // Far clip distance
    BitStream.WriteBit ( m_bOverrideFarClipDistance );
    if ( m_bOverrideFarClipDistance )
    {
        BitStream.Write ( m_fFarClip );
    }

    // Fog distance
    BitStream.WriteBit ( m_bOverrideFogDistance );
    if ( m_bOverrideFogDistance )
    {
        BitStream.Write ( m_fFogDistance );
    }

    BitStream.Write ( m_fAircraftMaxHeight );

    for (int i = WEAPONTYPE_PISTOL;i <= WEAPONTYPE_EXTINGUISHER;i++)
    {
        sWeaponPropertySync WeaponProperty;
        CWeaponStat* pWeaponStat = g_pGame->GetWeaponStatManager ()->GetWeaponStats( (eWeaponType)i );
        BitStream.WriteBit ( true );
        WeaponProperty.data.weaponType = (int)pWeaponStat->GetWeaponType();
        WeaponProperty.data.fAccuracy = pWeaponStat->GetAccuracy();
        WeaponProperty.data.fMoveSpeed = pWeaponStat->GetMoveSpeed();
        WeaponProperty.data.fTargetRange = pWeaponStat->GetTargetRange();
        WeaponProperty.data.fWeaponRange = pWeaponStat->GetWeaponRange();
        WeaponProperty.data.nAmmo = pWeaponStat->GetMaximumClipAmmo();
        WeaponProperty.data.nDamage = pWeaponStat->GetDamagePerHit();
        WeaponProperty.data.nFlags = pWeaponStat->GetFlags();

        WeaponProperty.data.anim_loop_start = pWeaponStat->GetWeaponAnimLoopStart();
        WeaponProperty.data.anim_loop_stop = pWeaponStat->GetWeaponAnimLoopStop();
        WeaponProperty.data.anim_loop_bullet_fire = pWeaponStat->GetWeaponAnimLoopFireTime();

        WeaponProperty.data.anim2_loop_start = pWeaponStat->GetWeaponAnim2LoopStart();
        WeaponProperty.data.anim2_loop_stop = pWeaponStat->GetWeaponAnim2LoopStop();
        WeaponProperty.data.anim2_loop_bullet_fire = pWeaponStat->GetWeaponAnim2LoopFireTime();

        WeaponProperty.data.anim_breakout_time = pWeaponStat->GetWeaponAnimBreakoutTime();
        BitStream.Write( &WeaponProperty );
    }

    for (int i = WEAPONTYPE_PISTOL;i <= WEAPONTYPE_TEC9;i++)
    {
        sWeaponPropertySync WeaponProperty;
        BitStream.WriteBit ( true );
        for (int j = 0; j <= 2;j++)
        {
            CWeaponStat* pWeaponStat = g_pGame->GetWeaponStatManager ()->GetWeaponStats( (eWeaponType)i, (eWeaponSkill)j );
            WeaponProperty.data.weaponType = (int)pWeaponStat->GetWeaponType();
            WeaponProperty.data.fAccuracy = pWeaponStat->GetAccuracy();
            WeaponProperty.data.fMoveSpeed = pWeaponStat->GetMoveSpeed();
            WeaponProperty.data.fTargetRange = pWeaponStat->GetTargetRange();
            WeaponProperty.data.fWeaponRange = pWeaponStat->GetWeaponRange();
            WeaponProperty.data.nAmmo = pWeaponStat->GetMaximumClipAmmo();
            WeaponProperty.data.nDamage = pWeaponStat->GetDamagePerHit();
            WeaponProperty.data.nFlags = pWeaponStat->GetFlags();

            WeaponProperty.data.anim_loop_start = pWeaponStat->GetWeaponAnimLoopStart();
            WeaponProperty.data.anim_loop_stop = pWeaponStat->GetWeaponAnimLoopStop();
            WeaponProperty.data.anim_loop_bullet_fire = pWeaponStat->GetWeaponAnimLoopFireTime();

            WeaponProperty.data.anim2_loop_start = pWeaponStat->GetWeaponAnim2LoopStart();
            WeaponProperty.data.anim2_loop_stop = pWeaponStat->GetWeaponAnim2LoopStop();
            WeaponProperty.data.anim2_loop_bullet_fire = pWeaponStat->GetWeaponAnim2LoopFireTime();

            WeaponProperty.data.anim_breakout_time = pWeaponStat->GetWeaponAnimBreakoutTime();
            BitStream.Write( &WeaponProperty );
        }
    }

    return true;
}
///////////////////////////////////////////////////////////////
//
// CLatentSendQueue::DoPulse
//
// Send next part of the active transfer
//
///////////////////////////////////////////////////////////////
void CLatentSendQueue::DoPulse ( int iTimeMsBetweenCalls )
{
    if ( m_TxQueue.empty () )
    {
        m_iBytesOwing = 0;
        return;
    }

    // Check if previous tx has completed
    if ( m_TxQueue.front ().uiReadPosition == m_TxQueue.front ().bufferRef->GetSize () && m_TxQueue.front ().bSendFinishing )
    {
        m_TxQueue.pop_front ();
        PostQueueRemove ();
        if ( m_TxQueue.empty () )
        {
            m_iBytesOwing = 0;
            return;
        }
    }

    m_uiCurrentRate = Max < uint > ( MIN_SEND_RATE, m_uiCurrentRate );

    // How many bytes to send this pulse
    int iBytesToSendThisPulse = iTimeMsBetweenCalls * m_uiCurrentRate / 1000;

    // Add bytes owing from last pulse
    iBytesToSendThisPulse += m_iBytesOwing;

    // Calc packet size depending on rate
    uint uiMaxPacketSize = Lerp ( MIN_PACKET_SIZE, UnlerpClamped ( MIN_PACKET_SIZE * 10, m_uiCurrentRate, MAX_PACKET_SIZE * 15 ), MAX_PACKET_SIZE );

    // Calc how many packets to do this pulse
    uint uiNumPackets = iBytesToSendThisPulse / uiMaxPacketSize;

    // Update carry over
    m_iBytesOwing = iBytesToSendThisPulse % uiMaxPacketSize;

    // Process item at front of queue
    SSendItem& activeTx = m_TxQueue.front ();
    for ( uint i = 0 ; i < uiNumPackets && !activeTx.bSendFinishing ; i++ )
    {
        // Send next part of data    
        NetBitStreamInterface* pBitStream = DoAllocateNetBitStream ( m_RemoteId, m_usBitStreamVersion );
        pBitStream->WriteBits ( &activeTx.uiId, 15 );

        // Next bit indicates if it has a special flag
        if ( activeTx.uiReadPosition == 0 )
        {
            // Head
            pBitStream->WriteBit ( 1 );
            pBitStream->Write ( (uchar)FLAG_HEAD );
            pBitStream->Write ( activeTx.usCategory );
            pBitStream->Write ( activeTx.bufferRef->GetSize () );
            pBitStream->Write ( activeTx.uiRate );
            if ( pBitStream->Version () >= 0x31 )
                pBitStream->Write ( activeTx.usResourceNetId );
            activeTx.bSendStarted = true;
        }
        else
        if ( activeTx.bufferRef->GetSize () == activeTx.uiReadPosition )
        {
            // Tail
            pBitStream->WriteBit ( 1 );
            pBitStream->Write ( (uchar)FLAG_TAIL );
            activeTx.bSendFinishing = true;
        }
        else
        {
            // Body
            pBitStream->WriteBit ( 0 );
        }

        // Align to next boundary
        pBitStream->AlignWriteToByteBoundary ();
        uint uiMaxDataSize = Max < int > ( 10, uiMaxPacketSize - pBitStream->GetNumberOfBytesUsed () );

        // Calc how much data to send
        uint uiDataOffset = activeTx.uiReadPosition;
        uint uiSizeToSend = Min ( uiMaxDataSize, activeTx.bufferRef->GetSize () - activeTx.uiReadPosition );
        activeTx.uiReadPosition += uiSizeToSend;

        pBitStream->Write ( (ushort)uiSizeToSend );
        pBitStream->Write ( activeTx.bufferRef->GetData () + uiDataOffset, uiSizeToSend );

        // Send
        DoSendPacket ( PACKET_ID_LATENT_TRANSFER, m_RemoteId, pBitStream, PACKET_PRIORITY_LOW, PACKET_RELIABILITY_RELIABLE_ORDERED, PACKET_ORDERING_DATA_TRANSFER );
        DoDeallocateNetBitStream ( pBitStream );
    }
}
Exemple #19
0
bool CProjectileSyncPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Write the source player and latency if any. Otherwize 0
    if ( m_pSourceElement )
    {
        BitStream.WriteBit ( true );
        BitStream.WriteCompressed ( m_pSourceElement->GetID () );

        unsigned short usLatency = static_cast < CPlayer * > ( m_pSourceElement )->GetPing ();
        BitStream.WriteCompressed ( usLatency );
    }
    else
        BitStream.WriteBit ( false );


    if ( m_OriginID != INVALID_ELEMENT_ID )
    {
        BitStream.WriteBit ( true );
        BitStream.WriteCompressed ( m_OriginID );
    }
    else
        BitStream.WriteBit ( false );

    SPositionSync position ( false );
    position.data.vecPosition = m_vecOrigin;
    BitStream.Write ( &position );

    SWeaponTypeSync weaponType;
    weaponType.data.ucWeaponType = m_ucWeaponType;
    BitStream.Write ( &weaponType );

    switch ( m_ucWeaponType )
    {
        case 16: // WEAPONTYPE_GRENADE
        case 17: // WEAPONTYPE_TEARGAS
        case 18: // WEAPONTYPE_MOLOTOV
        case 39: // WEAPONTYPE_REMOTE_SATCHEL_CHARGE
        {
            SFloatSync < 7, 17 > projectileForce;
            projectileForce.data.fValue = m_fForce;
            BitStream.Write ( &projectileForce );

            SVelocitySync velocity;
            velocity.data.vecVelocity = m_vecMoveSpeed;
            BitStream.Write ( &velocity );

            break;
        }
        case 19: // WEAPONTYPE_ROCKET
        case 20: // WEAPONTYPE_ROCKET_HS
        {
            if ( m_TargetID != INVALID_ELEMENT_ID )
            {
                BitStream.WriteBit ( true );
                BitStream.WriteCompressed ( m_TargetID );
            }
            else
                BitStream.WriteBit ( false );

            SVelocitySync velocity;
            velocity.data.vecVelocity = m_vecMoveSpeed;
            BitStream.Write ( &velocity );

            SRotationRadiansSync rotation ( true );
            rotation.data.vecRotation = m_vecRotation;
            BitStream.Write ( &rotation );

            break;
        }
        case 58: // WEAPONTYPE_FLARE
            break;
    }

    return true;
}
bool CMapInfoPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Write the map weather
    BitStream.Write ( m_ucWeather );
    BitStream.Write ( m_ucWeatherBlendingTo );
    BitStream.Write ( m_ucBlendedWeatherHour );

    BitStream.WriteBit ( m_bHasSkyGradient );
    if ( m_bHasSkyGradient )
    {
        BitStream.Write ( m_ucSkyGradientTR );
        BitStream.Write ( m_ucSkyGradientTG );
        BitStream.Write ( m_ucSkyGradientTB );
        BitStream.Write ( m_ucSkyGradientBR );
        BitStream.Write ( m_ucSkyGradientBG );
        BitStream.Write ( m_ucSkyGradientBB );
    }

    // Write heat haze
    BitStream.WriteBit ( m_bHasHeatHaze );
    if ( m_bHasHeatHaze )
    {
        SHeatHazeSync heatHaze ( m_HeatHazeSettings );
        BitStream.Write ( &heatHaze );
    }

    // Write the map hour
    BitStream.Write ( m_ucClockHour );
    BitStream.Write ( m_ucClockMin );

    BitStream.WriteCompressed ( m_ulMinuteDuration );

    // Write the map flags
    SMapInfoFlagsSync flags;
    flags.data.bShowNametags  = m_bShowNametags;
    flags.data.bShowRadar     = m_bShowRadar;
    flags.data.bCloudsEnabled = m_bCloudsEnabled;
    BitStream.Write ( &flags );

    // Write any other world conditions
    BitStream.Write ( m_fGravity );
    if ( m_fGameSpeed == 1.0f )
        BitStream.WriteBit ( true );
    else
    {
        BitStream.WriteBit ( false );
        BitStream.Write ( m_fGameSpeed );
    }
    BitStream.Write ( m_fWaveHeight );
    // Write world water level
    BitStream.Write ( m_WorldWaterLevelInfo.fSeaLevel );
    BitStream.WriteBit ( m_WorldWaterLevelInfo.bNonSeaLevelSet );
    if ( m_WorldWaterLevelInfo.bNonSeaLevelSet )
        BitStream.Write ( m_WorldWaterLevelInfo.fNonSeaLevel );

    BitStream.WriteCompressed ( m_usFPSLimit );

    // Write the garage states
    for ( unsigned char i = 0 ; i < MAX_GARAGES ; i++ )
    {
        const SGarageStates& garageStates = *m_pGarageStates;
        BitStream.WriteBit( garageStates[i] );
    }

    // Write the fun bugs state
    SFunBugsStateSync funBugs;
    funBugs.data.bQuickReload = g_pGame->IsGlitchEnabled ( CGame::GLITCH_QUICKRELOAD );
    funBugs.data.bFastFire    = g_pGame->IsGlitchEnabled ( CGame::GLITCH_FASTFIRE );
    funBugs.data.bFastMove    = g_pGame->IsGlitchEnabled ( CGame::GLITCH_FASTMOVE );
    funBugs.data.bCrouchBug   = g_pGame->IsGlitchEnabled ( CGame::GLITCH_CROUCHBUG );
    funBugs.data.bCloseRangeDamage = g_pGame->IsGlitchEnabled ( CGame::GLITCH_CLOSEDAMAGE );
    funBugs.data2.bHitAnim    = g_pGame->IsGlitchEnabled ( CGame::GLITCH_HITANIM );
    funBugs.data3.bFastSprint = g_pGame->IsGlitchEnabled ( CGame::GLITCH_FASTSPRINT );
    BitStream.Write ( &funBugs );

    BitStream.Write ( m_fJetpackMaxHeight );

    BitStream.WriteBit ( m_bOverrideWaterColor );
    if ( m_bOverrideWaterColor )
    {
        BitStream.Write ( m_ucWaterRed );
        BitStream.Write ( m_ucWaterGreen );
        BitStream.Write ( m_ucWaterBlue );
        BitStream.Write ( m_ucWaterAlpha );
    }

    // Interior sounds
    BitStream.WriteBit ( m_bInteriorSoundsEnabled );

    // Rain level
    BitStream.WriteBit ( m_bOverrideRainLevel );
    if ( m_bOverrideRainLevel )
    {
        BitStream.Write ( m_fRainLevel );
    }

    // Moon size
    if ( BitStream.Version () >= 0x40 )
    {
        BitStream.WriteBit ( m_bOverrideMoonSize );
        if ( m_bOverrideMoonSize )
        {
            BitStream.Write ( m_iMoonSize );
        }
    }

    // Sun size
    BitStream.WriteBit ( m_bOverrideSunSize );
    if ( m_bOverrideSunSize )
    {
        BitStream.Write ( m_fSunSize );
    }

    // Sun color
    BitStream.WriteBit ( m_bOverrideSunColor );
    if ( m_bOverrideSunColor )
    {
        BitStream.Write ( m_ucSunCoreR );
        BitStream.Write ( m_ucSunCoreG );
        BitStream.Write ( m_ucSunCoreB );
        BitStream.Write ( m_ucSunCoronaR );
        BitStream.Write ( m_ucSunCoronaG );
        BitStream.Write ( m_ucSunCoronaB );
    }

    // Wind velocity
    BitStream.WriteBit ( m_bOverrideWindVelocity );
    if ( m_bOverrideWindVelocity )
    {
        BitStream.Write ( m_fWindVelX );
        BitStream.Write ( m_fWindVelY );
        BitStream.Write ( m_fWindVelZ );
    }

    // Far clip distance
    BitStream.WriteBit ( m_bOverrideFarClipDistance );
    if ( m_bOverrideFarClipDistance )
    {
        BitStream.Write ( m_fFarClip );
    }

    // Fog distance
    BitStream.WriteBit ( m_bOverrideFogDistance );
    if ( m_bOverrideFogDistance )
    {
        BitStream.Write ( m_fFogDistance );
    }

    BitStream.Write ( m_fAircraftMaxHeight );

    if ( BitStream.Version () >= 0x3E ) 
        BitStream.Write ( m_fAircraftMaxVelocity );
    
    if ( BitStream.Version () >= 0x30 )
    {
        for (int i = WEAPONTYPE_BRASSKNUCKLE; i < WEAPONTYPE_PISTOL; i++)
        {
            bool bEnabled;
            bEnabled = g_pGame->GetJetpackWeaponEnabled ( (eWeaponType) i );
            BitStream.WriteBit ( bEnabled );
        }
    }
    for (int i = WEAPONTYPE_PISTOL;i <= WEAPONTYPE_EXTINGUISHER;i++)
    {
        sWeaponPropertySync WeaponProperty;
        CWeaponStat* pWeaponStat = g_pGame->GetWeaponStatManager ()->GetWeaponStats( (eWeaponType)i );
        BitStream.WriteBit ( true );
        WeaponProperty.data.weaponType = (int)pWeaponStat->GetWeaponType();
        WeaponProperty.data.fAccuracy = pWeaponStat->GetAccuracy();
        WeaponProperty.data.fMoveSpeed = pWeaponStat->GetMoveSpeed();
        WeaponProperty.data.fTargetRange = pWeaponStat->GetTargetRange();
        WeaponProperty.data.fWeaponRange = pWeaponStat->GetWeaponRange();
        WeaponProperty.data.nAmmo = pWeaponStat->GetMaximumClipAmmo();
        WeaponProperty.data.nDamage = pWeaponStat->GetDamagePerHit();
        WeaponProperty.data.nFlags = pWeaponStat->GetFlags();

        WeaponProperty.data.anim_loop_start = pWeaponStat->GetWeaponAnimLoopStart();
        WeaponProperty.data.anim_loop_stop = pWeaponStat->GetWeaponAnimLoopStop();
        WeaponProperty.data.anim_loop_bullet_fire = pWeaponStat->GetWeaponAnimLoopFireTime();

        WeaponProperty.data.anim2_loop_start = pWeaponStat->GetWeaponAnim2LoopStart();
        WeaponProperty.data.anim2_loop_stop = pWeaponStat->GetWeaponAnim2LoopStop();
        WeaponProperty.data.anim2_loop_bullet_fire = pWeaponStat->GetWeaponAnim2LoopFireTime();

        WeaponProperty.data.anim_breakout_time = pWeaponStat->GetWeaponAnimBreakoutTime();
        BitStream.Write( &WeaponProperty );
        if ( BitStream.Version () >= 0x30 )
        {
            BitStream.WriteBit ( g_pGame->GetJetpackWeaponEnabled ( (eWeaponType) i ) );
        }
    }

    for (int i = WEAPONTYPE_PISTOL;i <= WEAPONTYPE_TEC9;i++)
    {
        sWeaponPropertySync WeaponProperty;
        BitStream.WriteBit ( true );
        for (int j = 0; j <= 2;j++)
        {
            CWeaponStat* pWeaponStat = g_pGame->GetWeaponStatManager ()->GetWeaponStats( (eWeaponType)i, (eWeaponSkill)j );
            WeaponProperty.data.weaponType = (int)pWeaponStat->GetWeaponType();
            WeaponProperty.data.fAccuracy = pWeaponStat->GetAccuracy();
            WeaponProperty.data.fMoveSpeed = pWeaponStat->GetMoveSpeed();
            WeaponProperty.data.fTargetRange = pWeaponStat->GetTargetRange();
            WeaponProperty.data.fWeaponRange = pWeaponStat->GetWeaponRange();
            WeaponProperty.data.nAmmo = pWeaponStat->GetMaximumClipAmmo();
            WeaponProperty.data.nDamage = pWeaponStat->GetDamagePerHit();
            WeaponProperty.data.nFlags = pWeaponStat->GetFlags();

            WeaponProperty.data.anim_loop_start = pWeaponStat->GetWeaponAnimLoopStart();
            WeaponProperty.data.anim_loop_stop = pWeaponStat->GetWeaponAnimLoopStop();
            WeaponProperty.data.anim_loop_bullet_fire = pWeaponStat->GetWeaponAnimLoopFireTime();

            WeaponProperty.data.anim2_loop_start = pWeaponStat->GetWeaponAnim2LoopStart();
            WeaponProperty.data.anim2_loop_stop = pWeaponStat->GetWeaponAnim2LoopStop();
            WeaponProperty.data.anim2_loop_bullet_fire = pWeaponStat->GetWeaponAnim2LoopFireTime();

            WeaponProperty.data.anim_breakout_time = pWeaponStat->GetWeaponAnimBreakoutTime();
            BitStream.Write( &WeaponProperty );
        }
        if ( BitStream.Version () >= 0x36 )
        {
            BitStream.WriteBit ( g_pGame->GetJetpackWeaponEnabled ( (eWeaponType) i ) );
        }
    }
    if ( BitStream.Version () >= 0x30 )
    {
        for (int i = WEAPONTYPE_CAMERA; i <= WEAPONTYPE_PARACHUTE; i++)
        {
            bool bEnabled;
            bEnabled = g_pGame->GetJetpackWeaponEnabled ( (eWeaponType) i );
            BitStream.WriteBit ( bEnabled );
        }
    }

    multimap< unsigned short, CBuildingRemoval* >::const_iterator iter = g_pGame->GetBuildingRemovalManager ( )->IterBegin();
    for (; iter != g_pGame->GetBuildingRemovalManager ( )->IterEnd();++iter)
    {
        CBuildingRemoval * pBuildingRemoval = (*iter).second;
        BitStream.WriteBit( true );
        BitStream.Write( pBuildingRemoval->GetModel ( ) );
        BitStream.Write( pBuildingRemoval->GetRadius ( ) );
        BitStream.Write( pBuildingRemoval->GetPosition ( ).fX );
        BitStream.Write( pBuildingRemoval->GetPosition ( ).fY );
        BitStream.Write( pBuildingRemoval->GetPosition ( ).fZ );
        if ( BitStream.Version() >= 0x039 )
        {
            BitStream.Write ( pBuildingRemoval->GetInterior ( ) );
        }
    }
    BitStream.WriteBit( false );

    if ( BitStream.Version () >= 0x25 )
    {
        bool bOcclusionsEnabled = g_pGame->GetOcclusionsEnabled ();
        BitStream.WriteBit( bOcclusionsEnabled );
    }

    return true;
}
Exemple #21
0
bool CKeysyncPacket::Write ( NetBitStreamInterface& BitStream ) const
{
    // Got a player to write?
    if ( m_pSourceElement )
    {
        CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement );
        CVehicle* pVehicle = pSourcePlayer->GetOccupiedVehicle ();

        // Write the source player id
        ElementID PlayerID = pSourcePlayer->GetID ();
        BitStream.WriteCompressed ( PlayerID );

        // Write the keysync data
        const CControllerState& ControllerState = pSourcePlayer->GetPad ()->GetCurrentControllerState ();
        const CControllerState& LastControllerState = pSourcePlayer->GetPad ()->GetLastControllerState ();
        WriteSmallKeysync ( ControllerState, LastControllerState, BitStream );

        // Flags
        SKeysyncFlags flags;
        flags.data.bIsDucked = ( pSourcePlayer->IsDucked () == true );
        flags.data.bIsChoking = ( pSourcePlayer->IsChoking () == true );
        flags.data.bAkimboTargetUp = ( pSourcePlayer->IsAkimboArmUp () == true );
        flags.data.bSyncingVehicle = ( pVehicle != NULL && pSourcePlayer->GetOccupiedVehicleSeat () == 0 );

        // Write the flags
        BitStream.Write ( &flags );

        // If he's shooting
        if ( ControllerState.ButtonCircle )
        {
            // Write his current weapon slot
            unsigned int uiSlot = pSourcePlayer->GetWeaponSlot ();
            SWeaponSlotSync slot;
            slot.data.uiSlot = uiSlot;
            BitStream.Write ( &slot );

            if ( CWeaponNames::DoesSlotHaveAmmo ( uiSlot ) )
            {
                // Write his ammo in clip
                SWeaponAmmoSync ammo ( pSourcePlayer->GetWeaponType (), false, true );
                ammo.data.usAmmoInClip = pSourcePlayer->GetWeaponAmmoInClip ();
                BitStream.Write ( &ammo );

                // Write the weapon aim data
                SWeaponAimSync aim ( 0.0f );
                aim.data.vecOrigin = pSourcePlayer->GetSniperSourceVector ();
                pSourcePlayer->GetTargettingVector ( aim.data.vecTarget );
                aim.data.fArm = pSourcePlayer->GetAimDirection ();
                BitStream.Write ( &aim );

                // Write the driveby aim directoin
                BitStream.Write ( pSourcePlayer->GetDriveByDirection () );
            }
            else
            {
                pSourcePlayer->SetWeaponAmmoInClip ( 1 );
                pSourcePlayer->SetWeaponTotalAmmo ( 1 );
            }
        }

        // If he's in a vehicle, read out the small vehicle specific data
        if ( flags.data.bSyncingVehicle )
        {
            WriteVehicleSpecific ( pVehicle, BitStream );

            if ( pVehicle->GetUpgrades ()->HasUpgrade ( 1087 ) ) // Hydraulics?
            {
                BitStream.Write ( ControllerState.RightStickX );
                BitStream.Write ( ControllerState.RightStickY );
            }

            if ( pVehicle->GetVehicleType () == VEHICLE_PLANE ||
                 pVehicle->GetVehicleType () == VEHICLE_HELI )
            {
                BitStream.WriteBit ( ControllerState.LeftShoulder2 != 0);
                BitStream.WriteBit ( ControllerState.RightShoulder2 != 0);
            }
        }

        return true;
    }

    return false;
}
bool CLuaArgument::WriteToBitStream ( NetBitStreamInterface& bitStream, CFastHashMap < CLuaArguments*, unsigned long > * pKnownTables ) const
{
    SLuaTypeSync type;

    switch ( GetType () )
    {
        // Nil type
        case LUA_TNIL:
        {
            type.data.ucType = LUA_TNIL;
            bitStream.Write ( &type );
            break;
        }

        // Boolean type
        case LUA_TBOOLEAN:
        {
            type.data.ucType = LUA_TBOOLEAN;
            bitStream.Write ( &type );

            // Write the boolean to it
            bitStream.WriteBit ( GetBoolean () );
            break;
        }

        // Table argument
        case LUA_TTABLE:
        {
            ulong* pTableId;
            if ( pKnownTables && ( pTableId = MapFind ( *pKnownTables, m_pTableData ) ) )
            {
                // Self-referencing table
                type.data.ucType = LUA_TTABLEREF;
                bitStream.Write ( &type );
                bitStream.WriteCompressed ( *pTableId );
            }
            else
            {
                type.data.ucType = LUA_TTABLE;
                bitStream.Write ( &type );

                // Write the subtable to the bitstream
                m_pTableData->WriteToBitStream ( bitStream, pKnownTables );
            }
            break;
        }

        // Number argument?
        case LUA_TNUMBER:
        {
            type.data.ucType = LUA_TNUMBER;
            bitStream.Write ( &type );

            if ( bitStream.Version() < 0x59 )
            {
                // Old way
                int iNumber;
                if ( !ShouldUseInt( GetNumber(), &iNumber ) )
                {
                    bitStream.WriteBit ( true );
                    bitStream.Write ( static_cast < float > ( GetNumber() ) );
                }
                else
                {
                    bitStream.WriteBit ( false );
                    bitStream.WriteCompressed ( iNumber );
                }
            }
            else
            {
                // New way - Maybe use double to better preserve > 32bit numbers
                int iNumber;
                float fNumber;
                double dNumber;
                EDataType dataType = GetDataTypeToUse( GetNumber(), &iNumber, &fNumber, &dNumber );
                if ( dataType == DATA_TYPE_INT )
                {
                    bitStream.WriteBit ( false );
                    bitStream.WriteCompressed ( iNumber );
                }
                else
                if ( dataType == DATA_TYPE_FLOAT )
                {
                    bitStream.WriteBit ( true );
                    bitStream.WriteBit ( false );
                    bitStream.Write ( fNumber );
                }
                else
                {
                    bitStream.WriteBit ( true );
                    bitStream.WriteBit ( true );
                    bitStream.Write ( dNumber );
                }
            }
            break;
        }

        // String argument
        case LUA_TSTRING:
        {           
            // Grab the string and its length. Is it short enough to be sendable?
            const char* szTemp = m_strString.c_str ();
            size_t sizeTemp = m_strString.length ();
            unsigned short usLength = static_cast < unsigned short > ( sizeTemp );
            if ( sizeTemp == usLength )
            {
                // This is a string argument
                type.data.ucType = LUA_TSTRING;
                bitStream.Write ( &type );

                // Write its length
                bitStream.WriteCompressed ( usLength );

                // Write the content too if it's not empty
                if ( usLength > 0 )
                {
                    bitStream.Write ( szTemp, usLength );
                }
            }
            else
            {
                // This is a long string argument
                type.data.ucType = LUA_TSTRING_LONG;
                bitStream.Write ( &type );

                // Write its length
                uint uiLength = sizeTemp;
                bitStream.WriteCompressed ( uiLength );

                // Write the content too if it's not empty
                if ( uiLength > 0 )
                {
                    bitStream.AlignWriteToByteBoundary ();
                    bitStream.Write ( szTemp, uiLength );
                }
            }
            break;
        }

        // Element packet
        case LUA_TLIGHTUSERDATA:
        case LUA_TUSERDATA:
        {
            // Got a valid element to send?
            CClientEntity* pElement = GetElement ();
            if ( pElement )
            {
                // Clientside element?
                if ( !pElement->IsLocalEntity () )
                {
                    type.data.ucType = LUA_TLIGHTUSERDATA;
                    bitStream.Write ( &type );
                    bitStream.Write ( pElement->GetID () );
                }
                else
                {
                    // Write a nil though so other side won't get out of sync
                    type.data.ucType = LUA_TNIL;
                    bitStream.Write ( &type );
                    return false;
                }
            }
            else
            {
                // Write a nil though so other side won't get out of sync
                type.data.ucType = LUA_TNIL;
                bitStream.Write ( &type );
                return false;
            }
            break;
        }

        // Unpacketizable type.
        default:
        {
            // Unpacketizable
            LogUnableToPacketize ( "Couldn't packetize argument list, unknown type specified." );

            // Write a nil though so other side won't get out of sync
            type.data.ucType = LUA_TNIL;
            bitStream.Write ( &type );
            return false;
        }
    }

    // Success
    return true;
}
Exemple #23
0
bool CLuaArgument::WriteToBitStream ( NetBitStreamInterface& bitStream, CFastHashMap < CLuaArguments*, unsigned long > * pKnownTables ) const
{
    SLuaTypeSync type;

    switch ( GetType () )
    {
        // Nil type
        case LUA_TNIL:
        {
            type.data.ucType = LUA_TNIL;
            bitStream.Write ( &type );
            break;
        }

        // Boolean type
        case LUA_TBOOLEAN:
        {
            type.data.ucType = LUA_TBOOLEAN;
            bitStream.Write ( &type );

            // Write the boolean to it
            bitStream.WriteBit ( GetBoolean () );
            break;
        }

        // Table argument
        case LUA_TTABLE:
        {
            ulong* pThingy;
            if ( pKnownTables && ( pThingy = MapFind ( *pKnownTables, m_pTableData ) ) )
            {
                // Self-referencing table
                type.data.ucType = LUA_TTABLEREF;
                bitStream.Write ( &type );
                bitStream.WriteCompressed ( *pThingy );
            }
            else
            {
                type.data.ucType = LUA_TTABLE;
                bitStream.Write ( &type );

                // Write the subtable to the bitstream
                m_pTableData->WriteToBitStream ( bitStream, pKnownTables );
            }
            break;
        }

        // Number argument?
        case LUA_TNUMBER:
        {
            type.data.ucType = LUA_TNUMBER;
            bitStream.Write ( &type );
            float fNumber = static_cast < float > ( GetNumber () );
            long lNumber = static_cast < long > ( fNumber );
            float fNumberInteger = static_cast < float > ( lNumber );

            // Check if the number is an integer and can fit a long datatype
            if ( fabs ( fNumber ) > fabs ( fNumberInteger + 1 ) ||
                 fabs ( fNumber - fNumberInteger ) >= FLOAT_EPSILON )
            {
                bitStream.WriteBit ( true );
                bitStream.Write ( fNumber );
            }
            else
            {
                bitStream.WriteBit ( false );
                bitStream.WriteCompressed ( lNumber );
            }
            break;
        }

        // String argument
        case LUA_TSTRING:
        {           
            // Grab the string and its length. Is it short enough to be sendable?
            const char* szTemp = m_strString.c_str ();
            size_t sizeTemp = m_strString.length ();
            unsigned short usLength = static_cast < unsigned short > ( sizeTemp );
            if ( sizeTemp == usLength )
            {
                // This is a string argument
                type.data.ucType = LUA_TSTRING;
                bitStream.Write ( &type );

                // Write its length
                bitStream.WriteCompressed ( usLength );

                // Write the content too if it's not empty
                if ( usLength > 0 )
                {
                    bitStream.Write ( szTemp, usLength );
                }
            }
            else
            if ( sizeTemp > 65535 && bitStream.Version () >= 0x027 && g_pGame->CalculateMinClientRequirement () >= LONG_STRING_MIN_VERSION )
            {
                // This is a long string argument
                type.data.ucType = LUA_TSTRING_LONG;
                bitStream.Write ( &type );

                // Write its length
                uint uiLength = sizeTemp;
                bitStream.WriteCompressed ( uiLength );

                // Write the content too if it's not empty
                if ( uiLength > 0 )
                {
                    bitStream.AlignWriteToByteBoundary ();
                    bitStream.Write ( szTemp, uiLength );
                }
            }
            else
            {
                // Too long string
                LogUnableToPacketize ( "Couldn't packetize argument list. Invalid string specified, limit is 65535 characters."
                                       " To use longer strings, set script <min_mta_version> to " LONG_STRING_MIN_VERSION " or higher." );

                // Write a nil though so other side won't get out of sync
                type.data.ucType = LUA_TNIL;
                bitStream.Write ( &type );
                return false;
            }
            break;
        }

        // Element argument
        case LUA_TLIGHTUSERDATA:
        {
            // Grab the element from this userdata pointer. Valid and has a synced element ID?
            CElement* pElement = GetElement ();
            if ( pElement && pElement->GetID () != INVALID_ELEMENT_ID )
            {
                // Write its ID
                type.data.ucType = LUA_TLIGHTUSERDATA;
                bitStream.Write ( &type );
                bitStream.Write ( pElement->GetID () );
            }
            else
            {
                // Jax: this just spams the script debugger, it's not really neccesary
                // LogUnableToPacketize ( "Couldn't packetize argument list, invalid element specified." );

                // Write a nil though so other side won't get out of sync
                type.data.ucType = LUA_TNIL;
                bitStream.Write ( &type );
                return false;
            }

            break;
        }

        // Unpacketizable type.
        default:
        {
            // Unpacketizable
            LogUnableToPacketize ( "Couldn't packetize argument list, unknown type specified." );

            // Write a nil though so other side won't get out of sync
            type.data.ucType = LUA_TNIL;
            bitStream.Write ( &type );
            return false;
        }
    }

    // Success
    return true;
}