From b64e9fb7f52e4a2b75b49413fdc2194132885370 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 9 Mar 2014 00:17:23 +0000 Subject: Beds now work properly fixes #707 Also fixes FS392 Conflicts: src/Blocks/WorldInterface.h src/ClientHandle.cpp --- src/Blocks/BlockBed.cpp | 73 +++++++++++++++++++++++++++++++++++++---- src/Blocks/BroadcastInterface.h | 5 +-- src/Blocks/WorldInterface.h | 8 ++++- src/Entities/Player.h | 17 ++++++++-- src/World.h | 8 ++--- 5 files changed, 94 insertions(+), 17 deletions(-) diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index 3dad4feba..ca3927827 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -51,6 +51,49 @@ void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInt +class cTimeFastForwardTester : + public cPlayerListCallback +{ + virtual bool Item(cPlayer * a_Player) override + { + if (!a_Player->IsInBed()) + { + return true; + } + + return false; + } +}; + + + + + +class cPlayerBedStateUnsetter : + public cPlayerListCallback +{ +public: + cPlayerBedStateUnsetter(Vector3i a_Position, cWorldInterface & a_WorldInterface) : + m_Position(a_Position), m_WorldInterface(a_WorldInterface) + { + } + + virtual bool Item(cPlayer * a_Player) override + { + a_Player->SetIsInBed(false); + m_WorldInterface.GetBroadcastManager().BroadcastEntityAnimation(*a_Player, 2); + return false; + } + +private: + Vector3i m_Position; + cWorldInterface & m_WorldInterface; +}; + + + + + void cBlockBedHandler::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) { if (a_WorldInterface.GetDimension() != dimOverworld) @@ -69,6 +112,8 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface } else { + Vector3i PillowDirection(0, 0, 0); + if (Meta & 0x8) { // Is pillow @@ -77,16 +122,30 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface else { // Is foot end - Vector3i Direction = MetaDataToDirection( Meta & 0x7 ); - if (a_ChunkInterface.GetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z) == E_BLOCK_BED) // Must always use pillow location for sleeping + VERIFY((Meta & 0x4) != 1); // Occupied flag should never be set, else our compilator (intended) is broken + + PillowDirection = MetaDataToDirection(Meta & 0x7); + if (a_ChunkInterface.GetBlock(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z) == E_BLOCK_BED) // Must always use pillow location for sleeping { - a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z); + a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z); } } - a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, (Meta | (1 << 2))); - } - - } else { + + a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x4); // Where 0x4 = occupied bit + a_Player->SetIsInBed(true); + + 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 & 0xB); // Where 0xB = 1011, and zero is to make sure 'occupied' bit is always unset + } + } + } + else + { a_Player->SendMessageFailure("You can only sleep at night"); } } diff --git a/src/Blocks/BroadcastInterface.h b/src/Blocks/BroadcastInterface.h index f6ccd580b..01966ffbd 100644 --- a/src/Blocks/BroadcastInterface.h +++ b/src/Blocks/BroadcastInterface.h @@ -5,6 +5,7 @@ class cBroadcastInterface { public: - virtual void BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0; - virtual 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) = 0; + virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ) = 0; + virtual 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) = 0; + virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL) = 0; }; diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h index e59b00eff..580339d32 100644 --- a/src/Blocks/WorldInterface.h +++ b/src/Blocks/WorldInterface.h @@ -27,7 +27,13 @@ public: /** Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise */ virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) = 0; - + /** Sends the block on those coords to the player */ virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer * a_Player) = 0; + + /** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */ + virtual bool ForEachPlayer(cItemCallback & a_Callback) = 0; + + virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0; + }; diff --git a/src/Entities/Player.h b/src/Entities/Player.h index a795bb9eb..83a553821 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -275,6 +275,9 @@ public: /// Returns true if the player is currently flying. bool IsFlying(void) const { return m_IsFlying; } + /** Returns if a player is sleeping in a bed */ + bool IsInBed(void) const { return m_bIsInBed; } + /// returns true if the player has thrown out a floater. bool IsFishing(void) const { return m_IsFishing; } @@ -283,6 +286,9 @@ public: int GetFloaterID(void) const { return m_FloaterID; } // 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; } /// Starts eating the currently equipped item. Resets the eating timer and sends the proper animation packet void StartEating(void); @@ -376,8 +382,8 @@ protected: GroupList m_ResolvedGroups; GroupList m_Groups; - std::string m_PlayerName; - std::string m_LoadedWorldName; + AString m_PlayerName; + AString m_LoadedWorldName; /// Xp Level stuff enum @@ -465,7 +471,7 @@ protected: int m_FloaterID; - cTeam* m_Team; + cTeam * m_Team; @@ -488,6 +494,11 @@ protected: /// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) void ApplyFoodExhaustionFromMovement(); + + /** Flag representing whether the player is currently in a bed + Set by a right click on unoccupied bed, unset by a time fast forward or teleport */ + bool m_bIsInBed; + } ; // tolua_export diff --git a/src/World.h b/src/World.h index 0a0939dd1..738697c94 100644 --- a/src/World.h +++ b/src/World.h @@ -134,7 +134,7 @@ public: m_WeatherInterval = a_WeatherInterval; } - void SetTimeOfDay(Int64 a_TimeOfDay) + virtual void SetTimeOfDay(Int64 a_TimeOfDay) { m_TimeOfDay = a_TimeOfDay; m_TimeOfDaySecs = (double)a_TimeOfDay / 20.0; @@ -204,7 +204,7 @@ public: void BroadcastEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL); void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = NULL); void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); - void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL); + virtual void BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = NULL); void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount, cClientHandle * a_Exclude = NULL); // tolua_export void BroadcastPlayerListItem (const cPlayer & a_Player, bool a_IsOnline, const cClientHandle * a_Exclude = NULL); void BroadcastRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID, const cClientHandle * a_Exclude = NULL); @@ -217,7 +217,7 @@ public: void BroadcastTeleportEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL); void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL); void BroadcastTimeUpdate (const cClientHandle * a_Exclude = NULL); - virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ); + virtual void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ ); void BroadcastWeather (eWeather a_Weather, const cClientHandle * a_Exclude = NULL); virtual cBroadcastInterface & GetBroadcastManager() @@ -274,7 +274,7 @@ public: void RemovePlayer( cPlayer* a_Player ); /** Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true */ - bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << + virtual bool ForEachPlayer(cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << /** Calls the callback for the player of the given name; returns true if the player was found and the callback called, false if player not found. Callback return ignored */ bool DoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS << -- cgit v1.2.3 From 888c3f1af7b817ab770703ce0638e0eef07d2d31 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Sun, 9 Mar 2014 15:53:03 +0000 Subject: Fixed VERIFY --- src/Blocks/BlockBed.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index ca3927827..6a3c6a55b 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -122,7 +122,7 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface else { // Is foot end - VERIFY((Meta & 0x4) != 1); // Occupied flag should never be set, else our compilator (intended) is broken + VERIFY((Meta & 0x4) != 0x4); // Occupied flag should never be set, else our compilator (intended) is broken PillowDirection = MetaDataToDirection(Meta & 0x7); if (a_ChunkInterface.GetBlock(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z) == E_BLOCK_BED) // Must always use pillow location for sleeping -- cgit v1.2.3