summaryrefslogtreecommitdiffstats
path: root/source/blocks
diff options
context:
space:
mode:
authorlapayo94@gmail.com <lapayo94@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-07-15 22:36:34 +0200
committerlapayo94@gmail.com <lapayo94@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2012-07-15 22:36:34 +0200
commit14dce238450b419a5df2aa171ee91981910463b0 (patch)
treeaca42ecae2e62c44847db375a2f7ae6823ed3e9e /source/blocks
parentcThread uses AString instead of char * for name (fixed a warning) (diff)
downloadcuberite-14dce238450b419a5df2aa171ee91981910463b0.tar
cuberite-14dce238450b419a5df2aa171ee91981910463b0.tar.gz
cuberite-14dce238450b419a5df2aa171ee91981910463b0.tar.bz2
cuberite-14dce238450b419a5df2aa171ee91981910463b0.tar.lz
cuberite-14dce238450b419a5df2aa171ee91981910463b0.tar.xz
cuberite-14dce238450b419a5df2aa171ee91981910463b0.tar.zst
cuberite-14dce238450b419a5df2aa171ee91981910463b0.zip
Diffstat (limited to 'source/blocks')
-rw-r--r--source/blocks/Block.cpp302
-rw-r--r--source/blocks/Block.h54
-rw-r--r--source/blocks/BlockCactus.h51
-rw-r--r--source/blocks/BlockChest.h22
-rw-r--r--source/blocks/BlockCloth.cpp9
-rw-r--r--source/blocks/BlockCloth.h14
-rw-r--r--source/blocks/BlockCrops.h56
-rw-r--r--source/blocks/BlockDirt.cpp9
-rw-r--r--source/blocks/BlockDirt.h62
-rw-r--r--source/blocks/BlockDispenser.h22
-rw-r--r--source/blocks/BlockDoor.cpp60
-rw-r--r--source/blocks/BlockDoor.h29
-rw-r--r--source/blocks/BlockEntity.cpp15
-rw-r--r--source/blocks/BlockEntity.h16
-rw-r--r--source/blocks/BlockFire.cpp24
-rw-r--r--source/blocks/BlockFire.h14
-rw-r--r--source/blocks/BlockFlower.h32
-rw-r--r--source/blocks/BlockFluid.h20
-rw-r--r--source/blocks/BlockFurnace.h27
-rw-r--r--source/blocks/BlockGlowstone.h22
-rw-r--r--source/blocks/BlockIce.h26
-rw-r--r--source/blocks/BlockLadder.h28
-rw-r--r--source/blocks/BlockLeaves.h162
-rw-r--r--source/blocks/BlockMelon.h24
-rw-r--r--source/blocks/BlockMushroom.h42
-rw-r--r--source/blocks/BlockPiston.cpp51
-rw-r--r--source/blocks/BlockPiston.h15
-rw-r--r--source/blocks/BlockRedstone.cpp41
-rw-r--r--source/blocks/BlockRedstone.h33
-rw-r--r--source/blocks/BlockRedstoneOre.h26
-rw-r--r--source/blocks/BlockRedstoneRepeater.cpp34
-rw-r--r--source/blocks/BlockRedstoneRepeater.h46
-rw-r--r--source/blocks/BlockRedstoneTorch.h30
-rw-r--r--source/blocks/BlockSapling.h51
-rw-r--r--source/blocks/BlockSign.h42
-rw-r--r--source/blocks/BlockSlab.cpp17
-rw-r--r--source/blocks/BlockSlab.h33
-rw-r--r--source/blocks/BlockSnow.h39
-rw-r--r--source/blocks/BlockStairs.cpp18
-rw-r--r--source/blocks/BlockStairs.h14
-rw-r--r--source/blocks/BlockStems.h41
-rw-r--r--source/blocks/BlockStone.h18
-rw-r--r--source/blocks/BlockSugarcane.h43
-rw-r--r--source/blocks/BlockTallGrass.h35
-rw-r--r--source/blocks/BlockTorch.cpp15
-rw-r--r--source/blocks/BlockTorch.h25
-rw-r--r--source/blocks/BlockVine.cpp17
-rw-r--r--source/blocks/BlockVine.h23
-rw-r--r--source/blocks/BlockWood.h17
-rw-r--r--source/blocks/BlockWorkbench.cpp24
-rw-r--r--source/blocks/BlockWorkbench.h19
51 files changed, 1909 insertions, 0 deletions
diff --git a/source/blocks/Block.cpp b/source/blocks/Block.cpp
new file mode 100644
index 000000000..047caa989
--- /dev/null
+++ b/source/blocks/Block.cpp
@@ -0,0 +1,302 @@
+#include "Globals.h"
+#include "Block.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+#include "BlockDoor.h"
+#include "BlockFire.h"
+#include "BlockRedstone.h"
+#include "BlockRedstoneTorch.h"
+#include "BlockRedstoneRepeater.h"
+#include "BlockPiston.h"
+#include "BlockWorkbench.h"
+#include "BlockEntity.h"
+#include "BlockVine.h"
+#include "BlockTallGrass.h"
+#include "BlockSnow.h"
+#include "BlockCloth.h"
+#include "BlockSlab.h"
+#include "BlockDirt.h"
+#include "BlockTorch.h"
+#include "BlockWood.h"
+#include "BlockLeaves.h"
+#include "BlockSapling.h"
+#include "BlockFluid.h"
+#include "BlockChest.h"
+#include "BlockFurnace.h"
+#include "BlockDispenser.h"
+#include "BlockStairs.h"
+#include "BlockLadder.h"
+#include "BlockSign.h"
+#include "BlockCrops.h"
+#include "BlockSugarcane.h"
+#include "BlockFlower.h"
+#include "BlockMushroom.h"
+#include "BlockCactus.h"
+#include "BlockStems.h"
+#include "BlockGlowstone.h"
+#include "BlockRedstoneOre.h"
+#include "BlockStone.h"
+#include "BlockMelon.h"
+#include "BlockIce.h"
+
+bool cBlockHandler::m_HandlerInitialized = false;
+cBlockHandler *cBlockHandler::m_BlockHandler[256];
+
+cBlockHandler *cBlockHandler::GetBlockHandler(char a_BlockID)
+{
+ if(!m_HandlerInitialized)
+ { //We have to initialize
+ memset(m_BlockHandler, 0, sizeof(m_BlockHandler));
+ m_HandlerInitialized = true;
+ }
+ if(m_BlockHandler[a_BlockID])
+ return m_BlockHandler[a_BlockID];
+
+ return m_BlockHandler[a_BlockID] = CreateBlockHandler(a_BlockID);
+}
+
+cBlockHandler *cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockID)
+{
+ switch(a_BlockID)
+ {
+ case E_BLOCK_WOODEN_DOOR:
+ case E_BLOCK_IRON_DOOR:
+ return new cBlockDoorHandler(a_BlockID);
+ case E_BLOCK_FIRE:
+ return new cBlockFireHandler(a_BlockID);
+ case E_BLOCK_REDSTONE_TORCH_ON:
+ case E_BLOCK_REDSTONE_TORCH_OFF:
+ return new cBlockRedstoneTorchHandler(a_BlockID);
+ case E_BLOCK_REDSTONE_WIRE:
+ return new cBlockRedstoneHandler(a_BlockID);
+ case E_BLOCK_PISTON:
+ case E_BLOCK_STICKY_PISTON:
+ return new cBlockPistonHandler(a_BlockID);
+ case E_BLOCK_REDSTONE_REPEATER_ON:
+ case E_BLOCK_REDSTONE_REPEATER_OFF:
+ return new cBlockRedstoneRepeaterHandler(a_BlockID);
+ case E_BLOCK_WORKBENCH:
+ return new cBlockWorkbenchHandler(a_BlockID);
+ case E_BLOCK_SNOW:
+ return new cBlockSnowHandler(a_BlockID);
+ case E_BLOCK_TALL_GRASS:
+ return new cBlockTallGrassHandler(a_BlockID);
+ case E_BLOCK_VINES:
+ return new cBlockVineHandler(a_BlockID);
+ case ::E_BLOCK_WOOL:
+ return new cBlockClothHandler(a_BlockID);
+ case E_BLOCK_WOODEN_SLAB:
+ case E_BLOCK_STONE_SLAB:
+ case E_BLOCK_DOUBLE_WOODEN_SLAB:
+ case E_BLOCK_DOUBLE_STONE_SLAB:
+ return new cBlockSlabHandler(a_BlockID);
+ case E_BLOCK_LOG:
+ case E_BLOCK_PLANKS:
+ return new cBlockWoodHandler(a_BlockID);
+ case E_BLOCK_TORCH:
+ return new cBlockTorchHandler(a_BlockID);
+ case E_BLOCK_DIRT:
+ case E_BLOCK_GRASS:
+ return new cBlockDirtHandler(a_BlockID);
+ case E_BLOCK_LEAVES:
+ return new cBlockLeavesHandler(a_BlockID);
+ case E_BLOCK_SAPLING:
+ return new cBlockSaplingHandler(a_BlockID);
+ case E_BLOCK_WATER:
+ case E_BLOCK_STATIONARY_WATER:
+ case E_BLOCK_STATIONARY_LAVA:
+ case E_BLOCK_LAVA:
+ return new cBlockFluidHandler(a_BlockID);
+ case E_BLOCK_DISPENSER:
+ return new cBlockDispenserHandler(a_BlockID);
+ case E_BLOCK_FURNACE:
+ case E_BLOCK_LIT_FURNACE:
+ return new cBlockFurnaceHandler(a_BlockID);
+ case E_BLOCK_CHEST:
+ return new cBlockChestHandler(a_BlockID);
+ case E_BLOCK_ICE:
+ return new cBlockIceHandler(a_BlockID);
+ case E_BLOCK_LADDER:
+ return new cBlockLadderHandler(a_BlockID);
+ 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_WOODEN_STAIRS:
+ return new cBlockStairsHandler(a_BlockID);
+ case E_BLOCK_SIGN_POST:
+ case E_BLOCK_WALLSIGN:
+ return new cBlockSignHandler(a_BlockID);
+ case E_BLOCK_CROPS:
+ return new cBlockCropsHandler(a_BlockID);
+ case E_BLOCK_SUGARCANE:
+ return new cBlockSugarcaneHandler(a_BlockID);
+ case E_BLOCK_YELLOW_FLOWER:
+ case E_BLOCK_RED_ROSE:
+ return new cBlockFlowerHandler(a_BlockID);
+ case E_BLOCK_BROWN_MUSHROOM:
+ case E_BLOCK_RED_MUSHROOM:
+ return new cBlockMushroomHandler(a_BlockID);
+ case E_BLOCK_CACTUS:
+ return new cBlockCactusHandler(a_BlockID);
+ case E_BLOCK_MELON_STEM:
+ case E_BLOCK_PUMPKIN_STEM:
+ return new cBlockStemsHandler(a_BlockID);
+ case E_BLOCK_GLOWSTONE:
+ return new cBlockGlowstoneHandler(a_BlockID);
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ return new cBlockRedstoneOreHandler(a_BlockID);
+ case E_BLOCK_STONE:
+ case E_BLOCK_COBBLESTONE:
+ return new cBlockStoneHandler(a_BlockID);
+ case E_BLOCK_MELON:
+ return new cBlockMelonHandler(a_BlockID);
+ default:
+ return new cBlockHandler(a_BlockID);
+ break;
+ }
+}
+
+void cBlockHandler::Deinit()
+{
+ for(int i = 0; i < 256; i++)
+ {
+ delete m_BlockHandler[i];
+ }
+}
+
+cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockID)
+{
+ m_BlockID = a_BlockID;
+}
+
+void cBlockHandler::OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+
+}
+
+void cBlockHandler::OnPlacedByPlayer(cWorld *a_World, cPlayer * a_Player, int a_X, int a_Y, int a_Z, int a_Dir)
+{
+}
+
+void cBlockHandler::OnDestroyedByPlayer(cWorld *a_World, cPlayer * a_Player, int a_X, int a_Y, int a_Z)
+{
+}
+
+void cBlockHandler::OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir)
+{
+ //Notify the neighbors
+ NeighborChanged(a_World, a_X - 1, a_Y, a_Z);
+ NeighborChanged(a_World, a_X + 1, a_Y, a_Z);
+ NeighborChanged(a_World, a_X, a_Y - 1, a_Z);
+ NeighborChanged(a_World, a_X, a_Y + 1, a_Z);
+ NeighborChanged(a_World, a_X, a_Y, a_Z - 1);
+ NeighborChanged(a_World, a_X, a_Y, a_Z + 1);
+}
+
+void cBlockHandler::OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ //Notify the neighbors
+ NeighborChanged(a_World, a_X - 1, a_Y, a_Z);
+ NeighborChanged(a_World, a_X + 1, a_Y, a_Z);
+ NeighborChanged(a_World, a_X, a_Y - 1, a_Z);
+ NeighborChanged(a_World, a_X, a_Y + 1, a_Z);
+ NeighborChanged(a_World, a_X, a_Y, a_Z - 1);
+ NeighborChanged(a_World, a_X, a_Y, a_Z + 1);
+}
+
+void cBlockHandler::NeighborChanged(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ GetBlockHandler(a_World->GetBlock(a_X, a_Y, a_Z))->OnNeighborChanged(a_World, a_X, a_Y, a_Z);
+}
+
+void cBlockHandler::OnNeighborChanged(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+
+}
+
+void cBlockHandler::OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+
+}
+
+void cBlockHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, a_BlockMeta);
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+}
+
+
+int cBlockHandler::GetTickRate()
+{
+ return 10;
+}
+
+char cBlockHandler::GetDropCount()
+{
+ return 1;
+}
+
+int cBlockHandler::GetDropID()
+{
+ return m_BlockID;
+}
+
+char cBlockHandler::GetDropMeta(char a_BlockMeta)
+{
+ return a_BlockMeta; //This keeps most textures. The few other blocks have to override this
+}
+
+void cBlockHandler::DropBlock(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ cItems Drops;
+ char Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+ char DropCount = GetDropCount();
+ int DropItem = GetDropID();
+ if(DropCount > 0 && DropItem != E_ITEM_EMPTY)
+ {
+ Drops.push_back(cItem((ENUM_ITEM_ID)DropItem, DropCount, GetDropMeta(Meta)));
+ a_World->SpawnItemPickups(Drops, a_X, a_Y, a_Z);
+ }
+}
+
+bool cBlockHandler::CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ return true;
+}
+
+bool cBlockHandler::IsUseable()
+{
+ return false;
+}
+
+bool cBlockHandler::IsClickedThrough()
+{
+ return false;
+}
+
+bool cBlockHandler::IgnoreBuildCollision()
+{
+ return m_BlockID == E_BLOCK_AIR;
+}
+
+bool cBlockHandler::NeedsRandomTicks()
+{
+ return false;
+}
+
+bool cBlockHandler::AllowBlockOnTop()
+{
+ return true;
+}
+
+bool cBlockHandler::CanBePlacedOnSide()
+{
+ return true;
+}
+
+bool cBlockHandler::DropOnUnsuitable()
+{
+ return true;
+} \ No newline at end of file
diff --git a/source/blocks/Block.h b/source/blocks/Block.h
new file mode 100644
index 000000000..09cff8487
--- /dev/null
+++ b/source/blocks/Block.h
@@ -0,0 +1,54 @@
+#pragma once
+#include "../Defines.h"
+
+class cWorld;
+class cPlayer;
+
+
+
+class cBlockHandler
+{
+public:
+ cBlockHandler(BLOCKTYPE a_BlockID);
+ //Called when the block gets ticked
+ virtual void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ virtual void OnPlacedByPlayer(cWorld *a_World, cPlayer * a_Player, int a_X, int a_Y, int a_Z, int a_Dir);
+ virtual void OnDestroyedByPlayer(cWorld *a_World, cPlayer * a_Player, int a_X, int a_Y, int a_Z);
+ virtual void OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir);
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ virtual void OnNeighborChanged(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ static void NeighborChanged(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ virtual void OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ virtual int GetTickRate();
+ virtual char GetDropCount();
+ virtual int GetDropID();
+ virtual char GetDropMeta(char a_BlockMeta);
+ virtual bool NeedsRandomTicks();
+ //Item is -2 if it wasn´t a player
+ virtual void DropBlock(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ //This gets called if the player tries to place a block ontop of this block (Only if he aims directly on this block)
+ virtual bool AllowBlockOnTop();
+ virtual bool IsUseable();
+ virtual bool IsClickedThrough();
+ virtual bool IgnoreBuildCollision();
+ //Indicates this block can be placed on the side of other blocks. Default: true
+ virtual bool CanBePlacedOnSide();
+ //Does this block drops if it gets destroyed by an unsuitable situation? Default: true
+ virtual bool DropOnUnsuitable();
+
+ static cBlockHandler *GetBlockHandler(char a_BlockID);
+
+ static void Deinit();
+
+protected:
+ char m_BlockID;
+ static cBlockHandler *CreateBlockHandler(BLOCKTYPE a_BlockID);
+ static cBlockHandler *m_BlockHandler[256];
+ static bool m_HandlerInitialized; //used to detect if the blockhandlers are initialized
+};
+
+
+inline cBlockHandler *BlockHandler(char a_BlockID) { return cBlockHandler::GetBlockHandler(a_BlockID); } \ No newline at end of file
diff --git a/source/blocks/BlockCactus.h b/source/blocks/BlockCactus.h
new file mode 100644
index 000000000..4977d4a98
--- /dev/null
+++ b/source/blocks/BlockCactus.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockCactusHandler : public cBlockHandler
+{
+public:
+ cBlockCactusHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return 0;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ BLOCKTYPE Surface = a_World->GetBlock(a_X, a_Y - 1, a_Z);
+ if ((Surface != E_BLOCK_SAND) && (Surface != E_BLOCK_CACTUS))
+ {
+ // Cactus can only be placed on sand and itself
+ return false;
+ }
+
+ // Check surroundings. Cacti may ONLY be surrounded by air
+ if (
+ (a_World->GetBlock(a_X - 1, a_Y, a_Z) != E_BLOCK_AIR) ||
+ (a_World->GetBlock(a_X + 1, a_Y, a_Z) != E_BLOCK_AIR) ||
+ (a_World->GetBlock(a_X, a_Y, a_Z - 1) != E_BLOCK_AIR) ||
+ (a_World->GetBlock(a_X, a_Y, a_Z + 1) != E_BLOCK_AIR)
+ )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockChest.h b/source/blocks/BlockChest.h
new file mode 100644
index 000000000..557b2d640
--- /dev/null
+++ b/source/blocks/BlockChest.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "BlockEntity.h"
+#include "../cWorld.h"
+#include "../cPiston.h"
+#include "../cPlayer.h"
+
+class cBlockChestHandler : public cBlockEntityHandler
+{
+public:
+ cBlockChestHandler(BLOCKTYPE a_BlockID)
+ : cBlockEntityHandler(a_BlockID)
+ {
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+ }
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockCloth.cpp b/source/blocks/BlockCloth.cpp
new file mode 100644
index 000000000..a55b8dc7f
--- /dev/null
+++ b/source/blocks/BlockCloth.cpp
@@ -0,0 +1,9 @@
+#include "Globals.h"
+#include "BlockCloth.h"
+#include "../cItem.h"
+#include "../cPlayer.h"
+
+cBlockClothHandler::cBlockClothHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+} \ No newline at end of file
diff --git a/source/blocks/BlockCloth.h b/source/blocks/BlockCloth.h
new file mode 100644
index 000000000..dca7184cb
--- /dev/null
+++ b/source/blocks/BlockCloth.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockClothHandler : public cBlockHandler
+{
+public:
+ cBlockClothHandler(BLOCKTYPE a_BlockID);
+ char GetDropMeta(char a_BlockMeta)
+ {
+ return a_BlockMeta;
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockCrops.h b/source/blocks/BlockCrops.h
new file mode 100644
index 000000000..34af1a43c
--- /dev/null
+++ b/source/blocks/BlockCrops.h
@@ -0,0 +1,56 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+
+class cBlockCropsHandler : public cBlockHandler
+{
+public:
+ cBlockCropsHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool NeedsRandomTicks() override
+ {
+ return true;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_EMPTY;
+ }
+
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ MTRand rand;
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ ENUM_ITEM_ID Drop = E_ITEM_EMPTY;
+
+ cItems Drops;
+
+ if(Meta & 0x7) //Is Wheat
+ {
+ Drops.push_back(cItem(E_ITEM_WHEAT, 1, 0));
+ }
+ if(rand.randInt(3) == 0)
+ { //Drop an second seed
+ Drops.push_back(cItem(E_ITEM_SEEDS, 1, 0));
+ }
+ Drops.push_back(cItem(E_ITEM_SEEDS, 1, 0));
+ a_World->SpawnItemPickups(Drops, a_X, a_Y, a_Z);
+ }
+
+ void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+
+ //TODO: Handle Growing here
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) == E_BLOCK_FARMLAND;
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockDirt.cpp b/source/blocks/BlockDirt.cpp
new file mode 100644
index 000000000..ea8c6509d
--- /dev/null
+++ b/source/blocks/BlockDirt.cpp
@@ -0,0 +1,9 @@
+#include "Globals.h"
+#include "BlockDirt.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+
+cBlockDirtHandler::cBlockDirtHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
diff --git a/source/blocks/BlockDirt.h b/source/blocks/BlockDirt.h
new file mode 100644
index 000000000..49450b16d
--- /dev/null
+++ b/source/blocks/BlockDirt.h
@@ -0,0 +1,62 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+
+class cBlockDirtHandler : public cBlockHandler
+{
+public:
+ cBlockDirtHandler(BLOCKTYPE a_BlockID);
+
+
+ virtual bool NeedsRandomTicks()
+ {
+ return m_BlockID == E_BLOCK_GRASS;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_BLOCK_DIRT;
+ }
+
+
+ void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ if(m_BlockID == E_BLOCK_GRASS)
+ {
+ //Grass becomes dirt if there is something on top of them
+ BLOCKTYPE Above = a_World->GetBlock(a_X, a_Y + 1, a_Z);
+ if(!g_BlockTransparent[Above] && !g_BlockOneHitDig[Above])
+ {
+ a_World->FastSetBlock(a_X, a_Y, a_Z, E_BLOCK_DIRT, 0);
+ }
+
+
+ MTRand rand;
+ for (int i = 0; i < 2; i++) // Pick two blocks to grow to
+ {
+ int OfsX = rand.randInt(2) - 1; // [-1 .. 1]
+ int OfsY = rand.randInt(4) - 3; // [-3 .. 1]
+ int OfsZ = rand.randInt(2) - 1; // [-1 .. 1]
+
+ BLOCKTYPE DestBlock;
+ NIBBLETYPE DestMeta;
+ a_World->GetBlockTypeMeta(a_X + OfsX, a_Y + OfsY, a_Z + OfsZ, DestBlock, DestMeta);
+ if(DestBlock != E_BLOCK_DIRT)
+ {
+ continue;
+ }
+
+ BLOCKTYPE AboveDest;
+ NIBBLETYPE AboveMeta;
+ a_World->GetBlockTypeMeta(a_X + OfsX, a_Y + OfsY + 1, a_Z + OfsZ, AboveDest, AboveMeta);
+ if (g_BlockOneHitDig[AboveDest] || g_BlockTransparent[AboveDest])
+ {
+ a_World->FastSetBlock(a_X + OfsX, a_Y + OfsY, a_Z + OfsZ, E_BLOCK_GRASS, 0);
+ }
+ } // for i - repeat twice
+
+ }
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockDispenser.h b/source/blocks/BlockDispenser.h
new file mode 100644
index 000000000..4ccfe0dfc
--- /dev/null
+++ b/source/blocks/BlockDispenser.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "BlockEntity.h"
+#include "../cWorld.h"
+#include "../cPiston.h"
+#include "../cPlayer.h"
+
+class cBlockDispenserHandler : public cBlockEntityHandler
+{
+public:
+ cBlockDispenserHandler(BLOCKTYPE a_BlockID)
+ : cBlockEntityHandler(a_BlockID)
+ {
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+ }
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockDoor.cpp b/source/blocks/BlockDoor.cpp
new file mode 100644
index 000000000..e854281a5
--- /dev/null
+++ b/source/blocks/BlockDoor.cpp
@@ -0,0 +1,60 @@
+#include "Globals.h"
+#include "BlockDoor.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+#include "../cDoors.h"
+#include "../cPlayer.h"
+
+
+cBlockDoorHandler::cBlockDoorHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockDoorHandler::OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir)
+{
+
+}
+
+void cBlockDoorHandler::OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ char OldMeta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ if (OldMeta & 8)
+ {
+ // Was upper part of door
+ if (cDoors::IsDoor(a_World->GetBlock(a_X, a_Y - 1, a_Z)))
+ {
+ a_World->FastSetBlock(a_X, a_Y - 1, a_Z, E_BLOCK_AIR, 0);
+ }
+ }
+ else
+ {
+ // Was lower part
+ if (cDoors::IsDoor(a_World->GetBlock(a_X, a_Y + 1, a_Z)))
+ {
+ a_World->FastSetBlock(a_X, a_Y + 1, a_Z, E_BLOCK_AIR, 0);
+ }
+ }
+}
+
+void cBlockDoorHandler::OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+ cDoors::ChangeDoor(a_World, a_X, a_Y, a_Z);
+}
+
+char cBlockDoorHandler::GetDropCount()
+{
+ return 1;
+}
+
+void cBlockDoorHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ if (a_World->GetBlock(a_X, a_Y + 1, a_Z) == E_BLOCK_AIR)
+ {
+ a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation());
+ a_World->SetBlock(a_X, a_Y + 1, a_Z, m_BlockID, a_BlockMeta + 8);
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, a_BlockMeta);
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+ }
+} \ No newline at end of file
diff --git a/source/blocks/BlockDoor.h b/source/blocks/BlockDoor.h
new file mode 100644
index 000000000..180d3b48f
--- /dev/null
+++ b/source/blocks/BlockDoor.h
@@ -0,0 +1,29 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockDoorHandler : public cBlockHandler
+{
+public:
+ cBlockDoorHandler(BLOCKTYPE a_BlockID);
+ virtual void OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir);
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ virtual void OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+ virtual char GetDropCount();
+ virtual bool IsUseable()
+ {
+ return true;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ virtual int GetDropID()
+ {
+ return (m_BlockID == E_BLOCK_WOODEN_DOOR) ? E_ITEM_WOODEN_DOOR : E_ITEM_IRON_DOOR;
+ }
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockEntity.cpp b/source/blocks/BlockEntity.cpp
new file mode 100644
index 000000000..b34b01ee9
--- /dev/null
+++ b/source/blocks/BlockEntity.cpp
@@ -0,0 +1,15 @@
+#include "Globals.h"
+#include "BlockEntity.h"
+#include "../cItem.h"
+#include "../cPlayer.h"
+#include "../cWorld.h"
+
+cBlockEntityHandler::cBlockEntityHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockEntityHandler::OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+ a_World->UseBlockEntity(a_Player, a_X, a_Y, a_Z);
+}
diff --git a/source/blocks/BlockEntity.h b/source/blocks/BlockEntity.h
new file mode 100644
index 000000000..abdaa7615
--- /dev/null
+++ b/source/blocks/BlockEntity.h
@@ -0,0 +1,16 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockEntityHandler : public cBlockHandler
+{
+public:
+ cBlockEntityHandler(BLOCKTYPE a_BlockID);
+ virtual void OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+ virtual bool IsUseable()
+ {
+ return true;
+ }
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockFire.cpp b/source/blocks/BlockFire.cpp
new file mode 100644
index 000000000..5ca8dd902
--- /dev/null
+++ b/source/blocks/BlockFire.cpp
@@ -0,0 +1,24 @@
+#include "Globals.h"
+#include "BlockFire.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+
+cBlockFireHandler::cBlockFireHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockFireHandler::OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+ a_World->DigBlock(a_X, a_Y, a_Z);
+}
+
+char cBlockFireHandler::GetDropCount()
+{
+ return -1;
+}
+
+bool cBlockFireHandler::IsClickedThrough()
+{
+ return true;
+} \ No newline at end of file
diff --git a/source/blocks/BlockFire.h b/source/blocks/BlockFire.h
new file mode 100644
index 000000000..0a5396096
--- /dev/null
+++ b/source/blocks/BlockFire.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockFireHandler : public cBlockHandler
+{
+public:
+ cBlockFireHandler(BLOCKTYPE a_BlockID);
+ virtual void OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+ virtual bool IsClickedThrough();
+ virtual char GetDropCount();
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockFlower.h b/source/blocks/BlockFlower.h
new file mode 100644
index 000000000..12eaa4dc8
--- /dev/null
+++ b/source/blocks/BlockFlower.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockFlowerHandler : public cBlockHandler
+{
+public:
+ cBlockFlowerHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return 0;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return IsBlockTypeOfDirt(a_World->GetBlock(a_X, a_Y - 1, a_Z));
+ }
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockFluid.h b/source/blocks/BlockFluid.h
new file mode 100644
index 000000000..4da785523
--- /dev/null
+++ b/source/blocks/BlockFluid.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockFluidHandler : public cBlockHandler
+{
+public:
+ cBlockFluidHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+ virtual bool IgnoreBuildCollision()
+ {
+ return true;
+ }
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockFurnace.h b/source/blocks/BlockFurnace.h
new file mode 100644
index 000000000..927c925bd
--- /dev/null
+++ b/source/blocks/BlockFurnace.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "BlockEntity.h"
+#include "../cWorld.h"
+#include "../cPiston.h"
+#include "../cPlayer.h"
+
+class cBlockFurnaceHandler : public cBlockEntityHandler
+{
+public:
+ cBlockFurnaceHandler(BLOCKTYPE a_BlockID)
+ : cBlockEntityHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_FURNACE;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+ }
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockGlowstone.h b/source/blocks/BlockGlowstone.h
new file mode 100644
index 000000000..8d05cd799
--- /dev/null
+++ b/source/blocks/BlockGlowstone.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockGlowstoneHandler : public cBlockHandler
+{
+public:
+ cBlockGlowstoneHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return 0;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_GLOWSTONE_DUST;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockIce.h b/source/blocks/BlockIce.h
new file mode 100644
index 000000000..9b356e323
--- /dev/null
+++ b/source/blocks/BlockIce.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+
+class cBlockIceHandler : public cBlockHandler
+{
+public:
+ cBlockIceHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_EMPTY;
+ }
+
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ a_World->FastSetBlock(a_X, a_Y, a_Z, E_BLOCK_STATIONARY_WATER, 8);
+ //This is called later than the real destroying of this ice block
+ }
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockLadder.h b/source/blocks/BlockLadder.h
new file mode 100644
index 000000000..0b63cc8e6
--- /dev/null
+++ b/source/blocks/BlockLadder.h
@@ -0,0 +1,28 @@
+#pragma once
+#include "Block.h"
+#include "../cWorld.h"
+#include "../cLadder.h"
+
+class cBlockLadderHandler : public cBlockHandler
+{
+public:
+ cBlockLadderHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cLadder::DirectionToMetaData(a_Dir));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ char Dir = cLadder::MetaDataToDirection(a_World->GetBlockMeta( a_X, a_Y, a_Z));
+ AddDirection( a_X, a_Y, a_Z, Dir, true );
+ return a_World->GetBlock( a_X, a_Y, a_Z ) != E_BLOCK_AIR;
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockLeaves.h b/source/blocks/BlockLeaves.h
new file mode 100644
index 000000000..4bae2003f
--- /dev/null
+++ b/source/blocks/BlockLeaves.h
@@ -0,0 +1,162 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+#include "../BlockArea.h"
+
+
+
+// Leaves can be this many blocks that away (inclusive) from the log not to decay
+#define LEAVES_CHECK_DISTANCE 6
+
+#define PROCESS_NEIGHBOR(x,y,z) \
+ switch (a_Area.GetBlockType(x, y, z)) \
+ { \
+ case E_BLOCK_LEAVES: a_Area.SetBlockType(x, y, z, E_BLOCK_SPONGE + i + 1); break; \
+ case E_BLOCK_LOG: return true; \
+ }
+
+bool HasNearLog(cBlockArea &a_Area, int a_BlockX, int a_BlockY, int a_BlockZ);
+
+
+
+class cBlockLeavesHandler : public cBlockHandler
+{
+public:
+ cBlockLeavesHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID()
+ {
+ MTRand rand;
+
+ if(rand.randInt(5) == 0)
+ {
+ return E_ITEM_SAPLING;
+ }
+
+ return E_ITEM_EMPTY;
+ }
+
+ void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ cBlockHandler::OnDestroyed(a_World, a_X, a_Y, a_Z);
+
+ //0.5% chance of dropping an apple
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+ //check if Oak (0x1 and 0x2 bit not set)
+ MTRand rand;
+ if(!(Meta & 3) && rand.randInt(200) == 100)
+ {
+ cItems Drops;
+ Drops.push_back(cItem(E_ITEM_RED_APPLE, 1, 0));
+ a_World->SpawnItemPickups(Drops, a_X, a_Y, a_Z);
+ }
+ }
+
+ virtual void OnNeighborChanged(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+ a_World->SetBlockMeta(a_X, a_Y, a_Z, Meta & 0x7); //Unset 0x8 bit so it gets checked for decay
+ }
+
+ virtual bool NeedsRandomTicks()
+ {
+ return true;
+ }
+
+ virtual void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+ if ((Meta & 0x04) != 0)
+ {
+ // Player-placed leaves, don't decay
+ return;
+ }
+
+ if (Meta & 0x8)
+ {
+ // These leaves have been checked for decay lately and nothing around them changed
+ return;
+ }
+
+ // Get the data around the leaves:
+ cBlockArea Area;
+ if (!Area.Read(
+ a_World,
+ a_X - LEAVES_CHECK_DISTANCE, a_X + LEAVES_CHECK_DISTANCE,
+ a_Y - LEAVES_CHECK_DISTANCE, a_Y + LEAVES_CHECK_DISTANCE,
+ a_Z - LEAVES_CHECK_DISTANCE, a_Z + LEAVES_CHECK_DISTANCE,
+ cBlockArea::baTypes)
+ )
+ {
+ // Cannot check leaves, a chunk is missing too close
+ return;
+ }
+
+ if (HasNearLog(Area, a_X, a_Y, a_Z))
+ {
+ // Wood found, the leaves stay; mark them as checked:
+ a_World->SetBlockMeta(a_X, a_Y, a_Z, Meta | 0x8);
+ return;
+ }
+ // Decay the leaves:
+ DropBlock(a_World, a_X, a_Y, a_Z);
+
+ a_World->DigBlock(a_X, a_Y, a_Z);
+
+ }
+};
+
+
+bool HasNearLog(cBlockArea &a_Area, int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ // Filter the blocks into a {leaves, log, other (air)} set:
+ BLOCKTYPE * Types = a_Area.GetBlockTypes();
+ for (int i = a_Area.GetBlockCount() - 1; i > 0; i--)
+ {
+ switch (Types[i])
+ {
+ case E_BLOCK_LEAVES:
+ case E_BLOCK_LOG:
+ {
+ break;
+ }
+ default:
+ {
+ Types[i] = E_BLOCK_AIR;
+ break;
+ }
+ }
+ } // for i - Types[]
+
+ // Perform a breadth-first search to see if there's a log connected within 4 blocks of the leaves block:
+ // Simply replace all reachable leaves blocks with a sponge block plus iteration (in the Area) and see if we can reach a log in 4 iterations
+ a_Area.SetBlockType(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_SPONGE);
+ for (int i = 0; i < LEAVES_CHECK_DISTANCE; i++)
+ {
+ for (int y = a_BlockY - i; y <= a_BlockY + i; y++)
+ {
+ for (int z = a_BlockZ - i; z <= a_BlockZ + i; z++)
+ {
+ for (int x = a_BlockX - i; x <= a_BlockX + i; x++)
+ {
+ if (a_Area.GetBlockType(x, y, z) != E_BLOCK_SPONGE + i)
+ {
+ continue;
+ }
+ PROCESS_NEIGHBOR(x - 1, y, z);
+ PROCESS_NEIGHBOR(x + 1, y, z);
+ PROCESS_NEIGHBOR(x, y, z - 1);
+ PROCESS_NEIGHBOR(x, y, z + 1);
+ PROCESS_NEIGHBOR(x, y + 1, z);
+ PROCESS_NEIGHBOR(x, y - 1, z);
+ } // for x
+ } // for z
+ } // for y
+ } // for i - BFS iterations
+ return false;
+}
+
diff --git a/source/blocks/BlockMelon.h b/source/blocks/BlockMelon.h
new file mode 100644
index 000000000..921745795
--- /dev/null
+++ b/source/blocks/BlockMelon.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockMelonHandler : public cBlockHandler
+{
+public:
+ cBlockMelonHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_MELON_SLICE;
+ }
+
+ virtual char GetDropCount()
+ {
+ MTRand r1;
+ return 3 + r1.randInt(4);
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockMushroom.h b/source/blocks/BlockMushroom.h
new file mode 100644
index 000000000..5b2da6498
--- /dev/null
+++ b/source/blocks/BlockMushroom.h
@@ -0,0 +1,42 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockMushroomHandler : public cBlockHandler
+{
+public:
+ cBlockMushroomHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return 0;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ switch (a_World->GetBlock(a_X, a_Y - 1, a_Z))
+ {
+ case E_BLOCK_GLASS:
+ case E_BLOCK_CACTUS:
+ case E_BLOCK_ICE:
+ case E_BLOCK_LEAVES:
+ case E_BLOCK_AIR:
+ return false;
+ }
+ return true;
+ }
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockPiston.cpp b/source/blocks/BlockPiston.cpp
new file mode 100644
index 000000000..98463fd97
--- /dev/null
+++ b/source/blocks/BlockPiston.cpp
@@ -0,0 +1,51 @@
+#include "Globals.h"
+#include "BlockPiston.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+#include "../cRedstone.h"
+#include "../cPlayer.h"
+#include "../cPiston.h"
+
+
+
+#define AddPistonDir(x, y, z, dir, amount) switch (dir) { case 0: (y)-=(amount); break; case 1: (y)+=(amount); break;\
+ case 2: (z)-=(amount); break; case 3: (z)+=(amount); break;\
+ case 4: (x)-=(amount); break; case 5: (x)+=(amount); break; }
+
+
+
+
+cBlockPistonHandler::cBlockPistonHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockPistonHandler::OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir)
+{
+
+}
+
+void cBlockPistonHandler::OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ char OldMeta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ int newX = a_X;
+ int newY = a_Y;
+ int newZ = a_Z;
+ AddPistonDir(newX, newY, newZ, OldMeta & ~(8), 1);
+
+ if (a_World->GetBlock(newX, newY, newZ) == E_BLOCK_PISTON_EXTENSION)
+ {
+ a_World->SetBlock(newX, newY, newZ, E_BLOCK_AIR, 0);
+ }
+}
+
+void cBlockPistonHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cPiston::RotationPitchToMetaData(a_Player->GetRotation(), a_Player->GetPitch()));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+
+ cRedstone Redstone(a_World);
+ Redstone.ChangeRedstone(a_X, a_Y, a_Z, false);
+} \ No newline at end of file
diff --git a/source/blocks/BlockPiston.h b/source/blocks/BlockPiston.h
new file mode 100644
index 000000000..69d3a204f
--- /dev/null
+++ b/source/blocks/BlockPiston.h
@@ -0,0 +1,15 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockPistonHandler : public cBlockHandler
+{
+public:
+ cBlockPistonHandler(BLOCKTYPE a_BlockID);
+ virtual void OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir);
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z);
+
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockRedstone.cpp b/source/blocks/BlockRedstone.cpp
new file mode 100644
index 000000000..1171d124a
--- /dev/null
+++ b/source/blocks/BlockRedstone.cpp
@@ -0,0 +1,41 @@
+#include "Globals.h"
+#include "BlockRedstone.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+#include "../cRedstone.h"
+#include "../cTorch.h"
+
+cBlockRedstoneHandler::cBlockRedstoneHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockRedstoneHandler::OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir)
+{
+ cRedstone Redstone(a_World);
+ bool Added = false;
+ if(a_World->GetBlock(a_X, a_Y, a_Z) == E_BLOCK_REDSTONE_TORCH_ON)
+ Added = true;
+
+ Redstone.ChangeRedstone(a_X, a_Y, a_Z, Added);
+}
+
+void cBlockRedstoneHandler::OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ cRedstone Redstone(a_World);
+ Redstone.ChangeRedstone(a_X, a_Y, a_Z, false);
+}
+
+void cBlockRedstoneHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ switch(m_BlockID)
+ {
+ case E_BLOCK_REDSTONE_TORCH_ON:
+ case E_BLOCK_REDSTONE_TORCH_OFF:
+ a_BlockMeta = cTorch::DirectionToMetaData(a_Dir);
+ break;
+
+ }
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, a_BlockMeta);
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+} \ No newline at end of file
diff --git a/source/blocks/BlockRedstone.h b/source/blocks/BlockRedstone.h
new file mode 100644
index 000000000..21c19d4c5
--- /dev/null
+++ b/source/blocks/BlockRedstone.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "Block.h"
+#include "../cWorld.h"
+
+class cBlockRedstoneHandler : public cBlockHandler
+{
+public:
+ cBlockRedstoneHandler(BLOCKTYPE a_BlockID);
+ virtual void OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir);
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z);
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_REDSTONE_DUST;
+ }
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockRedstoneOre.h b/source/blocks/BlockRedstoneOre.h
new file mode 100644
index 000000000..5658d76ad
--- /dev/null
+++ b/source/blocks/BlockRedstoneOre.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+
+class cBlockRedstoneOreHandler : public cBlockHandler
+{
+public:
+ cBlockRedstoneOreHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_REDSTONE_DUST;
+ }
+
+ virtual char GetDropCount()
+ {
+ MTRand r1;
+ return 4 + r1.randInt(1);
+ }
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockRedstoneRepeater.cpp b/source/blocks/BlockRedstoneRepeater.cpp
new file mode 100644
index 000000000..639764aa5
--- /dev/null
+++ b/source/blocks/BlockRedstoneRepeater.cpp
@@ -0,0 +1,34 @@
+#include "Globals.h"
+#include "BlockRedstoneRepeater.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+#include "../cRedstone.h"
+#include "../cPlayer.h"
+
+cBlockRedstoneRepeaterHandler::cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockRedstoneRepeaterHandler::OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir)
+{
+ cRedstone Redstone(a_World);
+ Redstone.ChangeRedstone(a_X, a_Y, a_Z, false);
+}
+
+void cBlockRedstoneRepeaterHandler::OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+ cRedstone Redstone(a_World);
+ Redstone.ChangeRedstone(a_X, a_Y, a_Z, false);
+}
+
+void cBlockRedstoneRepeaterHandler::OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+ a_World->FastSetBlock(a_X, a_Y, a_Z, m_BlockID, ((a_World->GetBlockMeta(a_X, a_Y, a_Z) + 0x04) & 0x0f));
+}
+
+void cBlockRedstoneRepeaterHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cRedstone::RepeaterRotationToMetaData(a_Player->GetRotation()));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+} \ No newline at end of file
diff --git a/source/blocks/BlockRedstoneRepeater.h b/source/blocks/BlockRedstoneRepeater.h
new file mode 100644
index 000000000..e8618cdeb
--- /dev/null
+++ b/source/blocks/BlockRedstoneRepeater.h
@@ -0,0 +1,46 @@
+#pragma once
+#include "Block.h"
+#include "../cWorld.h"
+
+class cBlockRedstoneRepeaterHandler : public cBlockHandler
+{
+public:
+ cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockID);
+ virtual void OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir);
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z);
+
+ virtual void OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return 0;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_REDSTONE_REPEATER;
+ }
+
+ virtual bool IsUseable()
+ {
+ return true;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockRedstoneTorch.h b/source/blocks/BlockRedstoneTorch.h
new file mode 100644
index 000000000..6ae37cd1e
--- /dev/null
+++ b/source/blocks/BlockRedstoneTorch.h
@@ -0,0 +1,30 @@
+#pragma once
+#include "BlockRedstone.h"
+#include "../cTorch.h"
+
+
+class cBlockRedstoneTorchHandler : public cBlockRedstoneHandler
+{
+public:
+ cBlockRedstoneTorchHandler(BLOCKTYPE a_BlockID)
+ : cBlockRedstoneHandler(a_BlockID)
+ {
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ char Dir = cTorch::MetaDataToDirection(a_World->GetBlockMeta( a_X, a_Y, a_Z));
+ AddDirection( a_X, a_Y, a_Z, Dir, true );
+ return a_World->GetBlock( a_X, a_Y, a_Z ) != E_BLOCK_AIR;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_REDSTONE_TORCH_ON;
+ }
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return true;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockSapling.h b/source/blocks/BlockSapling.h
new file mode 100644
index 000000000..d0498afea
--- /dev/null
+++ b/source/blocks/BlockSapling.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "Block.h"
+#include "../cWorld.h"
+
+class cBlockSaplingHandler : public cBlockHandler
+{
+public:
+ cBlockSaplingHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool NeedsRandomTicks() override
+ {
+ return true;
+ }
+
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return a_BlockMeta & 3; //Only the first 2 bits contain the display information the others are for growing
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return IsBlockTypeOfDirt(a_World->GetBlock(a_X, a_Y - 1, a_Z));
+ }
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+ void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ if ((Meta & 0x08) != 0)
+ {
+ a_World->GrowTree(a_X, a_Y, a_Z);
+ }
+ else
+ {
+ a_World->SetBlockMeta(a_X, a_Y, a_Z, Meta | 0x08);
+ }
+ }
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockSign.h b/source/blocks/BlockSign.h
new file mode 100644
index 000000000..3b2e208e1
--- /dev/null
+++ b/source/blocks/BlockSign.h
@@ -0,0 +1,42 @@
+#pragma once
+#include "Block.h"
+#include "../cWorld.h"
+#include "../cSign.h"
+#include "../cPlayer.h"
+
+class cBlockSignHandler : public cBlockHandler
+{
+public:
+ cBlockSignHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ if(a_Dir == 1)
+ {
+ Meta = cSign::RotationToMetaData(a_Player->GetRotation());
+ Block = E_BLOCK_SIGN_POST;
+ }else{
+ Meta = cSign::DirectionToMetaData(a_Dir);
+ Block = E_BLOCK_WALLSIGN;
+ }
+
+ a_World->SetBlock(a_X, a_Y, a_Z, Block, Meta);
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_SIGN;
+ }
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockSlab.cpp b/source/blocks/BlockSlab.cpp
new file mode 100644
index 000000000..659dc7986
--- /dev/null
+++ b/source/blocks/BlockSlab.cpp
@@ -0,0 +1,17 @@
+#include "Globals.h"
+#include "BlockSlab.h"
+#include "../cItem.h"
+#include "../cPlayer.h"
+#include "../cWorld.h"
+
+cBlockSlabHandler::cBlockSlabHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+
+void cBlockSlabHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, DirectionToMetaData( a_Dir, a_BlockMeta ));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+} \ No newline at end of file
diff --git a/source/blocks/BlockSlab.h b/source/blocks/BlockSlab.h
new file mode 100644
index 000000000..05df819b2
--- /dev/null
+++ b/source/blocks/BlockSlab.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockSlabHandler : public cBlockHandler
+{
+public:
+ cBlockSlabHandler(BLOCKTYPE a_BlockID);
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return a_BlockMeta;
+ }
+
+ virtual char GetDropCount()
+ {
+ if(m_BlockID == E_BLOCK_DOUBLE_STONE_SLAB
+ || m_BlockID == E_BLOCK_DOUBLE_WOODEN_SLAB)
+ return 2;
+ return 1;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ static char DirectionToMetaData( char a_Direction, NIBBLETYPE Meta )
+ {
+ char result = Meta;
+ if( a_Direction == 0)
+ {
+ result |= 0x8;
+ }
+ return result;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockSnow.h b/source/blocks/BlockSnow.h
new file mode 100644
index 000000000..75143b73e
--- /dev/null
+++ b/source/blocks/BlockSnow.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockSnowHandler : public cBlockHandler
+{
+public:
+ cBlockSnowHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool IgnoreBuildCollision()
+ {
+ return true;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_SNOWBALL;
+ }
+
+ virtual char GetDropCount()
+ {
+ return 4;
+ }
+
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+
+ virtual bool DropOnUnsuitable()
+ {
+ return false;
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockStairs.cpp b/source/blocks/BlockStairs.cpp
new file mode 100644
index 000000000..cd4ad9907
--- /dev/null
+++ b/source/blocks/BlockStairs.cpp
@@ -0,0 +1,18 @@
+#include "Globals.h"
+#include "BlockStairs.h"
+#include "../cItem.h"
+#include "../cVine.h"
+#include "../cPlayer.h"
+#include "../cWorld.h"
+#include "../cStairs.h"
+
+cBlockStairsHandler::cBlockStairsHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockStairsHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cStairs::RotationToMetaData(a_Player->GetRotation(), a_Dir));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+} \ No newline at end of file
diff --git a/source/blocks/BlockStairs.h b/source/blocks/BlockStairs.h
new file mode 100644
index 000000000..d7de17c1f
--- /dev/null
+++ b/source/blocks/BlockStairs.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockStairsHandler : public cBlockHandler
+{
+public:
+ cBlockStairsHandler(BLOCKTYPE a_BlockID);
+
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockStems.h b/source/blocks/BlockStems.h
new file mode 100644
index 000000000..8f1d4ddca
--- /dev/null
+++ b/source/blocks/BlockStems.h
@@ -0,0 +1,41 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+
+class cBlockStemsHandler : public cBlockHandler
+{
+public:
+ cBlockStemsHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool NeedsRandomTicks()
+ {
+ return true;
+ }
+
+ virtual char GetDropMeta(char a_BlockMeta)
+ {
+ return 0;
+ }
+
+ virtual int GetDropID()
+ {
+ if(m_BlockID == E_BLOCK_MELON_STEM)
+ return E_ITEM_MELON_SEEDS;
+ return E_ITEM_PUMPKIN_SEEDS;
+ }
+
+ void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ //TODO: Handle Growing here
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) == E_BLOCK_FARMLAND;
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockStone.h b/source/blocks/BlockStone.h
new file mode 100644
index 000000000..d15e4730a
--- /dev/null
+++ b/source/blocks/BlockStone.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+
+class cBlockStoneHandler : public cBlockHandler
+{
+public:
+ cBlockStoneHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_COBBLESTONE;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockSugarcane.h b/source/blocks/BlockSugarcane.h
new file mode 100644
index 000000000..610052880
--- /dev/null
+++ b/source/blocks/BlockSugarcane.h
@@ -0,0 +1,43 @@
+#pragma once
+#include "Block.h"
+#include "../MersenneTwister.h"
+#include "../cWorld.h"
+
+class cBlockSugarcaneHandler : public cBlockHandler
+{
+public:
+ cBlockSugarcaneHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool NeedsRandomTicks()
+ {
+ return true;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_SUGARCANE;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ BLOCKTYPE Block = a_World->GetBlock(a_X, a_Y-1, a_Z);
+ if(!IsBlockTypeOfDirt(Block) && Block != E_BLOCK_SAND && Block != E_BLOCK_SUGARCANE)
+ return false;
+
+ return a_World->IsBlockDirectlyWatered(a_X, a_Y - 1, a_Z);
+ }
+
+ void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+
+ //TODO: Handle Growing here
+ }
+
+ virtual bool CanBePlacedOnSide()
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockTallGrass.h b/source/blocks/BlockTallGrass.h
new file mode 100644
index 000000000..a702bb8ca
--- /dev/null
+++ b/source/blocks/BlockTallGrass.h
@@ -0,0 +1,35 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockTallGrassHandler : public cBlockHandler
+{
+public:
+ cBlockTallGrassHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool IgnoreBuildCollision()
+ {
+ return true;
+ }
+
+ virtual int GetDropID()
+ {
+ return E_ITEM_SEEDS;
+ }
+
+ virtual char GetDropCount()
+ {
+ MTRand r1;
+ if(r1.randInt(10) == 5)
+ return 1;
+ return 0;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockTorch.cpp b/source/blocks/BlockTorch.cpp
new file mode 100644
index 000000000..d9597a9ac
--- /dev/null
+++ b/source/blocks/BlockTorch.cpp
@@ -0,0 +1,15 @@
+#include "Globals.h"
+#include "BlockTorch.h"
+#include "../cTorch.h"
+#include "../cWorld.h"
+
+cBlockTorchHandler::cBlockTorchHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockTorchHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cTorch::DirectionToMetaData(a_Dir));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+} \ No newline at end of file
diff --git a/source/blocks/BlockTorch.h b/source/blocks/BlockTorch.h
new file mode 100644
index 000000000..1e4827ac1
--- /dev/null
+++ b/source/blocks/BlockTorch.h
@@ -0,0 +1,25 @@
+#pragma once
+#include "Block.h"
+#include "../cTorch.h"
+#include "../cWorld.h"
+
+
+class cBlockTorchHandler : public cBlockHandler
+{
+public:
+ cBlockTorchHandler(BLOCKTYPE a_BlockID);
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z)
+ {
+ char Dir = cTorch::MetaDataToDirection(a_World->GetBlockMeta( a_X, a_Y, a_Z));
+ AddDirection( a_X, a_Y, a_Z, Dir, true );
+ return a_World->GetBlock( a_X, a_Y, a_Z ) != E_BLOCK_AIR;
+ }
+}; \ No newline at end of file
diff --git a/source/blocks/BlockVine.cpp b/source/blocks/BlockVine.cpp
new file mode 100644
index 000000000..fda3c818c
--- /dev/null
+++ b/source/blocks/BlockVine.cpp
@@ -0,0 +1,17 @@
+#include "Globals.h"
+#include "BlockVine.h"
+#include "../cItem.h"
+#include "../cVine.h"
+#include "../cPlayer.h"
+#include "../cWorld.h"
+
+cBlockVineHandler::cBlockVineHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockVineHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ a_World->SetBlock(a_X, a_Y, a_Z, m_BlockID, cVine::DirectionToMetaData(a_Dir));
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+} \ No newline at end of file
diff --git a/source/blocks/BlockVine.h b/source/blocks/BlockVine.h
new file mode 100644
index 000000000..d601e622c
--- /dev/null
+++ b/source/blocks/BlockVine.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockVineHandler : public cBlockHandler
+{
+public:
+ cBlockVineHandler(BLOCKTYPE a_BlockID);
+
+ virtual bool IgnoreBuildCollision()
+ {
+ return true;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, char a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockWood.h b/source/blocks/BlockWood.h
new file mode 100644
index 000000000..c93c44b4f
--- /dev/null
+++ b/source/blocks/BlockWood.h
@@ -0,0 +1,17 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockWoodHandler : public cBlockHandler
+{
+public:
+ cBlockWoodHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+ char GetDropMeta(char a_BlockMeta)
+ {
+ return a_BlockMeta;
+ }
+
+}; \ No newline at end of file
diff --git a/source/blocks/BlockWorkbench.cpp b/source/blocks/BlockWorkbench.cpp
new file mode 100644
index 000000000..095a6e1da
--- /dev/null
+++ b/source/blocks/BlockWorkbench.cpp
@@ -0,0 +1,24 @@
+#include "Globals.h"
+#include "BlockWorkbench.h"
+#include "../cItem.h"
+#include "../cPlayer.h"
+#include "../cCraftingWindow.h"
+
+cBlockWorkbenchHandler::cBlockWorkbenchHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+{
+}
+
+void cBlockWorkbenchHandler::OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir)
+{
+}
+
+void cBlockWorkbenchHandler::OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z)
+{
+}
+
+void cBlockWorkbenchHandler::OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+ cWindow* Window = new cCraftingWindow(0, true);
+ a_Player->OpenWindow(Window);
+}
diff --git a/source/blocks/BlockWorkbench.h b/source/blocks/BlockWorkbench.h
new file mode 100644
index 000000000..2a0936c08
--- /dev/null
+++ b/source/blocks/BlockWorkbench.h
@@ -0,0 +1,19 @@
+#pragma once
+#include "Block.h"
+
+
+class cBlockWorkbenchHandler : public cBlockHandler
+{
+public:
+ cBlockWorkbenchHandler(BLOCKTYPE a_BlockID);
+ virtual void OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir);
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z);
+
+ virtual void OnClick(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+ virtual bool IsUseable()
+ {
+ return true;
+ }
+
+
+}; \ No newline at end of file