diff options
Diffstat (limited to 'source/Entities/Minecart.cpp')
-rw-r--r-- | source/Entities/Minecart.cpp | 116 |
1 files changed, 89 insertions, 27 deletions
diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp index 0c0b7b58a..f75e23d8b 100644 --- a/source/Entities/Minecart.cpp +++ b/source/Entities/Minecart.cpp @@ -8,6 +8,7 @@ #include "Minecart.h" #include "../World.h" #include "../ClientHandle.h" +#include "../Chunk.h" #include "Player.h" @@ -16,7 +17,8 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) : super(etMinecart, a_X, a_Y, a_Z, 0.98, 0.7), - m_Payload(a_Payload) + m_Payload(a_Payload), + m_LastDamage(0) { SetMass(20.f); SetMaxHealth(6); @@ -51,30 +53,43 @@ void cMinecart::SpawnOn(cClientHandle & a_ClientHandle) void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) { - if ((GetPosY() > 0) && (GetPosY() < cChunkDef::Height)) + int PosY = (int)floor(GetPosY()); + if ((PosY <= 0) || (PosY >= cChunkDef::Height)) { - BLOCKTYPE BelowType = GetWorld()->GetBlock(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ())); - - if ( - (BelowType == E_BLOCK_RAIL) || - (BelowType == E_BLOCK_POWERED_RAIL) || - (BelowType == E_BLOCK_DETECTOR_RAIL) || - (BelowType == E_BLOCK_ACTIVATOR_RAIL) - ) + // Outside the world, just process normal falling physics + super::HandlePhysics(a_Dt, a_Chunk); + BroadcastMovementUpdate(); + return; + } + + int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width; + cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ); + if (Chunk == NULL) + { + // Inside an unloaded chunk, bail out all processing + return; + } + BLOCKTYPE BelowType = Chunk->GetBlock(RelPosX, PosY - 1, RelPosZ); + BLOCKTYPE InsideType = Chunk->GetBlock(RelPosX, PosY, RelPosZ); + + if (IsBlockRail(BelowType)) + { + HandleRailPhysics(a_Dt, *Chunk); + } + else + { + if (IsBlockRail(InsideType)) { - HandleRailPhysics(a_Dt, a_Chunk); + SetPosY(PosY + 1); + HandleRailPhysics(a_Dt, *Chunk); } else { - super::HandlePhysics(a_Dt, a_Chunk); + super::HandlePhysics(a_Dt, *Chunk); BroadcastMovementUpdate(); } } - else - { - super::HandlePhysics(a_Dt, a_Chunk); - BroadcastMovementUpdate(); - } } @@ -83,6 +98,7 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) static const double MAX_SPEED = 8; static const double MAX_SPEED_NEGATIVE = (0 - MAX_SPEED); + void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) { @@ -94,7 +110,9 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) */ // Get block meta below the cart - NIBBLETYPE BelowMeta = GetWorld()->GetBlockMeta(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ())); + int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width; + NIBBLETYPE BelowMeta = a_Chunk.GetMeta(RelPosX, (int)floor(GetPosY() - 1), RelPosZ); double SpeedX = GetSpeedX(), SpeedY = GetSpeedY(), SpeedZ = GetSpeedZ(); // Get current speed switch (BelowMeta) @@ -105,9 +123,6 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) SpeedY = 0; // Don't move vertically as on ground SpeedX = 0; // Correct diagonal movement from curved rails - // Set Y as current Y rounded up to bypass friction - SetPosY(floor(GetPosY())); - if (SpeedZ != 0) // Don't do anything if cart is stationary { if (SpeedZ > 0) @@ -130,8 +145,6 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) SpeedY = 0; SpeedZ = 0; - SetPosY(floor(GetPosY())); - if (SpeedX != 0) { if (SpeedX > 0) @@ -345,11 +358,51 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk) void cMinecart::DoTakeDamage(TakeDamageInfo & TDI) { + m_LastDamage = TDI.FinalDamage; super::DoTakeDamage(TDI); - if (GetHealth() == 0) + m_World->BroadcastEntityMetadata(*this); + + if (GetHealth() <= 0) { Destroy(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; + } + default: + { + ASSERT(!"Unhandled minecart type when spawning pickup!"); + return; + } + } + + m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ()); } } @@ -435,7 +488,8 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player) // cMinecartWithFurnace: cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) : - super(mpFurnace, a_X, a_Y, a_Z) + super(mpFurnace, a_X, a_Y, a_Z), + m_IsFueled(false) { } @@ -445,8 +499,16 @@ cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) : void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player) { - // Try to power the furnace with whatever the player is holding - // TODO + if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL) + { + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + + m_IsFueled = true; + m_World->BroadcastEntityMetadata(*this); + } } |