From 9f7db50de0537ae9e918ab3a9cf49e01eda93cf1 Mon Sep 17 00:00:00 2001 From: James Ravenscroft Date: Thu, 8 Aug 2013 16:32:14 +0100 Subject: [PATCH 1/5] Fixed food handler for mushroom soup - proper food level and saturation are applied and the player receives a wooden bowl back after nomming --- source/Items/ItemFood.h | 1 + source/Items/ItemHandler.cpp | 1 + source/Player.cpp | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/source/Items/ItemFood.h b/source/Items/ItemFood.h index 6434f3dc7..2ae572331 100644 --- a/source/Items/ItemFood.h +++ b/source/Items/ItemFood.h @@ -50,6 +50,7 @@ public: case E_ITEM_ROTTEN_FLESH: return FoodInfo(4, 0.8, 80); case E_ITEM_SPIDER_EYE: return FoodInfo(2, 3.2, 100); case E_ITEM_STEAK: return FoodInfo(8, 12.8); + case E_ITEM_MUSHROOM_SOUP: return FoodInfo(6, 7.2); } LOGWARNING("%s: Unknown food item (%d), returning zero nutrition", __FUNCTION__, m_ItemType); return FoodInfo(0, 0.f); diff --git a/source/Items/ItemHandler.cpp b/source/Items/ItemHandler.cpp index c81916f5f..f3f4ac6e7 100644 --- a/source/Items/ItemHandler.cpp +++ b/source/Items/ItemHandler.cpp @@ -181,6 +181,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType) case E_ITEM_RED_APPLE: case E_ITEM_GOLDEN_APPLE: case E_ITEM_ROTTEN_FLESH: + case E_ITEM_MUSHROOM_SOUP: case E_ITEM_SPIDER_EYE: { return new cItemFoodHandler(a_ItemType); diff --git a/source/Player.cpp b/source/Player.cpp index fb752ed87..6219523cf 100644 --- a/source/Player.cpp +++ b/source/Player.cpp @@ -400,7 +400,14 @@ void cPlayer::FinishEating(void) return; } ItemHandler->OnFoodEaten(m_World, this, &Item); + GetInventory().RemoveOneEquippedItem(); + + //if the food is mushroom soup, return a bowl to the inventory + if( Item.m_ItemType == E_ITEM_MUSHROOM_SOUP ) { + cItem emptyBowl(E_ITEM_BOWL, 1, 0, ""); + GetInventory().AddItem(emptyBowl, true, true); + } } From 2b9fdc3e36d45c9db9ccf0b2a5f3b24f2ab2e038 Mon Sep 17 00:00:00 2001 From: James Ravenscroft Date: Thu, 8 Aug 2013 16:57:34 +0100 Subject: [PATCH 2/5] Fixed the jump food exhaustion being added when player is swimming --- source/ClientHandle.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 52c4b3061..328e7de70 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -32,8 +32,7 @@ #include "Protocol/ProtocolRecognizer.h" - - +#define float2int(x) ((x)<0 ? ((int)(x))-1 : (int)(x)) #define AddPistonDir(x, y, z, dir, amount) switch (dir) { case 0: (y)-=(amount); break; case 1: (y)+=(amount); break;\ @@ -505,7 +504,13 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, // If a jump just started, process food exhaustion: if ((a_PosY > m_Player->GetPosY()) && !a_IsOnGround && m_Player->IsOnGround()) { - m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2); + // we only add this exhaustion if the player is not swimming - otherwise we end up with both jump + swim exhaustion + cWorld * World = m_Player->GetWorld(); + BLOCKTYPE BlockType = World->GetBlock( float2int(m_Player->GetPosX()), float2int(m_Player->GetPosY()), float2int(m_Player->GetPosZ()) ); + if(! IsBlockWater(BlockType) ) + { + m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2); + } } m_Player->MoveTo(Pos); From dace1f7bd2e661b4c771322162e9e1b52551dd56 Mon Sep 17 00:00:00 2001 From: James Ravenscroft Date: Fri, 9 Aug 2013 08:37:39 +0100 Subject: [PATCH 3/5] Added IsSwimming and IsSubmerged flags and access methods --- source/ClientHandle.cpp | 6 ++---- source/Player.cpp | 39 +++++++++++++++++++++++++++++---------- source/Player.h | 14 +++++++++++++- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 328e7de70..6df0cfa48 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -32,7 +32,6 @@ #include "Protocol/ProtocolRecognizer.h" -#define float2int(x) ((x)<0 ? ((int)(x))-1 : (int)(x)) #define AddPistonDir(x, y, z, dir, amount) switch (dir) { case 0: (y)-=(amount); break; case 1: (y)+=(amount); break;\ @@ -505,9 +504,8 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ, if ((a_PosY > m_Player->GetPosY()) && !a_IsOnGround && m_Player->IsOnGround()) { // we only add this exhaustion if the player is not swimming - otherwise we end up with both jump + swim exhaustion - cWorld * World = m_Player->GetWorld(); - BLOCKTYPE BlockType = World->GetBlock( float2int(m_Player->GetPosX()), float2int(m_Player->GetPosY()), float2int(m_Player->GetPosZ()) ); - if(! IsBlockWater(BlockType) ) + + if(! m_Player->IsSwimming() ) { m_Player->AddFoodExhaustion(m_Player->IsSprinting() ? 0.8 : 0.2); } diff --git a/source/Player.cpp b/source/Player.cpp index 6219523cf..eab6e08e5 100644 --- a/source/Player.cpp +++ b/source/Player.cpp @@ -61,6 +61,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) , m_SprintingMaxSpeed(0.13) , m_IsCrouched(false) , m_IsSprinting(false) + , m_IsSwimming(false) + , m_IsSubmerged(false) , m_EatingFinishTick(-1) { LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d", @@ -181,8 +183,11 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) super::Tick(a_Dt, a_Chunk); - //handle air drowning stuff - HandleAir(a_Chunk); + // set player swimming state + SetSwimState( a_Chunk); + + // handle air drowning stuff + HandleAir(); if (m_bDirtyPosition) { @@ -1326,20 +1331,34 @@ void cPlayer::UseEquippedItem() GetInventory().DamageEquippedItem(); } +void cPlayer::SetSwimState(cChunk & a_Chunk) +{ -void cPlayer::HandleAir(cChunk & a_Chunk) + BLOCKTYPE BlockIn; + int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelY = (int)floor(m_LastPosY + 0.1); + int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; + // first we check if the player is swimming + + // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk + VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn)); + + m_IsSwimming = IsBlockWater(BlockIn); + + // now we check if the player is submerged + + VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY+1, RelZ, BlockIn)); + + m_IsSubmerged = IsBlockWater(BlockIn); +} + +void cPlayer::HandleAir() { // Ref.: http://www.minecraftwiki.net/wiki/Chunk_format // see if the player is /submerged/ water (block above is water) // Get the type of block the player's standing in: - BLOCKTYPE BlockIn; - int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; - int RelY = (int)floor(m_LastPosY + 1.1); - int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; - // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk - VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn)); - if (IsBlockWater(BlockIn)) + if (IsSubmerged()) { // either reduce air level or damage player if(m_AirLevel < 1) diff --git a/source/Player.h b/source/Player.h index 542656b5a..ab9a17cf2 100644 --- a/source/Player.h +++ b/source/Player.h @@ -260,6 +260,12 @@ public: virtual bool IsSprinting(void) const { return m_IsSprinting; } virtual bool IsRclking (void) const { return IsEating(); } + /// Returns whether the player is swimming or not + virtual bool IsSwimming(void) const{ return m_IsSwimming; } + + /// Return whether the player is under water or not + virtual bool IsSubmerged(void) const{ return m_IsSubmerged; } + protected: typedef std::map< std::string, bool > PermissionMap; PermissionMap m_ResolvedPermissions; @@ -335,6 +341,9 @@ protected: bool m_IsCrouched; bool m_IsSprinting; + bool m_IsSwimming; + bool m_IsSubmerged; + /// The world tick in which eating will be finished. -1 if not eating Int64 m_EatingFinishTick; @@ -347,7 +356,10 @@ protected: void HandleFood(void); /// Called in each tick to handle air-related processing i.e. drowning - void HandleAir(cChunk & a_Chunk); + void HandleAir(); + + /// Called once per tick to set IsSwimming and IsSubmerged + void SetSwimState(cChunk & a_Chunk); /// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) void ApplyFoodExhaustionFromMovement(cChunk & a_Chunk); From ffce5d143fe2b6224ee7ff29e40c9a73af0463e4 Mon Sep 17 00:00:00 2001 From: James Ravenscroft Date: Fri, 9 Aug 2013 08:50:33 +0100 Subject: [PATCH 4/5] Removed the need to recalculate whether player is under water in ApplyFoodExhaustion --- source/Player.cpp | 14 +++----------- source/Player.h | 12 +++++++----- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/source/Player.cpp b/source/Player.cpp index eab6e08e5..ba165989a 100644 --- a/source/Player.cpp +++ b/source/Player.cpp @@ -192,7 +192,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) if (m_bDirtyPosition) { // Apply food exhaustion from movement: - ApplyFoodExhaustionFromMovement(a_Chunk); + ApplyFoodExhaustionFromMovement(); cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this); BroadcastMovementUpdate(m_ClientHandle); @@ -1445,7 +1445,7 @@ void cPlayer::HandleFood(void) -void cPlayer::ApplyFoodExhaustionFromMovement(cChunk & a_Chunk) +void cPlayer::ApplyFoodExhaustionFromMovement() { if (IsGameModeCreative()) { @@ -1463,14 +1463,6 @@ void cPlayer::ApplyFoodExhaustionFromMovement(cChunk & a_Chunk) return; } - // Get the type of block the player's standing in: - BLOCKTYPE BlockIn; - int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; - int RelY = (int)floor(m_LastPosY + 0.1); - int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; - // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk - VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn)); - // Apply the exhaustion based on distance travelled: double BaseExhaustion = Movement.Length(); if (IsSprinting()) @@ -1478,7 +1470,7 @@ void cPlayer::ApplyFoodExhaustionFromMovement(cChunk & a_Chunk) // 0.1 pt per meter sprinted BaseExhaustion = BaseExhaustion * 0.1; } - else if (IsBlockWater(BlockIn)) + else if (IsSwimming()) { // 0.015 pt per meter swum BaseExhaustion = BaseExhaustion * 0.015; diff --git a/source/Player.h b/source/Player.h index ab9a17cf2..105e7d0a1 100644 --- a/source/Player.h +++ b/source/Player.h @@ -253,6 +253,12 @@ public: /// Starts or stops sprinting, sends the max speed update to the client, if needed void SetSprint(bool a_IsSprinting); + /// Returns whether the player is swimming or not + virtual bool IsSwimming(void) const{ return m_IsSwimming; } + + /// Return whether the player is under water or not + virtual bool IsSubmerged(void) const{ return m_IsSubmerged; } + // tolua_end // cEntity overrides: @@ -260,11 +266,7 @@ public: virtual bool IsSprinting(void) const { return m_IsSprinting; } virtual bool IsRclking (void) const { return IsEating(); } - /// Returns whether the player is swimming or not - virtual bool IsSwimming(void) const{ return m_IsSwimming; } - /// Return whether the player is under water or not - virtual bool IsSubmerged(void) const{ return m_IsSubmerged; } protected: typedef std::map< std::string, bool > PermissionMap; @@ -362,7 +364,7 @@ protected: void SetSwimState(cChunk & a_Chunk); /// Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) - void ApplyFoodExhaustionFromMovement(cChunk & a_Chunk); + void ApplyFoodExhaustionFromMovement(); } ; // tolua_export From 6963e8119ce879843f4bac9042a0d8c8e588c524 Mon Sep 17 00:00:00 2001 From: James Ravenscroft Date: Fri, 9 Aug 2013 08:57:24 +0100 Subject: [PATCH 5/5] Fixed some formatting issues I accidentally introduced --- source/ClientHandle.cpp | 2 ++ source/Player.cpp | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 6df0cfa48..85500a2e4 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -34,6 +34,8 @@ + + #define AddPistonDir(x, y, z, dir, amount) switch (dir) { case 0: (y)-=(amount); break; case 1: (y)+=(amount); break;\ case 2: (z)-=(amount); break; case 3: (z)+=(amount); break;\ case 4: (x)-=(amount); break; case 5: (x)+=(amount); break; } diff --git a/source/Player.cpp b/source/Player.cpp index ba165989a..808976a6c 100644 --- a/source/Player.cpp +++ b/source/Player.cpp @@ -61,8 +61,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) , m_SprintingMaxSpeed(0.13) , m_IsCrouched(false) , m_IsSprinting(false) - , m_IsSwimming(false) - , m_IsSubmerged(false) + , m_IsSwimming(false) + , m_IsSubmerged(false) , m_EatingFinishTick(-1) { LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d", @@ -182,9 +182,9 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) } super::Tick(a_Dt, a_Chunk); - - // set player swimming state - SetSwimState( a_Chunk); + + // set player swimming state + SetSwimState( a_Chunk); // handle air drowning stuff HandleAir(); @@ -1338,18 +1338,19 @@ void cPlayer::SetSwimState(cChunk & a_Chunk) int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; int RelY = (int)floor(m_LastPosY + 0.1); int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; - // first we check if the player is swimming + + // first we check if the player is swimming // Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn)); - m_IsSwimming = IsBlockWater(BlockIn); - - // now we check if the player is submerged + m_IsSwimming = IsBlockWater(BlockIn); - VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY+1, RelZ, BlockIn)); + // now we check if the player is submerged - m_IsSubmerged = IsBlockWater(BlockIn); + VERIFY(a_Chunk.UnboundedRelGetBlockType(RelX, RelY+1, RelZ, BlockIn)); + + m_IsSubmerged = IsBlockWater(BlockIn); } void cPlayer::HandleAir()