void NetworkManagerClient::SendInputPacket() { //only send if there's any input to sent! const MoveList& moveList = InputManager::sInstance->GetMoveList(); if( moveList.HasMoves() ) { OutputMemoryBitStream inputPacket; inputPacket.Write( kInputCC ); mDeliveryNotificationManager.WriteState( inputPacket ); //eventually write the 3 latest moves so they have three chances to get through... int moveCount = moveList.GetMoveCount(); int firstMoveIndex = moveCount - 3; if( firstMoveIndex < 3 ) { firstMoveIndex = 0; } auto move = moveList.begin() + firstMoveIndex; //only need two bits to write the move count, because it's 0, 1, 2 or 3 inputPacket.Write( moveCount - firstMoveIndex, 2 ); for( ; firstMoveIndex < moveCount; ++firstMoveIndex, ++move ) { ///would be nice to optimize the time stamp... move->Write( inputPacket ); } SendPacket( inputPacket, mServerAddress ); } }
// Testing TEST( OutputMemoryBitStream, GetBitLength ) { OutputMemoryBitStream x = OutputMemoryBitStream(); x.Write( 12 ); x.Write( 2 ); x.Write( -2 ); x.Write( 0 ); uint32_t streamSize = x.GetBitLength(); // 4 entries * bytesInInt * 8 bits uint32_t numOfBitsWritten = 4 * sizeof( uint32_t ) * 8; EXPECT_EQ( streamSize, numOfBitsWritten ); x.Write( 0 ); // Write 32 more bits streamSize = x.GetBitLength(); EXPECT_EQ( streamSize, numOfBitsWritten + sizeof( uint32_t ) * 8 ); x.Write( true ); // 2 more bits x.Write( true ); streamSize = x.GetBitLength(); EXPECT_EQ( streamSize, numOfBitsWritten + sizeof( uint32_t ) * 8 + 2 ); }
void TurnData::Write( OutputMemoryBitStream& inOutputStream ) { inOutputStream.Write( mPlayerId ); inOutputStream.Write( mRandomValue ); inOutputStream.Write( mCRC ); mCommandList.Write( inOutputStream ); }
void NetworkManager::UpdateDelay() { //first process incoming packets, in case that removes us from delay NetworkManager::sInstance->ProcessIncomingPackets(); if( mState == NMS_Delay ) { mDelayHeartbeat -= Timing::sInstance.GetDeltaTime(); if( mDelayHeartbeat <= 0.0f ) { mDelayHeartbeat = kTimeBetweenDelayHeartbeat; } //find out who's missing and send them a heartbeat unordered_set< uint64_t > playerSet; for( auto& iter : mPlayerNameMap ) { playerSet.emplace( iter.first ); } Int64ToTurnDataMap& turnData = mTurnData[ mTurnNumber + 1 ]; for( auto& iter : turnData ) { playerSet.erase( iter.first ); } OutputMemoryBitStream packet; packet.Write( kDelayCC ); //whoever's left is who's missing for( auto& iter : playerSet ) { SendPacket( packet, iter ); } } }
void NetworkManager::TryStartGame() { if ( mState == NMS_Ready && IsMasterPeer() && mPlayerCount == mReadyCount ) { LOG( "Starting!" ); //let everyone know OutputMemoryBitStream outPacket; outPacket.Write( kStartCC ); //select a seed value uint32_t seed = RandGen::sInstance->GetRandomUInt32( 0, UINT32_MAX ); RandGen::sInstance->Seed( seed ); outPacket.Write( seed ); for ( auto &iter : mPlayerNameMap ) { if( iter.first != mPlayerId ) { SendPacket( outPacket, iter.first ); } } mTimeToStart = kStartDelay; mState = NMS_Starting; } }
void NetworkManagerClient::SendHelloPacket() { OutputMemoryBitStream helloPacket; helloPacket.Write( kHelloCC ); helloPacket.Write( mName ); SendPacket( helloPacket, mServerAddress ); }
void ReplicationManagerServer::Write( OutputMemoryBitStream& inOutputStream ) { //run through each replication command and do something... for( auto& pair: mNetworkIdToReplicationCommand ) { ReplicationCommand& replicationCommand = pair.second; if( replicationCommand.HasDirtyState() ) { int networkId = pair.first; //well, first write the network id... inOutputStream.Write( networkId ); //only need 2 bits for action... ReplicationAction action = replicationCommand.GetAction(); inOutputStream.Write( action, 2 ); uint32_t writtenState = 0; uint32_t dirtyState = replicationCommand.GetDirtyState(); //now do what? switch( action ) { case RA_Create: writtenState = WriteCreateAction( inOutputStream, networkId, dirtyState ); //once the create action is transmitted, future replication //of this object should be updates instead of creates replicationCommand.SetAction( RA_Update ); break; case RA_Update: writtenState = WriteUpdateAction( inOutputStream, networkId, dirtyState ); break; case RA_Destroy: //don't need anything other than state! writtenState = WriteDestroyAction( inOutputStream, networkId, dirtyState ); //add this to the list of replication commands to remove mNetworkIdsToRemove.emplace_back( networkId ); break; } //let's pretend everything was written- don't make this too hard replicationCommand.ClearDirtyState( writtenState ); } } //remove replication commands for destroyed objects if( !mNetworkIdsToRemove.empty() ) { for( auto id : mNetworkIdsToRemove ) { RemoveFromReplication( id ); } mNetworkIdsToRemove.clear(); } }
void NetworkManagerServer::SendWelcomePacket( ClientProxyPtr inClientProxy ) { OutputMemoryBitStream welcomePacket; welcomePacket.Write( kWelcomeCC ); welcomePacket.Write( inClientProxy->GetPlayerId() ); LOG( "Server Welcoming, new client '%s' as player %d", inClientProxy->GetName().c_str(), inClientProxy->GetPlayerId() ); SendPacket( welcomePacket, inClientProxy->GetSocketAddress() ); }
TEST( OutputMemoryBitStream, TestScratch ) { OutputMemoryBitStream x = OutputMemoryBitStream(); x.Write( 12 ); x.Write( std::string( "s" ) ); std::string b = "blahblahb"; x.Write( b ); x.PrintByteArray(); }
void NetworkManagerServer::WriteLastMoveTimestampIfDirty( OutputMemoryBitStream& inOutputStream, ClientProxyPtr inClientProxy ) { //first, dirty? bool isTimestampDirty = inClientProxy->IsLastMoveTimestampDirty(); inOutputStream.Write( isTimestampDirty ); if( isTimestampDirty ) { inOutputStream.Write( inClientProxy->GetUnprocessedMoveList().GetLastMoveTimestamp() ); inClientProxy->SetIsLastMoveTimestampDirty( false ); } }
bool ScoreBoardManager::Entry::Write( OutputMemoryBitStream& inOutputStream ) const { bool didSucceed = true; inOutputStream.Write( mColor ); inOutputStream.Write( mPlayerId ); inOutputStream.Write( mPlayerName ); inOutputStream.Write( mScore ); return didSucceed; }
void NetworkManager::SendReadyPacketsToPeers() { OutputMemoryBitStream outPacket; outPacket.Write( kReadyCC ); for( auto& iter : mPlayerNameMap ) { if( iter.first != mPlayerId ) { SendPacket( outPacket, iter.first ); } } }
void AckRange::Write( OutputMemoryBitStream& inOutputStream ) const { inOutputStream.Write( mStart ); bool hasCount = mCount > 1; inOutputStream.Write( hasCount ); if( hasCount ) { //most you can ack is 255... uint32_t countMinusOne = mCount - 1; uint8_t countToAck = countMinusOne > 255 ? 255 : static_cast< uint8_t >( countMinusOne ); inOutputStream.Write( countToAck ); } }
void NetworkServer::Finish(int player) { OutputMemoryBitStream ombs; ombs.Write(PacketType::PT_FINISH, 3); //Escribimos en nuestro OMBS las posiciones absolutas de los jugadores. ombs.Write(player, 2); sendToAllChar(ombs.GetBufferPtr()); for (int i = 0; i < 4; i++) { playerList[i].position = 0; } }
//should we ask the server for this? or run through the world ourselves? void NetworkManagerServer::AddWorldStateToPacket( OutputMemoryBitStream& inOutputStream ) { const auto& gameObjects = World::sInstance->GetGameObjects(); //now start writing objects- do we need to remember how many there are? we can check first... inOutputStream.Write( gameObjects.size() ); for( GameObjectPtr gameObject : gameObjects ) { inOutputStream.Write( gameObject->GetNetworkId() ); inOutputStream.Write( gameObject->GetClassId() ); gameObject->Write( inOutputStream, 0xffffffff ); } }
uint32_t NetworkManager::ComputeGlobalCRC() { //save into bit stream to reduce CRC calls OutputMemoryBitStream crcStream; uint32_t crc = static_cast<uint32_t>( crc32( 0, Z_NULL, 0 ) ); for ( auto& iter : mNetworkIdToGameObjectMap ) { iter.second->WriteForCRC( crcStream ); } crc = static_cast<uint32_t>( crc32( crc, reinterpret_cast<const Bytef*>(crcStream.GetBufferPtr()), crcStream.GetByteLength() ) ); return crc; }
void NetworkManagerServer::SendStatePacketToClient( ClientProxyPtr inClientProxy ) { //build state packet OutputMemoryBitStream statePacket; //it's state! statePacket.Write( kStateCC ); WriteLastMoveTimestampIfDirty( statePacket, inClientProxy ); AddScoreBoardStateToPacket( statePacket ); inClientProxy->GetReplicationManagerServer().Write( statePacket ); SendPacket( statePacket, inClientProxy->GetSocketAddress() ); }
uint32_t ReplicationManagerServer::WriteCreateAction( OutputMemoryBitStream& inOutputStream, int inNetworkId, uint32_t inDirtyState ) { //need object GameObjectPtr gameObject = NetworkManagerServer::sInstance->GetGameObject( inNetworkId ); //need 4 cc inOutputStream.Write( gameObject->GetClassId() ); return gameObject->Write( inOutputStream, inDirtyState ); }
void CommandList::Write(OutputMemoryBitStream& inOutputStream) { inOutputStream.Write(GetCount()); for (CommandPtr p : mCommands) { p->Write(inOutputStream); } }
bool InputState::Write( OutputMemoryBitStream& inOutputStream ) const { WriteSignedBinaryValue( inOutputStream, GetDesiredHorizontalDelta() ); WriteSignedBinaryValue( inOutputStream, GetDesiredVerticalDelta() ); inOutputStream.Write( mIsShooting ); return false; }
void ReplicationManagerServer::Write( OutputMemoryBitStream& inOutputStream, ReplicationManagerTransmissionData* ioTransmissinData ) { //run through each replication command and do something... for( auto& pair: mNetworkIdToReplicationCommand ) { ReplicationCommand& replicationCommand = pair.second; if( replicationCommand.HasDirtyState() ) { int networkId = pair.first; //well, first write the network id... inOutputStream.Write( networkId ); //only need 2 bits for action... ReplicationAction action = replicationCommand.GetAction(); inOutputStream.Write( action, 2 ); uint32_t writtenState = 0; uint32_t dirtyState = replicationCommand.GetDirtyState(); //now do what? switch( action ) { case RA_Create: writtenState = WriteCreateAction( inOutputStream, networkId, dirtyState ); break; case RA_Update: writtenState = WriteUpdateAction( inOutputStream, networkId, dirtyState ); break; case RA_Destroy: //don't need anything other than state! writtenState = WriteDestroyAction( inOutputStream, networkId, dirtyState ); break; } ioTransmissinData->AddTransmission( networkId, action, writtenState ); //let's pretend everything was written- don't make this too hard replicationCommand.ClearDirtyState( writtenState ); } } }
void NetworkManager::UpdateSendTurnPacket() { mSubTurnNumber++; if ( mSubTurnNumber == kSubTurnsPerTurn ) { //create our turn data TurnData data(mPlayerId, RandGen::sInstance->GetRandomUInt32(0, UINT32_MAX), ComputeGlobalCRC(), InputManager::sInstance->GetCommandList()); //we need to send a turn packet to all of our peers OutputMemoryBitStream packet; packet.Write( kTurnCC ); //we're sending data for 2 turns from now packet.Write( mTurnNumber + 2 ); packet.Write( mPlayerId ); data.Write( packet ); for ( auto &iter : mPlayerNameMap ) { if( iter.first != mPlayerId ) { SendPacket( packet, iter.first ); } } //save our turn data for turn + 2 mTurnData[ mTurnNumber + 2 ].emplace( mPlayerId, data ); InputManager::sInstance->ClearCommandList(); if ( mTurnNumber >= 0 ) { TryAdvanceTurn(); } else { //a negative turn means there's no possible commands yet mTurnNumber++; mSubTurnNumber = 0; } } }
void ChickenClassComponent::writeNetAbility(uint64_t PID, float posX, float posY, bool direction, int team) { OutputMemoryBitStream *outData = new OutputMemoryBitStream(); outData->Write(NetworkManager::sInstance->kPosCC); outData->Write(gameObjectRef->ID); outData->Write((int)3); // have to include the enum here outData->Write(PID); outData->Write(posX); outData->Write(posY); outData->Write(direction); outData->Write(team); dynamic_cast<PlayerNetworkComponent*>(gameObjectRef->GetComponent(COMPONENT_NETWORK))->outgoingPackets.push(outData); //if (!netComp) //netComp = dynamic_cast<PlayerNetworkComponent*>(gameObjectRef->GetComponent(COMPONENT_NETWORK)); //netComp->outgoingPackets.push(outData); }
void NetworkServer::Dispatch(){ clock_t time = clock(); if (time > dispatchTime + 125) { OutputMemoryBitStream ombs; ombs.Write(PacketType::PT_AUTHOR, 3); for (size_t i = 0; i < 4; i++) { //Escribimos en nuestro OMBS las posiciones absolutas de los jugadores. ombs.Write(playerList[i].position, 10); } ombs.Write(cheaterAlarm, 1); sendToAllChar(ombs.GetBufferPtr()); cheaterAlarm = 0; dispatchTime = time; } }
void NetworkManagerClient::SendInputPacket() { //only send if there's any input to send! MoveList& moveList = InputManager::sInstance->GetMoveList(); if( moveList.HasMoves() ) { OutputMemoryBitStream inputPacket; inputPacket.Write( kInputCC ); //we only want to send the last three moves int moveCount = moveList.GetMoveCount(); int startIndex = moveCount > 3 ? moveCount - 3 - 1 : 0; inputPacket.Write( moveCount - startIndex, 2 ); for( int i = startIndex; i < moveCount; ++i ) { moveList[i].Write( inputPacket ); } SendPacket( inputPacket, mServerAddress ); moveList.Clear(); } }
bool ScoreBoardManager::Write( OutputMemoryBitStream& inOutputStream ) const { int entryCount = static_cast<int>( mEntries.size() ); //we don't know our player names, so it's hard to check for remaining space in the packet... //not really a concern now though inOutputStream.Write( entryCount ); for( const Entry& entry: mEntries ) { entry.Write( inOutputStream ); } return true; }
void RoboCat::WriteForCRC( OutputMemoryBitStream& inStream ) { inStream.Write( mPlayerId ); inStream.Write( mNetworkId ); inStream.Write( mLocation ); inStream.Write( mHealth ); inStream.Write( mState ); inStream.Write( mTargetNetId ); }
void DeliveryNotificationManager::WriteAckData( OutputMemoryBitStream& inOutputStream ) { // What do we need to tell them we have recieved? bool hasAcks = ( mPendingAcks.size() > 0 ); inOutputStream.Write( hasAcks ); // Don't write anything else if ( !hasAcks ) { return; } // Write out one ack range at a time should be fine... mPendingAcks.front().Write( inOutputStream ); mPendingAcks.pop_front(); }
TEST( OutputMemoryBitStream, GetByteLength ) { OutputMemoryBitStream x = OutputMemoryBitStream(); x.Write( 12 ); x.Write( 2 ); x.Write( true ); uint32_t streamSize = x.GetByteLength(); uint32_t numOfBytesWritten = 9; EXPECT_EQ( streamSize, numOfBytesWritten ); x.Write( true ); // Writing one a bool won't add another bit EXPECT_EQ( streamSize, numOfBytesWritten ); x.Write( 8 ); // Write 32 more bits streamSize = x.GetByteLength(); EXPECT_NE( streamSize, numOfBytesWritten ); }
// Test if you can write to the buffer stream TEST( OutputMemoryBitStream, WritePrimatives ) { OutputMemoryBitStream x = OutputMemoryBitStream(); x.Write( 12 ); // write 4 bytes equal to 12 x.Write( 2 ); // write 4 bytes equal to 2 x.Write( -2 ); // write 4 bytes equal to -2 x.Write( 0 ); // write 4 bytes equal to 0 const char* buffer = x.GetBufferPtr(); // Check if each value was written to the stream EXPECT_EQ( int( *buffer ), 12 ); buffer = buffer + 4; EXPECT_EQ( int( *buffer ), 2 ); buffer = buffer + 4; EXPECT_EQ( int( *buffer ), -2 ); buffer = buffer + 4; EXPECT_EQ( int( *buffer ), 0 ); }