
// BlockFarmland.h

// Declares the cBlcokFarmlandHandler representing the block handler for farmland





#pragma once

#include "BlockHandler.h"
#include "../BlockArea.h"





class cBlockFarmlandHandler :
	public cBlockHandler
{
	typedef cBlockHandler super;
	
public:
	cBlockFarmlandHandler(void) :
		super(E_BLOCK_FARMLAND)
	{
	}


	virtual void OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
	{
		// TODO: Rain hydrates farmland, too. Check world weather, don't search for water if raining.
		// NOTE: The desert biomes do not get precipitation, so another check needs to be made.
		
		// Search for water in a close proximity:
		// Ref.: http://www.minecraftwiki.net/wiki/Farmland#Hydrated_Farmland_Tiles
		cBlockArea Area;
		if (!Area.Read(a_World, a_BlockX - 4, a_BlockX + 4, a_BlockY, a_BlockY + 1, a_BlockZ - 4, a_BlockZ + 4))
		{
			// Too close to the world edge, cannot check surroudnings; don't tick at all
			return;
		}
		bool Found = false;
		int NumBlocks = Area.GetBlockCount();
		BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
		for (int i = 0; i < NumBlocks; i++)
		{
			if (
				(BlockTypes[i] == E_BLOCK_WATER) ||
				(BlockTypes[i] == E_BLOCK_STATIONARY_WATER)
			)
			{
				Found = true;
				break;
			}
		}
		
		NIBBLETYPE BlockMeta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
		
		if (Found)
		{
			// Water was found, hydrate the block until hydration reaches 7:
			if (BlockMeta < 7)
			{
				a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, ++BlockMeta);
			}
			return;
		}

		// Water wasn't found, de-hydrate block:
		if (BlockMeta > 0)
		{
			a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, --BlockMeta);
			return;
		}
		
		// Farmland too dry. If nothing is growing on top, turn back to dirt:
		switch (a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))
		{
			case E_BLOCK_CROPS:
			case E_BLOCK_MELON_STEM:
			case E_BLOCK_PUMPKIN_STEM:
			{
				// Produce on top, don't revert
				break;
			}
			default:
			{
				a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DIRT, 0);
				break;
			}
		}
	}
} ;




