Refactor minecart collision detection code. (#4712)
* Refactor minecart collision detection code. - Use new GetBoundingBox function. - Handle descending and ascending rails. - Snap to descending rails. * Add message for UNREACHABLE
This commit is contained in:
parent
24833f7386
commit
4e4ef9052e
@ -158,6 +158,16 @@ void cMinecart::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
// Push cart upwards
|
// Push cart upwards
|
||||||
AddPosY(1);
|
AddPosY(1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// When a minecart gets to a descending rail, it should go down.
|
||||||
|
chunk->GetBlockTypeMeta(relPos.addedY(-1), InsideType, InsideMeta);
|
||||||
|
if (IsBlockRail(InsideType))
|
||||||
|
{
|
||||||
|
// Push cart downwards
|
||||||
|
AddPosY(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasDetectorRail = false;
|
bool WasDetectorRail = false;
|
||||||
@ -231,7 +241,8 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
SetSpeedX(0); // Correct diagonal movement from curved rails
|
SetSpeedX(0); // Correct diagonal movement from curved rails
|
||||||
|
|
||||||
// Execute both the entity and block collision checks
|
// Execute both the entity and block collision checks
|
||||||
bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta);
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
if (EntCol || BlckCol)
|
if (EntCol || BlckCol)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -250,7 +261,8 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
ApplyAcceleration({ 0.0, 0.0, -1.0 }, -0.1);
|
ApplyAcceleration({ 0.0, 0.0, -1.0 }, -0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_XM_XP: // EASTWEST
|
case E_META_RAIL_XM_XP: // EASTWEST
|
||||||
{
|
{
|
||||||
@ -259,7 +271,8 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
SetSpeedY(NO_SPEED);
|
SetSpeedY(NO_SPEED);
|
||||||
SetSpeedZ(NO_SPEED);
|
SetSpeedZ(NO_SPEED);
|
||||||
|
|
||||||
bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta);
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
if (EntCol || BlckCol)
|
if (EntCol || BlckCol)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -276,13 +289,21 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
ApplyAcceleration({ -1.0, 0.0, 0.0 }, -0.1);
|
ApplyAcceleration({ -1.0, 0.0, 0.0 }, -0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
|
case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
|
||||||
{
|
{
|
||||||
SetYaw(270);
|
SetYaw(270);
|
||||||
SetSpeedX(0);
|
SetSpeedX(0);
|
||||||
|
|
||||||
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetSpeedZ() >= 0)
|
if (GetSpeedZ() >= 0)
|
||||||
{
|
{
|
||||||
// SpeedZ POSITIVE, going SOUTH
|
// SpeedZ POSITIVE, going SOUTH
|
||||||
@ -295,13 +316,21 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
AddSpeedZ(1); // Slow down
|
AddSpeedZ(1); // Slow down
|
||||||
SetSpeedY(-GetSpeedZ()); // Upward movement is positive (0 minus negative number is positive number)
|
SetSpeedY(-GetSpeedZ()); // Upward movement is positive (0 minus negative number is positive number)
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
|
case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
|
||||||
{
|
{
|
||||||
SetYaw(270);
|
SetYaw(270);
|
||||||
SetSpeedX(0);
|
SetSpeedX(0);
|
||||||
|
|
||||||
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetSpeedZ() > 0)
|
if (GetSpeedZ() > 0)
|
||||||
{
|
{
|
||||||
// SpeedZ POSITIVE, going SOUTH
|
// SpeedZ POSITIVE, going SOUTH
|
||||||
@ -314,13 +343,21 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
AddSpeedZ(-0.5); // Speed up
|
AddSpeedZ(-0.5); // Speed up
|
||||||
SetSpeedY(GetSpeedZ()); // Downward movement negative
|
SetSpeedY(GetSpeedZ()); // Downward movement negative
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_ASCEND_XM: // ASCEND EAST
|
case E_META_RAIL_ASCEND_XM: // ASCEND EAST
|
||||||
{
|
{
|
||||||
SetYaw(180);
|
SetYaw(180);
|
||||||
SetSpeedZ(NO_SPEED);
|
SetSpeedZ(NO_SPEED);
|
||||||
|
|
||||||
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetSpeedX() >= NO_SPEED)
|
if (GetSpeedX() >= NO_SPEED)
|
||||||
{
|
{
|
||||||
AddSpeedX(0.5);
|
AddSpeedX(0.5);
|
||||||
@ -331,13 +368,21 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
AddSpeedX(1);
|
AddSpeedX(1);
|
||||||
SetSpeedY(-GetSpeedX());
|
SetSpeedY(-GetSpeedX());
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_ASCEND_XP: // ASCEND WEST
|
case E_META_RAIL_ASCEND_XP: // ASCEND WEST
|
||||||
{
|
{
|
||||||
SetYaw(180);
|
SetYaw(180);
|
||||||
SetSpeedZ(0);
|
SetSpeedZ(0);
|
||||||
|
|
||||||
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetSpeedX() > 0)
|
if (GetSpeedX() > 0)
|
||||||
{
|
{
|
||||||
AddSpeedX(-1);
|
AddSpeedX(-1);
|
||||||
@ -348,7 +393,8 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
AddSpeedX(-0.5);
|
AddSpeedX(-0.5);
|
||||||
SetSpeedY(GetSpeedX());
|
SetSpeedY(GetSpeedX());
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_CURVED_ZM_XM: // Ends pointing NORTH and WEST
|
case E_META_RAIL_CURVED_ZM_XM: // Ends pointing NORTH and WEST
|
||||||
{
|
{
|
||||||
@ -356,12 +402,16 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart
|
SetPosY(floor(GetPosY()) + 0.55); // Levitate dat cart
|
||||||
SetSpeedY(0);
|
SetSpeedY(0);
|
||||||
|
|
||||||
TestBlockCollision(a_RailMeta);
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
TestEntityCollision(a_RailMeta);
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// SnapToRail handles turning
|
// SnapToRail handles turning
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST
|
case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST
|
||||||
{
|
{
|
||||||
@ -369,10 +419,14 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
SetPosY(floor(GetPosY()) + 0.55);
|
SetPosY(floor(GetPosY()) + 0.55);
|
||||||
SetSpeedY(0);
|
SetSpeedY(0);
|
||||||
|
|
||||||
TestBlockCollision(a_RailMeta);
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
TestEntityCollision(a_RailMeta);
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST
|
case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST
|
||||||
{
|
{
|
||||||
@ -380,10 +434,14 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
SetPosY(floor(GetPosY()) + 0.55);
|
SetPosY(floor(GetPosY()) + 0.55);
|
||||||
SetSpeedY(0);
|
SetSpeedY(0);
|
||||||
|
|
||||||
TestBlockCollision(a_RailMeta);
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
TestEntityCollision(a_RailMeta);
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST
|
case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST
|
||||||
{
|
{
|
||||||
@ -391,17 +449,17 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::millisecon
|
|||||||
SetPosY(floor(GetPosY()) + 0.55);
|
SetPosY(floor(GetPosY()) + 0.55);
|
||||||
SetSpeedY(0);
|
SetSpeedY(0);
|
||||||
|
|
||||||
TestBlockCollision(a_RailMeta);
|
auto BlckCol = TestBlockCollision(a_RailMeta);
|
||||||
TestEntityCollision(a_RailMeta);
|
auto EntCol = TestEntityCollision(a_RailMeta);
|
||||||
|
if (EntCol || BlckCol)
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
{
|
||||||
ASSERT(!"Unhandled rail meta!"); // Dun dun DUN!
|
return;
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UNREACHABLE("Unsupported rail meta type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -724,14 +782,39 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cMinecart::IsSolidBlockAtPosition(Vector3i a_Pos)
|
||||||
|
{
|
||||||
|
BLOCKTYPE Block = m_World->GetBlock(a_Pos);
|
||||||
|
return !IsBlockRail(Block) && cBlockInfo::IsSolid(Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cMinecart::IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset)
|
bool cMinecart::IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset)
|
||||||
{
|
{
|
||||||
BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT + a_XOffset, POSY_TOINT + a_YOffset, POSZ_TOINT + a_ZOffset);
|
return IsSolidBlockAtPosition({POSX_TOINT + a_XOffset, POSY_TOINT + a_YOffset, POSZ_TOINT + a_ZOffset});
|
||||||
if (IsBlockRail(Block) || !cBlockInfo::IsSolid(Block))
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cMinecart::IsBlockCollisionAtOffset(Vector3i a_Offset)
|
||||||
|
{
|
||||||
|
auto BlockPosition = GetPosition().Floor() + a_Offset;
|
||||||
|
if (!IsSolidBlockAtPosition(BlockPosition))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
auto bbBlock = cBoundingBox(
|
||||||
|
static_cast<Vector3d>(BlockPosition),
|
||||||
|
static_cast<Vector3d>(BlockPosition + Vector3i(1, 1, 1))
|
||||||
|
);
|
||||||
|
|
||||||
|
return GetBoundingBox().DoesIntersect(bbBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -740,135 +823,218 @@ bool cMinecart::IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset
|
|||||||
|
|
||||||
bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
|
bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
|
||||||
{
|
{
|
||||||
|
auto SpeedX = GetSpeedX();
|
||||||
|
auto SpeedZ = GetSpeedZ();
|
||||||
|
|
||||||
|
// Don't do anything if minecarts aren't moving.
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wfloat-equal"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((SpeedX == 0) && (SpeedZ == 0))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto StopTheCart = true;
|
||||||
|
auto StopOffset = Vector3d();
|
||||||
|
|
||||||
switch (a_RailMeta)
|
switch (a_RailMeta)
|
||||||
{
|
{
|
||||||
case E_META_RAIL_ZM_ZP:
|
case E_META_RAIL_ZM_ZP:
|
||||||
{
|
{
|
||||||
if (GetSpeedZ() > 0)
|
if (SpeedZ > 0)
|
||||||
{
|
{
|
||||||
if (IsSolidBlockAtOffset(0, 0, 1))
|
StopOffset = Vector3d(0, 0, 0.4);
|
||||||
{
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, 1});
|
||||||
// We could try to detect a block in front based purely on coordinates, but xoft made a bounding box system - why not use? :P
|
|
||||||
cBoundingBox bbBlock(Vector3d(POSX_TOINT, POSY_TOINT, static_cast<int>(ceil(GetPosZ()))), 0.5, 1);
|
|
||||||
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
|
|
||||||
|
|
||||||
if (bbBlock.DoesIntersect(bbMinecart))
|
|
||||||
{
|
|
||||||
SetSpeed(0, 0, 0);
|
|
||||||
SetPosZ(floor(GetPosZ()) + 0.4);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
else // SpeedZ < 0
|
||||||
}
|
|
||||||
else if (GetSpeedZ() < 0)
|
|
||||||
{
|
{
|
||||||
if (IsSolidBlockAtOffset(0, 0, -1))
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, -1});
|
||||||
{
|
StopOffset = Vector3d(0, 0, 0.65);
|
||||||
cBoundingBox bbBlock(Vector3d(POSX_TOINT, POSY_TOINT, POSZ_TOINT - 1), 0.5, 1);
|
|
||||||
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ() - 1), GetWidth() / 2, GetHeight());
|
|
||||||
|
|
||||||
if (bbBlock.DoesIntersect(bbMinecart))
|
|
||||||
{
|
|
||||||
SetSpeed(0, 0, 0);
|
|
||||||
SetPosZ(floor(GetPosZ()) + 0.65);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_XM_XP:
|
case E_META_RAIL_XM_XP:
|
||||||
{
|
{
|
||||||
if (GetSpeedX() > 0)
|
if (SpeedX > 0)
|
||||||
{
|
{
|
||||||
if (IsSolidBlockAtOffset(1, 0, 0))
|
StopTheCart = IsBlockCollisionAtOffset({1, 0, 0});
|
||||||
{
|
StopOffset = Vector3d(0.4, 0, 0);
|
||||||
cBoundingBox bbBlock(Vector3d(static_cast<int>(ceil(GetPosX())), POSY_TOINT, POSZ_TOINT), 0.5, 1);
|
|
||||||
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
|
|
||||||
|
|
||||||
if (bbBlock.DoesIntersect(bbMinecart))
|
|
||||||
{
|
|
||||||
SetSpeed(0, 0, 0);
|
|
||||||
SetPosX(floor(GetPosX()) + 0.4);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
else // SpeedX < 0
|
||||||
}
|
|
||||||
else if (GetSpeedX() < 0)
|
|
||||||
{
|
{
|
||||||
if (IsSolidBlockAtOffset(-1, 0, 0))
|
StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0});
|
||||||
{
|
StopOffset = Vector3d(0.65, 0, 0);
|
||||||
cBoundingBox bbBlock(Vector3d(POSX_TOINT - 1, POSY_TOINT, POSZ_TOINT), 0.5, 1);
|
|
||||||
cBoundingBox bbMinecart(Vector3d(GetPosX() - 1, floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
|
|
||||||
|
|
||||||
if (bbBlock.DoesIntersect(bbMinecart))
|
|
||||||
{
|
|
||||||
SetSpeed(0, 0, 0);
|
|
||||||
SetPosX(floor(GetPosX()) + 0.65);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_META_RAIL_CURVED_ZM_XM:
|
|
||||||
{
|
|
||||||
bool IsBlockXM = IsSolidBlockAtOffset(-1, 0, 0);
|
|
||||||
bool IsBlockZM = IsSolidBlockAtOffset(0, 0, -1);
|
|
||||||
|
|
||||||
if (((GetSpeedZ() < 0) && IsBlockZM) || ((GetSpeedX() < 0) && IsBlockXM))
|
// Ascending rails check for one block on the way up, two on the way down.
|
||||||
|
case E_META_RAIL_ASCEND_XM:
|
||||||
{
|
{
|
||||||
SetSpeed(0, 0, 0);
|
StopOffset = Vector3d(0.5, 0, 0);
|
||||||
SetPosition(POSX_TOINT + 0.5, GetPosY(), POSZ_TOINT + 0.5);
|
|
||||||
return true;
|
if (SpeedX < 0)
|
||||||
}
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({-1, 1, 0});
|
||||||
break;
|
}
|
||||||
}
|
else // SpeedX > 0
|
||||||
case E_META_RAIL_CURVED_ZM_XP:
|
{
|
||||||
{
|
StopTheCart = IsBlockCollisionAtOffset({1, 0, 0}) || IsBlockCollisionAtOffset({1, 1, 0});
|
||||||
bool IsBlockXP = IsSolidBlockAtOffset(1, 0, 0);
|
}
|
||||||
bool IsBlockZM = IsSolidBlockAtOffset(0, 0, -1);
|
break;
|
||||||
|
}
|
||||||
if (((GetSpeedZ() < 0) && IsBlockZM) || ((GetSpeedX() > 0) && IsBlockXP))
|
case E_META_RAIL_ASCEND_XP:
|
||||||
{
|
{
|
||||||
SetSpeed(0, 0, 0);
|
StopOffset = Vector3d(0.5, 0, 0);
|
||||||
SetPosition(POSX_TOINT + 0.5, GetPosY(), POSZ_TOINT + 0.5);
|
|
||||||
return true;
|
if (SpeedX > 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({1, 1, 0});
|
||||||
|
}
|
||||||
|
else // SpeedX < 0
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0}) || IsBlockCollisionAtOffset({-1, 1, 0});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_META_RAIL_ASCEND_ZM:
|
||||||
|
{
|
||||||
|
StopOffset = Vector3d(0, 0, 0.5);
|
||||||
|
|
||||||
|
if (SpeedZ < 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({0, 1, -1});
|
||||||
|
}
|
||||||
|
else // SpeedZ > 0
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, 1}) || IsBlockCollisionAtOffset({0, 1, 1});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_META_RAIL_ASCEND_ZP:
|
||||||
|
{
|
||||||
|
StopOffset = Vector3d(0, 0, 0.5);
|
||||||
|
|
||||||
|
if (SpeedZ > 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({0, 1, 1});
|
||||||
|
}
|
||||||
|
else // SpeedZ < 0
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, -1}) || IsBlockCollisionAtOffset({0, 1, -1});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Curved rails allow movement across both the x and z axes. But when the cart is
|
||||||
|
// moving towards one of the rail endpoints, it will always have velocity towards
|
||||||
|
// the direction of that endpoint in the same axis.
|
||||||
|
case E_META_RAIL_CURVED_ZP_XP:
|
||||||
|
{
|
||||||
|
StopOffset = Vector3d(0.5, 0, 0.5);
|
||||||
|
|
||||||
|
if (SpeedZ > 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, 1});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (SpeedX > 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({1, 0, 0});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
UNREACHABLE("Invalid minecart movement");
|
||||||
}
|
}
|
||||||
case E_META_RAIL_CURVED_ZP_XM:
|
case E_META_RAIL_CURVED_ZP_XM:
|
||||||
{
|
{
|
||||||
bool IsBlockXM = IsSolidBlockAtOffset(-1, 0, 0);
|
StopOffset = Vector3d(0.5, 0, 0.5);
|
||||||
bool IsBlockZP = IsSolidBlockAtOffset(0, 0, +1);
|
|
||||||
|
|
||||||
if (((GetSpeedZ() > 0) && IsBlockZP) || ((GetSpeedX() < 0) && IsBlockXM))
|
if (SpeedZ > 0)
|
||||||
{
|
{
|
||||||
SetSpeed(0, 0, 0);
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, 1});
|
||||||
SetPosition(POSX_TOINT + 0.5, GetPosY(), POSZ_TOINT + 0.5);
|
break;
|
||||||
return true;
|
}
|
||||||
|
if (SpeedX < 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
UNREACHABLE("Invalid minecart movement");
|
||||||
}
|
}
|
||||||
case E_META_RAIL_CURVED_ZP_XP:
|
case E_META_RAIL_CURVED_ZM_XM:
|
||||||
{
|
{
|
||||||
bool IsBlockXP = IsSolidBlockAtOffset(1, 0, 0);
|
StopOffset = Vector3d(0.5, 0, 0.5);
|
||||||
bool IsBlockZP = IsSolidBlockAtOffset(0, 0, 1);
|
|
||||||
|
|
||||||
if (((GetSpeedZ() > 0) && IsBlockZP) || ((GetSpeedX() > 0) && IsBlockXP))
|
if (SpeedZ < 0)
|
||||||
{
|
{
|
||||||
SetSpeed(0, 0, 0);
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, -1});
|
||||||
SetPosition(POSX_TOINT + 0.5, GetPosY(), POSZ_TOINT + 0.5);
|
break;
|
||||||
return true;
|
}
|
||||||
|
if (SpeedX < 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({-1, 0, 0});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
UNREACHABLE("Invalid minecart movement");
|
||||||
}
|
}
|
||||||
default: break;
|
case E_META_RAIL_CURVED_ZM_XP:
|
||||||
|
{
|
||||||
|
StopOffset = Vector3d(0.5, 0, 0.5);
|
||||||
|
|
||||||
|
if (SpeedZ < 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({0, 0, -1});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
if (SpeedX > 0)
|
||||||
|
{
|
||||||
|
StopTheCart = IsBlockCollisionAtOffset({1, 0, 0});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
UNREACHABLE("Invalid minecart movement");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StopTheCart)
|
||||||
|
{
|
||||||
|
SetSpeed(0, 0, 0);
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wfloat-equal"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (StopOffset.x != 0)
|
||||||
|
{
|
||||||
|
SetPosX(POSX_TOINT + StopOffset.x);
|
||||||
|
}
|
||||||
|
if (StopOffset.z != 0)
|
||||||
|
{
|
||||||
|
SetPosZ(POSZ_TOINT + StopOffset.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,8 +83,13 @@ protected:
|
|||||||
void SnapToRail(NIBBLETYPE a_RailMeta);
|
void SnapToRail(NIBBLETYPE a_RailMeta);
|
||||||
/** Tests if a solid block is in front of a cart, and stops the cart (and returns true) if so; returns false if no obstruction */
|
/** Tests if a solid block is in front of a cart, and stops the cart (and returns true) if so; returns false if no obstruction */
|
||||||
bool TestBlockCollision(NIBBLETYPE a_RailMeta);
|
bool TestBlockCollision(NIBBLETYPE a_RailMeta);
|
||||||
|
/** Tests if there is a block at the specified position which is impassable to minecarts */
|
||||||
|
bool IsSolidBlockAtPosition(Vector3i a_Offset);
|
||||||
/** Tests if a solid block is at a specific offset of the minecart position */
|
/** Tests if a solid block is at a specific offset of the minecart position */
|
||||||
bool IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset);
|
bool IsSolidBlockAtOffset(int a_XOffset, int a_YOffset, int a_ZOffset);
|
||||||
|
|
||||||
|
bool IsBlockCollisionAtOffset(Vector3i a_Offset);
|
||||||
|
|
||||||
/** Tests if this mincecart's bounding box is intersecting another entity's bounding box (collision) and pushes mincecart away if necessary */
|
/** Tests if this mincecart's bounding box is intersecting another entity's bounding box (collision) and pushes mincecart away if necessary */
|
||||||
bool TestEntityCollision(NIBBLETYPE a_RailMeta);
|
bool TestEntityCollision(NIBBLETYPE a_RailMeta);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user