summaryrefslogtreecommitdiffstats
path: root/src/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'src/Blocks')
-rw-r--r--src/Blocks/BlockDoor.h4
-rw-r--r--src/Blocks/BlockSapling.h142
-rw-r--r--src/Blocks/BlockTorch.h16
3 files changed, 155 insertions, 7 deletions
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index 4773e6f0a..79ed4f723 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -55,6 +55,10 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
+ if ((a_BlockMeta & 0x08) != 0) // is top part of door
+ {
+ return;
+ }
switch (m_BlockType)
{
case E_BLOCK_WOODEN_DOOR:
diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h
index bec79c6f3..c15e0a195 100644
--- a/src/Blocks/BlockSapling.h
+++ b/src/Blocks/BlockSapling.h
@@ -3,6 +3,7 @@
#include "BlockHandler.h"
#include "../World.h"
+#include "../FastRandom.h"
@@ -34,17 +35,144 @@ public:
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
{
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
-
- if ((Meta & 0x08) != 0)
+ NIBBLETYPE Light = std::max(a_Chunk.GetBlockLight(a_RelX, a_RelY, a_RelZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelX, a_RelY, a_RelZ)));
+
+ // Only grow if we have the right amount of light
+ if (Light > 8)
+ {
+ cFastRandom random;
+ // Only grow if we are in the right growth stage and have the right amount of space around them.
+ if (((Meta & 0x08) != 0) && (random.NextInt(99) < 45) && CanGrowAt(a_Chunk, a_RelX, a_RelY, a_RelZ, Meta))
+ {
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ a_Chunk.GetWorld()->GrowTree(BlockX, a_RelY, BlockZ);
+ }
+ // Only move to the next growth stage if we haven't gone there yet
+ else if (((Meta & 0x08) == 0) && (random.NextInt(99) < 45))
+ {
+ a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08);
+ }
+ }
+ }
+
+ bool CanGrowAt(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
+ {
+ a_Meta = a_Meta & 0x07;
+ int CheckHeight = 0;
+ bool LargeTree = false;
+
+ // Get the height to check against
+ switch (a_Meta)
{
- int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
- int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
- a_Chunk.GetWorld()->GrowTree(BlockX, a_RelY, BlockZ);
+ case E_META_SAPLING_APPLE:
+ {
+ CheckHeight = 5;
+ break;
+ }
+ case E_META_SAPLING_CONIFER:
+ {
+ CheckHeight = 7;
+ if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta))
+ {
+ CheckHeight = 16;
+ LargeTree = true;
+ }
+ break;
+ }
+ case E_META_SAPLING_BIRCH:
+ {
+ CheckHeight = 6;
+ break;
+ }
+ case E_META_SAPLING_JUNGLE:
+ {
+ CheckHeight = 7;
+ if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta))
+ {
+ CheckHeight = 13;
+ LargeTree = true;
+ }
+ break;
+ }
+ // Dark Oaks only grow in a 2x2 area
+ case E_META_SAPLING_DARK_OAK:
+ {
+ if (!IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta))
+ {
+ return false;
+ }
+ CheckHeight = 7;
+ LargeTree = true;
+ break;
+ }
}
- else
+ // We should always get a valid CheckHeight
+ ASSERT(CheckHeight != 0);
+
+ // Don't grow a tree if we don't have enough space left above it in the chunk
+ if ((a_RelY + CheckHeight) > cChunkDef::Height)
+ {
+ return false;
+ }
+ bool CanGrow = true;
+
+ // Validate the neighbor blocks. They cannot be solid.
+ BLOCKTYPE check = E_BLOCK_AIR;
+ a_Chunk.UnboundedRelGetBlockType(a_RelX - 1, a_RelY, a_RelZ, check);
+ CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
+
+ a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY, a_RelZ, check);
+ CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
+
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ - 1, check);
+ CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
+
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ + 1, check);
+ CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
+
+
+
+ while (CheckHeight && CanGrow)
{
- a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08);
+ check = a_Chunk.GetBlock(a_RelX, a_RelY + CheckHeight, a_RelZ);
+ CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
+
+ // We have to check above the neighboring saplings as well
+ if (LargeTree)
+ {
+ a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ, check);
+ CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
+
+ a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY + CheckHeight, a_RelZ + 1, check);
+ CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
+
+ a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ + 1, check);
+ CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
+ }
+
+ --CheckHeight;
}
+
+ return CanGrow;
+ }
+
+private:
+ bool IsLargeTree(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
+ {
+ BLOCKTYPE type;
+ NIBBLETYPE meta;
+ bool LargeTree = true;
+ a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ, type, meta);
+ LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
+
+ a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ + 1, type, meta);
+ LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
+
+ a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ + 1, type, meta);
+ LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
+
+ return LargeTree;
}
} ;
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index 36d2fec67..0a834d13d 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -119,6 +119,22 @@ public:
// Toches can be placed on the top of these slabs only if the occupy the top half of the voxel
return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08));
}
+ case E_BLOCK_WOODEN_STAIRS:
+ case E_BLOCK_COBBLESTONE_STAIRS:
+ case E_BLOCK_BRICK_STAIRS:
+ case E_BLOCK_STONE_BRICK_STAIRS:
+ case E_BLOCK_NETHER_BRICK_STAIRS:
+ case E_BLOCK_SANDSTONE_STAIRS:
+ case E_BLOCK_SPRUCE_WOOD_STAIRS:
+ case E_BLOCK_BIRCH_WOOD_STAIRS:
+ case E_BLOCK_JUNGLE_WOOD_STAIRS:
+ case E_BLOCK_QUARTZ_STAIRS:
+ case E_BLOCK_ACACIA_WOOD_STAIRS:
+ case E_BLOCK_DARK_OAK_WOOD_STAIRS:
+ case E_BLOCK_RED_SANDSTONE_STAIRS:
+ {
+ return (a_BlockFace == BLOCK_FACE_TOP) && (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN);
+ }
default:
{
if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))