diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 4c0cefc3e..18ba84d88 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -471,6 +471,14 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) break; case E_BLOCK_DIG: { + LOG("TimeP: %f", m_Player->GetLastBlockActionTime() ); + LOG("TimeN: %f", cRoot::Get()->GetWorld()->GetTime() ); + if ( cRoot::Get()->GetWorld()->GetTime() - m_Player->GetLastBlockActionTime() < 0.1 ) { //only allow block interactions every 0.1 seconds + LOGWARN("Player %s tried to interact with a block too quickly! (could indicate bot)", GetUsername() ); + m_Player->SetLastBlockActionTime(); //Player tried to interact with a block. Reset last block interation time. + break; + } + m_Player->SetLastBlockActionTime(); //Player tried to interact with a block. Reset last block interation time. cPacket_BlockDig* PacketData = reinterpret_cast(a_Packet); LOG("OnBlockDig: %i %i %i Dir: %i Stat: %i", PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ, PacketData->m_Direction, PacketData->m_Status ); if( PacketData->m_Status == 0x04 ) // Drop block @@ -482,10 +490,10 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) cWorld* World = m_Player->GetWorld(); char OldBlock = World->GetBlock(PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ); char MetaData = World->GetBlockMeta(PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ); - bool bBroken = (PacketData->m_Status == 0x02) || g_BlockOneHitDig[(int)OldBlock] || ( (PacketData->m_Status == 0x00) && (World->GetGameMode() == 1) ); //need to change to check for client's gamemode. + bool bBroken = (PacketData->m_Status == 0x02) || g_BlockOneHitDig[(int)OldBlock] || ( (PacketData->m_Status == 0x00) && (m_Player->GetGameMode() == 1) ); cItem PickupItem; - if( bBroken && !(World->GetGameMode() == 1) ) // broken + if( bBroken && !(m_Player->GetGameMode() == 1) ) // broken { ENUM_ITEM_ID PickupID = cBlockToPickup::ToPickup( (ENUM_BLOCK_ID)OldBlock, m_Player->GetInventory().GetEquippedItem().m_ItemID ); PickupItem.m_ItemID = PickupID; @@ -579,10 +587,18 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) break; case E_BLOCK_PLACE: { + LOG("TimeP: %f", m_Player->GetLastBlockActionTime() ); + LOG("TimeN: %f", cRoot::Get()->GetWorld()->GetTime() ); + if ( cRoot::Get()->GetWorld()->GetTime() - m_Player->GetLastBlockActionTime() < 0.1 ) { //only allow block interactions every 0.1 seconds + LOGWARN("Player %s tried to interact with a block too quickly! (could indicate bot)", GetUsername() ); + m_Player->SetLastBlockActionTime(); //Player tried to interact with a block. Reset last block interation time. + break; + } + m_Player->SetLastBlockActionTime(); //Player tried to interact with a block. Reset last block interation time. cPacket_BlockPlace* PacketData = reinterpret_cast(a_Packet); cItem & Equipped = m_Player->GetInventory().GetEquippedItem(); //if( (Equipped.m_ItemID != PacketData->m_ItemType) ) // Not valid - if( (Equipped.m_ItemID != PacketData->m_ItemType) && (cRoot::Get()->GetWorld()->GetGameMode() != 1) ) // Not valid + if( (Equipped.m_ItemID != PacketData->m_ItemType) && (m_Player->GetGameMode() != 1) ) // Not valid { LOGWARN("Player %s tried to place a block that was not selected! (could indicate bot)", GetUsername() ); break; @@ -721,7 +737,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) if( IsValidBlock( PacketData->m_ItemType) ) { - if( (m_Player->GetInventory().RemoveItem( Item )) || (cRoot::Get()->GetWorld()->GetGameMode() == 1) ) + if( (m_Player->GetInventory().RemoveItem( Item )) || (m_Player->GetGameMode() == 1) ) { int X = PacketData->m_PosX; char Y = PacketData->m_PosY; @@ -914,7 +930,9 @@ void cClientHandle::SendLoginResponse() cPacket_Login LoginResponse; LoginResponse.m_ProtocolVersion = m_Player->GetUniqueID(); //LoginResponse.m_Username = ""; - LoginResponse.m_ServerMode = cRoot::Get()->GetWorld()->GetGameMode(); //set gamemode from world. + //m_Player->SetGameMode ( 0 ); + m_Player->SetGameMode ( cRoot::Get()->GetWorld()->GetGameMode() ); //set player's gamemode to server's gamemode at login. + LoginResponse.m_ServerMode = m_Player->GetGameMode(); //set gamemode from player. LoginResponse.m_MapSeed = 0; LoginResponse.m_Dimension = 0; Send( LoginResponse ); diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp index fee8df966..da589a70f 100644 --- a/source/cPlayer.cpp +++ b/source/cPlayer.cpp @@ -58,6 +58,8 @@ struct cPlayer::sPlayerState cPlayer::cPlayer(cClientHandle* a_Client, const char* a_PlayerName) : m_bBurnable(true) + , m_GameMode( 0 ) + , m_LastBlockActionTime( 0 ) , e_EPMetaState(NORMAL) , m_bVisible( true ) , m_LastGroundHeight( 0 ) @@ -107,6 +109,8 @@ cPlayer::~cPlayer(void) cRoot::Get()->GetWorld()->RemovePlayer( this ); // TODO - Remove from correct world? Or get rid of this? } + + void cPlayer::SpawnOn( cClientHandle* a_Target ) { if( a_Target == m_ClientHandle || !m_bVisible ) return; @@ -223,7 +227,7 @@ void cPlayer::InStateBurning(float a_Dt) { char block = GetWorld()->GetBlock( (int)m_Pos->x, (int)m_Pos->y, (int)m_Pos->z ); char bblock = GetWorld()->GetBlock( (int)m_Pos->x, (int)m_Pos->y -1, (int)m_Pos->z ); if(m_FireDamageInterval > 1000) { - + m_FireDamageInterval = 0; int rem = rand()%3 + 1; //Burn most of the time if(rem >= 2) { @@ -234,20 +238,20 @@ void cPlayer::InStateBurning(float a_Dt) { if(block == E_BLOCK_LAVA || block == E_BLOCK_STATIONARY_LAVA || block == E_BLOCK_FIRE || bblock == E_BLOCK_LAVA || bblock == E_BLOCK_STATIONARY_LAVA || bblock == E_BLOCK_FIRE) m_BurnPeriod = 0; - + if(m_BurnPeriod > 5) { - + cChunk* InChunk = GetWorld()->GetChunkUnreliable( m_ChunkX, m_ChunkY, m_ChunkZ ); e_EPMetaState = NORMAL; cPacket_Metadata md(NORMAL, GetUniqueID()); //md.m_UniqueID = GetUniqueID(); InChunk->Broadcast(md); m_BurnPeriod = 0; - - } + + } } - + } //----Change Entity MetaData @@ -359,7 +363,8 @@ void cPlayer::Respawn() // Create Respawn player packet cPacket_Respawn Packet; //Set Gamemode for packet by looking at world's gamemode (Need to check players gamemode.) - Packet.m_CreativeMode = (char)GetWorld()->GetGameMode(); + //Packet.m_CreativeMode = (char)GetWorld()->GetGameMode(); + Packet.m_CreativeMode = (char)m_GameMode; //Set GameMode packet based on Player's GameMode; //Send Packet m_ClientHandle->Send( Packet ); TeleportTo( GetWorld()->GetSpawnX(), GetWorld()->GetSpawnY(), GetWorld()->GetSpawnZ() ); @@ -389,6 +394,17 @@ void cPlayer::CloseWindow() m_CurrentWindow = 0; } +void cPlayer::SetLastBlockActionTime() +{ + m_LastBlockActionTime = cRoot::Get()->GetWorld()->GetTime(); +} + +void cPlayer::SetGameMode( int a_GameMode ) +{ + m_GameMode = a_GameMode; +} + + #ifdef SendMessage // Cause stupid windows.h defines SendMessage as SendMessageA #undef SendMessage #endif diff --git a/source/cPlayer.h b/source/cPlayer.h index d5ad6abac..1bb349a40 100644 --- a/source/cPlayer.h +++ b/source/cPlayer.h @@ -29,6 +29,11 @@ public: virtual void TeleportTo( cEntity* a_Entity ); //tolua_export virtual void TeleportTo( const double & a_PosX, const double & a_PosY, const double & a_PosZ ); //tolua_export + int GetGameMode() { return m_GameMode; } //return GameMode for player. + float GetLastBlockActionTime() { return m_LastBlockActionTime; } //return LastBlockActionTime for player. + void SetLastBlockActionTime(); + void SetGameMode( int a_GameMode ); + // Tries to move to a new position, with collision checks and stuff virtual void MoveTo( const Vector3d & a_NewPos ); //tolua_export @@ -65,13 +70,13 @@ public: bool SaveToDisk(); bool LoadFromDisk(); - + //Burning logic bool m_bBurnable; enum PMetaState{NORMAL,BURNING,CROUCHED,RIDING} e_EPMetaState; virtual void CheckMetaDataBurn(); virtual void InStateBurning(float a_Dt); - + protected: struct sPlayerState; sPlayerState* m_pState; @@ -93,5 +98,8 @@ protected: float m_FireDamageInterval; float m_BurnPeriod; + float m_LastBlockActionTime; + int m_GameMode; + cClientHandle* m_ClientHandle; }; //tolua_export