summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/Pawn.cpp17
-rw-r--r--src/Entities/Pickup.cpp105
-rw-r--r--src/Entities/Pickup.h2
-rw-r--r--src/Entities/Player.cpp2
4 files changed, 95 insertions, 31 deletions
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index a1c3a7610..e227dca6f 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -102,6 +102,23 @@ void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
return;
}
HandleFalling();
+
+ // Handle item pickup
+ if (m_Health > 0)
+ {
+ if (IsPlayer())
+ {
+ m_World->CollectPickupsByEntity(*this);
+ }
+ else if (IsMob())
+ {
+ cMonster & Mob = static_cast<cMonster &>(*this);
+ if (Mob.CanPickUpLoot())
+ {
+ m_World->CollectPickupsByEntity(*this);
+ }
+ }
+ }
}
diff --git a/src/Entities/Pickup.cpp b/src/Entities/Pickup.cpp
index fd2cc3a4b..bbc3313da 100644
--- a/src/Entities/Pickup.cpp
+++ b/src/Entities/Pickup.cpp
@@ -7,10 +7,12 @@
#include "Pickup.h"
#include "Player.h"
+#include "../Mobs/Villager.h"
#include "../ClientHandle.h"
#include "../World.h"
#include "../Server.h"
#include "../Bindings/PluginManager.h"
+#include "../Registries/Items.h"
#include "../Root.h"
#include "../Chunk.h"
@@ -209,7 +211,7 @@ bool cPickup::DoTakeDamage(TakeDamageInfo & a_TDI)
-bool cPickup::CollectedBy(cPlayer & a_Dest)
+bool cPickup::CollectedBy(cEntity & a_Dest)
{
if (m_bCollected)
{
@@ -217,6 +219,12 @@ bool cPickup::CollectedBy(cPlayer & a_Dest)
return false; // It's already collected!
}
+ // This type of entity can't pickup items
+ if (!a_Dest.IsPawn())
+ {
+ return false;
+ }
+
// Two seconds if player created the pickup (vomiting), half a second if anything else
if (m_Timer < (m_bIsPlayerCreated ? std::chrono::seconds(2) : std::chrono::milliseconds(500)))
{
@@ -224,43 +232,84 @@ bool cPickup::CollectedBy(cPlayer & a_Dest)
return false; // Not old enough
}
- // If the player is a spectator, he cannot collect anything
- if (a_Dest.IsGameModeSpectator())
+ // Checking for villagers
+ if (!a_Dest.IsPlayer() && a_Dest.IsMob())
{
- return false;
- }
- if (cRoot::Get()->GetPluginManager()->CallHookCollectingPickup(a_Dest, *this))
- {
- // LOG("Pickup %d cannot be collected by \"%s\", because a plugin has said no.", m_UniqueID, a_Dest->GetName().c_str());
- return false;
- }
+ auto & Mob = static_cast<cMonster &>(a_Dest);
+ if (Mob.GetMobType() == mtVillager)
+ {
+ // Villagers only pickup food
+ if (!ItemCategory::IsVillagerFood(m_Item.m_ItemType))
+ {
+ return false;
+ }
+
+ auto & Villager = static_cast<cVillager &>(Mob);
+ int NumAdded = Villager.GetInventory().AddItem(m_Item);
+ if (NumAdded > 0)
+ {
+ m_Item.m_ItemCount -= NumAdded;
+ m_World->BroadcastCollectEntity(*this, a_Dest, static_cast<unsigned>(NumAdded));
+
+ // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
+ m_World->BroadcastSoundEffect("entity.item.pickup", GetPosition(), 0.3f, (1.2f + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64));
+ if (m_Item.m_ItemCount <= 0)
+ {
+ // All of the pickup has been collected, schedule the pickup for destroying
+ m_bCollected = true;
+ }
+ m_Timer = std::chrono::milliseconds(0);
+ return true;
+ }
+ // Pickup cannot be collected because the entity has not enough space
+ return false;
+ }
- int NumAdded = a_Dest.GetInventory().AddItem(m_Item);
- if (NumAdded > 0)
+ }
+ else if (a_Dest.IsPlayer())
{
- // Check achievements
- switch (m_Item.m_ItemType)
+
+ auto & Player = static_cast<cPlayer &>(a_Dest);
+
+ // If the player is a spectator, he cannot collect anything
+ if (Player.IsGameModeSpectator())
{
- case E_BLOCK_LOG: a_Dest.AwardAchievement(CustomStatistic::AchMineWood); break;
- case E_ITEM_LEATHER: a_Dest.AwardAchievement(CustomStatistic::AchKillCow); break;
- case E_ITEM_DIAMOND: a_Dest.AwardAchievement(CustomStatistic::AchDiamonds); break;
- case E_ITEM_BLAZE_ROD: a_Dest.AwardAchievement(CustomStatistic::AchBlazeRod); break;
- default: break;
+ return false;
}
- m_Item.m_ItemCount -= NumAdded;
- m_World->BroadcastCollectEntity(*this, a_Dest, static_cast<unsigned>(NumAdded));
+ if (cRoot::Get()->GetPluginManager()->CallHookCollectingPickup(Player, *this))
+ {
+ // LOG("Pickup %d cannot be collected by \"%s\", because a plugin has said no.", m_UniqueID, a_Dest->GetName().c_str());
+ return false;
+ }
- // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
- m_World->BroadcastSoundEffect("entity.item.pickup", GetPosition(), 0.3f, (1.2f + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64));
- if (m_Item.m_ItemCount <= 0)
+ int NumAdded = Player.GetInventory().AddItem(m_Item);
+ if (NumAdded > 0)
{
- // All of the pickup has been collected, schedule the pickup for destroying
- m_bCollected = true;
+ // Check achievements
+ switch (m_Item.m_ItemType)
+ {
+ case E_BLOCK_LOG: Player.AwardAchievement(CustomStatistic::AchMineWood); break;
+ case E_ITEM_LEATHER: Player.AwardAchievement(CustomStatistic::AchKillCow); break;
+ case E_ITEM_DIAMOND: Player.AwardAchievement(CustomStatistic::AchDiamonds); break;
+ case E_ITEM_BLAZE_ROD: Player.AwardAchievement(CustomStatistic::AchBlazeRod); break;
+ default: break;
+ }
+
+ m_Item.m_ItemCount -= NumAdded;
+ m_World->BroadcastCollectEntity(*this, a_Dest, static_cast<unsigned>(NumAdded));
+
+ // Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
+ m_World->BroadcastSoundEffect("entity.item.pickup", GetPosition(), 0.3f, (1.2f + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64));
+ if (m_Item.m_ItemCount <= 0)
+ {
+ // All of the pickup has been collected, schedule the pickup for destroying
+ m_bCollected = true;
+ }
+ m_Timer = std::chrono::milliseconds(0);
+ return true;
}
- m_Timer = std::chrono::milliseconds(0);
- return true;
}
// LOG("Pickup %d cannot be collected by \"%s\", because there's no space in the inventory.", a_Dest->GetName().c_str(), m_UniqueID);
diff --git a/src/Entities/Pickup.h b/src/Entities/Pickup.h
index 73540a64e..c995055ff 100644
--- a/src/Entities/Pickup.h
+++ b/src/Entities/Pickup.h
@@ -33,7 +33,7 @@ public: // tolua_export
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
- bool CollectedBy(cPlayer & a_Dest); // tolua_export
+ bool CollectedBy(cEntity & a_Dest); // tolua_export
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 1d3bad306..b0ab94874 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -3213,8 +3213,6 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
if (m_Health > 0) // make sure player is alive
{
- m_World->CollectPickupsByPlayer(*this);
-
if ((m_EatingFinishTick >= 0_tick) && (m_EatingFinishTick <= m_World->GetWorldAge()))
{
FinishEating();