From fb9a00a64ed69d22a1c181bb0b3af99f8686c4dd Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Tue, 25 Sep 2012 09:54:36 +0000 Subject: Added the block dig animation packet (patch contributed by l0udPL) git-svn-id: http://mc-server.googlecode.com/svn/trunk@892 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Chunk.cpp | 16 ++++++++++++ source/Chunk.h | 1 + source/ChunkMap.cpp | 19 ++++++++++++++ source/ChunkMap.h | 2 ++ source/ClientHandle.cpp | 47 ++++++++++++++++++++++++++++++++-- source/ClientHandle.h | 8 ++++++ source/Protocol/Protocol.h | 1 + source/Protocol/Protocol125.cpp | 12 +++++++-- source/Protocol/Protocol125.h | 1 + source/Protocol/Protocol132.cpp | 19 +++++++++++++- source/Protocol/Protocol132.h | 1 + source/Protocol/ProtocolRecognizer.cpp | 10 ++++++++ source/Protocol/ProtocolRecognizer.h | 1 + source/World.cpp | 9 +++++++ source/World.h | 3 ++- 15 files changed, 144 insertions(+), 6 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 7cd3b961f..cb4e5511f 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -1771,6 +1771,22 @@ void cChunk::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a +void cChunk::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude) +{ + for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr ) + { + if (*itr == a_Exclude) + { + continue; + } + (*itr)->SendBlockBreakAnim(a_entityID, a_blockX, a_blockY, a_blockZ, a_stage); + } // for itr - LoadedByClient[] +} + + + + + void cChunk::BroadcastChunkData(cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude) { for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr ) diff --git a/source/Chunk.h b/source/Chunk.h index c9d1e0899..ac34640f8 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -188,6 +188,7 @@ public: void BroadcastCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL); void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // a_Src coords are Block * 8 + void BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude = NULL); void BroadcastChunkData (cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL); void SendBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client); diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index 508d5ae11..ee69e6cc0 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -465,6 +465,25 @@ void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, in +void cChunkMap::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude) +{ + cCSLock Lock(m_CSLayers); + int ChunkX, ChunkZ; + + cChunkDef::BlockToChunk(a_blockX, a_blockY, a_blockZ, ChunkX, ChunkZ); + cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ); + if (Chunk == NULL) + { + return; + } + // It's perfectly legal to broadcast packets even to invalid chunks! + Chunk->BroadcastBlockBreakAnimation(a_entityID, a_blockX, a_blockY, a_blockZ, a_stage, a_Exclude); +} + + + + + void cChunkMap::BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude) { cCSLock Lock(m_CSLayers); diff --git a/source/ChunkMap.h b/source/ChunkMap.h index 4165be089..8ddd9d6c7 100644 --- a/source/ChunkMap.h +++ b/source/ChunkMap.h @@ -76,6 +76,8 @@ public: void BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); void BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // a_Src coords are Block * 8 + + void BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude = NULL); void BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL); diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 2296ae23e..e32e03f16 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -91,6 +91,7 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance) , m_LastStreamedChunkZ(0x7fffffff) , m_ShouldCheckDownloaded(false) , m_UniqueID(0) + , m_BlockDigAnim(-1) { m_Protocol = new cProtocolRecognizer(this); @@ -534,9 +535,28 @@ void cClientHandle::HandleBlockDig(int a_BlockX, int a_BlockY, int a_BlockZ, cha ((a_Status == DIG_STATUS_STARTED) && (m_Player->GetGameMode() == 1)) ); + if ((a_Status == DIG_STATUS_STARTED) && (m_Player->GetGameMode() != eGameMode_Creative)) + { + // Start dig animation + // TODO: calculate real animation speed + m_BlockDigAnimSpeed = 10; + m_BlockDigX = a_BlockX; + m_BlockDigY = a_BlockY; + m_BlockDigZ = a_BlockZ; + m_BlockDigAnim = 0; + m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigX, m_BlockDigY, m_BlockDigZ, 0, this); + } + else if (m_BlockDigAnim != -1) + { + // End dig animation + m_BlockDigAnim = -1; + // It seems that 10 ends block animation + m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigX, m_BlockDigY, m_BlockDigZ, 10, this); + } + cItem & Equipped = m_Player->GetInventory().GetEquippedItem(); cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemID); - + if (bBroken) { ItemHandler->OnBlockDestroyed(World, m_Player, &Equipped, a_BlockX, a_BlockY, a_BlockZ); @@ -550,7 +570,6 @@ void cClientHandle::HandleBlockDig(int a_BlockX, int a_BlockY, int a_BlockZ, cha Handler->OnDigging(World, m_Player, a_BlockX, a_BlockY, a_BlockZ); ItemHandler->OnDiggingBlock(World, m_Player, &Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - // Check for clickthrough-blocks: int pX = a_BlockX; @@ -1049,6 +1068,21 @@ void cClientHandle::Tick(float a_Dt) m_Protocol->SendKeepAlive(m_PingID); m_LastPingTime = m_PingStartTime; } + + // Handle block break animation: + if ((m_Player != NULL) && (m_BlockDigAnim > -1)) + { + int lastAnimVal = m_BlockDigAnim; + m_BlockDigAnim += (int)(m_BlockDigAnimSpeed * a_Dt); + if (m_BlockDigAnim > 9000) + { + m_BlockDigAnim = 9000; + } + if (m_BlockDigAnim / 1000 != lastAnimVal / 1000) + { + m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigX, m_BlockDigY, m_BlockDigZ, (char)(m_BlockDigAnim / 1000), this); + } + } } @@ -1418,6 +1452,15 @@ void cClientHandle::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int +void cClientHandle::SendBlockBreakAnim(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage) +{ + m_Protocol->SendBlockBreakAnim(a_entityID, a_blockX, a_blockY, a_blockZ, a_stage); +} + + + + + void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) { // Check chunks being sent, erase them from m_ChunksToSend: diff --git a/source/ClientHandle.h b/source/ClientHandle.h index 8beecd7e4..1e627a017 100644 --- a/source/ClientHandle.h +++ b/source/ClientHandle.h @@ -101,6 +101,7 @@ public: void SendPlayerSpawn (const cPlayer & a_Player); void SendRespawn (void); void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch); // a_Src coords are Block * 8 + void SendBlockBreakAnim (int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage); void SendSpawnMob (const cMonster & a_Mob); void SendTeleportEntity (const cEntity & a_Entity); void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ); @@ -204,6 +205,13 @@ private: long long m_PingStartTime; long long m_LastPingTime; static const unsigned short PING_TIME_MS = 1000; //minecraft sends 1 per 20 ticks (1 second or every 1000 ms) + + // Values required for block dig animation + int m_BlockDigAnim; // Current stage of the animation; -1 if not digging + int m_BlockDigAnimSpeed; // Current speed of the animation (units ???) + int m_BlockDigX; + int m_BlockDigY; + int m_BlockDigZ; enum eState { diff --git a/source/Protocol/Protocol.h b/source/Protocol/Protocol.h index e871e958a..ada63af6b 100644 --- a/source/Protocol/Protocol.h +++ b/source/Protocol/Protocol.h @@ -72,6 +72,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0; virtual void SendRespawn (void) = 0; virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) = 0; // a_Src coords are Block * 8 + virtual void SendBlockBreakAnim (int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) = 0; virtual void SendSpawnMob (const cMonster & a_Mob) = 0; virtual void SendTeleportEntity (const cEntity & a_Entity) = 0; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 2ae82fb43..1f2edad63 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -585,8 +585,16 @@ void cProtocol125::SendRespawn(void) void cProtocol125::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) { - cCSLock Lock(m_CSPacket); - //TODO: Not needed in this protocol? + // Not needed in this protocol version +} + + + + + +void cProtocol125::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) +{ + // Not supported in this protocol version } diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h index 62c91c2e1..19a080506 100644 --- a/source/Protocol/Protocol125.h +++ b/source/Protocol/Protocol125.h @@ -56,6 +56,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendRespawn (void) override; virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 + virtual void SendBlockBreakAnim (int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) override; virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendTeleportEntity (const cEntity & a_Entity) override; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; diff --git a/source/Protocol/Protocol132.cpp b/source/Protocol/Protocol132.cpp index a39697526..d8c9f1f27 100644 --- a/source/Protocol/Protocol132.cpp +++ b/source/Protocol/Protocol132.cpp @@ -61,7 +61,8 @@ enum PACKET_CHUNK_DATA = 0x33, PACKET_BLOCK_CHANGE = 0x35, PACKET_BLOCK_ACTION = 0x36, - PACKET_SOUND_EFFECT = 0x3e + PACKET_BLOCK_BREAK_ANIM = 0x37, + PACKET_SOUND_EFFECT = 0x3e } ; @@ -349,6 +350,22 @@ void cProtocol132::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int +void cProtocol132::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) +{ + cCSLock Lock(m_CSPacket); + WriteByte (PACKET_BLOCK_BREAK_ANIM); + WriteInt (a_entityID); + WriteInt (a_BlockX); + WriteInt (a_BlockY); + WriteInt (a_BlockZ); + WriteByte (stage); + Flush(); +} + + + + + void cProtocol132::SendSpawnMob(const cMonster & a_Mob) { cCSLock Lock(m_CSPacket); diff --git a/source/Protocol/Protocol132.h b/source/Protocol/Protocol132.h index 5fb82148d..977ddca92 100644 --- a/source/Protocol/Protocol132.h +++ b/source/Protocol/Protocol132.h @@ -38,6 +38,7 @@ public: virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override; virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8 + virtual void SendBlockBreakAnim (int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) override; virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendUnloadChunk (int a_ChunkX, int a_ChunkZ) override; virtual void SendWholeInventory (const cWindow & a_Window) override; diff --git a/source/Protocol/ProtocolRecognizer.cpp b/source/Protocol/ProtocolRecognizer.cpp index 96a831063..aadd20de0 100644 --- a/source/Protocol/ProtocolRecognizer.cpp +++ b/source/Protocol/ProtocolRecognizer.cpp @@ -364,6 +364,16 @@ void cProtocolRecognizer::SendSoundEffect(const AString & a_SoundName, int a_Src +void cProtocolRecognizer::SendBlockBreakAnim(int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendBlockBreakAnim(a_entityID, a_BlockX, a_BlockY, a_BlockZ, stage); +} + + + + + void cProtocolRecognizer::SendSpawnMob(const cMonster & a_Mob) { ASSERT(m_Protocol != NULL); diff --git a/source/Protocol/ProtocolRecognizer.h b/source/Protocol/ProtocolRecognizer.h index 0a42c279f..e870eca29 100644 --- a/source/Protocol/ProtocolRecognizer.h +++ b/source/Protocol/ProtocolRecognizer.h @@ -67,6 +67,7 @@ public: virtual void SendPlayerSpawn (const cPlayer & a_Player) override; virtual void SendRespawn (void) override; virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; + virtual void SendBlockBreakAnim (int a_entityID, int a_BlockX, int a_BlockY, int a_BlockZ, char stage) override; virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendTeleportEntity (const cEntity & a_Entity) override; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; diff --git a/source/World.cpp b/source/World.cpp index 9b241c8ee..184cff869 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -1431,6 +1431,15 @@ void cWorld::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a +void cWorld::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude ) +{ + m_ChunkMap->BroadcastBlockBreakAnimation(a_entityID, a_blockX, a_blockY, a_blockZ, a_stage, a_Exclude); +} + + + + + void cWorld::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude) { m_ChunkMap->BroadcastBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Exclude); diff --git a/source/World.h b/source/World.h index 1cbd6a2fb..f688efebf 100644 --- a/source/World.h +++ b/source/World.h @@ -93,7 +93,8 @@ public: void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL); void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL); void BroadcastSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude = NULL); // a_Src coords are Block * 8 - + void BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude = NULL); + /// If there is a block entity at the specified coods, sends it to all clients except a_Exclude void BroadcastBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); -- cgit v1.2.3