diff --git a/CONTRIBUTORS b/CONTRIBUTORS index d0f123003..175218c50 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -29,6 +29,7 @@ Howaner ion232 (Arran Ireland) jan64 jasperarmstrong +jclever77 (Jon Clever) kevinr (Kevin Riggle) keyboard KingCol13 diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp index 1016773e9..cd66c523b 100644 --- a/src/Entities/Boat.cpp +++ b/src/Entities/Boat.cpp @@ -14,6 +14,36 @@ +class cBoatCollisionCallback +{ +public: + cBoatCollisionCallback(cBoat * a_Boat, cEntity * a_Attachee) : + m_Boat(a_Boat), m_Attachee(a_Attachee) + { + } + + bool operator()(cEntity & a_Entity) + { + // Checks if boat is empty and if given entity is a mob + if ((m_Attachee == nullptr) && (a_Entity.IsMob())) + { + // if so attach and return true + a_Entity.AttachTo(m_Boat); + return true; + } + + return false; + } + +protected: + cBoat * m_Boat; + cEntity * m_Attachee; +}; + + + + + cBoat::cBoat(Vector3d a_Pos, eMaterial a_Material) : Super(etBoat, a_Pos, 1.375f, 0.5625f), m_LastDamage(0), m_ForwardDirection(0), @@ -311,3 +341,20 @@ cItem cBoat::MaterialToItem(eMaterial a_Material) + +void cBoat::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +{ + /** Special version of cEntity::HandlePhysics(...) function for boats, checks if mobs + colliding with the boat can be attached and does if that's the case, then returns to + normal physics calcualtions */ + + // Calculate boat's bounding box, run collision callback on all entities in said box + cBoatCollisionCallback BoatCollisionCallback(this, m_Attachee); + Vector3d BoatPosition = GetPosition(); + cBoundingBox bbBoat( + Vector3d(BoatPosition.x, floor(BoatPosition.y), BoatPosition.z), GetWidth() / 2, GetHeight()); + m_World->ForEachEntityInBox(bbBoat, BoatCollisionCallback); + + // Return to calculating physics normally + Super::HandlePhysics(a_Dt, a_Chunk); +} diff --git a/src/Entities/Boat.h b/src/Entities/Boat.h index 4a583a26c..455e740e2 100644 --- a/src/Entities/Boat.h +++ b/src/Entities/Boat.h @@ -48,6 +48,7 @@ public: virtual bool DoTakeDamage(TakeDamageInfo & TDI) override; virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override; + virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; int GetLastDamage(void) const { return m_LastDamage; } int GetForwardDirection(void) const { return m_ForwardDirection; } diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index 1f454c857..123965916 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -21,6 +21,35 @@ +class cMinecartAttachCallback +{ +public: + cMinecartAttachCallback(cMinecart * a_Minecart, cEntity * a_Attachee) : + m_Minecart(a_Minecart), m_Attachee(a_Attachee) + { + } + + bool operator () (cEntity & a_Entity) + { + // Check if minecart is empty and if given entity is a mob + if ((m_Attachee == nullptr) && (a_Entity.IsMob())) + { + // if so, attach to minecart and return true + a_Entity.AttachTo(m_Minecart); + return true; + } + return false; + } + +protected: + cMinecart * m_Minecart; + cEntity * m_Attachee; +}; + + + + + class cMinecartCollisionCallback { public: @@ -1054,6 +1083,12 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) return false; } + // Collision was true, create bounding box for minecart, call attach callback for all entities within that box + cMinecartAttachCallback MinecartAttachCallback(this, m_Attachee); + Vector3d MinecartPosition = GetPosition(); + cBoundingBox bbMinecart(Vector3d(MinecartPosition.x, floor(MinecartPosition.y), MinecartPosition.z), GetWidth() / 2, GetHeight()); + m_World->ForEachEntityInBox(bbMinecart, MinecartAttachCallback); + switch (a_RailMeta) { case E_META_RAIL_ZM_ZP: