void CElementRPCs::RemoveElementData ( NetBitStreamInterface& bitStream ) { // Read out the entity id and name length ElementID ID; unsigned short usNameLength; bool bRecursive; if ( bitStream.ReadCompressed ( ID ) && bitStream.ReadCompressed ( usNameLength ) ) { // Allocate a buffer for the name char* szName = new char [ usNameLength + 1 ]; szName [ usNameLength ] = NULL; // Read it out plus whether it's recursive or not if ( bitStream.Read ( szName, usNameLength ) && bitStream.ReadBit ( bRecursive ) ) { // Grab the entity CClientEntity* pEntity = CElementIDs::GetElement ( ID ); if ( pEntity ) { // Remove that name pEntity->DeleteCustomData ( szName, bRecursive ); } } // Delete the name buffer delete [] szName; } }
bool CLuaArguments::ReadFromBitStream(NetBitStreamInterface& bitStream, std::vector<CLuaArguments*>* pKnownTables) { bool bKnownTablesCreated = false; if (!pKnownTables) { pKnownTables = new std::vector<CLuaArguments*>(); bKnownTablesCreated = true; } unsigned int uiNumArgs; bool bResult; #if MTA_DM_VERSION >= 0x150 bResult = bitStream.ReadCompressed(uiNumArgs); #else unsigned short usNumArgs; if (bitStream.Version() < 0x05B) { // We got the old version bResult = bitStream.ReadCompressed(usNumArgs); uiNumArgs = usNumArgs; } else { // Check if we got the new version if ((bResult = bitStream.ReadCompressed(usNumArgs))) { if (usNumArgs == 0xFFFF) // We got the new version bResult = bitStream.ReadCompressed(uiNumArgs); else // We got the old version uiNumArgs = usNumArgs; } } #endif if (bResult) { pKnownTables->push_back(this); for (unsigned int ui = 0; ui < uiNumArgs; ++ui) { CLuaArgument* pArgument = new CLuaArgument(bitStream, pKnownTables); m_Arguments.push_back(pArgument); } } if (bKnownTablesCreated) delete pKnownTables; return true; }
void CWeaponRPCs::TakeWeapon ( NetBitStreamInterface& bitStream ) { // Read out weapon id and ammo amount ElementID ID; SWeaponTypeSync weaponType; if ( bitStream.ReadCompressed ( ID ) && bitStream.Read ( &weaponType ) ) { unsigned char ucWeaponID = weaponType.data.ucWeaponType; CClientPed * pPed = m_pPedManager->Get ( ID, true ); if ( pPed ) { // Don't change remote players weapons (affects sync) if ( pPed->GetType () == CCLIENTPED || ( CClientPlayer * ) pPed == m_pPlayerManager->GetLocalPlayer () ) { // Is the weapon id valid? (may not be neccessary, just being safe) if ( CClientPickupManager::IsValidWeaponID ( ucWeaponID ) ) { // Remove the weapon pPed->RemoveWeapon ( static_cast < eWeaponType > ( ucWeaponID ) ); } } } } }
bool CLuaArguments::ReadFromBitStream ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables ) { bool bKnownTablesCreated = false; if ( !pKnownTables ) { pKnownTables = new std::vector < CLuaArguments* > (); bKnownTablesCreated = true; } unsigned short usNumArgs; if ( bitStream.ReadCompressed ( usNumArgs ) ) { pKnownTables->push_back ( this ); for ( unsigned short us = 0 ; us < usNumArgs ; us++ ) { CLuaArgument* pArgument = new CLuaArgument ( bitStream, pKnownTables ); m_Arguments.push_back ( pArgument ); } } if ( bKnownTablesCreated ) delete pKnownTables; return true; }
void CElementRPCs::SetElementData ( NetBitStreamInterface& bitStream ) { ElementID ID; unsigned short usNameLength; if ( bitStream.ReadCompressed ( ID ) && bitStream.ReadCompressed ( usNameLength ) ) { char* szName = new char [ usNameLength + 1 ]; szName [ usNameLength ] = NULL; CLuaArgument Argument; if ( bitStream.Read ( szName, usNameLength ) && Argument.ReadFromBitStream ( bitStream ) ) { CClientEntity* pEntity = CElementIDs::GetElement ( ID ); if ( pEntity ) { pEntity->SetCustomData ( szName, Argument, NULL ); } } delete [] szName; } }
void CPedRPCs::SetPedMoveAnim ( CClientEntity* pSource, NetBitStreamInterface& bitStream ) { unsigned int uiMoveAnim; if ( bitStream.ReadCompressed ( uiMoveAnim ) ) { CClientPed* pPed = m_pPedManager->Get ( pSource->GetID (), true ); if ( pPed ) { pPed->SetMoveAnim ( (eMoveAnim)uiMoveAnim ); } } }
void CWeaponRPCs::TakeAllWeapons ( NetBitStreamInterface& bitStream ) { ElementID ID; if ( bitStream.ReadCompressed ( ID ) ) { CClientPed * pPed = m_pPedManager->Get ( ID, true ); if ( pPed ) { // Remove all our weapons pPed->RemoveAllWeapons (); } } }
void CWeaponRPCs::SetWeaponSlot ( NetBitStreamInterface& bitStream ) { ElementID ID; SWeaponSlotSync slot; if ( bitStream.ReadCompressed ( ID ) && bitStream.Read ( &slot ) ) { CClientPed * pPed = m_pPedManager->Get ( ID, true ); if ( pPed ) { pPed->SetCurrentWeaponSlot ( (eWeaponSlot) slot.data.uiSlot ); } } }
bool CCustomDataPacket::Read(NetBitStreamInterface& BitStream) { unsigned short usNameLength; if (BitStream.Read(m_ElementID) && BitStream.ReadCompressed(usNameLength) && usNameLength > 0 && usNameLength <= MAX_CUSTOMDATA_NAME_LENGTH) { m_szName = new char[usNameLength + 1]; if (BitStream.Read(m_szName, usNameLength)) { m_szName[usNameLength] = 0; if (m_Value.ReadFromBitStream(BitStream)) { return true; } } } return false; }
void CElementRPCs::RemoveElementData ( CClientEntity* pSource, NetBitStreamInterface& bitStream ) { // Read out the name length unsigned short usNameLength; bool bRecursive; if ( bitStream.ReadCompressed ( usNameLength ) ) { SString strName; // Read out the name plus whether it's recursive or not if ( bitStream.ReadStringCharacters ( strName, usNameLength ) && bitStream.ReadBit ( bRecursive ) ) { // Remove that name pSource->DeleteCustomData ( strName, bRecursive ); } } }
void CWeaponRPCs::TakeWeaponAmmo ( NetBitStreamInterface& bitStream ) { ElementID ID; SWeaponTypeSync weaponType; if ( bitStream.ReadCompressed ( ID ) && bitStream.Read ( &weaponType ) ) { unsigned char ucWeaponID = weaponType.data.ucWeaponType; SWeaponAmmoSync ammo ( ucWeaponID, true, false ); if ( bitStream.Read ( &ammo ) ) { unsigned short usAmmo = ammo.data.usTotalAmmo; CClientPed * pPed = m_pPedManager->Get ( ID, true ); if ( pPed ) { // Valid weapon id? if ( !CClientPickupManager::IsValidWeaponID ( ucWeaponID ) ) return; // Do we have it? CWeapon* pPlayerWeapon = pPed->GetWeapon ( (eWeaponType) ucWeaponID ); if ( pPlayerWeapon == NULL ) return; unsigned char ucAmmoInClip = static_cast < unsigned char > ( pPlayerWeapon->GetAmmoInClip () ); pPlayerWeapon->SetAmmoInClip ( 0 ); unsigned long ulWeaponAmmo = pPlayerWeapon->GetAmmoTotal (); if ( ulWeaponAmmo - usAmmo < 0 ) ulWeaponAmmo = 0; else ulWeaponAmmo -= usAmmo; // Remove the weapon ammo pPlayerWeapon->SetAmmoTotal ( ulWeaponAmmo ); if ( pPlayerWeapon->GetAmmoTotal () > ucAmmoInClip ) pPlayerWeapon->SetAmmoInClip ( ucAmmoInClip ); else if ( pPlayerWeapon->GetAmmoTotal () <= ucAmmoInClip ) pPlayerWeapon->SetAmmoInClip ( pPlayerWeapon->GetAmmoTotal () ); } } } }
void CElementRPCs::SetElementData ( CClientEntity* pSource, NetBitStreamInterface& bitStream ) { unsigned short usNameLength; if ( bitStream.ReadCompressed ( usNameLength ) ) { // We should never receive an illegal name length from the server if ( usNameLength > MAX_CUSTOMDATA_NAME_LENGTH ) { CLogger::ErrorPrintf ( "RPC SetElementData name length > MAX_CUSTOMDATA_NAME_LENGTH" ); return; } SString strName; CLuaArgument Argument; if ( bitStream.ReadStringCharacters ( strName, usNameLength ) && Argument.ReadFromBitStream ( bitStream ) ) { pSource->SetCustomData ( strName, Argument, NULL ); } } }
void CRPCFunctions::PlayerTarget ( NetBitStreamInterface & bitStream ) { if ( m_pSourcePlayer->IsJoined () ) { ElementID TargetID; bitStream.ReadCompressed ( TargetID ); CElement* pTarget = NULL; if ( TargetID != INVALID_ELEMENT_ID ) pTarget = CElementIDs::GetElement ( TargetID ); m_pSourcePlayer->SetTargetedElement ( pTarget ); // Call our script event CLuaArguments Arguments; if ( pTarget ) Arguments.PushElement ( pTarget ); else Arguments.PushBoolean ( false ); m_pSourcePlayer->CallEvent ( "onPlayerTarget", Arguments ); } }
bool CLuaEventPacket::Read(NetBitStreamInterface& BitStream) { unsigned short usNameLength; if (BitStream.ReadCompressed(usNameLength)) { if (usNameLength < (MAX_EVENT_NAME_LENGTH - 1) && BitStream.ReadStringCharacters(m_strName, usNameLength) && BitStream.Read(m_ElementID)) { // Faster than using a constructor m_ArgumentsStore.DeleteArguments(); if(!m_ArgumentsStore.ReadFromBitStream(BitStream)) return false; m_pArguments = &m_ArgumentsStore; return true; } } return false; }
bool CPlayerJoinDataPacket::Read ( NetBitStreamInterface& BitStream ) { m_szNick [ MAX_NICK_LENGTH ] = 0; m_szSerialUser [MAX_SERIAL_LENGTH] = 0; // Read out the stuff if ( !BitStream.Read ( m_usNetVersion ) || !BitStream.Read ( m_usMTAVersion ) ) return false; if ( m_usMTAVersion < 0x0102 ) { // Clients earlier than 1.0.2 do not have a bitstream version m_usBitStreamVersion = 0x01; } else { if ( !BitStream.Read ( m_usBitStreamVersion ) ) return false; } if ( m_usBitStreamVersion >= 0x0b ) { unsigned int uiLength; BitStream.ReadCompressed ( uiLength ); if ( uiLength < 1 || uiLength > 100 ) return false; m_strPlayerVersion.assign ( uiLength, 32 ); BitStream.Read ( &m_strPlayerVersion.at ( 0 ), uiLength ); } if ( m_usBitStreamVersion >= 0x0e ) m_bOptionalUpdateInfoRequired = BitStream.ReadBit (); else m_bOptionalUpdateInfoRequired = false; return ( BitStream.Read ( m_ucGameVersion ) && BitStream.Read ( m_szNick, MAX_NICK_LENGTH ) && BitStream.Read ( reinterpret_cast < char* > ( &m_Password ), 16 ) && BitStream.Read ( m_szSerialUser, MAX_SERIAL_LENGTH ) ); }
void CRPCFunctions::RequestStealthKill ( NetBitStreamInterface & bitStream ) { ElementID ID; bitStream.ReadCompressed ( ID ); CElement * pElement = CElementIDs::GetElement ( ID ); if ( pElement ) { int elementType = pElement->GetType (); if ( elementType == CElement::PLAYER || elementType == CElement::PED ) { CPed * pTarget = static_cast < CPed * > ( pElement ); // Are they both alive? if ( !m_pSourcePlayer->IsDead () && !pTarget->IsDead () ) { //Do we have any record of the killer currently having a knife? if ( m_pSourcePlayer->GetWeaponType( 1 ) == 4 ) { // Are they close enough? if ( DistanceBetweenPoints3D ( m_pSourcePlayer->GetPosition (), pTarget->GetPosition () ) <= STEALTH_KILL_RANGE ) { CLuaArguments Arguments; Arguments.PushElement ( pTarget ); if ( m_pSourcePlayer->CallEvent ( "onPlayerStealthKill", Arguments, false ) ) { // Start the stealth kill CStaticFunctionDefinitions::KillPed ( pTarget, m_pSourcePlayer, 4 /*WEAPONTYPE_KNIFE*/, 9/*BODYPART_HEAD*/, true ); } } } else { //You shouldn't be able to get here without cheating to get a knife. if ( !g_pGame->GetConfig ()->IsDisableAC ( "2" ) ) { CStaticFunctionDefinitions::KickPlayer ( m_pSourcePlayer, NULL, "AC #2: You were kicked from the game" ); } } } } } }
void CWeaponRPCs::GiveWeaponAmmo ( NetBitStreamInterface& bitStream ) { ElementID ID; SWeaponTypeSync weaponType; if ( bitStream.ReadCompressed ( ID ) && bitStream.Read ( &weaponType ) ) { unsigned char ucWeaponID = weaponType.data.ucWeaponType; SWeaponAmmoSync ammo ( ucWeaponID, true, false ); if ( bitStream.Read ( &ammo ) ) { unsigned short usAmmo = ammo.data.usTotalAmmo; CClientPed * pPed = m_pPedManager->Get ( ID, true ); if ( pPed ) { // Valid weapon id? if ( !CClientPickupManager::IsValidWeaponID ( ucWeaponID ) ) return; // Do we have it? CWeapon* pPlayerWeapon = pPed->GetWeapon ( (eWeaponType) ucWeaponID ); if ( pPlayerWeapon == NULL ) return; unsigned long ulWeaponAmmo = pPlayerWeapon->GetAmmoTotal (); ulWeaponAmmo += usAmmo; // Adjust the ammo to 9999 if it's above if ( ulWeaponAmmo > 9999 ) { ulWeaponAmmo = 9999; } // Add the weapon ammo pPlayerWeapon->SetAmmoTotal ( ulWeaponAmmo ); } } } }
bool CLuaArgument::ReadFromBitStream ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables ) { DeleteTableData (); SLuaTypeSync type; // Read out the type if ( bitStream.Read ( &type ) ) { // Depending on what type... switch ( type.data.ucType ) { // Nil type case LUA_TNIL: { m_iType = LUA_TNIL; break; } // Boolean type case LUA_TBOOLEAN: { bool bValue; if ( bitStream.ReadBit ( bValue ) ) ReadBool ( bValue ); break; } // Number type case LUA_TNUMBER: { bool bIsFloatingPoint; if ( bitStream.ReadBit ( bIsFloatingPoint ) && bIsFloatingPoint ) { float fNum; if ( bitStream.Read ( fNum ) ) ReadNumber ( fNum ); } else { long lNum; if ( bitStream.ReadCompressed ( lNum ) ) ReadNumber ( lNum ); } break; } // Table type case LUA_TTABLE: { m_pTableData = new CLuaArguments ( bitStream, pKnownTables ); m_bWeakTableRef = false; m_iType = LUA_TTABLE; m_pTableData->ValidateTableKeys (); break; } // Table reference case LUA_TTABLEREF: { unsigned long ulTableRef; if ( bitStream.ReadCompressed ( ulTableRef ) ) { if ( pKnownTables && ulTableRef < pKnownTables->size () ) { m_pTableData = pKnownTables->at ( ulTableRef ); m_bWeakTableRef = true; m_iType = LUA_TTABLE; } } break; } // String type case LUA_TSTRING: { // Read out the string length unsigned short usLength; if ( bitStream.ReadCompressed ( usLength ) && usLength ) { // Allocate a buffer and read the string into it char* szValue = new char [ usLength + 1 ]; if ( bitStream.Read ( szValue, usLength ) ) { // Put it into us ReadString ( std::string ( szValue, usLength ) ); } // Delete the buffer delete [] szValue; } else ReadString ( "" ); break; } // Long string type case LUA_TSTRING_LONG: { // Read out the string length uint uiLength; if ( bitStream.ReadCompressed ( uiLength ) && uiLength ) { bitStream.AlignReadToByteBoundary (); // Allocate a buffer and read the string into it char* szValue = new char [ uiLength + 1 ]; assert ( szValue ); if ( bitStream.Read ( szValue, uiLength ) ) { // Put it into us ReadString ( std::string ( szValue, uiLength ) ); } // Delete the buffer delete [] szValue; } else ReadString ( "" ); // Enforce min_mta_version version rule if ( uiLength > 65535 && g_pGame->CalculateMinClientRequirement () < LONG_STRING_MIN_VERSION ) { 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." ); m_iType = LUA_TNIL; } break; } // Element type? case LUA_TLIGHTUSERDATA: { ElementID ElementID; if ( bitStream.Read ( ElementID ) ) { CElement * element = CElementIDs::GetElement ( ElementID ); ReadElement ( element ); } break; } } } return true; }
// Can't use bitStream.Version() here as it is sometimes not set bool CLuaArgument::ReadFromBitStream(NetBitStreamInterface& bitStream, std::vector<CLuaArguments*>* pKnownTables) { DeleteTableData(); SLuaTypeSync type; // Read out the type if (bitStream.Read(&type)) { // Depending on what type... switch (type.data.ucType) { // Nil type case LUA_TNIL: { m_iType = LUA_TNIL; break; } // Boolean type case LUA_TBOOLEAN: { bool bValue; if (bitStream.ReadBit(bValue)) ReadBool(bValue); break; } // Number type case LUA_TNUMBER: { if (bitStream.ReadBit()) { if (bitStream.ReadBit()) { double dNum; if (bitStream.Read(dNum)) ReadNumber(dNum); } else { float fNum; if (bitStream.Read(fNum)) ReadNumber(RoundFromFloatSource(fNum)); } } else { int iNum; if (bitStream.ReadCompressed(iNum)) ReadNumber(iNum); } break; } // Table type case LUA_TTABLE: { m_pTableData = new CLuaArguments(bitStream, pKnownTables); m_bWeakTableRef = false; m_iType = LUA_TTABLE; m_pTableData->ValidateTableKeys(); break; } // Table reference case LUA_TTABLEREF: { unsigned long ulTableRef; if (bitStream.ReadCompressed(ulTableRef)) { if (pKnownTables && ulTableRef < pKnownTables->size()) { m_pTableData = pKnownTables->at(ulTableRef); m_bWeakTableRef = true; m_iType = LUA_TTABLE; } } break; } // String type case LUA_TSTRING: { // Read out the string length unsigned short usLength; if (bitStream.ReadCompressed(usLength) && usLength) { // Allocate a buffer and read the string into it char* szValue = new char[usLength + 1]; if (bitStream.Read(szValue, usLength)) { // Put it into us ReadString(std::string(szValue, usLength)); } // Delete the buffer delete[] szValue; } else ReadString(""); break; } // Long string type case LUA_TSTRING_LONG: { // Read out the string length uint uiLength; if (bitStream.ReadCompressed(uiLength) && uiLength) { bitStream.AlignReadToByteBoundary(); // Allocate a buffer and read the string into it char* szValue = new char[uiLength + 1]; assert(szValue); if (bitStream.Read(szValue, uiLength)) { // Put it into us ReadString(std::string(szValue, uiLength)); } // Delete the buffer delete[] szValue; } else ReadString(""); break; } // Element type? case LUA_TLIGHTUSERDATA: case LUA_TUSERDATA: { ElementID ElementID; if (bitStream.Read(ElementID)) { ReadElementID(ElementID); } break; } } } return true; }
bool CProjectileSyncPacket::Read ( NetBitStreamInterface& BitStream ) { bool bHasOrigin; if ( !BitStream.ReadBit ( bHasOrigin ) ) return false; m_OriginID = INVALID_ELEMENT_ID; if ( bHasOrigin && !BitStream.ReadCompressed ( m_OriginID ) ) return false; SPositionSync origin ( false ); if ( !BitStream.Read ( &origin ) ) return false; m_vecOrigin = origin.data.vecPosition; SWeaponTypeSync weaponType; if ( !BitStream.Read ( &weaponType ) ) return false; m_ucWeaponType = weaponType.data.ucWeaponType; 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; if ( !BitStream.Read ( &projectileForce ) ) return false; m_fForce = projectileForce.data.fValue; SVelocitySync velocity; if ( !BitStream.Read ( &velocity ) ) return false; m_vecMoveSpeed = velocity.data.vecVelocity; break; } case 19: // WEAPONTYPE_ROCKET case 20: // WEAPONTYPE_ROCKET_HS { bool bHasTarget; if ( !BitStream.ReadBit ( bHasTarget ) ) return false; m_TargetID = INVALID_ELEMENT_ID; if ( bHasTarget && !BitStream.ReadCompressed ( m_TargetID ) ) return false; SVelocitySync velocity; if ( !BitStream.Read ( &velocity ) ) return false; m_vecMoveSpeed = velocity.data.vecVelocity; SRotationRadiansSync rotation ( true ); if ( !BitStream.Read ( &rotation ) ) return false; m_vecRotation = rotation.data.vecRotation; break; } case 58: // WEAPONTYPE_FLARE case 21: // WEAPONTYPE_FREEFALL_BOMB break; default: return false; } return true; }
bool CLuaArgument::ReadFromBitStream ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables ) { DeleteTableData (); SLuaTypeSync type; // Read out the type if ( bitStream.Read ( &type ) ) { // Depending on what type... switch ( type.data.ucType ) { // Nil type case LUA_TNIL: { m_iType = LUA_TNIL; break; } // Boolean type case LUA_TBOOLEAN: { bool bValue; if ( bitStream.ReadBit ( bValue ) ) Read(bValue); break; } // Number type case LUA_TNUMBER: { bool bIsFloatingPoint; if ( bitStream.ReadBit ( bIsFloatingPoint ) && bIsFloatingPoint ) { float fNum; if ( bitStream.Read ( fNum ) ) Read ( (double) fNum ); } else { long lNum; if ( bitStream.ReadCompressed ( lNum ) ) Read ( (double) lNum ); } break; } // Table type case LUA_TTABLE: { m_pTableData = new CLuaArguments ( bitStream, pKnownTables ); m_bWeakTableRef = false; m_iType = LUA_TTABLE; break; } // Table reference case LUA_TTABLEREF: { unsigned long ulTableRef; if ( bitStream.ReadCompressed ( ulTableRef ) ) { if ( pKnownTables && ulTableRef < pKnownTables->size () ) { m_pTableData = pKnownTables->at ( ulTableRef ); m_bWeakTableRef = true; m_iType = LUA_TTABLE; } } break; } // String type case LUA_TSTRING: { // Read out the string length unsigned short usLength; if ( bitStream.ReadCompressed ( usLength ) && usLength ) { // Allocate a buffer and read the string into it char* szValue = new char [ usLength + 1 ]; if ( bitStream.Read ( szValue, usLength ) ) { // Put it into us szValue [ usLength ] = 0; Read ( szValue ); } // Delete the buffer delete [] szValue; } else Read ( "" ); break; } // Element type? case LUA_TLIGHTUSERDATA: { ElementID ElementID; if ( bitStream.ReadCompressed ( ElementID ) ) { CElement * element = CElementIDs::GetElement ( ElementID ); Read ( element ); } break; } } } return true; }
bool CVehiclePuresyncPacket::Read ( NetBitStreamInterface& BitStream ) { // Got a player to read? if ( m_pSourceElement ) { CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement ); // Player is in a vehicle? CVehicle* pVehicle = pSourcePlayer->GetOccupiedVehicle (); if ( pVehicle ) { // Read out the time context unsigned char ucTimeContext = 0; if ( !BitStream.Read ( ucTimeContext ) ) return false; // Only read this packet if it matches the current time context that // player is in. if ( !pSourcePlayer->CanUpdateSync ( ucTimeContext ) ) { return false; } // Read out the keysync data CControllerState ControllerState; if ( !ReadFullKeysync ( ControllerState, BitStream ) ) return false; // Read out its position SPositionSync position ( false ); if ( !BitStream.Read ( &position ) ) return false; pSourcePlayer->SetPosition ( position.data.vecPosition ); // Jax: don't allow any outdated packets through unsigned char ucSeat; if ( !BitStream.Read ( ucSeat ) ) return false; if ( ucSeat != pSourcePlayer->GetOccupiedVehicleSeat () ) { // Mis-matching seats can happen when we warp into a different one, // which will screw up the whole packet return false; } // Read out the vehicle matrix only if he's the driver unsigned int uiSeat = pSourcePlayer->GetOccupiedVehicleSeat (); if ( uiSeat == 0 ) { // Read out the vehicle rotation in degrees SRotationDegreesSync rotation; if( !BitStream.Read ( &rotation ) ) return false; // Set it pVehicle->SetPosition ( position.data.vecPosition ); pVehicle->SetRotationDegrees ( rotation.data.vecRotation ); // Move speed vector SVelocitySync velocity; if ( !BitStream.Read ( &velocity ) ) return false; pVehicle->SetVelocity ( velocity.data.vecVelocity ); pSourcePlayer->SetVelocity ( velocity.data.vecVelocity ); // Turn speed vector SVelocitySync turnSpeed; if ( !BitStream.Read ( &turnSpeed ) ) return false; pVehicle->SetTurnSpeed ( turnSpeed.data.vecVelocity ); // Health SVehicleHealthSync health; if ( !BitStream.Read ( &health ) ) return false; float fPreviousHealth = pVehicle->GetHealth (); float fHealth = health.data.fValue; // Less than last time? if ( fHealth < fPreviousHealth ) { // Grab the delta health float fDeltaHealth = fPreviousHealth - fHealth; if ( fDeltaHealth > 0.0f ) { // Call the onVehicleDamage event CLuaArguments Arguments; Arguments.PushNumber ( fDeltaHealth ); pVehicle->CallEvent ( "onVehicleDamage", Arguments ); } } pVehicle->SetHealth ( fHealth ); // Trailer chain CVehicle* pTowedByVehicle = pVehicle; CVehicle* pTrailer = NULL; ElementID TrailerID; bool bHasTrailer; if ( !BitStream.ReadBit ( bHasTrailer ) ) return false; while ( bHasTrailer ) { BitStream.ReadCompressed ( TrailerID ); CElement* pElement = CElementIDs::GetElement ( TrailerID ); if ( pElement ) pTrailer = static_cast < CVehicle* > ( pElement ); // Read out the trailer position and rotation SPositionSync trailerPosition ( false ); if ( !BitStream.Read ( &trailerPosition ) ) return false; SRotationDegreesSync trailerRotation; if ( !BitStream.Read ( &trailerRotation ) ) return false; // If we found the trailer if ( pTrailer ) { // Set its position and rotation pTrailer->SetPosition ( trailerPosition.data.vecPosition ); pTrailer->SetRotationDegrees ( trailerRotation.data.vecRotation ); // Is this a new trailer, attached? CVehicle* pCurrentTrailer = pTowedByVehicle->GetTowedVehicle (); if ( pCurrentTrailer != pTrailer ) { // If theres a trailer already attached if ( pCurrentTrailer ) { pTowedByVehicle->SetTowedVehicle ( NULL ); pCurrentTrailer->SetTowedByVehicle ( NULL ); // Tell everyone to detach them CVehicleTrailerPacket AttachPacket ( pTowedByVehicle, pCurrentTrailer, false ); g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( AttachPacket ); // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement ( pTowedByVehicle ); pCurrentTrailer->CallEvent ( "onTrailerDetach", Arguments ); } // If something else is towing this trailer CVehicle* pCurrentVehicle = pTrailer->GetTowedByVehicle (); if ( pCurrentVehicle ) { pCurrentVehicle->SetTowedVehicle ( NULL ); pTrailer->SetTowedByVehicle ( NULL ); // Tell everyone to detach them CVehicleTrailerPacket AttachPacket ( pCurrentVehicle, pTrailer, false ); g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( AttachPacket ); // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement ( pCurrentVehicle ); pTrailer->CallEvent ( "onTrailerDetach", Arguments ); } pTowedByVehicle->SetTowedVehicle ( pTrailer ); pTrailer->SetTowedByVehicle ( pTowedByVehicle ); // Execute the attach trailer script function CLuaArguments Arguments; Arguments.PushElement ( pTowedByVehicle ); bool bContinue = pTrailer->CallEvent ( "onTrailerAttach", Arguments ); // Attach or detach trailers depending on the event outcome CVehicleTrailerPacket TrailerPacket ( pTowedByVehicle, pTrailer, bContinue ); g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( TrailerPacket ); } } else break; pTowedByVehicle = pTrailer; if ( BitStream.ReadBit ( bHasTrailer ) == false ) return false; } // If there was a trailer before CVehicle* pCurrentTrailer = pTowedByVehicle->GetTowedVehicle (); if ( pCurrentTrailer ) { pTowedByVehicle->SetTowedVehicle ( NULL ); pCurrentTrailer->SetTowedByVehicle ( NULL ); // Tell everyone else to detach them CVehicleTrailerPacket AttachPacket ( pTowedByVehicle, pCurrentTrailer, false ); g_pGame->GetPlayerManager ()->BroadcastOnlyJoined ( AttachPacket ); // Execute the detach trailer script function CLuaArguments Arguments; Arguments.PushElement ( pTowedByVehicle ); pCurrentTrailer->CallEvent ( "onTrailerDetach", Arguments ); } } // Player health SPlayerHealthSync health; if ( !BitStream.Read ( &health ) ) return false; float fHealth = health.data.fValue; float fOldHealth = pSourcePlayer->GetHealth (); float fHealthLoss = fOldHealth - fHealth; // Less than last packet's frame? if ( fHealth < fOldHealth && fHealthLoss > 0 ) { // Call the onPlayerDamage event CLuaArguments Arguments; Arguments.PushNil (); Arguments.PushNumber ( false ); Arguments.PushNumber ( false ); Arguments.PushNumber ( fHealthLoss ); pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments ); } pSourcePlayer->SetHealth ( fHealth ); // Armor SPlayerArmorSync armor; if ( !BitStream.Read ( &armor ) ) return false; float fArmor = armor.data.fValue; float fOldArmor = pSourcePlayer->GetArmor (); float fArmorLoss = fOldArmor - fArmor; // Less than last packet's frame? if ( fArmor < fOldArmor && fArmorLoss > 0 ) { // Call the onPlayerDamage event CLuaArguments Arguments; Arguments.PushNil (); Arguments.PushNumber ( false ); Arguments.PushNumber ( false ); Arguments.PushNumber ( fArmorLoss ); pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments ); } pSourcePlayer->SetArmor ( fArmor ); // Flags SVehiclePuresyncFlags flags; if ( !BitStream.Read ( &flags ) ) return false; pSourcePlayer->SetWearingGoggles ( flags.data.bIsWearingGoggles ); pSourcePlayer->SetDoingGangDriveby ( flags.data.bIsDoingGangDriveby ); // Weapon sync if ( flags.data.bHasAWeapon ) { SWeaponSlotSync slot; if ( !BitStream.Read ( &slot ) ) return false; pSourcePlayer->SetWeaponSlot ( slot.data.uiSlot ); if ( flags.data.bIsDoingGangDriveby && CWeaponNames::DoesSlotHaveAmmo ( slot.data.uiSlot ) ) { // Read the ammo states SWeaponAmmoSync ammo ( pSourcePlayer->GetWeaponType (), false, true ); if ( !BitStream.Read ( &ammo ) ) return false; pSourcePlayer->SetWeaponAmmoInClip ( ammo.data.usAmmoInClip ); // Read aim data SWeaponAimSync aim ( pSourcePlayer->GetWeaponRange (), true ); if ( !BitStream.Read ( &aim ) ) return false; pSourcePlayer->SetAimDirection ( aim.data.fArm ); pSourcePlayer->SetSniperSourceVector ( aim.data.vecOrigin ); pSourcePlayer->SetTargettingVector ( aim.data.vecTarget ); // Read the driveby direction SDrivebyDirectionSync driveby; if ( !BitStream.Read ( &driveby ) ) return false; pSourcePlayer->SetDriveByDirection ( driveby.data.ucDirection ); } } else pSourcePlayer->SetWeaponSlot ( 0 ); // Vehicle specific data if he's the driver if ( uiSeat == 0 ) { ReadVehicleSpecific ( pVehicle, BitStream ); // Set vehicle specific stuff if he's the driver pVehicle->SetSirenActive ( flags.data.bIsSirenOrAlarmActive ); pVehicle->SetSmokeTrailEnabled ( flags.data.bIsSmokeTrailEnabled ); pVehicle->SetLandingGearDown ( flags.data.bIsLandingGearDown ); pVehicle->SetOnGround ( flags.data.bIsOnGround ); pVehicle->SetInWater ( flags.data.bIsInWater ); pVehicle->SetDerailed ( flags.data.bIsDerailed ); pVehicle->SetHeliSearchLightVisible ( flags.data.bIsHeliSearchLightVisible ); } // Read the vehicle_look_left and vehicle_look_right control states // if it's an aircraft. if ( flags.data.bIsAircraft ) { ControllerState.LeftShoulder2 = BitStream.ReadBit () * 255; ControllerState.RightShoulder2 = BitStream.ReadBit () * 255; } pSourcePlayer->GetPad ()->NewControllerState ( ControllerState ); // Success return true; } } return false; }
bool CPlayerPuresyncPacket::Read ( NetBitStreamInterface& BitStream ) { if ( m_pSourceElement ) { CPlayer * pSourcePlayer = static_cast < CPlayer * > ( m_pSourceElement ); // Read out the time context unsigned char ucTimeContext = 0; if ( !BitStream.Read ( ucTimeContext ) ) return false; // Only read this packet if it matches the current time context that // player is in. if ( !pSourcePlayer->CanUpdateSync ( ucTimeContext ) ) { return false; } // Read out keys CControllerState ControllerState; ReadFullKeysync ( ControllerState, BitStream ); pSourcePlayer->GetPad ()->NewControllerState ( ControllerState ); // Read the flags SPlayerPuresyncFlags flags; if ( !BitStream.Read ( &flags ) ) return false; pSourcePlayer->SetInWater ( flags.data.bIsInWater ); pSourcePlayer->SetOnGround ( flags.data.bIsOnGround ); pSourcePlayer->SetHasJetPack ( flags.data.bHasJetPack ); pSourcePlayer->SetDucked ( flags.data.bIsDucked ); pSourcePlayer->SetWearingGoggles ( flags.data.bWearsGoogles ); pSourcePlayer->SetChoking ( flags.data.bIsChoking ); pSourcePlayer->SetAkimboArmUp ( flags.data.bAkimboTargetUp ); pSourcePlayer->SetOnFire ( flags.data.bIsOnFire ); pSourcePlayer->SetStealthAiming ( flags.data.bStealthAiming ); // Contact element CElement* pContactElement = NULL; if ( flags.data.bHasContact ) { ElementID Temp; if ( !BitStream.ReadCompressed ( Temp ) ) return false; pContactElement = CElementIDs::GetElement ( Temp ); } CElement * pPreviousContactElement = pSourcePlayer->GetContactElement (); pSourcePlayer->SetContactElement ( pContactElement ); if ( pPreviousContactElement != pContactElement ) { // Call our onPlayerContact event CLuaArguments Arguments; if ( pPreviousContactElement ) Arguments.PushElement ( pPreviousContactElement ); else Arguments.PushNil (); if ( pContactElement ) Arguments.PushElement ( pContactElement ); else Arguments.PushNil (); pSourcePlayer->CallEvent ( "onPlayerContact", Arguments ); } // Player position SPositionSync position ( false ); if ( !BitStream.Read ( &position ) ) return false; if ( pContactElement ) { pSourcePlayer->SetContactPosition ( position.data.vecPosition ); // Get the true position CVector vecTempPos = pContactElement->GetPosition (); position.data.vecPosition += vecTempPos; } pSourcePlayer->SetPosition ( position.data.vecPosition ); // Player rotation SPedRotationSync rotation; if ( !BitStream.Read ( &rotation ) ) return false; pSourcePlayer->SetRotation ( rotation.data.fRotation ); // Move speed vector if ( flags.data.bSyncingVelocity ) { SVelocitySync velocity; if ( !BitStream.Read ( &velocity ) ) return false; pSourcePlayer->SetVelocity ( velocity.data.vecVelocity ); } // Health ( stored with damage ) SPlayerHealthSync health; if ( !BitStream.Read ( &health ) ) return false; float fHealth = health.data.fValue; // Armor SPlayerArmorSync armor; if ( !BitStream.Read ( &armor ) ) return false; float fArmor = armor.data.fValue; float fOldArmor = pSourcePlayer->GetArmor (); float fArmorLoss = fOldArmor - fArmor; pSourcePlayer->SetArmor ( fArmor ); // Read out and set the camera rotation float fCameraRotation; if ( !BitStream.Read ( fCameraRotation ) ) return false; pSourcePlayer->SetCameraRotation ( fCameraRotation ); if ( flags.data.bHasAWeapon ) { if ( BitStream.Version () >= 0x0d ) { // Check client has the weapon we think he has unsigned char ucWeaponType; if ( !BitStream.Read ( ucWeaponType ) ) return false; if ( pSourcePlayer->GetWeaponType () != ucWeaponType ) return false; } // Current weapon slot SWeaponSlotSync slot; if ( !BitStream.Read ( &slot ) ) return false; unsigned int uiSlot = slot.data.uiSlot; pSourcePlayer->SetWeaponSlot ( uiSlot ); if ( CWeaponNames::DoesSlotHaveAmmo ( uiSlot ) ) { // Read out the ammo states SWeaponAmmoSync ammo ( pSourcePlayer->GetWeaponType (), true, true ); if ( !BitStream.Read ( &ammo ) ) return false; pSourcePlayer->SetWeaponAmmoInClip ( ammo.data.usAmmoInClip ); pSourcePlayer->SetWeaponTotalAmmo ( ammo.data.usTotalAmmo ); // Read out the aim data SWeaponAimSync sync ( pSourcePlayer->GetWeaponRange (), ( ControllerState.RightShoulder1 || ControllerState.ButtonCircle ) ); if ( !BitStream.Read ( &sync ) ) return false; // Set the arm directions and whether or not arms are up pSourcePlayer->SetAimDirection ( sync.data.fArm ); // Read the aim data only if he's shooting or aiming if ( sync.isFull() ) { pSourcePlayer->SetSniperSourceVector ( sync.data.vecOrigin ); pSourcePlayer->SetTargettingVector ( sync.data.vecTarget ); } } else { pSourcePlayer->SetWeaponAmmoInClip ( 1 ); pSourcePlayer->SetWeaponTotalAmmo ( 1 ); } } else { pSourcePlayer->SetWeaponSlot ( 0 ); pSourcePlayer->SetWeaponAmmoInClip ( 1 ); pSourcePlayer->SetWeaponTotalAmmo ( 1 ); } // Read out damage info if changed if ( BitStream.ReadBit () == true ) { ElementID DamagerID; if ( !BitStream.ReadCompressed ( DamagerID ) ) return false; SWeaponTypeSync weaponType; if ( !BitStream.Read ( &weaponType ) ) return false; SBodypartSync bodyPart; if ( !BitStream.Read ( &bodyPart ) ) return false; pSourcePlayer->SetDamageInfo ( DamagerID, weaponType.data.ucWeaponType, bodyPart.data.uiBodypart ); } // If we know the player's dead, make sure the health we send on is 0 if ( pSourcePlayer->IsDead () ) fHealth = 0.0f; float fOldHealth = pSourcePlayer->GetHealth (); float fHealthLoss = fOldHealth - fHealth; pSourcePlayer->SetHealth ( fHealth ); // Less than last packet's frame? if ( fHealthLoss > 0 || fArmorLoss > 0 ) { float fDamage = 0.0f; if ( fHealthLoss > 0 ) fDamage += fHealthLoss; if ( fArmorLoss > 0 ) fDamage += fArmorLoss; // Call the onPlayerDamage event CLuaArguments Arguments; CElement* pKillerElement = CElementIDs::GetElement ( pSourcePlayer->GetPlayerAttacker () ); if ( pKillerElement ) Arguments.PushElement ( pKillerElement ); else Arguments.PushNil (); Arguments.PushNumber ( pSourcePlayer->GetAttackWeapon () ); Arguments.PushNumber ( pSourcePlayer->GetAttackBodyPart () ); Arguments.PushNumber ( fDamage ); pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments ); } // Success return true; } return false; }
void CWeaponRPCs::GiveWeapon ( NetBitStreamInterface& bitStream ) { // Read out weapon id and ammo amount ElementID ID; SWeaponTypeSync weaponType; if ( bitStream.ReadCompressed ( ID ) && bitStream.Read ( &weaponType ) ) { SWeaponAmmoSync ammo ( weaponType.data.ucWeaponType, true, false ); if ( bitStream.Read ( &ammo ) ) { bool bGiveWeapon = bitStream.ReadBit (); unsigned char ucWeaponID = weaponType.data.ucWeaponType; unsigned short usAmmo = ammo.data.usTotalAmmo; CClientPed * pPed = m_pPedManager->Get ( ID, true ); if ( pPed ) { // Don't change remote players weapons (affects sync) if ( pPed->GetType () == CCLIENTPED || pPed->GetType () == CCLIENTPLAYER ) { // Valid weapon id? if ( ucWeaponID == 0 || CClientPickupManager::IsValidWeaponID ( ucWeaponID ) ) { // Adjust the ammo to 9999 if it's above if ( usAmmo > 9999 ) usAmmo = 9999; // Give the local player the weapon CWeapon* pPlayerWeapon = NULL; if ( ucWeaponID != 0 ) { pPlayerWeapon = pPed->GiveWeapon ( static_cast < eWeaponType > ( ucWeaponID ), usAmmo ); if ( pPlayerWeapon && bGiveWeapon ) pPlayerWeapon->SetAsCurrentWeapon (); } else { // This could be entered into a hack of the year competition. Its about as hacky as it gets. // For some stupid reason, going from brassknuckles to unarmed causes the knuckles to remain // on display but unusable. So, what we do is switch to a MELEE weapon (creating one if necessary) // then switch back to unarmed from there, which works fine. CWeapon* oldWeapon = pPed->GetWeapon (WEAPONSLOT_TYPE_UNARMED); if ( oldWeapon ) { eWeaponType unarmedWeapon = oldWeapon->GetType(); pPed->RemoveWeapon ( unarmedWeapon ); if ( bGiveWeapon || pPed->GetCurrentWeaponSlot() == WEAPONSLOT_TYPE_UNARMED ) { oldWeapon = NULL; if ( unarmedWeapon == WEAPONTYPE_BRASSKNUCKLE ) { oldWeapon = pPed->GetWeapon(WEAPONSLOT_TYPE_MELEE); if ( oldWeapon && oldWeapon->GetType() == WEAPONTYPE_UNARMED ) { oldWeapon = pPed->GiveWeapon(WEAPONTYPE_GOLFCLUB, 100); } else { oldWeapon = NULL; } pPed->SetCurrentWeaponSlot ( WEAPONSLOT_TYPE_MELEE ); } // switch to the unarmed slot pPed->SetCurrentWeaponSlot ( WEAPONSLOT_TYPE_UNARMED ); // if we created a special MELEE weapon just for this, remove it now if ( oldWeapon ) { oldWeapon->Remove(); } } } else { // Probably the ped is streamed out pPed->GiveWeapon ( WEAPONTYPE_UNARMED, 1 ); if ( bGiveWeapon ) pPed->SetCurrentWeaponSlot ( WEAPONSLOT_TYPE_UNARMED ); } } } } } } } }
void CRPCFunctions::CursorEvent ( NetBitStreamInterface & bitStream ) { SMouseButtonSync button; unsigned char ucButton; CVector2D vecCursorPosition; unsigned short usX; unsigned short usY; SPositionSync position ( false ); CVector vecPosition; bool bHasCollisionElement; ElementID elementID; if ( bitStream.Read ( &button ) && bitStream.ReadCompressed ( usX ) && bitStream.ReadCompressed ( usY ) && bitStream.Read ( &position ) && bitStream.ReadBit ( bHasCollisionElement ) && ( !bHasCollisionElement || bitStream.ReadCompressed ( elementID ) ) ) { ucButton = button.data.ucButton; vecCursorPosition.fX = static_cast < float > ( usX ); vecCursorPosition.fY = static_cast < float > ( usY ); vecPosition = position.data.vecPosition; if ( !bHasCollisionElement ) elementID = INVALID_ELEMENT_ID; } else return; if ( m_pSourcePlayer->IsJoined () ) { // Get the button and state const char* szButton = NULL; const char* szState = NULL; switch ( ucButton ) { case 0: szButton = "left"; szState = "down"; break; case 1: szButton = "left"; szState = "up"; break; case 2: szButton = "middle"; szState = "down"; break; case 3: szButton = "middle"; szState = "up"; break; case 4: szButton = "right"; szState = "down"; break; case 5: szButton = "right"; szState = "up"; break; } if ( szButton && szState ) { CElement* pElement = CElementIDs::GetElement ( elementID ); if ( pElement ) { // Call the onElementClicked event CLuaArguments Arguments; Arguments.PushString ( szButton ); Arguments.PushString ( szState ); Arguments.PushElement ( m_pSourcePlayer ); Arguments.PushNumber ( vecPosition.fX ); Arguments.PushNumber ( vecPosition.fY ); Arguments.PushNumber ( vecPosition.fZ ); pElement->CallEvent ( "onElementClicked", Arguments ); } // Call the onPlayerClick event CLuaArguments Arguments; Arguments.PushString ( szButton ); Arguments.PushString ( szState ); if ( pElement ) Arguments.PushElement ( pElement ); else Arguments.PushNil (); Arguments.PushNumber ( vecPosition.fX ); Arguments.PushNumber ( vecPosition.fY ); Arguments.PushNumber ( vecPosition.fZ ); Arguments.PushNumber ( vecCursorPosition.fX ); Arguments.PushNumber ( vecCursorPosition.fY ); m_pSourcePlayer->CallEvent ( "onPlayerClick", Arguments ); // TODO: iterate server-side element managers for the click events, eg: colshapes } } }