summaryrefslogtreecommitdiffstats
path: root/source/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'source/Blocks')
-rw-r--r--source/Blocks/BlockCactus.h37
-rw-r--r--source/Blocks/BlockCrops.h4
-rw-r--r--source/Blocks/BlockDoor.h4
-rw-r--r--source/Blocks/BlockFlower.h4
-rw-r--r--source/Blocks/BlockFluid.h8
-rw-r--r--source/Blocks/BlockHandler.cpp25
-rw-r--r--source/Blocks/BlockHandler.h9
-rw-r--r--source/Blocks/BlockLadder.h19
-rw-r--r--source/Blocks/BlockMushroom.h11
-rw-r--r--source/Blocks/BlockRail.h212
-rw-r--r--source/Blocks/BlockRedstone.h4
-rw-r--r--source/Blocks/BlockRedstoneRepeater.h4
-rw-r--r--source/Blocks/BlockSapling.h4
-rw-r--r--source/Blocks/BlockSnow.h5
-rw-r--r--source/Blocks/BlockStems.h4
-rw-r--r--source/Blocks/BlockSugarcane.h36
-rw-r--r--source/Blocks/BlockTallGrass.h4
-rw-r--r--source/Blocks/BlockTorch.h11
-rw-r--r--source/Blocks/BlockVine.h105
19 files changed, 344 insertions, 166 deletions
diff --git a/source/Blocks/BlockCactus.h b/source/Blocks/BlockCactus.h
index daa0e02c2..516f024d8 100644
--- a/source/Blocks/BlockCactus.h
+++ b/source/Blocks/BlockCactus.h
@@ -24,9 +24,13 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- BLOCKTYPE Surface = a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
+ if (a_RelY <= 0)
+ {
+ return false;
+ }
+ BLOCKTYPE Surface = a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ);
if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS))
{
// Cactus can only be placed on sand and itself
@@ -34,15 +38,28 @@ public:
}
// Check surroundings. Cacti may ONLY be surrounded by air
- if (
- (a_World->GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ) != E_BLOCK_AIR) ||
- (a_World->GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ) != E_BLOCK_AIR) ||
- (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1) != E_BLOCK_AIR) ||
- (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1) != E_BLOCK_AIR)
- )
+ static const struct
{
- return false;
- }
+ int x, z;
+ } Coords[] =
+ {
+ {-1, 0},
+ { 1, 0},
+ { 0, -1},
+ { 0, 1},
+ } ;
+ for (int i = 0; i < ARRAYCOUNT(Coords); i++)
+ {
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ if (
+ a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta) &&
+ (BlockType != E_BLOCK_AIR)
+ )
+ {
+ return false;
+ }
+ } // for i - Coords[]
return true;
}
diff --git a/source/Blocks/BlockCrops.h b/source/Blocks/BlockCrops.h
index 0a8017a91..a269c7c32 100644
--- a/source/Blocks/BlockCrops.h
+++ b/source/Blocks/BlockCrops.h
@@ -44,9 +44,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) == E_BLOCK_FARMLAND;
+ return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND));
}
diff --git a/source/Blocks/BlockDoor.h b/source/Blocks/BlockDoor.h
index 0e4a5ff52..a988c2d4b 100644
--- a/source/Blocks/BlockDoor.h
+++ b/source/Blocks/BlockDoor.h
@@ -74,9 +74,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return (a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) != E_BLOCK_AIR);
+ return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
}
diff --git a/source/Blocks/BlockFlower.h b/source/Blocks/BlockFlower.h
index 7db42c9fc..b46273c51 100644
--- a/source/Blocks/BlockFlower.h
+++ b/source/Blocks/BlockFlower.h
@@ -24,9 +24,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return IsBlockTypeOfDirt(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ));
+ return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ));
}
diff --git a/source/Blocks/BlockFluid.h b/source/Blocks/BlockFluid.h
index a8cd9c497..b184a5b33 100644
--- a/source/Blocks/BlockFluid.h
+++ b/source/Blocks/BlockFluid.h
@@ -26,22 +26,22 @@ public:
}
- virtual void Check(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual void Check(int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk) override
{
switch (m_BlockType)
{
case E_BLOCK_STATIONARY_LAVA:
{
- a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LAVA, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
+ a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_LAVA, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
break;
}
case E_BLOCK_STATIONARY_WATER:
{
- a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WATER, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
+ a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_WATER, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
break;
}
}
- super::Check(a_World, a_BlockX, a_BlockY, a_BlockZ);
+ super::Check(a_RelX, a_RelY, a_RelZ, a_Chunk);
}
} ;
diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp
index 71d56f94d..991102aca 100644
--- a/source/Blocks/BlockHandler.cpp
+++ b/source/Blocks/BlockHandler.cpp
@@ -351,16 +351,7 @@ const char * cBlockHandler::GetStepSound()
-bool cBlockHandler::CanBePlacedAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
-{
- return CanBeAt(a_World, a_BlockX, a_BlockY, a_BlockZ);
-}
-
-
-
-
-
-bool cBlockHandler::CanBeAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
+bool cBlockHandler::CanBeAt(int a_BlockX, int a_BlockY, int a_BlockZ, const cChunk & a_Chunk)
{
return true;
}
@@ -423,21 +414,25 @@ bool cBlockHandler::DoesDropOnUnsuitable(void)
-void cBlockHandler::Check(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
+void cBlockHandler::Check(int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk)
{
- if (!CanBeAt(a_World, a_BlockX, a_BlockY, a_BlockZ))
+ if (!CanBeAt(a_RelX, a_RelY, a_RelZ, a_Chunk))
{
if (DoesDropOnUnsuitable())
{
- DropBlock(a_World, NULL, a_BlockX, a_BlockY, a_BlockZ);
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ DropBlock(a_Chunk.GetWorld(), NULL, BlockX, a_RelY, BlockZ);
}
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
+ a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
}
else
{
// Wake up the simulators for this block:
- a_World->WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ a_Chunk.GetWorld()->GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, &a_Chunk);
}
}
diff --git a/source/Blocks/BlockHandler.h b/source/Blocks/BlockHandler.h
index e551668f9..4c91463bc 100644
--- a/source/Blocks/BlockHandler.h
+++ b/source/Blocks/BlockHandler.h
@@ -3,6 +3,7 @@
#include "../Defines.h"
#include "../Item.h"
+#include "../Chunk.h"
@@ -74,14 +75,14 @@ public:
/// Returns step sound name of block
virtual const char * GetStepSound(void);
- /// Checks if the block can stay at the specified coords in the world
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ);
+ /// Checks if the block can stay at the specified relative coords in the chunk
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk);
/** Checks if the block can be placed at this point.
Default: CanBeAt(...)
NOTE: This call doesn't actually place the block
*/
- virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
+ // virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
/// Called when the player tries to place a block on top of this block (Only if he aims directly on this block); return false to disallow
virtual bool DoesAllowBlockOnTop(void);
@@ -109,7 +110,7 @@ public:
By default drops if position no more suitable (CanBeAt(), DoesDropOnUnsuitable(), Drop()),
and wakes up all simulators on the block.
*/
- virtual void Check(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ);
+ virtual void Check(int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk);
/// Get the blockhandler for a specific block id
diff --git a/source/Blocks/BlockLadder.h b/source/Blocks/BlockLadder.h
index 5f0b09737..280f0deb1 100644
--- a/source/Blocks/BlockLadder.h
+++ b/source/Blocks/BlockLadder.h
@@ -69,20 +69,13 @@ public:
}
- virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- if (LadderCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
- {
- return true;
- }
- return (FindSuitableBlockFace(a_World, a_BlockX, a_BlockY, a_BlockZ) != BLOCK_FACE_BOTTOM);
- }
-
-
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
- {
- char BlockFace = cLadder::MetaDataToDirection(a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
- return CanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, BlockFace);
+ // TODO: Use cTorch::AdjustCoordsByMeta(), then cChunk::UnboundedRelGetBlock() and finally some comparison
+ char BlockFace = cLadder::MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ return LadderCanBePlacedAt(a_Chunk.GetWorld(), BlockX, a_RelY, BlockZ, BlockFace);
}
diff --git a/source/Blocks/BlockMushroom.h b/source/Blocks/BlockMushroom.h
index 96bdbc310..62cc898c0 100644
--- a/source/Blocks/BlockMushroom.h
+++ b/source/Blocks/BlockMushroom.h
@@ -24,9 +24,16 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- switch (a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))
+ if (a_RelY <= 0)
+ {
+ return false;
+ }
+
+ // TODO: Cannot be at too much daylight
+
+ switch (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ))
{
case E_BLOCK_GLASS:
case E_BLOCK_CACTUS:
diff --git a/source/Blocks/BlockRail.h b/source/Blocks/BlockRail.h
index 733f92c8c..60865abf5 100644
--- a/source/Blocks/BlockRail.h
+++ b/source/Blocks/BlockRail.h
@@ -8,19 +8,36 @@
+/// Meta values for the rail
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_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
-};
+ E_RAIL_CURVED_NORTH_EAST = 9,
+
+ // Some useful synonyms:
+ E_RAIL_DIR_X = E_RAIL_EAST_WEST,
+ E_RAIL_DIR_Z = E_RAIL_NORTH_SOUTH,
+ E_RAIL_ASCEND_XP = E_RAIL_ASCEND_EAST,
+ E_RAIL_ASCEND_XM = E_RAIL_ASCEND_WEST,
+ E_RAIL_ASCEND_ZM = E_RAIL_ASCEND_NORTH,
+ E_RAIL_ASCEND_ZP = E_RAIL_ASCEND_SOUTH,
+ E_RAIL_CURVED_XPZP = E_RAIL_CURVED_SOUTH_EAST,
+ E_RAIL_CURVED_XMZP = E_RAIL_CURVED_SOUTH_WEST,
+ E_RAIL_CURVED_XMZM = E_RAIL_CURVED_NORTH_WEST,
+ E_RAIL_CURVED_XPZM = E_RAIL_CURVED_NORTH_EAST,
+} ;
+
+
+
+
enum ENUM_PURE
{
@@ -65,46 +82,45 @@ public:
}
- virtual bool CanBeAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)])
+ if (a_RelY <= 0)
{
return false;
}
- NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ if (!g_BlockIsSolid[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)])
+ {
+ return false;
+ }
+
+ NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
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)])
+ // Mapping between the meta and the neighbors that need checking
+ Meta -= E_RAIL_ASCEND_EAST; // Base index at zero
+ static const struct
{
- return false;
+ 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;
}
- break;
+ return g_BlockIsSolid[BlockType];
}
}
return true;
@@ -159,16 +175,16 @@ public:
}
if (RailsCnt > 1)
{
- if (Neighbors[3] && Neighbors[0]) return E_RAIL_CURVED_SOUTH_EAST;
- else if(Neighbors[3] && Neighbors[1]) return E_RAIL_CURVED_SOUTH_WEST;
- else if(Neighbors[2] && Neighbors[0]) return E_RAIL_CURVED_NORTH_EAST;
- else if(Neighbors[2] && Neighbors[1]) return E_RAIL_CURVED_NORTH_WEST;
- else if(Neighbors[7] && Neighbors[2]) return E_RAIL_ASCEND_SOUTH;
- else if(Neighbors[3] && Neighbors[6]) return E_RAIL_ASCEND_NORTH;
- else if(Neighbors[5] && Neighbors[0]) return E_RAIL_ASCEND_WEST;
- else if(Neighbors[4] && Neighbors[1]) return E_RAIL_ASCEND_EAST;
- else if(Neighbors[0] && Neighbors[1]) return E_RAIL_EAST_WEST;
- else if(Neighbors[2] && Neighbors[3]) return E_RAIL_NORTH_SOUTH;
+ if (Neighbors[3] && Neighbors[0]) return E_RAIL_CURVED_SOUTH_EAST;
+ else if (Neighbors[3] && Neighbors[1]) return E_RAIL_CURVED_SOUTH_WEST;
+ else if (Neighbors[2] && Neighbors[0]) return E_RAIL_CURVED_NORTH_EAST;
+ else if (Neighbors[2] && Neighbors[1]) return E_RAIL_CURVED_NORTH_WEST;
+ else if (Neighbors[7] && Neighbors[2]) return E_RAIL_ASCEND_SOUTH;
+ else if (Neighbors[3] && Neighbors[6]) return E_RAIL_ASCEND_NORTH;
+ else if (Neighbors[5] && Neighbors[0]) return E_RAIL_ASCEND_WEST;
+ else if (Neighbors[4] && Neighbors[1]) return E_RAIL_ASCEND_EAST;
+ else if (Neighbors[0] && Neighbors[1]) return E_RAIL_EAST_WEST;
+ else if (Neighbors[2] && Neighbors[3]) return E_RAIL_NORTH_SOUTH;
ASSERT(!"Weird neighbor count");
}
return Meta;
@@ -177,68 +193,130 @@ public:
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;
+ if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL)
+ {
+ return false;
+ }
NIBBLETYPE 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ 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;
}
}
@@ -246,7 +324,7 @@ public:
}
- bool IsNotConnected(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Pure = 0)
+ bool IsNotConnected(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Pure = 0)
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false);
NIBBLETYPE Meta;
diff --git a/source/Blocks/BlockRedstone.h b/source/Blocks/BlockRedstone.h
index ce0ff64d5..3a4649d7e 100644
--- a/source/Blocks/BlockRedstone.h
+++ b/source/Blocks/BlockRedstone.h
@@ -22,9 +22,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)];
+ return ((a_RelY > 0) && g_BlockIsSolid[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)]);
}
diff --git a/source/Blocks/BlockRedstoneRepeater.h b/source/Blocks/BlockRedstoneRepeater.h
index fbd415160..4a16149fd 100644
--- a/source/Blocks/BlockRedstoneRepeater.h
+++ b/source/Blocks/BlockRedstoneRepeater.h
@@ -38,9 +38,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) != E_BLOCK_AIR;
+ return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
}
diff --git a/source/Blocks/BlockSapling.h b/source/Blocks/BlockSapling.h
index 18fdb9d05..957331886 100644
--- a/source/Blocks/BlockSapling.h
+++ b/source/Blocks/BlockSapling.h
@@ -25,9 +25,9 @@ public:
}
- virtual bool CanBeAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return IsBlockTypeOfDirt(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ));
+ return (a_RelY > 0) && IsBlockTypeOfDirt(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ));
}
diff --git a/source/Blocks/BlockSnow.h b/source/Blocks/BlockSnow.h
index 2a5009b69..f150f497c 100644
--- a/source/Blocks/BlockSnow.h
+++ b/source/Blocks/BlockSnow.h
@@ -29,10 +29,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- BLOCKTYPE UnderlyingBlock = a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
- return g_BlockIsSnowable[UnderlyingBlock];
+ return (a_RelY > 0) && g_BlockIsSnowable[a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)];
}
diff --git a/source/Blocks/BlockStems.h b/source/Blocks/BlockStems.h
index ba93097f9..44c4d9cc9 100644
--- a/source/Blocks/BlockStems.h
+++ b/source/Blocks/BlockStems.h
@@ -41,9 +41,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) == E_BLOCK_FARMLAND;
+ return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) == E_BLOCK_FARMLAND));
}
diff --git a/source/Blocks/BlockSugarcane.h b/source/Blocks/BlockSugarcane.h
index 9470900f0..a9503ba37 100644
--- a/source/Blocks/BlockSugarcane.h
+++ b/source/Blocks/BlockSugarcane.h
@@ -23,16 +23,46 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- switch (a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))
+ if (a_RelY <= 0)
+ {
+ return false;
+ }
+ switch (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ))
{
case E_BLOCK_DIRT:
case E_BLOCK_GRASS:
case E_BLOCK_FARMLAND:
case E_BLOCK_SAND:
{
- return a_World->IsBlockDirectlyWatered(a_BlockX, a_BlockY - 1, a_BlockZ);
+ static const struct
+ {
+ int x, z;
+ } Coords[] =
+ {
+ {-1, 0},
+ { 1, 0},
+ { 0, -1},
+ { 0, 1},
+ } ;
+ a_RelY -= 1;
+ for (int i = 0; i < ARRAYCOUNT(Coords); i++)
+ {
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ if (!a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta))
+ {
+ // Too close to the edge, cannot simulate
+ return true;
+ }
+ if (IsBlockWater(BlockType))
+ {
+ return true;
+ }
+ } // for i - Coords[]
+ // Not directly neighboring a water block
+ return false;
}
case E_BLOCK_SUGARCANE:
{
diff --git a/source/Blocks/BlockTallGrass.h b/source/Blocks/BlockTallGrass.h
index 702ebf14c..eea629bf5 100644
--- a/source/Blocks/BlockTallGrass.h
+++ b/source/Blocks/BlockTallGrass.h
@@ -34,9 +34,9 @@ public:
}
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- return a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) != E_BLOCK_AIR;
+ return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
}
diff --git a/source/Blocks/BlockTorch.h b/source/Blocks/BlockTorch.h
index 43c5cdb4c..3cc487421 100644
--- a/source/Blocks/BlockTorch.h
+++ b/source/Blocks/BlockTorch.h
@@ -98,6 +98,7 @@ public:
}
+ /*
virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
{
if (TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
@@ -107,12 +108,16 @@ public:
return (FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ) != BLOCK_FACE_BOTTOM);
}
+ */
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
- char Face = cTorch::MetaDataToDirection(a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
- return TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, Face);
+ // TODO: Use cTorch::AdjustCoordsByMeta(), then cChunk::UnboundedRelGetBlock() and finally some comparison
+ char Face = cTorch::MetaDataToDirection(a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ return TorchCanBePlacedAt(a_Chunk.GetWorld(), BlockX, a_RelY, BlockZ, Face);
}
diff --git a/source/Blocks/BlockVine.h b/source/Blocks/BlockVine.h
index 2f35c11d9..88338e86d 100644
--- a/source/Blocks/BlockVine.h
+++ b/source/Blocks/BlockVine.h
@@ -25,45 +25,98 @@ public:
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
+ // TODO: Disallow placement where the vine doesn't attach to something properly
+ BLOCKTYPE BlockType = 0;
+ NIBBLETYPE BlockMeta;
+ a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
+ if (BlockType == m_BlockType)
+ {
+ a_BlockMeta = BlockMeta | cVine::DirectionToMetaData(a_BlockFace);
+ }
+ else
+ {
+ a_BlockMeta = cVine::DirectionToMetaData(a_BlockFace);
+ }
a_BlockType = m_BlockType;
- a_BlockMeta = cVine::DirectionToMetaData(a_BlockFace);
return true;
}
- virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
+ /// Returns true if the specified block type is good for vines to attach to
+ static bool IsBlockAttachable(BLOCKTYPE a_BlockType)
{
- if (
- (a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ ) == E_BLOCK_VINES) &&
- (cVine::MetaDataToDirection(a_World->GetBlockMeta(a_BlockX, a_BlockY + 1, a_BlockZ)) == a_BlockFace)
- )
+ return (a_BlockType == E_BLOCK_LEAVES) || g_BlockIsSolid[a_BlockType];
+ }
+
+
+ /// Returns the meta that has the maximum allowable sides of the vine, given the surroundings
+ NIBBLETYPE GetMaxMeta(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
+ {
+ static const struct
{
- return true;
- }
-
- BLOCKTYPE TopBlock = a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ);
- if (g_BlockIsSolid[TopBlock] || (TopBlock == E_BLOCK_LEAVES))
+ int x, z;
+ int Bit;
+ } Coords[] =
{
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
- BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- if (!g_BlockIsSolid[BaseBlock] && (BaseBlock != E_BLOCK_LEAVES))
+ { 0, 1, 1}, // south, ZP
+ {-1, 0, 2}, // west, XM
+ { 0, -1, 4}, // north, ZM
+ { 1, 0, 8}, // east, XP
+ } ;
+ int res = 0;
+ for (int i = 0; i < ARRAYCOUNT(Coords); i++)
+ {
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ if (
+ a_Chunk.UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta) &&
+ IsBlockAttachable(BlockType)
+ )
{
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false);
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_VINES, 0);
+ res |= Coords[i].Bit;
}
- return true;
}
-
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
- BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- return (g_BlockIsSolid[BaseBlock] || (BaseBlock == E_BLOCK_LEAVES));
+ return res;
}
-
-
- virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
+
+
+ void Check(int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk) override
{
- char Dir = cVine::MetaDataToDirection(a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ));
- return CanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, Dir);
+ NIBBLETYPE CurMeta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
+ NIBBLETYPE MaxMeta = GetMaxMeta(a_Chunk, a_RelX, a_RelY, a_RelZ);
+
+ // Check if vine above us, add its meta to MaxMeta
+ if ((a_RelY < cChunkDef::Height - 1) && (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == m_BlockType))
+ {
+ MaxMeta |= a_Chunk.GetMeta(a_RelX, a_RelY + 1, a_RelZ);
+ }
+
+ NIBBLETYPE Common = CurMeta & MaxMeta; // Neighbors that we have and are legal
+ if (Common != CurMeta)
+ {
+ // There is a neighbor missing, need to update the meta or even destroy the block
+ bool HasTop = (a_RelY < cChunkDef::Height - 1) && IsBlockAttachable(a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ));
+ if ((Common == 0) && !HasTop)
+ {
+ // The vine just lost all its support, destroy the block:
+ if (DoesDropOnUnsuitable())
+ {
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ DropBlock(a_Chunk.GetWorld(), NULL, BlockX, a_RelY, BlockZ);
+ }
+ a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0);
+ return;
+ }
+ a_Chunk.SetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, Common);
+ }
+ else
+ {
+ // Wake up the simulators for this block:
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ a_Chunk.GetWorld()->GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, &a_Chunk);
+ }
}