summaryrefslogtreecommitdiffstats
path: root/source/Entities/Minecart.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Entities/Minecart.cpp')
-rw-r--r--source/Entities/Minecart.cpp116
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);
+ }
}