1
0

Merge pull request #1734 from mc-server/pistons

Handle client 'leave bed' request
This commit is contained in:
Mattes D 2015-03-14 22:44:04 +01:00
commit 65d2ef32e9
7 changed files with 46 additions and 57 deletions

View File

@ -1,14 +1,9 @@
#include "Globals.h"
#include "BlockBed.h"
#include "BroadcastInterface.h"
#include "ChunkInterface.h"
#include "Entities/../World.h"
#include "Entities/Player.h"
#include "WorldInterface.h"
@ -64,21 +59,22 @@ class cPlayerBedStateUnsetter :
public cPlayerListCallback
{
public:
cPlayerBedStateUnsetter(Vector3i a_Position, cWorldInterface & a_WorldInterface) :
m_Position(a_Position), m_WorldInterface(a_WorldInterface)
cPlayerBedStateUnsetter(Vector3i a_Position, cChunkInterface & a_ChunkInterface) :
m_Position(a_Position),
m_ChunkInterface(a_ChunkInterface)
{
}
virtual bool Item(cPlayer * a_Player) override
{
cBlockBedHandler::SetBedOccupationState(m_ChunkInterface, a_Player->GetLastBedPos(), false);
a_Player->SetIsInBed(false);
m_WorldInterface.GetBroadcastManager().BroadcastEntityAnimation(*a_Player, 2);
return false;
}
private:
Vector3i m_Position;
cWorldInterface & m_WorldInterface;
cChunkInterface & m_ChunkInterface;
};
@ -97,7 +93,7 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
if (a_WorldInterface.GetTimeOfDay() > 13000)
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (Meta & 0x4)
if ((Meta & 0x4) == 0x4)
{
a_Player->SendMessageFailure("This bed is occupied");
}
@ -105,7 +101,7 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
{
Vector3i PillowDirection(0, 0, 0);
if (Meta & 0x8)
if ((Meta & 0x8) == 0x8)
{
// Is pillow
a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX, a_BlockY, a_BlockZ);
@ -122,15 +118,15 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
}
}
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x4); // Where 0x4 = occupied bit
a_Player->SetIsInBed(true);
a_Player->SetBedPos(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
SetBedOccupationState(a_ChunkInterface, a_Player->GetLastBedPos(), true);
a_Player->SetIsInBed(true);
a_Player->SendMessageSuccess("Home position set successfully");
cTimeFastForwardTester Tester;
if (a_WorldInterface.ForEachPlayer(Tester))
{
cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_WorldInterface);
cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_ChunkInterface);
a_WorldInterface.ForEachPlayer(Unsetter);
a_WorldInterface.SetTimeOfDay(0);
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x0b); // Clear the "occupied" bit of the bed's block

View File

@ -4,9 +4,9 @@
#include "BlockHandler.h"
#include "MetaRotator.h"
#include "Item.h"
#include "ChunkInterface.h"
class cChunkInterface;
class cPlayer;
class cWorldInterface;
@ -21,17 +21,14 @@ public:
: cMetaRotator<cBlockHandler, 0x3, 0x02, 0x03, 0x00, 0x01, true>(a_BlockType)
{
}
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool IsUseable(void) override
{
return true;
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
@ -39,14 +36,12 @@ public:
a_Pickups.push_back(cItem(E_ITEM_BED, 1, 0));
}
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
{
return true;
}
// Bed specific helper functions
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
@ -61,7 +56,6 @@ public:
return ((char)a_Rotation + 2) % 4;
}
static Vector3i MetaDataToDirection(NIBBLETYPE a_MetaData)
{
switch (a_MetaData)
@ -73,6 +67,21 @@ public:
}
return Vector3i();
}
static void SetBedOccupationState(cChunkInterface & a_ChunkInterface, const Vector3i & a_BedPosition, bool a_IsOccupied)
{
auto Meta = a_ChunkInterface.GetBlockMeta(a_BedPosition.x, a_BedPosition.y, a_BedPosition.z);
if (a_IsOccupied)
{
Meta |= 0x04; // Where 0x4 = occupied bit
}
else
{
Meta &= 0x0b; // Clear the "occupied" bit of the bed's block
}
a_ChunkInterface.SetBlockMeta(a_BedPosition.x, a_BedPosition.y, a_BedPosition.z, Meta);
}
} ;

View File

@ -1322,10 +1322,7 @@ void cChunkMap::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYP
void cChunkMap::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients)
{
cChunkInterface ChunkInterface(this);
if (a_BlockType == E_BLOCK_AIR)
{
BlockHandler(GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnDestroyed(ChunkInterface, *m_World, a_BlockX, a_BlockY, a_BlockZ);
}
BlockHandler(GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnDestroyed(ChunkInterface, *m_World, a_BlockX, a_BlockY, a_BlockZ);
int ChunkX, ChunkZ, X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
cChunkDef::AbsoluteToRelative( X, Y, Z, ChunkX, ChunkZ);

View File

@ -21,6 +21,7 @@
#include "Items/ItemHandler.h"
#include "Blocks/BlockHandler.h"
#include "Blocks/BlockSlab.h"
#include "Blocks/BlockBed.h"
#include "Blocks/ChunkInterface.h"
#include "Root.h"
@ -1501,30 +1502,6 @@ void cClientHandle::HandleAnimation(int a_Animation)
return;
}
// Because the animation ID sent to servers by clients are different to those sent back, we need this
switch (a_Animation)
{
case 0: // No animation - wiki.vg doesn't say that client has something specific for it, so I suppose it will just become -1
case 1:
case 2:
case 3:
{
a_Animation--; // Offset by -1
break;
}
case 5:
case 6:
case 7:
{
a_Animation -= 2; // Offset by -2
break;
}
default: // Anything else is the same
{
break;
}
}
m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, a_Animation, this);
}
@ -1766,7 +1743,9 @@ void cClientHandle::HandleEntityLeaveBed(int a_EntityID)
return;
}
m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, 2);
cChunkInterface Interface(GetPlayer()->GetWorld()->GetChunkMap());
cBlockBedHandler::SetBedOccupationState(Interface, GetPlayer()->GetLastBedPos(), false);
GetPlayer()->SetIsInBed(false);
}

View File

@ -314,8 +314,18 @@ public:
// tolua_end
/** Sets a player's in-bed state; we can't be sure plugins will keep this value updated, so no exporting */
void SetIsInBed(bool a_Flag) { m_bIsInBed = a_Flag; }
/** Sets a player's in-bed state
We can't be sure plugins will keep this value updated, so no exporting
If value is false (not in bed), will update players of the fact that they have been ejected from the bed
*/
void SetIsInBed(bool a_Flag)
{
m_bIsInBed = a_Flag;
if (!a_Flag)
{
GetWorld()->BroadcastEntityAnimation(*this, 2);
}
}
/** Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet */
void StartEating(void);

View File

@ -2105,9 +2105,7 @@ void cProtocol180::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer)
void cProtocol180::HandlePacketAnimation(cByteBuffer & a_ByteBuffer)
{
HANDLE_READ(a_ByteBuffer, ReadBEInt, int, EntityID);
HANDLE_READ(a_ByteBuffer, ReadByte, Byte, Animation);
m_Client->HandleAnimation(Animation);
m_Client->HandleAnimation(1); // Packet exists solely for arm-swing notification
}

View File

@ -3638,7 +3638,7 @@ void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World)
////////////////////////////////////////////////////////////////////////////////
// cWorld::cTaskSendBlockTo
// cWorld::cTaskSendBlockToAllPlayers
cWorld::cTaskSendBlockToAllPlayers::cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue) :
m_SendQueue(a_SendQueue)