2013-07-29 07:13:03 -04:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum ENUM_PURE
|
|
|
|
{
|
|
|
|
E_PURE_UPDOWN = 0,
|
|
|
|
E_PURE_DOWN = 1,
|
|
|
|
E_PURE_NONE = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cBlockRailHandler :
|
2019-10-16 04:06:34 -04:00
|
|
|
public cClearMetaOnDrop<cBlockHandler>
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
using super = cClearMetaOnDrop<cBlockHandler>;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
public:
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
cBlockRailHandler(BLOCKTYPE a_BlockType):
|
|
|
|
super(a_BlockType)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
virtual bool GetPlacementBlockTypeMeta(
|
2017-07-31 16:17:52 -04:00
|
|
|
cChunkInterface & a_ChunkInterface, cPlayer & a_Player,
|
2014-07-17 16:50:58 -04:00
|
|
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
2013-07-29 07:13:03 -04:00
|
|
|
int a_CursorX, int a_CursorY, int a_CursorZ,
|
|
|
|
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
|
|
|
) override
|
|
|
|
{
|
|
|
|
a_BlockType = m_BlockType;
|
2017-09-12 16:47:09 -04:00
|
|
|
Vector3i Pos{ a_BlockX, a_BlockY, a_BlockZ };
|
2017-11-20 06:13:11 -05:00
|
|
|
a_BlockMeta = FindMeta(a_ChunkInterface, Pos);
|
2017-09-12 16:47:09 -04:00
|
|
|
return a_Player.GetWorld()->DoWithChunkAt(Pos,
|
|
|
|
[this, Pos, &a_ChunkInterface](cChunk & a_Chunk)
|
|
|
|
{
|
|
|
|
auto RelPos = cChunkDef::AbsoluteToRelative(Pos);
|
|
|
|
return CanBeAt(a_ChunkInterface, RelPos.x, RelPos.y, RelPos.z, a_Chunk);
|
|
|
|
}
|
|
|
|
);
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void OnPlaced(
|
|
|
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
|
|
|
Vector3i a_BlockPos,
|
|
|
|
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
|
|
|
|
) override
|
2013-12-25 09:12:48 -05:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_BlockType, a_BlockMeta);
|
|
|
|
|
|
|
|
// Alert diagonal rails:
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE);
|
2013-12-25 09:12:48 -05:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void OnBroken(
|
|
|
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
|
|
|
|
Vector3i a_BlockPos,
|
|
|
|
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
|
|
|
|
) override
|
2013-12-25 09:12:48 -05:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta);
|
|
|
|
|
|
|
|
// Alert diagonal rails:
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE);
|
|
|
|
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE);
|
2013-12-25 09:12:48 -05:00
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) override
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
auto meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
|
|
|
|
auto newMeta = FindMeta(a_ChunkInterface, a_BlockPos);
|
|
|
|
if (IsUnstable(a_ChunkInterface, a_BlockPos) && (meta != newMeta))
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
a_ChunkInterface.FastSetBlock(a_BlockPos, m_BlockType, (m_BlockType == E_BLOCK_RAIL) ? newMeta : newMeta | (meta & 0x08));
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-01 08:06:32 -05:00
|
|
|
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (a_RelY <= 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2014-10-24 19:22:31 -04:00
|
|
|
if (!cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)))
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
|
|
|
switch (Meta)
|
|
|
|
{
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_ASCEND_XP:
|
|
|
|
case E_META_RAIL_ASCEND_XM:
|
|
|
|
case E_META_RAIL_ASCEND_ZM:
|
|
|
|
case E_META_RAIL_ASCEND_ZP:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
// Mapping between the meta and the neighbors that need checking
|
2013-09-03 07:33:54 -04:00
|
|
|
Meta -= E_META_RAIL_ASCEND_XP; // Base index at zero
|
2013-07-29 07:13:03 -04:00
|
|
|
static const struct
|
|
|
|
{
|
|
|
|
int x, z;
|
|
|
|
} Coords[] =
|
|
|
|
{
|
|
|
|
{ 1, 0}, // east, XP
|
|
|
|
{-1, 0}, // west, XM
|
|
|
|
{ 0, -1}, // north, ZM
|
|
|
|
{ 0, 1}, // south, ZP
|
|
|
|
} ;
|
|
|
|
BLOCKTYPE BlockType;
|
|
|
|
NIBBLETYPE BlockMeta;
|
|
|
|
if (!a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[Meta].x, a_RelY, a_RelZ + Coords[Meta].z, BlockType, BlockMeta))
|
|
|
|
{
|
|
|
|
// Too close to the edge, cannot simulate
|
|
|
|
return true;
|
|
|
|
}
|
2014-10-24 19:22:31 -04:00
|
|
|
return cBlockInfo::FullyOccupiesVoxel(BlockType);
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-20 06:13:11 -05:00
|
|
|
NIBBLETYPE FindMeta(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
NIBBLETYPE Meta = 0;
|
|
|
|
char RailsCnt = 0;
|
2014-07-17 16:15:34 -04:00
|
|
|
bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP
|
2014-04-18 15:09:44 -04:00
|
|
|
memset(Neighbors, 0, sizeof(Neighbors));
|
2017-11-20 06:13:11 -05:00
|
|
|
Neighbors[0] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(1, 0, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_EAST, E_PURE_DOWN));
|
2017-11-21 16:54:21 -05:00
|
|
|
Neighbors[1] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(-1, 0, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_WEST, E_PURE_DOWN));
|
|
|
|
Neighbors[2] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 0, -1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_NORTH, E_PURE_DOWN));
|
2017-11-20 06:13:11 -05:00
|
|
|
Neighbors[3] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 0, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos, BLOCK_FACE_SOUTH, E_PURE_DOWN));
|
|
|
|
Neighbors[4] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(1, 1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_EAST, E_PURE_NONE));
|
2017-11-21 16:54:21 -05:00
|
|
|
Neighbors[5] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_WEST, E_PURE_NONE));
|
2017-11-20 06:13:11 -05:00
|
|
|
Neighbors[6] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, -1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_NORTH, E_PURE_NONE));
|
|
|
|
Neighbors[7] = (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos + Vector3i(0, 1, 0), BLOCK_FACE_SOUTH, E_PURE_NONE));
|
|
|
|
if (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(1, -1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_EAST))
|
2014-12-05 10:59:11 -05:00
|
|
|
{
|
2013-07-29 07:13:03 -04:00
|
|
|
Neighbors[0] = true;
|
2014-12-05 10:59:11 -05:00
|
|
|
}
|
2017-11-20 06:13:11 -05:00
|
|
|
if (IsUnstable(a_ChunkInterface, a_BlockPos - Vector3i(1, 1, 0)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_WEST))
|
2014-12-05 10:59:11 -05:00
|
|
|
{
|
2013-07-29 07:13:03 -04:00
|
|
|
Neighbors[1] = true;
|
2014-12-05 10:59:11 -05:00
|
|
|
}
|
2017-11-20 06:13:11 -05:00
|
|
|
if (IsUnstable(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_NORTH))
|
2014-12-05 10:59:11 -05:00
|
|
|
{
|
2013-07-29 07:13:03 -04:00
|
|
|
Neighbors[2] = true;
|
2014-12-05 10:59:11 -05:00
|
|
|
}
|
2017-11-20 06:13:11 -05:00
|
|
|
if (IsUnstable(a_ChunkInterface, a_BlockPos + Vector3i(0, -1, 1)) || !IsNotConnected(a_ChunkInterface, a_BlockPos - Vector3i(0, 1, 0), BLOCK_FACE_SOUTH))
|
2014-12-05 10:59:11 -05:00
|
|
|
{
|
2013-07-29 07:13:03 -04:00
|
|
|
Neighbors[3] = true;
|
2014-12-05 10:59:11 -05:00
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
if (Neighbors[i])
|
|
|
|
{
|
|
|
|
RailsCnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (RailsCnt == 1)
|
|
|
|
{
|
2014-12-05 10:59:11 -05:00
|
|
|
if (Neighbors[7])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_ZP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[6])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_ZM;
|
|
|
|
}
|
|
|
|
else if (Neighbors[5])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_XM;
|
|
|
|
}
|
|
|
|
else if (Neighbors[4])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_XP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[0] || Neighbors[1])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_XM_XP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[2] || Neighbors[3])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ZM_ZP;
|
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
ASSERT(!"Weird neighbor count");
|
|
|
|
return Meta;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (Neighbors[i + 4])
|
|
|
|
{
|
|
|
|
Neighbors[i] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (RailsCnt > 1)
|
|
|
|
{
|
2014-12-05 10:59:11 -05:00
|
|
|
if (Neighbors[3] && Neighbors[0] && CanThisRailCurve())
|
|
|
|
{
|
|
|
|
return E_META_RAIL_CURVED_ZP_XP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[3] && Neighbors[1] && CanThisRailCurve())
|
|
|
|
{
|
|
|
|
return E_META_RAIL_CURVED_ZP_XM;
|
|
|
|
}
|
|
|
|
else if (Neighbors[2] && Neighbors[0] && CanThisRailCurve())
|
|
|
|
{
|
|
|
|
return E_META_RAIL_CURVED_ZM_XP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[2] && Neighbors[1] && CanThisRailCurve())
|
|
|
|
{
|
|
|
|
return E_META_RAIL_CURVED_ZM_XM;
|
|
|
|
}
|
|
|
|
else if (Neighbors[7] && Neighbors[2])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_ZP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[3] && Neighbors[6])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_ZM;
|
|
|
|
}
|
|
|
|
else if (Neighbors[5] && Neighbors[0])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_XM;
|
|
|
|
}
|
|
|
|
else if (Neighbors[4] && Neighbors[1])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ASCEND_XP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[0] && Neighbors[1])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_XM_XP;
|
|
|
|
}
|
|
|
|
else if (Neighbors[2] && Neighbors[3])
|
|
|
|
{
|
|
|
|
return E_META_RAIL_ZM_ZP;
|
|
|
|
}
|
2014-01-19 13:24:56 -05:00
|
|
|
|
|
|
|
if (CanThisRailCurve())
|
|
|
|
{
|
|
|
|
ASSERT(!"Weird neighbor count");
|
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
return Meta;
|
|
|
|
}
|
|
|
|
|
2014-01-19 13:24:56 -05:00
|
|
|
inline bool CanThisRailCurve(void)
|
|
|
|
{
|
|
|
|
return m_BlockType == E_BLOCK_RAIL;
|
|
|
|
}
|
|
|
|
|
2017-11-20 06:13:11 -05:00
|
|
|
bool IsUnstable(cChunkInterface & a_ChunkInterface, Vector3i a_Pos)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos)))
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2017-11-20 06:13:11 -05:00
|
|
|
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_Pos);
|
2013-07-29 07:13:03 -04:00
|
|
|
switch (Meta)
|
|
|
|
{
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_ZM_ZP:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH, E_PURE_DOWN) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH, E_PURE_DOWN)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_XM_XP:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST, E_PURE_DOWN) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST, E_PURE_DOWN)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_ASCEND_XP:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_EAST) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_ASCEND_XM:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_WEST)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_ASCEND_ZM:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_NORTH) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_ASCEND_ZP:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos + Vector3i(0, 1, 0), BLOCK_FACE_SOUTH)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_CURVED_ZP_XP:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_CURVED_ZP_XM:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_SOUTH) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_CURVED_ZM_XM:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_WEST)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-09-03 07:33:54 -04:00
|
|
|
case E_META_RAIL_CURVED_ZM_XP:
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
if (
|
2017-11-20 06:13:11 -05:00
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_NORTH) ||
|
|
|
|
IsNotConnected(a_ChunkInterface, a_Pos, BLOCK_FACE_EAST)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-20 06:13:11 -05:00
|
|
|
bool IsNotConnected(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, eBlockFace a_BlockFace, char a_Pure = 0)
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
AddFaceDirection(a_Pos.x, a_Pos.y, a_Pos.z, a_BlockFace, false);
|
2013-07-29 07:13:03 -04:00
|
|
|
NIBBLETYPE Meta;
|
2017-11-20 06:13:11 -05:00
|
|
|
if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos)))
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos + Vector3i(0, 1, 0))) || (a_Pure != E_PURE_UPDOWN))
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
if (!IsBlockRail(a_ChunkInterface.GetBlock(a_Pos - Vector3i(0, 1, 0))) || (a_Pure == E_PURE_NONE))
|
2013-07-29 07:13:03 -04:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
Meta = a_ChunkInterface.GetBlockMeta(a_Pos - Vector3i(0, 1, 0));
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
Meta = a_ChunkInterface.GetBlockMeta(a_Pos + Vector3i(0, 1, 0));
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-20 06:13:11 -05:00
|
|
|
Meta = a_ChunkInterface.GetBlockMeta(a_Pos);
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
switch (a_BlockFace)
|
|
|
|
{
|
|
|
|
case BLOCK_FACE_NORTH:
|
|
|
|
{
|
|
|
|
if (
|
2013-09-03 07:33:54 -04:00
|
|
|
(Meta == E_META_RAIL_ZM_ZP) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_ZM) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_ZP) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZP_XP) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZP_XM)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
case BLOCK_FACE_SOUTH:
|
|
|
|
{
|
|
|
|
if (
|
2013-09-03 07:33:54 -04:00
|
|
|
(Meta == E_META_RAIL_ZM_ZP) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_ZM) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_ZP) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZM_XP) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZM_XM)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-07-29 07:13:03 -04:00
|
|
|
case BLOCK_FACE_EAST:
|
|
|
|
{
|
|
|
|
if (
|
2013-09-03 07:33:54 -04:00
|
|
|
(Meta == E_META_RAIL_XM_XP) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_XP) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_XM) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZP_XM) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZM_XM)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case BLOCK_FACE_WEST:
|
|
|
|
{
|
|
|
|
if (
|
2013-09-03 07:33:54 -04:00
|
|
|
(Meta == E_META_RAIL_XM_XP) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_XP) ||
|
|
|
|
(Meta == E_META_RAIL_ASCEND_XM) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZP_XP) ||
|
|
|
|
(Meta == E_META_RAIL_CURVED_ZM_XP)
|
2013-07-29 07:13:03 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2015-05-19 07:28:31 -04:00
|
|
|
case BLOCK_FACE_NONE:
|
|
|
|
case BLOCK_FACE_YM:
|
|
|
|
case BLOCK_FACE_YP:
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2014-03-23 22:11:01 -04:00
|
|
|
|
|
|
|
virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
// Bit 0x08 is a flag when a_Meta is in the range 0x00--0x05 and 0x0A--0x0F.
|
|
|
|
// Bit 0x08 specifies direction when a_Meta is in the range 0x06-0x09.
|
|
|
|
if ((a_Meta < 0x06) || (a_Meta > 0x09))
|
|
|
|
{
|
|
|
|
// Save powered rail flag.
|
|
|
|
NIBBLETYPE OtherMeta = a_Meta & 0x08;
|
|
|
|
// Rotates according to table; 0x07 == 0111.
|
2015-05-09 03:25:09 -04:00
|
|
|
// Rails can either be flat (North / South) or Ascending (Asc. East)
|
2014-03-23 22:11:01 -04:00
|
|
|
switch (a_Meta & 0x07)
|
|
|
|
{
|
2015-05-09 03:25:09 -04:00
|
|
|
case 0x00: return 0x01 + OtherMeta; // North / South -> East / West
|
|
|
|
case 0x01: return 0x00 + OtherMeta; // East / West -> North / South
|
2014-03-23 22:11:01 -04:00
|
|
|
|
|
|
|
case 0x02: return 0x04 + OtherMeta; // Asc. East -> Asc. North
|
|
|
|
case 0x04: return 0x03 + OtherMeta; // Asc. North -> Asc. West
|
2014-03-26 08:54:17 -04:00
|
|
|
case 0x03: return 0x05 + OtherMeta; // Asc. West -> Asc. South
|
|
|
|
case 0x05: return 0x02 + OtherMeta; // Asc. South -> Asc. East
|
2014-03-23 22:11:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (a_Meta)
|
|
|
|
{
|
|
|
|
// Corner Directions
|
|
|
|
case 0x06: return 0x09; // Northwest Cnr. -> Southwest Cnr.
|
|
|
|
case 0x07: return 0x06; // Northeast Cnr. -> Northwest Cnr.
|
|
|
|
case 0x08: return 0x07; // Southeast Cnr. -> Northeast Cnr.
|
|
|
|
case 0x09: return 0x08; // Southwest Cnr. -> Southeast Cnr.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// To avoid a compiler warning;
|
|
|
|
return a_Meta;
|
|
|
|
}
|
|
|
|
|
2016-12-09 06:29:04 -05:00
|
|
|
|
|
|
|
|
2014-03-23 22:11:01 -04:00
|
|
|
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
// Bit 0x08 is a flag for value in the range 0x00--0x05 and specifies direction for values withint 0x006--0x09.
|
|
|
|
if ((a_Meta < 0x06) || (a_Meta > 0x09))
|
|
|
|
{
|
|
|
|
// Save powered rail flag.
|
|
|
|
NIBBLETYPE OtherMeta = a_Meta & 0x08;
|
|
|
|
// Rotates according to table; 0x07 == 0111.
|
2015-05-09 03:25:09 -04:00
|
|
|
// Rails can either be flat (North / South) or Ascending (Asc. East)
|
2014-03-23 22:11:01 -04:00
|
|
|
switch (a_Meta & 0x07)
|
|
|
|
{
|
2015-05-09 03:25:09 -04:00
|
|
|
case 0x00: return 0x01 + OtherMeta; // North / South -> East / West
|
|
|
|
case 0x01: return 0x00 + OtherMeta; // East / West -> North / South
|
2014-03-23 22:11:01 -04:00
|
|
|
|
|
|
|
case 0x02: return 0x05 + OtherMeta; // Asc. East -> Asc. South
|
|
|
|
case 0x05: return 0x03 + OtherMeta; // Asc. South -> Asc. West
|
2014-03-26 08:54:17 -04:00
|
|
|
case 0x03: return 0x04 + OtherMeta; // Asc. West -> Asc. North
|
|
|
|
case 0x04: return 0x02 + OtherMeta; // Asc. North -> Asc. East
|
2014-03-23 22:11:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (a_Meta)
|
|
|
|
{
|
|
|
|
// Corner Directions
|
|
|
|
case 0x06: return 0x07; // Northwest Cnr. -> Northeast Cnr.
|
|
|
|
case 0x07: return 0x08; // Northeast Cnr. -> Southeast Cnr.
|
|
|
|
case 0x08: return 0x09; // Southeast Cnr. -> Southwest Cnr.
|
|
|
|
case 0x09: return 0x06; // Southwest Cnr. -> Northwest Cnr.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// To avoid a compiler warning;
|
|
|
|
return a_Meta;
|
|
|
|
}
|
|
|
|
|
2016-12-09 06:29:04 -05:00
|
|
|
|
|
|
|
|
2014-03-23 22:11:01 -04:00
|
|
|
virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
// MirrorXY basically flips the ZP and ZM parts of the meta
|
|
|
|
if (m_BlockType == E_BLOCK_RAIL)
|
2014-03-23 22:11:01 -04:00
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
// Basic rails can have curves and thus their meta behaves differently from specialized rails:
|
|
|
|
switch (a_Meta)
|
2014-03-23 22:11:01 -04:00
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
case E_META_RAIL_ASCEND_XM: return E_META_RAIL_ASCEND_XM;
|
|
|
|
case E_META_RAIL_ASCEND_XP: return E_META_RAIL_ASCEND_XP;
|
|
|
|
case E_META_RAIL_ASCEND_ZM: return E_META_RAIL_ASCEND_ZP;
|
|
|
|
case E_META_RAIL_ASCEND_ZP: return E_META_RAIL_ASCEND_ZM;
|
|
|
|
case E_META_RAIL_CURVED_ZM_XM: return E_META_RAIL_CURVED_ZP_XM;
|
|
|
|
case E_META_RAIL_CURVED_ZM_XP: return E_META_RAIL_CURVED_ZP_XP;
|
|
|
|
case E_META_RAIL_CURVED_ZP_XM: return E_META_RAIL_CURVED_ZM_XM;
|
|
|
|
case E_META_RAIL_CURVED_ZP_XP: return E_META_RAIL_CURVED_ZM_XP;
|
|
|
|
case E_META_RAIL_XM_XP: return E_META_RAIL_XM_XP;
|
|
|
|
case E_META_RAIL_ZM_ZP: return E_META_RAIL_ZM_ZP;
|
2014-03-23 22:11:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
// Specialized rails don't have curves, instead they use bit 0x08 as a flag
|
|
|
|
NIBBLETYPE flag = a_Meta & 0x08;
|
|
|
|
switch (a_Meta & 0x07)
|
2014-03-23 22:11:01 -04:00
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
case E_META_RAIL_ASCEND_XM: return flag | E_META_RAIL_ASCEND_XM;
|
|
|
|
case E_META_RAIL_ASCEND_XP: return flag | E_META_RAIL_ASCEND_XP;
|
|
|
|
case E_META_RAIL_ASCEND_ZM: return flag | E_META_RAIL_ASCEND_ZP;
|
|
|
|
case E_META_RAIL_ASCEND_ZP: return flag | E_META_RAIL_ASCEND_ZM;
|
|
|
|
case E_META_RAIL_XM_XP: return flag | E_META_RAIL_XM_XP;
|
|
|
|
case E_META_RAIL_ZM_ZP: return flag | E_META_RAIL_ZM_ZP;
|
2014-03-23 22:11:01 -04:00
|
|
|
}
|
|
|
|
}
|
2016-12-09 06:29:04 -05:00
|
|
|
ASSERT(!"Unknown rail meta");
|
2014-03-23 22:11:01 -04:00
|
|
|
return a_Meta;
|
|
|
|
}
|
|
|
|
|
2016-12-09 06:29:04 -05:00
|
|
|
|
|
|
|
|
2014-03-23 22:11:01 -04:00
|
|
|
virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
// MirrorYZ basically flips the XP and XM parts of the meta
|
|
|
|
if (m_BlockType == E_BLOCK_RAIL)
|
2014-03-23 22:11:01 -04:00
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
// Basic rails can have curves and thus their meta behaves differently from specialized rails:
|
|
|
|
switch (a_Meta)
|
2014-03-23 22:11:01 -04:00
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
case E_META_RAIL_ASCEND_XM: return E_META_RAIL_ASCEND_XP;
|
|
|
|
case E_META_RAIL_ASCEND_XP: return E_META_RAIL_ASCEND_XM;
|
|
|
|
case E_META_RAIL_ASCEND_ZM: return E_META_RAIL_ASCEND_ZM;
|
|
|
|
case E_META_RAIL_ASCEND_ZP: return E_META_RAIL_ASCEND_ZP;
|
|
|
|
case E_META_RAIL_CURVED_ZM_XM: return E_META_RAIL_CURVED_ZM_XP;
|
|
|
|
case E_META_RAIL_CURVED_ZM_XP: return E_META_RAIL_CURVED_ZM_XM;
|
|
|
|
case E_META_RAIL_CURVED_ZP_XM: return E_META_RAIL_CURVED_ZP_XP;
|
|
|
|
case E_META_RAIL_CURVED_ZP_XP: return E_META_RAIL_CURVED_ZP_XM;
|
|
|
|
case E_META_RAIL_XM_XP: return E_META_RAIL_XM_XP;
|
|
|
|
case E_META_RAIL_ZM_ZP: return E_META_RAIL_ZM_ZP;
|
2014-03-23 22:11:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
// Specialized rails don't have curves, instead they use bit 0x08 as a flag
|
|
|
|
NIBBLETYPE flag = a_Meta & 0x08;
|
|
|
|
switch (a_Meta & 0x07)
|
2014-03-23 22:11:01 -04:00
|
|
|
{
|
2016-12-09 06:29:04 -05:00
|
|
|
case E_META_RAIL_ASCEND_XM: return flag | E_META_RAIL_ASCEND_XP;
|
|
|
|
case E_META_RAIL_ASCEND_XP: return flag | E_META_RAIL_ASCEND_XM;
|
|
|
|
case E_META_RAIL_ASCEND_ZM: return flag | E_META_RAIL_ASCEND_ZM;
|
|
|
|
case E_META_RAIL_ASCEND_ZP: return flag | E_META_RAIL_ASCEND_ZP;
|
|
|
|
case E_META_RAIL_XM_XP: return flag | E_META_RAIL_XM_XP;
|
|
|
|
case E_META_RAIL_ZM_ZP: return flag | E_META_RAIL_ZM_ZP;
|
2014-03-23 22:11:01 -04:00
|
|
|
}
|
|
|
|
}
|
2016-12-09 06:29:04 -05:00
|
|
|
ASSERT(!"Unknown rail meta");
|
2014-03-23 22:11:01 -04:00
|
|
|
return a_Meta;
|
|
|
|
}
|
2015-06-30 10:50:15 -04:00
|
|
|
|
2016-12-09 06:29:04 -05:00
|
|
|
|
|
|
|
|
2015-06-30 10:50:15 -04:00
|
|
|
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
|
|
|
|
{
|
|
|
|
UNUSED(a_Meta);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-07-29 07:13:03 -04:00
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|