diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index e5897bccd..cb3ebf8f4 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1690,6 +1690,10 @@ + + diff --git a/source/Blocks/BlockBed.h b/source/Blocks/BlockBed.h index cbef5bb4d..b7b055aa8 100644 --- a/source/Blocks/BlockBed.h +++ b/source/Blocks/BlockBed.h @@ -10,64 +10,18 @@ public: cBlockBedHandler(BLOCKTYPE a_BlockID) : cBlockHandler(a_BlockID) { - } + virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override; + virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override; + virtual void OnUse(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z) override; - - - virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override + virtual bool IsUseable() override { - if( a_Dir != 1 ) // Can only be placed on the floor - return; - - NIBBLETYPE Meta = RotationToMetaData( a_Player->GetRotation() ); - Vector3i Direction = MetaDataToDirection( Meta ); - - if (a_World->GetBlock(a_X+Direction.x, a_Y, a_Z+Direction.z) != E_BLOCK_AIR) - { - return; - } - - a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_BED, Meta); - a_World->SetBlock(a_X + Direction.x, a_Y, a_Z + Direction.z, E_BLOCK_BED, Meta | 0x8); - - OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir); + return true; } - - - - - - virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override - { - char OldMeta = a_World->GetBlockMeta(a_X, a_Y, a_Z); - - Vector3i ThisPos( a_X, a_Y, a_Z ); - Vector3i Direction = MetaDataToDirection( OldMeta & 0x7 ); - if (OldMeta & 0x8) - { - // Was pillow - if (a_World->GetBlock(ThisPos - Direction) == E_BLOCK_BED) - { - a_World->FastSetBlock(ThisPos - Direction, E_BLOCK_AIR, 0); - } - } - else - { - // Was foot end - if (a_World->GetBlock(ThisPos + Direction) == E_BLOCK_BED) - { - a_World->FastSetBlock(ThisPos + Direction, E_BLOCK_AIR, 0); - } - } - } - - - - - + virtual int GetDropID() override { return E_ITEM_BED; @@ -78,10 +32,6 @@ public: return 0; } - - - - virtual bool AllowBlockOnTop() override { return false; @@ -90,7 +40,7 @@ public: - + // Bed specific helper functions static NIBBLETYPE RotationToMetaData( float a_Rotation ) { a_Rotation += 180 + (180/4); // So its not aligned with axis @@ -101,10 +51,6 @@ public: return ((char)a_Rotation+2) % 4; } - - - - static Vector3i MetaDataToDirection( NIBBLETYPE a_MetaData ) { switch( a_MetaData ) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index e7a828c66..606134f38 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -1787,6 +1787,18 @@ void cChunk::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_bl +void cChunk::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) +{ + for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr ) + { + (*itr)->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); + } // 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 ac34640f8..a76ec4e58 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -189,6 +189,7 @@ 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 BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ); 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 ee69e6cc0..af8f09820 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -484,6 +484,25 @@ void cChunkMap::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a +void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) +{ + 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->BroadcastUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); +} + + + + + 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 8ddd9d6c7..87873cac2 100644 --- a/source/ChunkMap.h +++ b/source/ChunkMap.h @@ -79,6 +79,8 @@ public: void BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude = NULL); + void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ); + void BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL); /// Broadcasts the block entity, if it is at the coords specified, to all clients except a_Exclude diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 1585a08b0..af0f686d1 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -962,6 +962,24 @@ bool cClientHandle::HandleHandshake(const AString & a_Username) +void cClientHandle::HandleEntityAction(int a_EntityID, char a_ActionID) +{ + if( a_EntityID != m_Player->GetUniqueID() ) + { + // We should only receive entity actions from the entity that is performing the action + return; + } + + if( a_ActionID == 3 ) // Leave bed + { + m_Player->GetWorld()->BroadcastPlayerAnimation( *m_Player, 3 ); + } +} + + + + + void cClientHandle::SendData(const char * a_Data, int a_Size) { { @@ -1461,6 +1479,15 @@ void cClientHandle::SendBlockBreakAnim(int a_entityID, int a_blockX, int a_block +void cClientHandle::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) +{ + m_Protocol->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); +} + + + + + 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 e5625eb20..94f132ea0 100644 --- a/source/ClientHandle.h +++ b/source/ClientHandle.h @@ -117,6 +117,7 @@ public: void SendWholeInventory (const cWindow & a_Window); void SendWindowClose (char a_WindowID); void SendWindowOpen (char a_WindowID, char a_WindowType, const AString & a_WindowTitle, char a_NumSlots); + void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ); const AString & GetUsername(void) const; //tolua_export @@ -161,6 +162,7 @@ public: void HandleDisconnect (const AString & a_Reason); void HandleKeepAlive (int a_KeepAliveID); bool HandleHandshake (const AString & a_Username); + void HandleEntityAction (int a_EntityID, char a_ActionID); /** Called when the protocol has finished logging the user in. Return true to allow the user in; false to kick them. diff --git a/source/Protocol/Protocol.h b/source/Protocol/Protocol.h index ada63af6b..c187387c1 100644 --- a/source/Protocol/Protocol.h +++ b/source/Protocol/Protocol.h @@ -84,6 +84,7 @@ public: virtual void SendWholeInventory (const cWindow & a_Window) = 0; virtual void SendWindowClose (char a_WindowID) = 0; virtual void SendWindowOpen (char a_WindowID, char a_WindowType, const AString & a_WindowTitle, char a_NumSlots) = 0; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0; /// Returns the ServerID used for authentication through session.minecraft.net virtual AString GetAuthServerID(void) = 0; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index 1f2edad63..bec6a19b6 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -46,7 +46,7 @@ enum PACKET_BLOCK_DIG = 0x0e, PACKET_BLOCK_PLACE = 0x0f, PACKET_SLOT_SELECTED = 0x10, - PACKET_ADD_TO_INV = 0x11, // TODO: Sure this is not Use Bed?? + PACKET_USE_BED = 0x11, // TODO: Sure this is not Use Bed?? PACKET_ANIMATION = 0x12, PACKET_PACKET_ENTITY_ACTION = 0x13, PACKET_PLAYER_SPAWN = 0x14, @@ -778,6 +778,22 @@ void cProtocol125::SendWindowOpen(char a_WindowID, char a_WindowType, const AStr +void cProtocol125::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) +{ + cCSLock Lock(m_CSPacket); + WriteByte(PACKET_USE_BED); + WriteInt (a_Entity.GetUniqueID()); + WriteByte(0); // Unknown byte only 0 has been observed + WriteInt (a_BlockX); + WriteByte(a_BlockY); + WriteInt (a_BlockZ); + Flush(); +} + + + + + AString cProtocol125::GetAuthServerID(void) { // http://wiki.vg/wiki/index.php?title=Session&oldid=2262 @@ -985,7 +1001,7 @@ int cProtocol125::ParseEntityAction(void) { HANDLE_PACKET_READ(ReadBEInt, int, EntityID); HANDLE_PACKET_READ(ReadChar, char, ActionID); - // TODO: m_Client->HandleEntityAction(...); + m_Client->HandleEntityAction(EntityID, ActionID); return PARSE_OK; } diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h index 19a080506..84dfa7a72 100644 --- a/source/Protocol/Protocol125.h +++ b/source/Protocol/Protocol125.h @@ -68,6 +68,7 @@ public: virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWindowClose (char a_WindowID) override; virtual void SendWindowOpen (char a_WindowID, char a_WindowType, const AString & a_WindowTitle, char a_NumSlots) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; virtual AString GetAuthServerID(void) override; diff --git a/source/Protocol/ProtocolRecognizer.cpp b/source/Protocol/ProtocolRecognizer.cpp index ac231bc51..edd34b7dc 100644 --- a/source/Protocol/ProtocolRecognizer.cpp +++ b/source/Protocol/ProtocolRecognizer.cpp @@ -485,6 +485,16 @@ void cProtocolRecognizer::SendWindowOpen(char a_WindowID, char a_WindowType, con +void cProtocolRecognizer::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); +} + + + + + AString cProtocolRecognizer::GetAuthServerID(void) { ASSERT(m_Protocol != NULL); diff --git a/source/Protocol/ProtocolRecognizer.h b/source/Protocol/ProtocolRecognizer.h index e870eca29..2e2f5a9e9 100644 --- a/source/Protocol/ProtocolRecognizer.h +++ b/source/Protocol/ProtocolRecognizer.h @@ -79,6 +79,7 @@ public: virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWindowClose (char a_WindowID) override; virtual void SendWindowOpen (char a_WindowID, char a_WindowType, const AString & a_WindowTitle, char a_NumSlots) override; + virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) override; virtual AString GetAuthServerID(void) override; diff --git a/source/World.cpp b/source/World.cpp index 03438b227..8bb14eb53 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -1440,6 +1440,15 @@ void cWorld::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_bl +void cWorld::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) +{ + m_ChunkMap->BroadcastUseBed(a_Entity, a_BlockX, a_BlockY, a_BlockZ); +} + + + + + 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 08ccc4226..302461495 100644 --- a/source/World.h +++ b/source/World.h @@ -94,6 +94,7 @@ public: 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); + void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ); /// 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);