summaryrefslogtreecommitdiffstats
path: root/source/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'source/Blocks')
-rw-r--r--source/Blocks/BlockHandler.cpp4
-rw-r--r--source/Blocks/BlockRail.h315
2 files changed, 319 insertions, 0 deletions
diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp
index 88f279ff5..53e9c4a06 100644
--- a/source/Blocks/BlockHandler.cpp
+++ b/source/Blocks/BlockHandler.cpp
@@ -45,6 +45,7 @@
#include "BlockBed.h"
#include "BlockFarmland.h"
#include "BlockMycelium.h"
+#include "BlockRail.h"
@@ -124,6 +125,9 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_PISTON: return new cBlockPistonHandler (a_BlockType);
case E_BLOCK_PLANKS: return new cBlockWoodHandler (a_BlockType);
case E_BLOCK_PUMPKIN_STEM: return new cBlockStemsHandler (a_BlockType);
+ case E_BLOCK_RAIL: return new cBlockRailHandler (a_BlockType);
+ case E_BLOCK_POWERED_RAIL: return new cBlockRailHandler (a_BlockType);
+ case E_BLOCK_DETECTOR_RAIL: return new cBlockRailHandler (a_BlockType);
case E_BLOCK_REDSTONE_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_REDSTONE_ORE_GLOWING: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_REDSTONE_REPEATER_OFF: return new cBlockRedstoneRepeaterHandler(a_BlockType);
diff --git a/source/Blocks/BlockRail.h b/source/Blocks/BlockRail.h
new file mode 100644
index 000000000..fb2000884
--- /dev/null
+++ b/source/Blocks/BlockRail.h
@@ -0,0 +1,315 @@
+
+#pragma once
+
+#include "BlockEntity.h"
+#include "../World.h"
+
+
+
+
+
+enum ENUM_RAIL_DIRECTIONS
+{
+ E_RAIL_NORTH_SOUTH = 0,
+ E_RAIL_EAST_WEST = 1,
+ E_RAIL_ASCEND_EAST = 2,
+ E_RAIL_ASCEND_WEST = 3,
+ E_RAIL_ASCEND_NORTH = 4,
+ E_RAIL_ASCEND_SOUTH = 5,
+ E_RAIL_CURVED_SOUTH_EAST = 6,
+ E_RAIL_CURVED_SOUTH_WEST = 7,
+ E_RAIL_CURVED_NORTH_WEST = 8,
+ E_RAIL_CURVED_NORTH_EAST = 9
+};
+
+enum ENUM_PURE
+{
+ E_PURE_UPDOWN = 0,
+ E_PURE_DOWN = 1,
+ E_PURE_NONE = 2
+};
+
+
+
+
+
+class cBlockRailHandler :
+ public cBlockHandler
+{
+public:
+ cBlockRailHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+ virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
+ {
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ));
+ OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
+ NeighborChanged(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ);
+ NeighborChanged(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ);
+ NeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1);
+ NeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1);
+ NeighborChanged(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ);
+ NeighborChanged(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ);
+ NeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ - 1);
+ NeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ + 1);
+ }
+
+ virtual void OnNeighborChanged(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ if(IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ))
+ a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ));
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ if(!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)])
+ return false;
+ char Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ switch(Meta)
+ {
+ case E_RAIL_ASCEND_EAST:
+ {
+ if(!g_BlockIsSolid[a_World->GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ)])
+ return false;
+ break;
+ }
+ case E_RAIL_ASCEND_WEST:
+ {
+ if(!g_BlockIsSolid[a_World->GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ)])
+ return false;
+ break;
+ }
+ case E_RAIL_ASCEND_NORTH:
+ {
+ if(!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1)])
+ return false;
+ break;
+ }
+ case E_RAIL_ASCEND_SOUTH:
+ {
+ if(!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1)])
+ return false;
+ break;
+ }
+ }
+ return true;
+ }
+
+ char FindMeta(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
+ {
+ char Meta = 0;
+ char RailsCnt = 0;
+ bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP
+ memset(Neighbors, false, sizeof(Neighbors));
+ if(IsUnstable(a_World, a_BlockX + 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN))
+ Neighbors[0] = true;
+ if(IsUnstable(a_World, a_BlockX - 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST, E_PURE_DOWN))
+ Neighbors[1] = true;
+ if(IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ - 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_DOWN))
+ Neighbors[2] = true;
+ if(IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ + 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_DOWN))
+ Neighbors[3] = true;
+ if(IsUnstable(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_EAST, E_PURE_NONE))
+ Neighbors[4] = true;
+ if(IsUnstable(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_WEST, E_PURE_NONE))
+ Neighbors[5] = true;
+ if(IsUnstable(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_NONE))
+ Neighbors[6] = true;
+ if(IsUnstable(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_NONE))
+ Neighbors[7] = true;
+ if(IsUnstable(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_EAST))
+ Neighbors[0] = true;
+ if(IsUnstable(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_WEST))
+ Neighbors[1] = true;
+ if(IsUnstable(a_World, a_BlockX, a_BlockY - 1, a_BlockZ - 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NORTH))
+ Neighbors[2] = true;
+ if(IsUnstable(a_World, a_BlockX, a_BlockY - 1, a_BlockZ + 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_SOUTH))
+ Neighbors[3] = true;
+ for(int i = 0; i < 8; i++)
+ {
+ if(Neighbors[i])
+ {
+ RailsCnt++;
+ }
+ }
+ if(RailsCnt == 1)
+ {
+ if(Neighbors[7]) Meta = E_RAIL_ASCEND_SOUTH;
+ else if(Neighbors[6]) Meta = E_RAIL_ASCEND_NORTH;
+ else if(Neighbors[5]) Meta = E_RAIL_ASCEND_WEST;
+ else if(Neighbors[4]) Meta = E_RAIL_ASCEND_EAST;
+ else if(Neighbors[0] || Neighbors[1]) Meta = E_RAIL_EAST_WEST;
+ else if(Neighbors[2] || Neighbors[3]) Meta = E_RAIL_NORTH_SOUTH;
+ return Meta;
+ }
+ for(int i = 0; i < 4; i++)
+ {
+ if(Neighbors[i+4])
+ {
+ Neighbors[i] = true;
+ }
+ }
+ if(RailsCnt > 1)
+ {
+ if(Neighbors[3] && Neighbors[0]) Meta = E_RAIL_CURVED_SOUTH_EAST;
+ else if(Neighbors[3] && Neighbors[1]) Meta = E_RAIL_CURVED_SOUTH_WEST;
+ else if(Neighbors[2] && Neighbors[0]) Meta = E_RAIL_CURVED_NORTH_EAST;
+ else if(Neighbors[2] && Neighbors[1]) Meta = E_RAIL_CURVED_NORTH_WEST;
+ else if(Neighbors[7] && Neighbors[2]) Meta = E_RAIL_ASCEND_SOUTH;
+ else if(Neighbors[3] && Neighbors[6]) Meta = E_RAIL_ASCEND_NORTH;
+ else if(Neighbors[5] && Neighbors[0]) Meta = E_RAIL_ASCEND_WEST;
+ else if(Neighbors[4] && Neighbors[1]) Meta = E_RAIL_ASCEND_EAST;
+ else if(Neighbors[0] && Neighbors[1]) Meta = E_RAIL_EAST_WEST;
+ else if(Neighbors[2] && Neighbors[3]) Meta = E_RAIL_NORTH_SOUTH;
+ }
+ return Meta;
+ }
+
+ bool IsUnstable(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
+ {
+ if(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL) return false;
+ char Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ switch(Meta)
+ {
+ case E_RAIL_NORTH_SOUTH:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_DOWN) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_DOWN)) return true;
+ break;
+ }
+ case E_RAIL_EAST_WEST:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST, E_PURE_DOWN)) return true;
+ break;
+ }
+ case E_RAIL_ASCEND_EAST:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_EAST) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST)) return true;
+ break;
+ }
+ case E_RAIL_ASCEND_WEST:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_WEST)) return true;
+ break;
+ }
+ case E_RAIL_ASCEND_NORTH:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH)) return true;
+ break;
+ }
+ case E_RAIL_ASCEND_SOUTH:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_SOUTH)) return true;
+ break;
+ }
+ case E_RAIL_CURVED_SOUTH_EAST:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST)) return true;
+ break;
+ }
+ case E_RAIL_CURVED_SOUTH_WEST:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST)) return true;
+ break;
+ }
+ case E_RAIL_CURVED_NORTH_WEST:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST)) return true;
+ break;
+ }
+ case E_RAIL_CURVED_NORTH_EAST:
+ {
+ if(IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH) ||
+ IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST)) return true;
+ break;
+ }
+ }
+ return false;
+ }
+
+ bool IsNotConnected(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, char a_Pure = 0)
+ {
+ AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Direction, false);
+ char Meta;
+ if(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL)
+ {
+ if((a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ) != E_BLOCK_RAIL) || (a_Pure != E_PURE_UPDOWN))
+ {
+ if((a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) != E_BLOCK_RAIL) || (a_Pure == E_PURE_NONE))
+ {
+ return true;
+ }
+ else
+ {
+ Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ);
+ }
+ }
+ else
+ {
+ Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY + 1, a_BlockZ);
+ }
+ }
+ else
+ {
+ Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ }
+ switch(a_Direction)
+ {
+ case BLOCK_FACE_NORTH:
+ {
+ if(Meta == E_RAIL_NORTH_SOUTH ||
+ Meta == E_RAIL_ASCEND_NORTH ||
+ Meta == E_RAIL_ASCEND_SOUTH ||
+ Meta == E_RAIL_CURVED_SOUTH_EAST ||
+ Meta == E_RAIL_CURVED_SOUTH_WEST)
+ return false;
+ break;
+ }
+ case BLOCK_FACE_SOUTH:
+ {
+ if(Meta == E_RAIL_NORTH_SOUTH ||
+ Meta == E_RAIL_ASCEND_NORTH ||
+ Meta == E_RAIL_ASCEND_SOUTH ||
+ Meta == E_RAIL_CURVED_NORTH_EAST ||
+ Meta == E_RAIL_CURVED_NORTH_WEST)
+ return false;
+ break;
+ }
+ case BLOCK_FACE_EAST:
+ {
+ if(Meta == E_RAIL_EAST_WEST ||
+ Meta == E_RAIL_ASCEND_EAST ||
+ Meta == E_RAIL_ASCEND_WEST ||
+ Meta == E_RAIL_CURVED_SOUTH_WEST ||
+ Meta == E_RAIL_CURVED_NORTH_WEST)
+ return false;
+ break;
+ }
+ case BLOCK_FACE_WEST:
+ {
+ if(Meta == E_RAIL_EAST_WEST ||
+ Meta == E_RAIL_ASCEND_EAST ||
+ Meta == E_RAIL_ASCEND_WEST ||
+ Meta == E_RAIL_CURVED_SOUTH_EAST ||
+ Meta == E_RAIL_CURVED_NORTH_EAST)
+ return false;
+ break;
+ }
+ }
+ return true;
+ }
+} ;
+
+
+
+