From d7669c6709d3c8818bcffd30f65a9b77eeaed81c Mon Sep 17 00:00:00 2001
From: "madmaxoft@gmail.com"
 <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>
Date: Sun, 17 Jun 2012 05:34:37 +0000
Subject: [PATCH] Fixed leaves blockticking - must touch neighboring chunks,
 too, instead of self at wrong places.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@626 0a769ca7-a7f5-676a-18bf-c427514a06d6
---
 source/cChunk.cpp | 77 +++++++++++++++++++++++++++++++++--------------
 source/cChunk.h   |  1 +
 2 files changed, 55 insertions(+), 23 deletions(-)

diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index 70ece5893..647478339 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -591,29 +591,7 @@ void cChunk::TickBlocks(MTRand & a_TickRandom)
 				break;
 			}
 			
-			case E_BLOCK_LEAVES:
-			{
-				NIBBLETYPE Meta = GetMeta(m_BlockTickX, m_BlockTickY, m_BlockTickZ);
-				if (((Meta & 0x04) == 0) && ((Meta & 0x08) == 1)){
-					int x,y,z,f = 0;
-					for( y = 4; y > - 5; y-- ) {
-						for( x = - 4; x < 5; x++ ){
-							for( z = - 4; z < 5; z++ ){
-								if((x<0 ? -x : x) + (y<0 ? -y : y) + (z<0 ? -z : z) > 4) continue;
-								if(GetBlock(m_BlockTickX + x, m_BlockTickY + y, m_BlockTickZ + z) == E_BLOCK_LOG){
-									f = 1;
-								}
-							}
-						}
-					}
-					if(f==0){
-						SetBlock(m_BlockTickX, m_BlockTickY, m_BlockTickZ, 0, 0);
-					}else{
-						SetMeta(m_BlockTickX, m_BlockTickY, m_BlockTickZ, Meta -= 8);
-					}
-				}
-				break;
-			}
+			case E_BLOCK_LEAVES: TickLeaves(m_BlockTickX, m_BlockTickY, m_BlockTickZ); break;
 			
 			default:
 			{
@@ -759,6 +737,59 @@ void cChunk::TickFarmland(int a_RelX, int a_RelY, int a_RelZ)
 
 
 
+void cChunk::TickLeaves(int a_RelX, int a_RelY, int a_RelZ)
+{
+	// Since leaves-checking is a costly operation, it is done only if leaves are marked for checking (Meta has its 0x08 bit cleared)
+	// TODO: The meta is cleared (check flag set) each time a block next to the leaves changes
+	
+	NIBBLETYPE Meta = GetMeta(m_BlockTickX, m_BlockTickY, m_BlockTickZ);
+	if ((Meta & 0x04) != 0)
+	{
+		// Player-placed leaves, don't decay
+		return;
+	}
+	if ((Meta & 0x08) == 0)
+	{
+		// These leaves have been checked for decay lately and nothing around them changed
+		return;
+	}
+	
+	// TODO: We need a proper BFS check - is the leaves block connected to a log via other leaves blocks?
+	for (int y = 4; y > - 5; y--)
+	{
+		for (int z = - 4; z < 5; z++ )
+		{
+			for (int x = - 4; x < 5; x++ )
+			{
+				if (abs(x) + abs(y) + abs(z) > 4)
+				{
+					// Too far away
+					continue;
+				}
+				BLOCKTYPE  BlockType;
+				NIBBLETYPE BlockMeta;
+				if (!UnboundedRelGetBlock(a_RelX + x, a_RelY + y, a_RelZ + z, BlockType, BlockMeta))
+				{
+					// Too close to unloaded chunks, don't check at all
+					return;
+				} 
+				if (BlockType == E_BLOCK_LOG)
+				{
+					// Wood found, the leaves stay; mark them as checked:
+					SetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ, Meta & 0x07);
+					return;
+				}
+			}
+		}
+	}
+	// Decay the leaves. Let them drop something if the random is right
+	m_World->DigBlock(m_PosX * cChunkDef::Width + a_RelX, a_RelY, m_PosZ * cChunkDef::Width + a_RelZ);
+}
+
+
+
+
+
 void cChunk::GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_TickRandom)
 {
 	// Convert the stem BlockType into produce BlockType
diff --git a/source/cChunk.h b/source/cChunk.h
index 7ebb37e43..9ecbe89b8 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -237,6 +237,7 @@ private:
 	void TickGrass       (int a_RelX, int a_RelY, int a_RelZ, MTRand & a_TickRandom);
 	void TickMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, int a_BlockIdx, BLOCKTYPE a_BlockType, MTRand & a_TickRandom);
 	void TickFarmland    (int a_RelX, int a_RelY, int a_RelZ);
+	void TickLeaves      (int a_RelX, int a_RelY, int a_RelZ);
 	
 	/// Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking)
 	void GrowSugarcane   (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);