summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2021-01-02 14:50:34 +0100
committerGitHub <noreply@github.com>2021-01-02 14:50:34 +0100
commit16aeb84cd35996a6b41f10cbc48a677eeccc911c (patch)
treeae877926559d59a534bbf3c22651e6df7ffe8d71
parentFix version typo in CMakeLists.txt (#5098) (diff)
downloadcuberite-16aeb84cd35996a6b41f10cbc48a677eeccc911c.tar
cuberite-16aeb84cd35996a6b41f10cbc48a677eeccc911c.tar.gz
cuberite-16aeb84cd35996a6b41f10cbc48a677eeccc911c.tar.bz2
cuberite-16aeb84cd35996a6b41f10cbc48a677eeccc911c.tar.lz
cuberite-16aeb84cd35996a6b41f10cbc48a677eeccc911c.tar.xz
cuberite-16aeb84cd35996a6b41f10cbc48a677eeccc911c.tar.zst
cuberite-16aeb84cd35996a6b41f10cbc48a677eeccc911c.zip
-rw-r--r--src/BlockEntities/BeaconEntity.cpp17
-rw-r--r--src/BlockEntities/BeaconEntity.h1
-rw-r--r--src/BlockEntities/BlockEntity.cpp141
-rw-r--r--src/BlockEntities/BlockEntity.h79
-rw-r--r--src/BlockEntities/BrewingstandEntity.cpp44
-rw-r--r--src/BlockEntities/BrewingstandEntity.h11
-rw-r--r--src/BlockEntities/ChestEntity.cpp33
-rw-r--r--src/BlockEntities/ChestEntity.h3
-rw-r--r--src/BlockEntities/DropSpenserEntity.cpp28
-rw-r--r--src/BlockEntities/DropSpenserEntity.h2
-rw-r--r--src/BlockEntities/EnderChestEntity.cpp18
-rw-r--r--src/BlockEntities/EnderChestEntity.h2
-rw-r--r--src/BlockEntities/FlowerPotEntity.cpp13
-rw-r--r--src/BlockEntities/FlowerPotEntity.h2
-rw-r--r--src/BlockEntities/FurnaceEntity.cpp45
-rw-r--r--src/BlockEntities/FurnaceEntity.h7
-rw-r--r--src/Chunk.cpp9
-rw-r--r--src/Entities/Entity.cpp71
-rw-r--r--src/Entities/Entity.h9
-rw-r--r--src/Entities/EntityEffect.h2
-rw-r--r--src/Entities/Minecart.cpp157
-rw-r--r--src/Entities/Minecart.h28
-rw-r--r--src/Entities/Pawn.cpp29
-rw-r--r--src/Entities/Pawn.h7
-rw-r--r--src/Entities/Player.cpp3
-rw-r--r--src/Entities/Player.h4
-rw-r--r--src/Mobs/Horse.cpp28
-rw-r--r--src/Mobs/Horse.h6
-rw-r--r--src/Mobs/Monster.cpp44
-rw-r--r--src/Mobs/Monster.h6
-rw-r--r--src/Mobs/PassiveMonster.cpp9
-rw-r--r--src/Mobs/PassiveMonster.h6
-rw-r--r--src/UI/Window.cpp1
33 files changed, 405 insertions, 460 deletions
diff --git a/src/BlockEntities/BeaconEntity.cpp b/src/BlockEntities/BeaconEntity.cpp
index a7bdbca2d..e59d31f52 100644
--- a/src/BlockEntities/BeaconEntity.cpp
+++ b/src/BlockEntities/BeaconEntity.cpp
@@ -271,6 +271,20 @@ void cBeaconEntity::CopyFrom(const cBlockEntity & a_Src)
+void cBeaconEntity::OnRemoveFromWorld()
+{
+ const auto Window = GetWindow();
+ if (Window != nullptr)
+ {
+ // Tell window its owner is destroyed:
+ Window->OwnerDestroyed();
+ }
+}
+
+
+
+
+
void cBeaconEntity::SendTo(cClientHandle & a_Client)
{
a_Client.SendUpdateBlockEntity(*this);
@@ -316,6 +330,3 @@ bool cBeaconEntity::UsedBy(cPlayer * a_Player)
}
return true;
}
-
-
-
diff --git a/src/BlockEntities/BeaconEntity.h b/src/BlockEntities/BeaconEntity.h
index 21c35610d..e5230e2cb 100644
--- a/src/BlockEntities/BeaconEntity.h
+++ b/src/BlockEntities/BeaconEntity.h
@@ -29,6 +29,7 @@ public: // tolua_export
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
+ virtual void OnRemoveFromWorld() override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual bool UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp
index 44d5e2d19..a3b6b33a3 100644
--- a/src/BlockEntities/BlockEntity.cpp
+++ b/src/BlockEntities/BlockEntity.cpp
@@ -28,56 +28,52 @@
-void cBlockEntity::SetPos(Vector3i a_NewPos)
+cBlockEntity::cBlockEntity(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta, const Vector3i a_Pos, cWorld * const a_World) :
+ m_Pos(a_Pos),
+ m_RelX(a_Pos.x - cChunkDef::Width * FAST_FLOOR_DIV(a_Pos.x, cChunkDef::Width)),
+ m_RelZ(a_Pos.z - cChunkDef::Width * FAST_FLOOR_DIV(a_Pos.z, cChunkDef::Width)),
+ m_BlockType(a_BlockType),
+ m_BlockMeta(a_BlockMeta),
+ m_World(a_World)
{
- ASSERT(m_World == nullptr); // Cannot move block entities that represent world blocks (only use this for cBlockArea's BEs)
- m_Pos = a_NewPos;
}
-bool cBlockEntity::IsBlockEntityBlockType(BLOCKTYPE a_BlockType)
+OwnedBlockEntity cBlockEntity::Clone(const Vector3i a_Pos)
{
- switch (a_BlockType)
- {
- case E_BLOCK_BEACON:
- case E_BLOCK_BED:
- case E_BLOCK_BREWING_STAND:
- case E_BLOCK_CHEST:
- case E_BLOCK_COMMAND_BLOCK:
- case E_BLOCK_DISPENSER:
- case E_BLOCK_DROPPER:
- case E_BLOCK_ENCHANTMENT_TABLE:
- case E_BLOCK_ENDER_CHEST:
- case E_BLOCK_END_PORTAL:
- case E_BLOCK_FLOWER_POT:
- case E_BLOCK_FURNACE:
- case E_BLOCK_HEAD:
- case E_BLOCK_HOPPER:
- case E_BLOCK_JUKEBOX:
- case E_BLOCK_LIT_FURNACE:
- case E_BLOCK_MOB_SPAWNER:
- case E_BLOCK_NOTE_BLOCK:
- case E_BLOCK_SIGN_POST:
- case E_BLOCK_TRAPPED_CHEST:
- case E_BLOCK_WALLSIGN:
- {
- return true;
- }
- default:
- {
- return false;
- }
- }
+ auto res = CreateByBlockType(m_BlockType, m_BlockMeta, a_Pos, nullptr);
+ res->CopyFrom(*this);
+ return res;
+}
+
+
+
+
+
+cItems cBlockEntity::ConvertToPickups() const
+{
+ return {};
}
-OwnedBlockEntity cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World)
+void cBlockEntity::CopyFrom(const cBlockEntity & a_Src)
+{
+ // Nothing to copy, but check that we're copying the right entity:
+ ASSERT(m_BlockType == a_Src.m_BlockType);
+ ASSERT(m_BlockMeta == a_Src.m_BlockMeta);
+}
+
+
+
+
+
+OwnedBlockEntity cBlockEntity::CreateByBlockType(const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta, const Vector3i a_Pos, cWorld * const a_World)
{
switch (a_BlockType)
{
@@ -117,29 +113,82 @@ OwnedBlockEntity cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETY
-OwnedBlockEntity cBlockEntity::Clone(Vector3i a_Pos)
+void cBlockEntity::Destroy()
{
- auto res = CreateByBlockType(m_BlockType, m_BlockMeta, a_Pos, nullptr);
- res->CopyFrom(*this);
- return res;
}
-cItems cBlockEntity::ConvertToPickups() const
+bool cBlockEntity::IsBlockEntityBlockType(const BLOCKTYPE a_BlockType)
{
- return {};
+ switch (a_BlockType)
+ {
+ case E_BLOCK_BEACON:
+ case E_BLOCK_BED:
+ case E_BLOCK_BREWING_STAND:
+ case E_BLOCK_CHEST:
+ case E_BLOCK_COMMAND_BLOCK:
+ case E_BLOCK_DISPENSER:
+ case E_BLOCK_DROPPER:
+ case E_BLOCK_ENCHANTMENT_TABLE:
+ case E_BLOCK_ENDER_CHEST:
+ case E_BLOCK_END_PORTAL:
+ case E_BLOCK_FLOWER_POT:
+ case E_BLOCK_FURNACE:
+ case E_BLOCK_HEAD:
+ case E_BLOCK_HOPPER:
+ case E_BLOCK_JUKEBOX:
+ case E_BLOCK_LIT_FURNACE:
+ case E_BLOCK_MOB_SPAWNER:
+ case E_BLOCK_NOTE_BLOCK:
+ case E_BLOCK_SIGN_POST:
+ case E_BLOCK_TRAPPED_CHEST:
+ case E_BLOCK_WALLSIGN:
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
}
-void cBlockEntity::CopyFrom(const cBlockEntity & a_Src)
+void cBlockEntity::OnRemoveFromWorld()
{
- // Nothing to copy, but check that we're copying the right entity:
- ASSERT(m_BlockType == a_Src.m_BlockType);
- ASSERT(m_BlockMeta == a_Src.m_BlockMeta);
+}
+
+
+
+
+
+void cBlockEntity::SetPos(const Vector3i a_NewPos)
+{
+ ASSERT(m_World == nullptr); // Cannot move block entities that represent world blocks (only use this for cBlockArea's BEs)
+ m_Pos = a_NewPos;
+}
+
+
+
+
+
+void cBlockEntity::SetWorld(cWorld * const a_World)
+{
+ m_World = a_World;
+}
+
+
+
+
+
+bool cBlockEntity::Tick(const std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
+{
+ UNUSED(a_Dt);
+ return false;
}
diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h
index 3355cdf44..3e9cf38e7 100644
--- a/src/BlockEntities/BlockEntity.h
+++ b/src/BlockEntities/BlockEntity.h
@@ -24,41 +24,14 @@ using cBlockEntities = std::unordered_map<size_t, OwnedBlockEntity>;
class cBlockEntity
{
protected:
- cBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World) :
- m_Pos(a_Pos),
- m_RelX(a_Pos.x - cChunkDef::Width * FAST_FLOOR_DIV(a_Pos.x, cChunkDef::Width)),
- m_RelZ(a_Pos.z - cChunkDef::Width * FAST_FLOOR_DIV(a_Pos.z, cChunkDef::Width)),
- m_BlockType(a_BlockType),
- m_BlockMeta(a_BlockMeta),
- m_World(a_World)
- {
- }
+
+ cBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
public:
// tolua_end
- virtual ~cBlockEntity() {} // force a virtual destructor in all descendants
-
- virtual void Destroy() {}
-
- void SetWorld(cWorld * a_World)
- {
- m_World = a_World;
- }
-
- /** Updates the internally stored position.
- Note that this should not ever be used for world-contained block entities, it is meant only for when BEs in a cBlockArea are manipulated.
- Asserts that the block entity is not assigned to a world. */
- void SetPos(Vector3i a_NewPos);
-
- /** Returns true if the specified blocktype is supposed to have an associated block entity. */
- static bool IsBlockEntityBlockType(BLOCKTYPE a_BlockType);
-
- /** Creates a new block entity for the specified block type at the specified absolute pos.
- If a_World is valid, then the entity is created bound to that world
- Returns nullptr for unknown block types. */
- static OwnedBlockEntity CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World = nullptr);
+ virtual ~cBlockEntity() = default; // force a virtual destructor in all descendants
/** Makes an exact copy of this block entity, except for its m_World (set to nullptr), and at a new position.
Uses CopyFrom() to copy the properties. */
@@ -73,6 +46,37 @@ public:
Super::CopyFrom(a_Src) to copy the common ones. */
virtual void CopyFrom(const cBlockEntity & a_Src);
+ /** Creates a new block entity for the specified block type at the specified absolute pos.
+ If a_World is valid, then the entity is created bound to that world
+ Returns nullptr for unknown block types. */
+ static OwnedBlockEntity CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World = nullptr);
+
+ virtual void Destroy();
+
+ /** Returns true if the specified blocktype is supposed to have an associated block entity. */
+ static bool IsBlockEntityBlockType(BLOCKTYPE a_BlockType);
+
+ /** Called when the block entity is removed from a world. */
+ virtual void OnRemoveFromWorld();
+
+ /** Sends the packet defining the block entity to the client specified.
+ To send to all eligible clients, use cWorld::BroadcastBlockEntity() */
+ virtual void SendTo(cClientHandle & a_Client) = 0;
+
+ /** Updates the internally stored position.
+ Note that this should not ever be used for world-contained block entities, it is meant only for when BEs in a cBlockArea are manipulated.
+ Asserts that the block entity is not assigned to a world. */
+ void SetPos(Vector3i a_NewPos);
+
+ void SetWorld(cWorld * a_World);
+
+ /** Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing. */
+ virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk);
+
+ /** Called when a player uses this entity; should open the UI window.
+ returns true if the use was successful, return false to use the block as a "normal" block */
+ virtual bool UsedBy(cPlayer * a_Player) = 0;
+
// tolua_begin
// Position, in absolute block coordinates:
@@ -95,21 +99,6 @@ public:
// tolua_end
- /** Called when a player uses this entity; should open the UI window.
- returns true if the use was successful, return false to use the block as a "normal" block */
- virtual bool UsedBy( cPlayer * a_Player) = 0;
-
- /** Sends the packet defining the block entity to the client specified.
- To send to all eligible clients, use cWorld::BroadcastBlockEntity() */
- virtual void SendTo(cClientHandle & a_Client) = 0;
-
- /** Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing. */
- virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
- {
- UNUSED(a_Dt);
- return false;
- }
-
protected:
diff --git a/src/BlockEntities/BrewingstandEntity.cpp b/src/BlockEntities/BrewingstandEntity.cpp
index 9c43f257f..44a077bc0 100644
--- a/src/BlockEntities/BrewingstandEntity.cpp
+++ b/src/BlockEntities/BrewingstandEntity.cpp
@@ -13,7 +13,6 @@
cBrewingstandEntity::cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
- m_IsDestroyed(false),
m_IsBrewing(false),
m_TimeBrewed(0),
m_RemainingFuel(0)
@@ -25,30 +24,6 @@ cBrewingstandEntity::cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo
-cBrewingstandEntity::~cBrewingstandEntity()
-{
- // Tell window its owner is destroyed
- cWindow * Window = GetWindow();
- if (Window != nullptr)
- {
- Window->OwnerDestroyed();
- }
-}
-
-
-
-
-
-void cBrewingstandEntity::Destroy()
-{
- m_IsDestroyed = true;
- Super::Destroy();
-}
-
-
-
-
-
void cBrewingstandEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
@@ -70,6 +45,20 @@ void cBrewingstandEntity::CopyFrom(const cBlockEntity & a_Src)
+void cBrewingstandEntity::OnRemoveFromWorld()
+{
+ const auto Window = GetWindow();
+ if (Window != nullptr)
+ {
+ // Tell window its owner is destroyed:
+ Window->OwnerDestroyed();
+ }
+}
+
+
+
+
+
void cBrewingstandEntity::SendTo(cClientHandle & a_Client)
{
// Nothing needs to be sent
@@ -206,11 +195,6 @@ void cBrewingstandEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
{
Super::OnSlotChanged(a_ItemGrid, a_SlotNum);
- if (m_IsDestroyed)
- {
- return;
- }
-
ASSERT(a_ItemGrid == &m_Contents);
// Check for fuel
diff --git a/src/BlockEntities/BrewingstandEntity.h b/src/BlockEntities/BrewingstandEntity.h
index 5f6822ff7..67a6da1a3 100644
--- a/src/BlockEntities/BrewingstandEntity.h
+++ b/src/BlockEntities/BrewingstandEntity.h
@@ -8,6 +8,7 @@
+
class cClientHandle;
@@ -43,11 +44,9 @@ public:
/** Constructor used for normal operation */
cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
- virtual ~cBrewingstandEntity() override;
-
- // cBlockEntity overrides:
- virtual void Destroy() override;
+ // cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
+ virtual void OnRemoveFromWorld() override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual bool UsedBy(cPlayer * a_Player) override;
@@ -110,12 +109,8 @@ public:
/** Gets the recipes. Will be called if the brewing stand gets loaded from the world. */
void LoadRecipes(void);
-
protected:
- /** Set to true when the brewing stand entity has been destroyed to prevent the block being set again */
- bool m_IsDestroyed;
-
/** Set to true if the brewing stand is brewing an item */
bool m_IsBrewing;
diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp
index 8c8e75b25..e225cf96e 100644
--- a/src/BlockEntities/ChestEntity.cpp
+++ b/src/BlockEntities/ChestEntity.cpp
@@ -32,31 +32,31 @@ cChestEntity::cChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector
-cChestEntity::~cChestEntity()
+void cChestEntity::CopyFrom(const cBlockEntity & a_Src)
{
- if (m_Neighbour != nullptr)
- {
- // Neighbour may share a window with us, force the window shut
- m_Neighbour->DestroyWindow();
- m_Neighbour->m_Neighbour = nullptr;
- }
+ Super::CopyFrom(a_Src);
+ auto & src = static_cast<const cChestEntity &>(a_Src);
+ m_Contents.CopyFrom(src.m_Contents);
- DestroyWindow();
+ // Reset the neighbor and player count, there's no sense in copying these:
+ m_Neighbour = nullptr;
+ m_NumActivePlayers = 0;
}
-void cChestEntity::CopyFrom(const cBlockEntity & a_Src)
+void cChestEntity::OnRemoveFromWorld()
{
- Super::CopyFrom(a_Src);
- auto & src = static_cast<const cChestEntity &>(a_Src);
- m_Contents.CopyFrom(src.m_Contents);
+ if (m_Neighbour != nullptr)
+ {
+ // Neighbour may share a window with us, force the window shut:
+ m_Neighbour->DestroyWindow();
+ m_Neighbour->m_Neighbour = nullptr;
+ }
- // Reset the neighbor and player count, there's no sense in copying these:
- m_Neighbour = nullptr;
- m_NumActivePlayers = 0;
+ DestroyWindow();
}
@@ -199,11 +199,10 @@ void cChestEntity::OpenNewWindow(void)
void cChestEntity::DestroyWindow()
{
- cWindow * Window = GetWindow();
+ const auto Window = GetWindow();
if (Window != nullptr)
{
Window->OwnerDestroyed();
- CloseWindow();
}
}
diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h
index 7c28214eb..ee59fa7b9 100644
--- a/src/BlockEntities/ChestEntity.h
+++ b/src/BlockEntities/ChestEntity.h
@@ -37,10 +37,9 @@ public:
/** Constructor used for normal operation */
cChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
- virtual ~cChestEntity() override;
-
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
+ virtual void OnRemoveFromWorld() override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/DropSpenserEntity.cpp b/src/BlockEntities/DropSpenserEntity.cpp
index 259cec7a3..814b0c147 100644
--- a/src/BlockEntities/DropSpenserEntity.cpp
+++ b/src/BlockEntities/DropSpenserEntity.cpp
@@ -26,20 +26,6 @@ cDropSpenserEntity::cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_Block
-cDropSpenserEntity::~cDropSpenserEntity()
-{
- // Tell window its owner is destroyed
- cWindow * Window = GetWindow();
- if (Window != nullptr)
- {
- Window->OwnerDestroyed();
- }
-}
-
-
-
-
-
void cDropSpenserEntity::AddDropSpenserDir(Vector3i & a_RelCoord, NIBBLETYPE a_Direction)
{
switch (a_Direction & E_META_DROPSPENSER_FACING_MASK)
@@ -132,6 +118,20 @@ void cDropSpenserEntity::CopyFrom(const cBlockEntity & a_Src)
+void cDropSpenserEntity::OnRemoveFromWorld()
+{
+ const auto Window = GetWindow();
+ if (Window != nullptr)
+ {
+ // Tell window its owner is destroyed:
+ Window->OwnerDestroyed();
+ }
+}
+
+
+
+
+
bool cDropSpenserEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);
diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h
index e16149797..9eb3d15ea 100644
--- a/src/BlockEntities/DropSpenserEntity.h
+++ b/src/BlockEntities/DropSpenserEntity.h
@@ -43,10 +43,10 @@ public:
// tolua_end
cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
- virtual ~cDropSpenserEntity() override;
// cBlockEntity overrides:
virtual void CopyFrom(const cBlockEntity & a_Src) override;
+ virtual void OnRemoveFromWorld() override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool UsedBy(cPlayer * a_Player) override;
diff --git a/src/BlockEntities/EnderChestEntity.cpp b/src/BlockEntities/EnderChestEntity.cpp
index 44bfaf7d4..c5d490766 100644
--- a/src/BlockEntities/EnderChestEntity.cpp
+++ b/src/BlockEntities/EnderChestEntity.cpp
@@ -25,23 +25,23 @@ cEnderChestEntity::cEnderChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMe
-cEnderChestEntity::~cEnderChestEntity()
+void cEnderChestEntity::SendTo(cClientHandle & a_Client)
{
- cWindow * Window = GetWindow();
- if (Window != nullptr)
- {
- Window->OwnerDestroyed();
- }
+ // Send a dummy "number of players with chest open" packet to make the chest visible:
+ a_Client.SendBlockAction(m_Pos.x, m_Pos.y, m_Pos.z, 1, 0, m_BlockType);
}
-void cEnderChestEntity::SendTo(cClientHandle & a_Client)
+void cEnderChestEntity::OnRemoveFromWorld()
{
- // Send a dummy "number of players with chest open" packet to make the chest visible:
- a_Client.SendBlockAction(m_Pos.x, m_Pos.y, m_Pos.z, 1, 0, m_BlockType);
+ const auto Window = GetWindow();
+ if (Window != nullptr)
+ {
+ Window->OwnerDestroyed();
+ }
}
diff --git a/src/BlockEntities/EnderChestEntity.h b/src/BlockEntities/EnderChestEntity.h
index bb5974b15..d2fb4d67e 100644
--- a/src/BlockEntities/EnderChestEntity.h
+++ b/src/BlockEntities/EnderChestEntity.h
@@ -20,9 +20,9 @@ class cEnderChestEntity :
public: // tolua_export
cEnderChestEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
- virtual ~cEnderChestEntity() override;
// cBlockEntity overrides:
+ virtual void OnRemoveFromWorld() override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle & a_Client) override;
diff --git a/src/BlockEntities/FlowerPotEntity.cpp b/src/BlockEntities/FlowerPotEntity.cpp
index 60b2db4f5..bc936c246 100644
--- a/src/BlockEntities/FlowerPotEntity.cpp
+++ b/src/BlockEntities/FlowerPotEntity.cpp
@@ -23,18 +23,9 @@ cFlowerPotEntity::cFlowerPotEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
-void cFlowerPotEntity::Destroy(void)
+cItems cFlowerPotEntity::ConvertToPickups() const
{
- // Drop the contents as pickups:
- if (!m_Item.IsEmpty())
- {
- ASSERT(m_World != nullptr);
- cItems Pickups;
- Pickups.Add(m_Item);
- m_World->SpawnItemPickups(Pickups, Vector3d(0.5, 0.5, 0.5) + m_Pos);
-
- m_Item.Empty();
- }
+ return cItem(m_Item);
}
diff --git a/src/BlockEntities/FlowerPotEntity.h b/src/BlockEntities/FlowerPotEntity.h
index c93e2f4d9..1d95ef570 100644
--- a/src/BlockEntities/FlowerPotEntity.h
+++ b/src/BlockEntities/FlowerPotEntity.h
@@ -43,7 +43,7 @@ public: // tolua_export
// tolua_end
// cBlockEntity overrides:
- virtual void Destroy(void) override;
+ virtual cItems ConvertToPickups() const override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
virtual bool UsedBy(cPlayer * a_Player) override;
virtual void SendTo(cClientHandle & a_Client) override;
diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp
index b325f4e5c..6b2e7bbac 100644
--- a/src/BlockEntities/FurnaceEntity.cpp
+++ b/src/BlockEntities/FurnaceEntity.cpp
@@ -25,7 +25,6 @@ enum
cFurnaceEntity::cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
m_CurrentRecipe(nullptr),
- m_IsDestroyed(false),
m_IsCooking(a_BlockType == E_BLOCK_LIT_FURNACE),
m_NeedCookTime(0),
m_TimeCooked(0),
@@ -41,30 +40,6 @@ cFurnaceEntity::cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Ve
-cFurnaceEntity::~cFurnaceEntity()
-{
- // Tell window its owner is destroyed
- cWindow * Window = GetWindow();
- if (Window != nullptr)
- {
- Window->OwnerDestroyed();
- }
-}
-
-
-
-
-
-void cFurnaceEntity::Destroy()
-{
- m_IsDestroyed = true;
- Super::Destroy();
-}
-
-
-
-
-
void cFurnaceEntity::CopyFrom(const cBlockEntity & a_Src)
{
Super::CopyFrom(a_Src);
@@ -73,7 +48,6 @@ void cFurnaceEntity::CopyFrom(const cBlockEntity & a_Src)
m_CurrentRecipe = src.m_CurrentRecipe;
m_FuelBurnTime = src.m_FuelBurnTime;
m_IsCooking = src.m_IsCooking;
- m_IsDestroyed = src.m_IsDestroyed;
m_IsLoading = src.m_IsLoading;
m_LastInput = src.m_LastInput;
m_NeedCookTime = src.m_NeedCookTime;
@@ -85,6 +59,20 @@ void cFurnaceEntity::CopyFrom(const cBlockEntity & a_Src)
+void cFurnaceEntity::OnRemoveFromWorld()
+{
+ const auto Window = GetWindow();
+ if (Window != nullptr)
+ {
+ // Tell window its owner is destroyed:
+ Window->OwnerDestroyed();
+ }
+}
+
+
+
+
+
void cFurnaceEntity::SendTo(cClientHandle & a_Client)
{
// Nothing needs to be sent
@@ -259,11 +247,6 @@ void cFurnaceEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
{
Super::OnSlotChanged(a_ItemGrid, a_SlotNum);
- if (m_IsDestroyed)
- {
- return;
- }
-
if (m_IsLoading)
{
return;
diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h
index 079b45fef..c6b5ee09f 100644
--- a/src/BlockEntities/FurnaceEntity.h
+++ b/src/BlockEntities/FurnaceEntity.h
@@ -41,11 +41,9 @@ public:
/** Constructor used for normal operation */
cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World);
- virtual ~cFurnaceEntity() override;
-
// cBlockEntity overrides:
- virtual void Destroy() override;
virtual void CopyFrom(const cBlockEntity & a_Src) override;
+ virtual void OnRemoveFromWorld() override;
virtual void SendTo(cClientHandle & a_Client) override;
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual bool UsedBy(cPlayer * a_Player) override;
@@ -118,9 +116,6 @@ protected:
/** The item that is being smelted */
cItem m_LastInput;
- /** Set to true when the furnace entity has been destroyed to prevent the block being set again */
- bool m_IsDestroyed;
-
/** Set to true if the furnace is cooking an item */
bool m_IsCooking;
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 0d0b0896a..ff5757703 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -220,6 +220,12 @@ void cChunk::OnUnload()
// Notify the entity:
Entity->OnRemoveFromWorld(*Entity->GetWorld());
}
+
+ // Notify all block entities of imminent unload:
+ for (auto & BlockEntity : m_BlockEntities)
+ {
+ BlockEntity.second->OnRemoveFromWorld();
+ }
}
@@ -452,6 +458,7 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock
if (affectedArea.IsInside(itr->second->GetPos()))
{
itr->second->Destroy();
+ itr->second->OnRemoveFromWorld();
itr = m_BlockEntities.erase(itr);
}
else
@@ -760,6 +767,7 @@ void cChunk::MoveEntityToNewChunk(OwnedEntity a_Entity)
if (Neighbor == nullptr)
{
LOGWARNING("%s: Failed to move entity, destination chunk unreachable. Entity lost", __FUNCTION__);
+ a_Entity->OnRemoveFromWorld(*m_World);
return;
}
@@ -1267,6 +1275,7 @@ void cChunk::SetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Blo
if (BlockEntity != nullptr)
{
BlockEntity->Destroy();
+ BlockEntity->OnRemoveFromWorld();
RemoveBlockEntity(BlockEntity);
}
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 579541dd3..438117650 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -80,32 +80,6 @@ cEntity::cEntity(eEntityType a_EntityType, Vector3d a_Pos, double a_Width, doubl
-cEntity::~cEntity()
-{
- /*
- // DEBUG:
- FLOGD("Deleting entity {0} at pos {1:.2f} ~ [{2}, {3}]; ptr {4}",
- m_UniqueID,
- m_Pos,
- GetChunkX(), GetChunkZ(),
- static_cast<void *>(this)
- );
- */
-
- if (m_AttachedTo != nullptr)
- {
- Detach();
- }
- if (m_Attachee != nullptr)
- {
- m_Attachee->Detach();
- }
-}
-
-
-
-
-
const char * cEntity::GetClass(void) const
{
return "cEntity";
@@ -174,7 +148,22 @@ void cEntity::OnAddToWorld(cWorld & a_World)
void cEntity::OnRemoveFromWorld(cWorld & a_World)
{
- RemoveAllLeashedMobs();
+ // Remove all mobs from the leashed list of mobs:
+ while (!m_LeashedMobs.empty())
+ {
+ m_LeashedMobs.front()->Unleash(false, true);
+ }
+
+ if (m_AttachedTo != nullptr)
+ {
+ Detach();
+ }
+
+ if (m_Attachee != nullptr)
+ {
+ m_Attachee->Detach();
+ }
+
a_World.BroadcastDestroyEntity(*this);
}
@@ -244,7 +233,6 @@ void cEntity::Destroy()
// Also, not storing the returned pointer means automatic destruction
VERIFY(a_World.RemoveEntity(*this));
});
- Destroyed();
}
@@ -813,10 +801,17 @@ void cEntity::KilledBy(TakeDamageInfo & a_TDI)
cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_TDI, emptystring);
}
- // Drop loot:
- cItems Drops;
- GetDrops(Drops, a_TDI.Attacker);
- m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
+ // Drop loot, unless the attacker was a creative mode player:
+ if (
+ (a_TDI.Attacker == nullptr) ||
+ !a_TDI.Attacker->IsPlayer() ||
+ !static_cast<cPlayer *>(a_TDI.Attacker)->IsGameModeCreative()
+ )
+ {
+ cItems Drops;
+ GetDrops(Drops, a_TDI.Attacker);
+ m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
+ }
m_World->BroadcastEntityStatus(*this, esGenericDead);
}
@@ -2328,18 +2323,6 @@ void cEntity::RemoveLeashedMob(cMonster * a_Monster)
-void cEntity::RemoveAllLeashedMobs()
-{
- while (!m_LeashedMobs.empty())
- {
- m_LeashedMobs.front()->Unleash(false, true);
- }
-}
-
-
-
-
-
void cEntity::BroadcastLeashedMobs()
{
// If has any mob leashed broadcast every leashed entity to this
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 20712e7ea..85cf35661 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -169,7 +169,7 @@ public:
cEntity(eEntityType a_EntityType, Vector3d a_Pos, double a_Width, double a_Height);
- virtual ~cEntity();
+ virtual ~cEntity() = default;
/** Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed).
Adds the entity to the world. */
@@ -296,7 +296,7 @@ public:
// tolua_end
/** Destroys the entity, schedules it for memory freeing and broadcasts the DestroyEntity packet */
- virtual void Destroy();
+ void Destroy();
// tolua_begin
/** Makes this pawn take damage from an attack by a_Attacker. Damage values are calculated automatically and DoTakeDamage() called */
@@ -594,9 +594,6 @@ public:
/** Removes a mob from the leashed list of mobs. */
void RemoveLeashedMob(cMonster * a_Monster);
- /** Removes all mobs from the leashed list of mobs. */
- void RemoveAllLeashedMobs();
-
/** Returs whether the entity has any mob leashed to it. */
bool HasAnyMobLeashed() const { return m_LeashedMobs.size() > 0; }
@@ -723,8 +720,6 @@ protected:
Should handle degenerate cases such as moving to the same world. */
virtual void DoMoveToWorld(const sWorldChangeInfo & a_WorldChangeInfo);
- virtual void Destroyed(void) {} // Called after the entity has been destroyed
-
/** Applies friction to an entity
@param a_Speed The speed vector to apply changes to
@param a_SlowdownMultiplier The factor to reduce the speed by */
diff --git a/src/Entities/EntityEffect.h b/src/Entities/EntityEffect.h
index eebf0e3c8..b4e01d8d9 100644
--- a/src/Entities/EntityEffect.h
+++ b/src/Entities/EntityEffect.h
@@ -73,7 +73,7 @@ public:
@param a_OtherEffect The other effect to copy */
cEntityEffect & operator =(cEntityEffect a_OtherEffect);
- virtual ~cEntityEffect(void) {}
+ virtual ~cEntityEffect(void) = default;
/** Creates a pointer to the proper entity effect from the effect type
@warning This function creates raw pointers that must be manually managed.
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp
index 59d369c5b..fbe4f756e 100644
--- a/src/Entities/Minecart.cpp
+++ b/src/Entities/Minecart.cpp
@@ -1203,7 +1203,6 @@ bool cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
{
if ((TDI.Attacker != nullptr) && TDI.Attacker->IsPlayer() && static_cast<cPlayer *>(TDI.Attacker)->IsGameModeCreative())
{
- Destroy();
TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative
SetInvulnerableTicks(0);
return Super::DoTakeDamage(TDI); // No drops for creative
@@ -1217,43 +1216,32 @@ bool cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
m_World->BroadcastEntityMetadata(*this);
- if (GetHealth() <= 0)
- {
- Destroy();
+ return true;
+}
- cItems Drops;
- switch (m_Payload)
- {
- case mpNone:
- {
- Drops.push_back(cItem(E_ITEM_MINECART, 1, 0));
- break;
- }
- case mpChest:
- {
- Drops.push_back(cItem(E_ITEM_CHEST_MINECART, 1, 0));
- break;
- }
- case mpFurnace:
- {
- Drops.push_back(cItem(E_ITEM_FURNACE_MINECART, 1, 0));
- break;
- }
- case mpTNT:
- {
- Drops.push_back(cItem(E_ITEM_MINECART_WITH_TNT, 1, 0));
- break;
- }
- case mpHopper:
- {
- Drops.push_back(cItem(E_ITEM_MINECART_WITH_HOPPER, 1, 0));
- break;
- }
- }
- m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
+
+
+
+void cMinecart::KilledBy(TakeDamageInfo & a_TDI)
+{
+ Super::KilledBy(a_TDI);
+
+ Destroy();
+}
+
+
+
+
+
+void cMinecart::OnRemoveFromWorld(cWorld & a_World)
+{
+ if (m_bIsOnDetectorRail)
+ {
+ m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
}
- return true;
+
+ Super::OnRemoveFromWorld(a_World);
}
@@ -1314,18 +1302,6 @@ void cMinecart::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
-void cMinecart::Destroyed()
-{
- if (m_bIsOnDetectorRail)
- {
- m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
- }
-}
-
-
-
-
-
////////////////////////////////////////////////////////////////////////////////
// cRideableMinecart:
@@ -1340,6 +1316,15 @@ cRideableMinecart::cRideableMinecart(Vector3d a_Pos, const cItem & a_Content, in
+void cRideableMinecart::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ a_Drops.emplace_back(E_ITEM_MINECART);
+}
+
+
+
+
+
void cRideableMinecart::OnRightClicked(cPlayer & a_Player)
{
Super::OnRightClicked(a_Player);
@@ -1386,6 +1371,31 @@ cMinecartWithChest::cMinecartWithChest(Vector3d a_Pos):
+void cMinecartWithChest::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ m_Contents.CopyToItems(a_Drops);
+ a_Drops.emplace_back(E_ITEM_CHEST_MINECART);
+}
+
+
+
+
+
+void cMinecartWithChest::OnRemoveFromWorld(cWorld & a_World)
+{
+ const auto Window = GetWindow();
+ if (Window != nullptr)
+ {
+ Window->OwnerDestroyed();
+ }
+
+ Super::OnRemoveFromWorld(a_World);
+}
+
+
+
+
+
void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
{
// If the window is not created, open it anew:
@@ -1419,32 +1429,6 @@ void cMinecartWithChest::OpenNewWindow()
-void cMinecartWithChest::Destroyed()
-{
- if (GetWindow() != nullptr)
- {
- GetWindow()->OwnerDestroyed();
- }
- cItems Pickups;
- m_Contents.CopyToItems(Pickups);
-
-
- // Schedule the pickups creation for the next world tick
- // This avoids a deadlock when terminating the world
- // Note that the scheduled task may be run when this object is no longer valid, we need to store everything in the task's captured variables
- auto posX = GetPosX();
- auto posY = GetPosY() + 1;
- auto posZ = GetPosZ();
- GetWorld()->ScheduleTask(1, [Pickups, posX, posY, posZ](cWorld & World)
- {
- World.SpawnItemPickups(Pickups, posX, posY, posZ, 4);
- });
-}
-
-
-
-
-
////////////////////////////////////////////////////////////////////////////////
// cMinecartWithFurnace:
@@ -1459,6 +1443,15 @@ cMinecartWithFurnace::cMinecartWithFurnace(Vector3d a_Pos):
+void cMinecartWithFurnace::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ a_Drops.emplace_back(E_ITEM_FURNACE_MINECART);
+}
+
+
+
+
+
void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
{
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL)
@@ -1526,6 +1519,15 @@ cMinecartWithTNT::cMinecartWithTNT(Vector3d a_Pos):
+void cMinecartWithTNT::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ a_Drops.emplace_back(E_ITEM_MINECART_WITH_TNT);
+}
+
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// cMinecartWithHopper:
@@ -1536,3 +1538,12 @@ cMinecartWithHopper::cMinecartWithHopper(Vector3d a_Pos):
// TODO: Make it suck up blocks and travel further than any other cart and physics and put and take blocks
// AND AVARYTHING!!
+
+
+
+
+
+void cMinecartWithHopper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
+{
+ a_Drops.emplace_back(E_ITEM_MINECART_WITH_HOPPER);
+}
diff --git a/src/Entities/Minecart.h b/src/Entities/Minecart.h
index ad3b3d40d..73011b7b5 100644
--- a/src/Entities/Minecart.h
+++ b/src/Entities/Minecart.h
@@ -40,12 +40,12 @@ public:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
- virtual void Destroyed() override;
+ virtual void KilledBy(TakeDamageInfo & a_TDI) override;
+ virtual void OnRemoveFromWorld(cWorld & a_World) override;
int LastDamage(void) const { return m_LastDamage; }
ePayload GetPayload(void) const { return m_Payload; }
-
protected:
ePayload m_Payload;
@@ -99,7 +99,7 @@ protected:
-class cRideableMinecart :
+class cRideableMinecart final :
public cMinecart
{
using Super = cMinecart;
@@ -114,6 +114,7 @@ public:
int GetBlockHeight(void) const {return m_Height;}
// cEntity overrides:
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
protected:
@@ -127,7 +128,7 @@ protected:
-class cMinecartWithChest :
+class cMinecartWithChest final :
public cMinecart,
public cItemGrid::cListener,
public cEntityWindowOwner
@@ -154,7 +155,6 @@ protected:
cItemGrid m_Contents;
void OpenNewWindow(void);
- virtual void Destroyed() override;
// cItemGrid::cListener overrides:
virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum) override
@@ -173,6 +173,8 @@ protected:
}
// cEntity overrides:
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
+ virtual void OnRemoveFromWorld(cWorld & a_World) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
} ;
@@ -180,7 +182,7 @@ protected:
-class cMinecartWithFurnace :
+class cMinecartWithFurnace final :
public cMinecart
{
using Super = cMinecart;
@@ -192,6 +194,7 @@ public:
cMinecartWithFurnace(Vector3d a_Pos);
// cEntity overrides:
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
@@ -213,22 +216,27 @@ private:
-class cMinecartWithTNT :
+class cMinecartWithTNT final :
public cMinecart
{
using Super = cMinecart;
public:
+
CLASS_PROTODEF(cMinecartWithTNT)
cMinecartWithTNT(Vector3d a_Pos);
+
+private:
+
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
} ;
-class cMinecartWithHopper :
+class cMinecartWithHopper final :
public cMinecart
{
using Super = cMinecart;
@@ -238,4 +246,8 @@ public:
CLASS_PROTODEF(cMinecartWithHopper)
cMinecartWithHopper(Vector3d a_Pos);
+
+private:
+
+ virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
} ;
diff --git a/src/Entities/Pawn.cpp b/src/Entities/Pawn.cpp
index 9857fa29c..35efe05ce 100644
--- a/src/Entities/Pawn.cpp
+++ b/src/Entities/Pawn.cpp
@@ -28,25 +28,6 @@ cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height) :
-cPawn::~cPawn()
-{
- ASSERT(m_TargetingMe.size() == 0);
-}
-
-
-
-
-
-void cPawn::Destroyed()
-{
- StopEveryoneFromTargetingMe();
- Super::Destroyed();
-}
-
-
-
-
-
void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
std::vector<cEntityEffect *> EffectsToTick;
@@ -453,6 +434,16 @@ void cPawn::HandleFalling(void)
+void cPawn::OnRemoveFromWorld(cWorld & a_World)
+{
+ StopEveryoneFromTargetingMe();
+ Super::OnRemoveFromWorld(a_World);
+}
+
+
+
+
+
void cPawn::StopEveryoneFromTargetingMe()
{
std::vector<cMonster*>::iterator i = m_TargetingMe.begin();
diff --git a/src/Entities/Pawn.h b/src/Entities/Pawn.h
index f4b1cbbbf..1a9285b77 100644
--- a/src/Entities/Pawn.h
+++ b/src/Entities/Pawn.h
@@ -23,8 +23,6 @@ public:
CLASS_PROTODEF(cPawn)
cPawn(eEntityType a_EntityType, double a_Width, double a_Height);
- virtual ~cPawn() override;
- virtual void Destroyed() override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
@@ -33,6 +31,7 @@ public:
virtual bool IsInvisible() const override;
virtual void HandleAir(void) override;
virtual void HandleFalling(void);
+ virtual void OnRemoveFromWorld(cWorld & a_World) override;
/** Tells all pawns which are targeting us to stop targeting us. */
void StopEveryoneFromTargetingMe();
@@ -85,7 +84,3 @@ private:
/** A list of all monsters that are targeting this pawn. */
std::vector<cMonster*> m_TargetingMe;
} ; // tolua_export
-
-
-
-
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index fb0cdf271..391a5ce71 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -280,10 +280,9 @@ cPlayer::~cPlayer(void)
-void cPlayer::Destroyed()
+void cPlayer::OnRemoveFromWorld(cWorld & a_World)
{
CloseWindow(false);
- Super::Destroyed();
}
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index bdcacd608..1e7a17e4f 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -54,6 +54,8 @@ public:
virtual ~cPlayer() override;
+ virtual void OnRemoveFromWorld(cWorld & a_World) override;
+
virtual void SpawnOn(cClientHandle & a_Client) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
@@ -784,8 +786,6 @@ protected:
/** Sets the speed and sends it to the client, so that they are forced to move so. */
virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) override;
- virtual void Destroyed(void) override;
-
/** Filters out damage for creative mode / friendly fire */
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
diff --git a/src/Mobs/Horse.cpp b/src/Mobs/Horse.cpp
index e42241700..d3ba066cc 100644
--- a/src/Mobs/Horse.cpp
+++ b/src/Mobs/Horse.cpp
@@ -32,19 +32,6 @@ cHorse::cHorse(int Type, int Color, int Style, int TameTimes) :
-cHorse::~cHorse()
-{
- auto Window = GetWindow();
- if (Window != nullptr)
- {
- Window->OwnerDestroyed();
- }
-}
-
-
-
-
-
void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
Super::Tick(a_Dt, a_Chunk);
@@ -123,6 +110,21 @@ void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
+void cHorse::OnRemoveFromWorld(cWorld & a_World)
+{
+ const auto Window = GetWindow();
+ if (Window != nullptr)
+ {
+ Window->OwnerDestroyed();
+ }
+
+ Super::OnRemoveFromWorld(a_World);
+}
+
+
+
+
+
void cHorse::OnRightClicked(cPlayer & a_Player)
{
Super::OnRightClicked(a_Player);
diff --git a/src/Mobs/Horse.h b/src/Mobs/Horse.h
index f9c236ffc..4f35071c0 100644
--- a/src/Mobs/Horse.h
+++ b/src/Mobs/Horse.h
@@ -17,7 +17,6 @@ class cHorse:
public:
cHorse(int Type, int Color, int Style, int TameTimes);
- virtual ~cHorse() override;
CLASS_PROTODEF(cHorse)
@@ -25,6 +24,7 @@ public:
virtual void InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
+ virtual void OnRemoveFromWorld(cWorld & a_World) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
bool IsSaddled (void) const {return !m_Saddle.IsEmpty(); }
@@ -66,7 +66,3 @@ private:
cItem m_Armor;
} ;
-
-
-
-
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 048393e67..7e8e7eba3 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -135,17 +135,15 @@ cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const A
-cMonster::~cMonster()
+void cMonster::OnRemoveFromWorld(cWorld & a_World)
{
- ASSERT(GetTarget() == nullptr);
-}
-
-
-
+ SetTarget(nullptr); // Tell them we're no longer targeting them.
+ if (m_LovePartner != nullptr)
+ {
+ m_LovePartner->ResetLoveMode();
+ }
-void cMonster::OnRemoveFromWorld(cWorld & a_World)
-{
if (IsLeashed())
{
cEntity * LeashedTo = GetLeashedTo();
@@ -165,20 +163,6 @@ void cMonster::OnRemoveFromWorld(cWorld & a_World)
-void cMonster::Destroyed()
-{
- SetTarget(nullptr); // Tell them we're no longer targeting them.
- if (m_LovePartner != nullptr)
- {
- m_LovePartner->ResetLoveMode();
- }
- Super::Destroyed();
-}
-
-
-
-
-
void cMonster::SpawnOn(cClientHandle & a_Client)
{
a_Client.SendSpawnMob(*this);
@@ -762,22 +746,14 @@ void cMonster::CheckEventSeePlayer(cChunk & a_Chunk)
const auto MyHeadPosition = GetPosition().addedY(GetHeight());
// Enumerate all players within sight:
- m_World->ForEachEntityInBox({ GetPosition(), m_SightDistance * 2.0 }, [this, &TargetPlayer, &ClosestDistance, MyHeadPosition](cEntity & a_Entity)
+ m_World->ForEachPlayer([this, &TargetPlayer, &ClosestDistance, MyHeadPosition](cPlayer & a_Player)
{
- if (!a_Entity.IsPlayer())
- {
- // Continue iteration:
- return false;
- }
-
- const auto Player = static_cast<cPlayer *>(&a_Entity);
-
- if (!Player->CanMobsTarget())
+ if (!a_Player.CanMobsTarget())
{
return false;
}
- const auto TargetHeadPosition = a_Entity.GetPosition().addedY(a_Entity.GetHeight());
+ const auto TargetHeadPosition = a_Player.GetPosition().addedY(a_Player.GetHeight());
const auto TargetDistance = (TargetHeadPosition - MyHeadPosition).SqrLength();
// TODO: Currently all mobs see through lava, but only Nether-native mobs should be able to.
@@ -786,7 +762,7 @@ void cMonster::CheckEventSeePlayer(cChunk & a_Chunk)
cLineBlockTracer::LineOfSightTrace(*GetWorld(), MyHeadPosition, TargetHeadPosition, cLineBlockTracer::losAirWaterLava)
)
{
- TargetPlayer = Player;
+ TargetPlayer = &a_Player;
ClosestDistance = TargetDistance;
}
diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h
index aeb8a3bf9..eb8905ae3 100644
--- a/src/Mobs/Monster.h
+++ b/src/Mobs/Monster.h
@@ -48,14 +48,10 @@ public:
*/
cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, const AString & a_SoundAmbient, double a_Width, double a_Height);
- virtual ~cMonster() override;
+ CLASS_PROTODEF(cMonster)
virtual void OnRemoveFromWorld(cWorld & a_World) override;
- virtual void Destroyed() override;
-
- CLASS_PROTODEF(cMonster)
-
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp
index e9c4070db..90d88024d 100644
--- a/src/Mobs/PassiveMonster.cpp
+++ b/src/Mobs/PassiveMonster.cpp
@@ -37,15 +37,6 @@ bool cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
-void cPassiveMonster::Destroyed()
-{
- Super::Destroyed();
-}
-
-
-
-
-
void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
Super::Tick(a_Dt, a_Chunk);
diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h
index 15900a95d..400cc3885 100644
--- a/src/Mobs/PassiveMonster.h
+++ b/src/Mobs/PassiveMonster.h
@@ -30,10 +30,4 @@ public:
/** When hit by someone, run away */
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
-
- virtual void Destroyed(void) override;
};
-
-
-
-
diff --git a/src/UI/Window.cpp b/src/UI/Window.cpp
index 07b84916d..23661e150 100644
--- a/src/UI/Window.cpp
+++ b/src/UI/Window.cpp
@@ -418,7 +418,6 @@ void cWindow::SetProperty(size_t a_Property, short a_Value)
void cWindow::OwnerDestroyed()
{
- m_Owner = nullptr;
// Close window for each player. Note that the last one needs special handling
while (m_OpenedBy.size() > 1)
{