From c24905426c77d33416c1fc46fcf0ad0747551417 Mon Sep 17 00:00:00 2001 From: "luksor111@gmail.com" Date: Sun, 25 Nov 2012 13:50:20 +0000 Subject: [PATCH] Implemented rail placement mechanics. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1065 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- VC2008/MCServer.vcproj | 4 + source/Blocks/BlockHandler.cpp | 4 + source/Blocks/BlockRail.h | 315 +++++++++++++++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 source/Blocks/BlockRail.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index 28951e076..6d7054b1b 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -1874,6 +1874,10 @@ RelativePath="..\source\blocks\BlockPiston.h" > + + 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; + } +} ; + + + +