1
0
Fork 0

Handle client 'leave bed' request

* Fixes #1728
This commit is contained in:
Tiger Wang 2015-02-08 21:21:48 +00:00
parent 1ce9164694
commit 3869f76cc2
9 changed files with 92 additions and 61 deletions

View File

@ -5,7 +5,6 @@
#include "BroadcastInterface.h"
#include "ChunkInterface.h"
#include "Entities/../World.h"
#include "Entities/Player.h"
#include "WorldInterface.h"
@ -64,21 +63,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 +97,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 +105,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,19 +122,12 @@ 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);
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
}
a_WorldInterface.ScheduleTask(20, cWorld::cTaskTryAwakeSleepingPlayers(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_ChunkInterface));
}
}
else

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

@ -11,6 +11,7 @@ typedef cItemCallback<cBlockEntity> cBlockEntityCallback;
class cMonster;
class cPlayer;
class cTask;
class cWorldInterface
@ -59,4 +60,8 @@ public:
/** Wakes up the simulators for the specified block */
virtual void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
/** Queues a task onto the tick thread, with the specified delay.
The task object will be deleted once the task is finished */
virtual void ScheduleTask(int a_DelayTicks, cTask * a_Task) = 0;
};

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

@ -18,6 +18,7 @@
#include "Items/ItemHandler.h"
#include "Blocks/BlockHandler.h"
#include "Blocks/BlockSlab.h"
#include "Blocks/BlockBed.h"
#include "Blocks/ChunkInterface.h"
#include "Root.h"
@ -1498,30 +1499,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);
}
@ -1763,7 +1740,8 @@ void cClientHandle::HandleEntityLeaveBed(int a_EntityID)
return;
}
m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, 2);
cBlockBedHandler::SetBedOccupationState(cChunkInterface(GetPlayer()->GetWorld()->GetChunkMap()), 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

@ -2101,9 +2101,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

@ -47,6 +47,7 @@
#include "Generating/Trees.h"
#include "Bindings/PluginManager.h"
#include "Blocks/BlockHandler.h"
#include "Blocks/BlockBed.cpp"
#include "Tracer.h"
@ -3578,7 +3579,7 @@ void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World)
////////////////////////////////////////////////////////////////////////////////
// cWorld::cTaskSendBlockTo
// cWorld::cTaskSendBlockToAllPlayers
cWorld::cTaskSendBlockToAllPlayers::cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue) :
m_SendQueue(a_SendQueue)
@ -3620,6 +3621,30 @@ void cWorld::cTaskSendBlockToAllPlayers::Run(cWorld & a_World)
////////////////////////////////////////////////////////////////////////////////
// cWorld::cTaskSendBlockToAllPlayers
cWorld::cTaskTryAwakeSleepingPlayers::cTaskTryAwakeSleepingPlayers(const Vector3i & a_Position, cChunkInterface & a_ChunkInterface) :
m_Position(a_Position),
m_ChunkInterface(a_ChunkInterface)
{
}
void cWorld::cTaskTryAwakeSleepingPlayers::Run(cWorld & a_World)
{
cTimeFastForwardTester Tester;
if (a_World.ForEachPlayer(Tester))
{
cPlayerBedStateUnsetter Unsetter(m_Position, m_ChunkInterface);
a_World.ForEachPlayer(Unsetter);
a_World.SetTimeOfDay(0);
}
}
////////////////////////////////////////////////////////////////////////////////
// cWorld::cChunkGeneratorCallbacks:

View File

@ -45,6 +45,7 @@ class cEntity;
class cBlockEntity;
class cWorldGenerator; // The generator that actually generates the chunks for a single world
class cChunkGenerator; // The thread responsible for generating chunks
class cChunkInterface;
class cBeaconEntity;
class cChestEntity;
class cDispenserEntity;
@ -140,6 +141,21 @@ public:
std::vector<Vector3i> m_SendQueue;
};
class cTaskTryAwakeSleepingPlayers :
public cTask
{
public:
cTaskTryAwakeSleepingPlayers(const Vector3i & a_Position, cChunkInterface & a_ChunkInterface);
protected:
// cTask overrides:
virtual void Run(cWorld & a_World) override;
private:
Vector3i m_Position;
cChunkInterface & m_ChunkInterface;
};
static const char * GetClassStatic(void) // Needed for ManualBindings's ForEach templates
{
@ -695,7 +711,7 @@ public:
/** Queues a task onto the tick thread, with the specified delay.
The task object will be deleted once the task is finished */
void ScheduleTask(int a_DelayTicks, cTask * a_Task);
virtual void ScheduleTask(int a_DelayTicks, cTask * a_Task) override;
/** Returns the number of chunks loaded */
int GetNumChunks() const; // tolua_export