summaryrefslogtreecommitdiffstats
path: root/source/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'source/Blocks')
-rw-r--r--source/Blocks/BlockBed.h123
-rw-r--r--source/Blocks/BlockCactus.h64
-rw-r--r--source/Blocks/BlockChest.h26
-rw-r--r--source/Blocks/BlockCloth.h23
-rw-r--r--source/Blocks/BlockCrops.h64
-rw-r--r--source/Blocks/BlockDirt.h72
-rw-r--r--source/Blocks/BlockDispenser.h22
-rw-r--r--source/Blocks/BlockDoor.cpp74
-rw-r--r--source/Blocks/BlockDoor.h31
-rw-r--r--source/Blocks/BlockEntity.h31
-rw-r--r--source/Blocks/BlockFire.h33
-rw-r--r--source/Blocks/BlockFlower.h38
-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/BlockGravel.h18
-rw-r--r--source/Blocks/BlockHandler.cpp448
-rw-r--r--source/Blocks/BlockHandler.h90
-rw-r--r--source/Blocks/BlockIce.h26
-rw-r--r--source/Blocks/BlockLadder.h40
-rw-r--r--source/Blocks/BlockLeaves.h167
-rw-r--r--source/Blocks/BlockMelon.h29
-rw-r--r--source/Blocks/BlockMushroom.h47
-rw-r--r--source/Blocks/BlockNote.h13
-rw-r--r--source/Blocks/BlockOre.h58
-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/BlockRedstoneRepeater.cpp39
-rw-r--r--source/Blocks/BlockRedstoneRepeater.h52
-rw-r--r--source/Blocks/BlockRedstoneTorch.h28
-rw-r--r--source/Blocks/BlockSand.h18
-rw-r--r--source/Blocks/BlockSapling.h56
-rw-r--r--source/Blocks/BlockSign.h47
-rw-r--r--source/Blocks/BlockSlab.h51
-rw-r--r--source/Blocks/BlockSnow.h44
-rw-r--r--source/Blocks/BlockStairs.h22
-rw-r--r--source/Blocks/BlockStems.h46
-rw-r--r--source/Blocks/BlockStone.h18
-rw-r--r--source/Blocks/BlockSugarcane.h71
-rw-r--r--source/Blocks/BlockTallGrass.h41
-rw-r--r--source/Blocks/BlockTorch.h166
-rw-r--r--source/Blocks/BlockVine.h35
-rw-r--r--source/Blocks/BlockWood.h22
-rw-r--r--source/Blocks/BlockWorkbench.h36
46 files changed, 2538 insertions, 0 deletions
diff --git a/source/Blocks/BlockBed.h b/source/Blocks/BlockBed.h
new file mode 100644
index 000000000..cbef5bb4d
--- /dev/null
+++ b/source/Blocks/BlockBed.h
@@ -0,0 +1,123 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../World.h"
+#include "../Sign.h"
+#include "../Player.h"
+
+class cBlockBedHandler : public cBlockHandler
+{
+public:
+ cBlockBedHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+
+
+
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ if( a_Dir != 1 ) // Can only be placed on the floor
+ return;
+
+ NIBBLETYPE Meta = RotationToMetaData( a_Player->GetRotation() );
+ Vector3i Direction = MetaDataToDirection( Meta );
+
+ if (a_World->GetBlock(a_X+Direction.x, a_Y, a_Z+Direction.z) != E_BLOCK_AIR)
+ {
+ return;
+ }
+
+ a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_BED, Meta);
+ a_World->SetBlock(a_X + Direction.x, a_Y, a_Z + Direction.z, E_BLOCK_BED, Meta | 0x8);
+
+ OnPlacedByPlayer(a_World, a_Player, a_X, a_Y, a_Z, a_Dir);
+ }
+
+
+
+
+
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ char OldMeta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ Vector3i ThisPos( a_X, a_Y, a_Z );
+ Vector3i Direction = MetaDataToDirection( OldMeta & 0x7 );
+ if (OldMeta & 0x8)
+ {
+ // Was pillow
+ if (a_World->GetBlock(ThisPos - Direction) == E_BLOCK_BED)
+ {
+ a_World->FastSetBlock(ThisPos - Direction, E_BLOCK_AIR, 0);
+ }
+ }
+ else
+ {
+ // Was foot end
+ if (a_World->GetBlock(ThisPos + Direction) == E_BLOCK_BED)
+ {
+ a_World->FastSetBlock(ThisPos + Direction, E_BLOCK_AIR, 0);
+ }
+ }
+ }
+
+
+
+
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_BED;
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+
+
+
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+
+
+
+
+ static NIBBLETYPE RotationToMetaData( float a_Rotation )
+ {
+ a_Rotation += 180 + (180/4); // So its not aligned with axis
+ if( a_Rotation > 360.f ) a_Rotation -= 360.f;
+
+ a_Rotation = (a_Rotation/360) * 4;
+
+ return ((char)a_Rotation+2) % 4;
+ }
+
+
+
+
+
+ static Vector3i MetaDataToDirection( NIBBLETYPE a_MetaData )
+ {
+ switch( a_MetaData )
+ {
+ case 0: // south +z
+ return Vector3i(0, 0, 1);
+ case 1: // west -x
+ return Vector3i(-1, 0, 0);
+ case 2: // north -z
+ return Vector3i(0, 0, -1);
+ case 3: // east +x
+ return Vector3i(1, 0, 0);
+ };
+ return Vector3i();
+ }
+};
diff --git a/source/Blocks/BlockCactus.h b/source/Blocks/BlockCactus.h
new file mode 100644
index 000000000..964646299
--- /dev/null
+++ b/source/Blocks/BlockCactus.h
@@ -0,0 +1,64 @@
+
+#pragma once
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockCactusHandler :
+ public cBlockHandler
+{
+public:
+ cBlockCactusHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+
+ virtual bool CanBeAt(cWorld * a_World, int a_X, int a_Y, int a_Z) override
+ {
+ 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 CanBePlacedOnSide() override
+ {
+ return false;
+ }
+
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.cloth";
+ }
+
+};
+
+
+
+
diff --git a/source/Blocks/BlockChest.h b/source/Blocks/BlockChest.h
new file mode 100644
index 000000000..db67fe1c8
--- /dev/null
+++ b/source/Blocks/BlockChest.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "BlockEntity.h"
+#include "../World.h"
+#include "../Piston.h"
+#include "../Player.h"
+
+class cBlockChestHandler : public cBlockEntityHandler
+{
+public:
+ cBlockChestHandler(BLOCKTYPE a_BlockID)
+ : cBlockEntityHandler(a_BlockID)
+ {
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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);
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+
+};
diff --git a/source/Blocks/BlockCloth.h b/source/Blocks/BlockCloth.h
new file mode 100644
index 000000000..452ad2237
--- /dev/null
+++ b/source/Blocks/BlockCloth.h
@@ -0,0 +1,23 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockClothHandler : public cBlockHandler
+{
+public:
+ cBlockClothHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return a_BlockMeta;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.cloth";
+ }
+
+};
diff --git a/source/Blocks/BlockCrops.h b/source/Blocks/BlockCrops.h
new file mode 100644
index 000000000..b30139e79
--- /dev/null
+++ b/source/Blocks/BlockCrops.h
@@ -0,0 +1,64 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.h"
+
+class cBlockCropsHandler : public cBlockHandler
+{
+public:
+ cBlockCropsHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool NeedsRandomTicks() override
+ {
+ return true;
+ }
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_EMPTY;
+ }
+
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ MTRand rand;
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+
+ 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) override
+ {
+
+ //TODO: Handle Growing here
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) == E_BLOCK_FARMLAND;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+
+};
diff --git a/source/Blocks/BlockDirt.h b/source/Blocks/BlockDirt.h
new file mode 100644
index 000000000..5a2487f1b
--- /dev/null
+++ b/source/Blocks/BlockDirt.h
@@ -0,0 +1,72 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.h"
+
+class cBlockDirtHandler : public cBlockHandler
+{
+public:
+ cBlockDirtHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+
+ virtual bool NeedsRandomTicks() override
+ {
+ return m_BlockID == E_BLOCK_GRASS;
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_BLOCK_DIRT;
+ }
+
+
+ void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ if (m_BlockID != E_BLOCK_GRASS)
+ {
+ return;
+ }
+
+ // Grass becomes dirt if there is something on top of it:
+ 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);
+ return;
+ }
+
+ // Grass spreads to adjacent blocks:
+ 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
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.gravel";
+ }
+
+};
diff --git a/source/Blocks/BlockDispenser.h b/source/Blocks/BlockDispenser.h
new file mode 100644
index 000000000..eee75a39a
--- /dev/null
+++ b/source/Blocks/BlockDispenser.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "BlockEntity.h"
+#include "../World.h"
+#include "../Piston.h"
+#include "../Player.h"
+
+class cBlockDispenserHandler : public cBlockEntityHandler
+{
+public:
+ cBlockDispenserHandler(BLOCKTYPE a_BlockID)
+ : cBlockEntityHandler(a_BlockID)
+ {
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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..deed8a256
--- /dev/null
+++ b/source/Blocks/BlockDoor.cpp
@@ -0,0 +1,74 @@
+#include "Globals.h"
+#include "BlockDoor.h"
+#include "../Item.h"
+#include "../World.h"
+#include "../Doors.h"
+#include "../Player.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::OnDigging(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);
+}
+
+void cBlockDoorHandler::OnUse(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, NIBBLETYPE 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);
+ }
+}
+
+AString cBlockDoorHandler::GetStepSound(void)
+{
+ if (m_BlockID == E_BLOCK_WOODEN_DOOR)
+ return "step.wood";
+
+ else
+ return "step.stone";
+}
diff --git a/source/Blocks/BlockDoor.h b/source/Blocks/BlockDoor.h
new file mode 100644
index 000000000..3316f50a4
--- /dev/null
+++ b/source/Blocks/BlockDoor.h
@@ -0,0 +1,31 @@
+#pragma once
+#include "BlockHandler.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) override;
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override;
+ virtual void OnDigging(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z) override;
+ virtual void OnUse(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z) override;
+ virtual AString GetStepSound(void) override;
+ virtual char GetDropCount() override;
+ virtual bool IsUseable() override
+ {
+ return true;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override;
+
+ virtual int GetDropID() override
+ {
+ return (m_BlockID == E_BLOCK_WOODEN_DOOR) ? E_ITEM_WOODEN_DOOR : E_ITEM_IRON_DOOR;
+ }
+
+ virtual bool CanBePlacedOnSide() override
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/Blocks/BlockEntity.h b/source/Blocks/BlockEntity.h
new file mode 100644
index 000000000..caf6ee342
--- /dev/null
+++ b/source/Blocks/BlockEntity.h
@@ -0,0 +1,31 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockEntityHandler : public cBlockHandler
+{
+public:
+ cBlockEntityHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual void OnUse(cWorld * a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ a_World->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ);
+ }
+
+ virtual bool IsUseable() override
+ {
+ return true;
+ }
+};
+
+
+
+
diff --git a/source/Blocks/BlockFire.h b/source/Blocks/BlockFire.h
new file mode 100644
index 000000000..1fecf9a14
--- /dev/null
+++ b/source/Blocks/BlockFire.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockFireHandler : public cBlockHandler
+{
+public:
+ cBlockFireHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual void OnDigging(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z) override
+ {
+ a_World->DigBlock(a_X, a_Y, a_Z);
+ }
+
+ virtual char GetDropCount() override
+ {
+ return -1;
+ }
+
+ virtual bool IsClickedThrough() override
+ {
+ return true;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+
+};
diff --git a/source/Blocks/BlockFlower.h b/source/Blocks/BlockFlower.h
new file mode 100644
index 000000000..35a55fcac
--- /dev/null
+++ b/source/Blocks/BlockFlower.h
@@ -0,0 +1,38 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockFlowerHandler : public cBlockHandler
+{
+public:
+ cBlockFlowerHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ return IsBlockTypeOfDirt(a_World->GetBlock(a_X, a_Y - 1, a_Z));
+ }
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+ virtual bool CanBePlacedOnSide() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+
+};
diff --git a/source/Blocks/BlockFluid.h b/source/Blocks/BlockFluid.h
new file mode 100644
index 000000000..c5ac660b0
--- /dev/null
+++ b/source/Blocks/BlockFluid.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockFluidHandler : public cBlockHandler
+{
+public:
+ cBlockFluidHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+ virtual bool IgnoreBuildCollision() override
+ {
+ 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..4157b5049
--- /dev/null
+++ b/source/Blocks/BlockFurnace.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "BlockEntity.h"
+#include "../World.h"
+#include "../Piston.h"
+#include "../Player.h"
+
+class cBlockFurnaceHandler : public cBlockEntityHandler
+{
+public:
+ cBlockFurnaceHandler(BLOCKTYPE a_BlockID)
+ : cBlockEntityHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_FURNACE;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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..0b906e2fe
--- /dev/null
+++ b/source/Blocks/BlockGlowstone.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockGlowstoneHandler : public cBlockHandler
+{
+public:
+ cBlockGlowstoneHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_GLOWSTONE_DUST;
+ }
+}; \ No newline at end of file
diff --git a/source/Blocks/BlockGravel.h b/source/Blocks/BlockGravel.h
new file mode 100644
index 000000000..da47db9bb
--- /dev/null
+++ b/source/Blocks/BlockGravel.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockGravelHandler : public cBlockHandler
+{
+public:
+ cBlockGravelHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.gravel";
+ }
+
+};
diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp
new file mode 100644
index 000000000..e6b384a23
--- /dev/null
+++ b/source/Blocks/BlockHandler.cpp
@@ -0,0 +1,448 @@
+#include "Globals.h"
+#include "BlockHandler.h"
+#include "../Item.h"
+#include "../World.h"
+#include "BlockSand.h"
+#include "BlockGravel.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 "BlockStone.h"
+#include "BlockMelon.h"
+#include "BlockIce.h"
+#include "BlockOre.h"
+#include "BlockNote.h"
+#include "BlockBed.h"
+
+
+
+
+
+bool cBlockHandler::m_HandlerInitialized = false;
+cBlockHandler *cBlockHandler::m_BlockHandler[256];
+
+
+
+
+
+cBlockHandler *cBlockHandler::GetBlockHandler(BLOCKTYPE a_BlockID)
+{
+ if (!m_HandlerInitialized)
+ {
+ //We have to initialize
+ memset(m_BlockHandler, 0, sizeof(m_BlockHandler));
+ m_HandlerInitialized = true;
+ }
+ if (m_BlockHandler[a_BlockID] != NULL)
+ {
+ 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_SAND:
+ return new cBlockSandHandler(a_BlockID);
+ case E_BLOCK_GRAVEL:
+ return new cBlockGravelHandler(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_DIAMOND_ORE:
+ case E_BLOCK_GOLD_ORE:
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ case E_BLOCK_EMERALD_ORE:
+ case E_BLOCK_IRON_ORE:
+ case E_BLOCK_LAPIS_ORE:
+ case E_BLOCK_COAL_ORE:
+ return new cBlockOreHandler(a_BlockID);
+ case E_BLOCK_STONE:
+ case E_BLOCK_COBBLESTONE:
+ return new cBlockStoneHandler(a_BlockID);
+ case E_BLOCK_MELON:
+ return new cBlockMelonHandler(a_BlockID);
+ case E_BLOCK_NOTE_BLOCK:
+ return new cBlockNoteHandler(a_BlockID);
+ case E_BLOCK_BED:
+ return new cBlockBedHandler(a_BlockID);
+ default:
+ return new cBlockHandler(a_BlockID);
+ break;
+ }
+}
+
+
+
+
+
+void cBlockHandler::Deinit()
+{
+ for(int i = 0; i < 256; i++)
+ {
+ delete m_BlockHandler[i];
+ }
+ m_HandlerInitialized = false;
+}
+
+
+
+
+
+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::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+}
+
+
+
+
+
+void cBlockHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+}
+
+
+
+
+
+void cBlockHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE 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);
+}
+
+
+
+
+
+char cBlockHandler::GetDropCount()
+{
+ return 1;
+}
+
+
+
+
+
+int cBlockHandler::GetDropID()
+{
+ return m_BlockID;
+}
+
+
+
+
+
+NIBBLETYPE cBlockHandler::GetDropMeta(NIBBLETYPE 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;
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_X, a_Y, a_Z);
+ char DropCount = GetDropCount();
+ short DropItem = (short)GetDropID();
+ if (DropCount > 0 && (DropItem != E_ITEM_EMPTY))
+ {
+ Drops.push_back(cItem(DropItem, DropCount, GetDropMeta(Meta)));
+ a_World->SpawnItemPickups(Drops, a_X, a_Y, a_Z);
+ }
+}
+
+
+
+
+
+AString cBlockHandler::GetStepSound() {
+ return "step.stone";
+}
+
+
+
+
+
+bool cBlockHandler::CanBePlacedAt(cWorld *a_World, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ return CanBeAt(a_World, 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;
+}
+
+
+
+
diff --git a/source/Blocks/BlockHandler.h b/source/Blocks/BlockHandler.h
new file mode 100644
index 000000000..859870c4a
--- /dev/null
+++ b/source/Blocks/BlockHandler.h
@@ -0,0 +1,90 @@
+#pragma once
+#include "../Defines.h"
+
+class cWorld;
+class cPlayer;
+
+
+
+class cBlockHandler
+{
+public:
+ cBlockHandler(BLOCKTYPE a_BlockID);
+
+ // Called when the block gets ticked either by a random tick or by a queued tick
+ virtual void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z);
+
+ // Will be called by cBlockHandler::PlaceBlock after the player has placed a new block
+ virtual void OnPlacedByPlayer(cWorld *a_World, cPlayer * a_Player, int a_X, int a_Y, int a_Z, int a_Dir);
+ // Will be called before the player has destroyed a block
+ virtual void OnDestroyedByPlayer(cWorld *a_World, cPlayer * a_Player, int a_X, int a_Y, int a_Z);
+ // Will be called when a new block was placed. Will be called before OnPlacedByPlayer
+ virtual void OnPlaced(cWorld *a_World, int a_X, int a_Y, int a_Z, int a_Dir);
+ // Will be called before a block gets destroyed / replaced with air
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ // Will be called when a direct neighbor of this block has been changed (The position is the own position, not the neighbor position)
+ virtual void OnNeighborChanged(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ // Notifies all neighbors of the give block about a change
+ static void NeighborChanged(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ // Will be called while the player diggs the block.
+ virtual void OnDigging(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+ // Will be called if the user right clicks the block and the block is useable
+ virtual void OnUse(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z);
+ // This function handles the real block placement for the give block by a player and also calls the OnPlacedByPlayer function
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ // Indicates how much items are dropped DEFAULT: 1
+ virtual char GetDropCount();
+ // Indicates the id dropped by this block DEFAULT: BlockID
+ virtual int GetDropID();
+ // Indicates the Drop Meta data based on the block meta DEFAULT: BlockMeta
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta);
+ // This function handles the dropping of a block based on the Drop id, drop count and drop meta. This will not destroy the block
+ virtual void DropBlock(cWorld *a_World, int a_X, int a_Y, int a_Z);
+ /// Returns step sound name of block
+ virtual AString GetStepSound();
+
+ // Indicates whether this block needs random ticks DEFAULT: False
+ virtual bool NeedsRandomTicks();
+
+ /// 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 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);
+
+ /// 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 AllowBlockOnTop(void);
+
+ /// Called to check whether this block supports a rclk action. If it returns true, OnUse() is called
+ virtual bool IsUseable(void);
+
+ // Indicates whether the client will click through this block. For example digging a fire will hit the block below the fire so fire is clicked through
+ virtual bool IsClickedThrough(void);
+
+ // Checks if the player can build "inside" this block. For example blocks placed "on" snow will be placed at the same position. So: Snow ignores Build collision
+ virtual bool IgnoreBuildCollision(void);
+
+ /// Indicates this block can be placed on the side of other blocks. Default: true
+ virtual bool CanBePlacedOnSide();
+
+ /// Does this block drop if it gets destroyed by an unsuitable situation? Default: true
+ virtual bool DropOnUnsuitable();
+
+
+ // Static function to get the blockhandler for an specific block id
+ static cBlockHandler * GetBlockHandler(BLOCKTYPE a_BlockID);
+
+ // Deletes all initialised block handlers
+ static void Deinit();
+
+protected:
+ BLOCKTYPE m_BlockID;
+ // Creates a new blockhandler for the given block id. For internal use only, use GetBlockHandler instead.
+ static cBlockHandler *CreateBlockHandler(BLOCKTYPE a_BlockID);
+ static cBlockHandler *m_BlockHandler[256];
+ static bool m_HandlerInitialized; //used to detect if the blockhandlers are initialized
+};
+
+// Shortcut to get the blockhandler for a specific block
+inline cBlockHandler *BlockHandler(BLOCKTYPE a_BlockID) { return cBlockHandler::GetBlockHandler(a_BlockID); } \ No newline at end of file
diff --git a/source/Blocks/BlockIce.h b/source/Blocks/BlockIce.h
new file mode 100644
index 000000000..cc5cc8920
--- /dev/null
+++ b/source/Blocks/BlockIce.h
@@ -0,0 +1,26 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.h"
+
+class cBlockIceHandler : public cBlockHandler
+{
+public:
+ cBlockIceHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_EMPTY;
+ }
+
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ 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..ee48df848
--- /dev/null
+++ b/source/Blocks/BlockLadder.h
@@ -0,0 +1,40 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../World.h"
+#include "../Ladder.h"
+
+class cBlockLadderHandler : public cBlockHandler
+{
+public:
+ cBlockLadderHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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 CanBePlacedAt(cWorld *a_World, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ AddDirection( a_X, a_Y, a_Z, a_Dir, true );
+ return a_World->GetBlock( a_X, a_Y, a_Z ) != E_BLOCK_AIR;
+ }
+
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ char Dir = cLadder::MetaDataToDirection(a_World->GetBlockMeta( a_X, a_Y, a_Z));
+ return CanBePlacedAt(a_World, a_X, a_Y, a_Z, Dir);
+ }
+
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+
+};
diff --git a/source/Blocks/BlockLeaves.h b/source/Blocks/BlockLeaves.h
new file mode 100644
index 000000000..65c47f8de
--- /dev/null
+++ b/source/Blocks/BlockLeaves.h
@@ -0,0 +1,167 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.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, (BLOCKTYPE)(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() override
+ {
+ 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) override
+ {
+ 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) override
+ {
+ 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() override
+ {
+ return true;
+ }
+
+ virtual void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ 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);
+
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+};
+
+
+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..87fb7e1e8
--- /dev/null
+++ b/source/Blocks/BlockMelon.h
@@ -0,0 +1,29 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockMelonHandler : public cBlockHandler
+{
+public:
+ cBlockMelonHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_MELON_SLICE;
+ }
+
+ virtual char GetDropCount() override
+ {
+ MTRand r1;
+ return (char)(3 + r1.randInt(4));
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+};
diff --git a/source/Blocks/BlockMushroom.h b/source/Blocks/BlockMushroom.h
new file mode 100644
index 000000000..c4119bad0
--- /dev/null
+++ b/source/Blocks/BlockMushroom.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockMushroomHandler : public cBlockHandler
+{
+public:
+ cBlockMushroomHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ 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() override
+ {
+ return false;
+ }
+
+
+ virtual bool CanBePlacedOnSide() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+};
diff --git a/source/Blocks/BlockNote.h b/source/Blocks/BlockNote.h
new file mode 100644
index 000000000..896a5d03b
--- /dev/null
+++ b/source/Blocks/BlockNote.h
@@ -0,0 +1,13 @@
+#pragma once
+#include "BlockHandler.h"
+#include "BlockEntity.h"
+
+class cBlockNoteHandler : public cBlockEntityHandler
+{
+public:
+ cBlockNoteHandler(BLOCKTYPE a_BlockID)
+ : cBlockEntityHandler(a_BlockID)
+ {
+ }
+
+};
diff --git a/source/Blocks/BlockOre.h b/source/Blocks/BlockOre.h
new file mode 100644
index 000000000..556a215ce
--- /dev/null
+++ b/source/Blocks/BlockOre.h
@@ -0,0 +1,58 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.h"
+
+class cBlockOreHandler : public cBlockHandler
+{
+public:
+ cBlockOreHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual char GetDropCount() override
+ {
+ MTRand r1;
+ switch(m_BlockID)
+ {
+ case E_BLOCK_LAPIS_ORE:
+ return 4 + (char)r1.randInt(4);
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ return 4 + (char)r1.randInt(1);
+ default:
+ return 1;
+ }
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_Meta) override
+ {
+ switch(m_BlockID)
+ {
+ case E_BLOCK_LAPIS_ORE:
+ return 4;
+ default:
+ return 0;
+ }
+ }
+
+ virtual int GetDropID() override
+ {
+ switch(m_BlockID)
+ {
+ case E_BLOCK_DIAMOND_ORE:
+ return E_ITEM_DIAMOND;
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ return E_ITEM_REDSTONE_DUST;
+ case E_BLOCK_EMERALD_ORE:
+ return E_ITEM_EMERALD;
+ case E_BLOCK_LAPIS_ORE:
+ return E_ITEM_DYE;
+ case E_BLOCK_COAL_ORE:
+ return E_ITEM_COAL;
+ }
+ return m_BlockID;
+ }
+}; \ No newline at end of file
diff --git a/source/Blocks/BlockPiston.cpp b/source/Blocks/BlockPiston.cpp
new file mode 100644
index 000000000..a4ed13d88
--- /dev/null
+++ b/source/Blocks/BlockPiston.cpp
@@ -0,0 +1,51 @@
+#include "Globals.h"
+#include "BlockPiston.h"
+#include "../Item.h"
+#include "../World.h"
+#include "../Redstone.h"
+#include "../Player.h"
+#include "../Piston.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, NIBBLETYPE 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..dbce9bae5
--- /dev/null
+++ b/source/Blocks/BlockPiston.h
@@ -0,0 +1,15 @@
+#pragma once
+#include "BlockHandler.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) override;
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override;
+
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override;
+
+}; \ No newline at end of file
diff --git a/source/Blocks/BlockRedstone.cpp b/source/Blocks/BlockRedstone.cpp
new file mode 100644
index 000000000..7653436f4
--- /dev/null
+++ b/source/Blocks/BlockRedstone.cpp
@@ -0,0 +1,41 @@
+#include "Globals.h"
+#include "BlockRedstone.h"
+#include "../Item.h"
+#include "../World.h"
+#include "../Redstone.h"
+#include "../Torch.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, NIBBLETYPE 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..9b83b1b29
--- /dev/null
+++ b/source/Blocks/BlockRedstone.h
@@ -0,0 +1,33 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../World.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) override;
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override;
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override;
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_REDSTONE_DUST;
+ }
+
+ virtual bool CanBePlacedOnSide() override
+ {
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/Blocks/BlockRedstoneRepeater.cpp b/source/Blocks/BlockRedstoneRepeater.cpp
new file mode 100644
index 000000000..861f6e221
--- /dev/null
+++ b/source/Blocks/BlockRedstoneRepeater.cpp
@@ -0,0 +1,39 @@
+#include "Globals.h"
+#include "BlockRedstoneRepeater.h"
+#include "../Item.h"
+#include "../World.h"
+#include "../Redstone.h"
+#include "../Player.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::OnUse(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::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z)
+{
+ OnUse(a_World, a_Player, a_X, a_Y, a_Z);
+}
+
+void cBlockRedstoneRepeaterHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE 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..a928f554f
--- /dev/null
+++ b/source/Blocks/BlockRedstoneRepeater.h
@@ -0,0 +1,52 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../World.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) override;
+ virtual void OnDestroyed(cWorld *a_World, int a_X, int a_Y, int a_Z) override;
+
+ virtual void OnDigging(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z) override;
+ virtual void OnUse(cWorld *a_World, cPlayer *a_Player, int a_X, int a_Y, int a_Z) override;
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_REDSTONE_REPEATER;
+ }
+
+ virtual bool IsUseable() override
+ {
+ return true;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override;
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+
+
+ virtual bool CanBePlacedOnSide() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+};
diff --git a/source/Blocks/BlockRedstoneTorch.h b/source/Blocks/BlockRedstoneTorch.h
new file mode 100644
index 000000000..eeb2afc5c
--- /dev/null
+++ b/source/Blocks/BlockRedstoneTorch.h
@@ -0,0 +1,28 @@
+
+#pragma once
+#include "BlockRedstone.h"
+#include "BlockTorch.h"
+#include "../Torch.h"
+
+
+
+
+
+class cBlockRedstoneTorchHandler : public cBlockTorchHandler
+{
+public:
+ cBlockRedstoneTorchHandler(BLOCKTYPE a_BlockID)
+ : cBlockTorchHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID(void) override
+ {
+ return E_ITEM_REDSTONE_TORCH_ON;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+};
diff --git a/source/Blocks/BlockSand.h b/source/Blocks/BlockSand.h
new file mode 100644
index 000000000..69fda5ec6
--- /dev/null
+++ b/source/Blocks/BlockSand.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockSandHandler : public cBlockHandler
+{
+public:
+ cBlockSandHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.sand";
+ }
+
+};
diff --git a/source/Blocks/BlockSapling.h b/source/Blocks/BlockSapling.h
new file mode 100644
index 000000000..c9862349a
--- /dev/null
+++ b/source/Blocks/BlockSapling.h
@@ -0,0 +1,56 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../World.h"
+
+class cBlockSaplingHandler : public cBlockHandler
+{
+public:
+ cBlockSaplingHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool NeedsRandomTicks() override
+ {
+ return true;
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ 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) override
+ {
+ return IsBlockTypeOfDirt(a_World->GetBlock(a_X, a_Y - 1, a_Z));
+ }
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+ void OnUpdate(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ 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() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+};
diff --git a/source/Blocks/BlockSign.h b/source/Blocks/BlockSign.h
new file mode 100644
index 000000000..dd82605b3
--- /dev/null
+++ b/source/Blocks/BlockSign.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../World.h"
+#include "../Sign.h"
+#include "../Player.h"
+
+class cBlockSignHandler : public cBlockHandler
+{
+public:
+ cBlockSignHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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() override
+ {
+ return E_ITEM_SIGN;
+ }
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+};
diff --git a/source/Blocks/BlockSlab.h b/source/Blocks/BlockSlab.h
new file mode 100644
index 000000000..ad9970d67
--- /dev/null
+++ b/source/Blocks/BlockSlab.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockSlabHandler : public cBlockHandler
+{
+public:
+ cBlockSlabHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return a_BlockMeta;
+ }
+
+ virtual char GetDropCount() override
+ {
+ 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, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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);
+ }
+
+ static char DirectionToMetaData( char a_Direction, NIBBLETYPE Meta )
+ {
+ char result = Meta;
+ if( a_Direction == 0)
+ {
+ result |= 0x8;
+ }
+ return result;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ if (m_BlockID == E_BLOCK_WOODEN_SLAB || m_BlockID ==E_BLOCK_DOUBLE_WOODEN_SLAB)
+ return "step.wood";
+
+ else
+ return "step.stone";
+ }
+};
diff --git a/source/Blocks/BlockSnow.h b/source/Blocks/BlockSnow.h
new file mode 100644
index 000000000..c8e6b4c1c
--- /dev/null
+++ b/source/Blocks/BlockSnow.h
@@ -0,0 +1,44 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockSnowHandler : public cBlockHandler
+{
+public:
+ cBlockSnowHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool IgnoreBuildCollision() override
+ {
+ return true;
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_SNOWBALL;
+ }
+
+ virtual char GetDropCount() override
+ {
+ return 4;
+ }
+
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+
+ virtual bool DropOnUnsuitable() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.cloth";
+ }
+
+};
diff --git a/source/Blocks/BlockStairs.h b/source/Blocks/BlockStairs.h
new file mode 100644
index 000000000..4d0007bc5
--- /dev/null
+++ b/source/Blocks/BlockStairs.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../Stairs.h"
+
+class cBlockStairsHandler : public cBlockHandler
+{
+public:
+ cBlockStairsHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+
+ }
+
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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);
+ }
+
+ //TODO: step sound
+};
diff --git a/source/Blocks/BlockStems.h b/source/Blocks/BlockStems.h
new file mode 100644
index 000000000..be4519a52
--- /dev/null
+++ b/source/Blocks/BlockStems.h
@@ -0,0 +1,46 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.h"
+
+class cBlockStemsHandler : public cBlockHandler
+{
+public:
+ cBlockStemsHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool NeedsRandomTicks() override
+ {
+ return true;
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+ virtual int GetDropID() override
+ {
+ 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) override
+ {
+ //TODO: Handle Growing here
+ }
+
+ virtual bool CanBeAt(cWorld *a_World, int a_X, int a_Y, int a_Z) override
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) == E_BLOCK_FARMLAND;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+
+};
diff --git a/source/Blocks/BlockStone.h b/source/Blocks/BlockStone.h
new file mode 100644
index 000000000..8b645bf1e
--- /dev/null
+++ b/source/Blocks/BlockStone.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../MersenneTwister.h"
+#include "../World.h"
+
+class cBlockStoneHandler : public cBlockHandler
+{
+public:
+ cBlockStoneHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual int GetDropID() override
+ {
+ 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..1d477b42b
--- /dev/null
+++ b/source/Blocks/BlockSugarcane.h
@@ -0,0 +1,71 @@
+
+#pragma once
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockSugarcaneHandler :
+ public cBlockHandler
+{
+public:
+ cBlockSugarcaneHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+
+ virtual bool NeedsRandomTicks() override
+ {
+ return true;
+ }
+
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_SUGARCANE;
+ }
+
+
+ virtual bool CanBeAt(cWorld * a_World, int a_X, int a_Y, int a_Z) override
+ {
+ switch (a_World->GetBlock(a_X, a_Y - 1, a_Z))
+ {
+ case E_BLOCK_DIRT:
+ case E_BLOCK_GRASS:
+ case E_BLOCK_FARMLAND:
+ case E_BLOCK_SAND:
+ {
+ return a_World->IsBlockDirectlyWatered(a_X, a_Y - 1, a_Z);
+ }
+ case E_BLOCK_SUGARCANE:
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ void OnUpdate(cWorld * a_World, int a_X, int a_Y, int a_Z) override
+ {
+ //TODO: Handle Growing here
+ }
+
+
+ virtual bool CanBePlacedOnSide() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+
+};
+
+
+
+
diff --git a/source/Blocks/BlockTallGrass.h b/source/Blocks/BlockTallGrass.h
new file mode 100644
index 000000000..f5bb1b373
--- /dev/null
+++ b/source/Blocks/BlockTallGrass.h
@@ -0,0 +1,41 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockTallGrassHandler : public cBlockHandler
+{
+public:
+ cBlockTallGrassHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool IgnoreBuildCollision() override
+ {
+ return true;
+ }
+
+ virtual int GetDropID() override
+ {
+ return E_ITEM_SEEDS;
+ }
+
+ virtual char GetDropCount() override
+ {
+ 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) override
+ {
+ return a_World->GetBlock(a_X, a_Y - 1, a_Z) != E_BLOCK_AIR;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+
+};
diff --git a/source/Blocks/BlockTorch.h b/source/Blocks/BlockTorch.h
new file mode 100644
index 000000000..450b5ecab
--- /dev/null
+++ b/source/Blocks/BlockTorch.h
@@ -0,0 +1,166 @@
+
+#pragma once
+#include "BlockHandler.h"
+#include "../Torch.h"
+#include "../World.h"
+
+
+
+
+
+class cBlockTorchHandler : public cBlockHandler
+{
+public:
+ cBlockTorchHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+
+ virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ if(!TorchCanBePlacedAt(a_World, a_X, a_Y, a_Z, a_Dir))
+ {
+ a_Dir = FindSuitableDirection(a_World, a_X, a_Y, a_Z);
+
+ if(a_Dir == BLOCK_FACE_BOTTOM)
+ return;
+ }
+
+ 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);
+ }
+
+
+ virtual bool AllowBlockOnTop(void) override
+ {
+ return false;
+ }
+
+
+ static bool CanBePlacedOn(BLOCKTYPE a_BlockType, char a_Direction)
+ {
+ switch (a_BlockType)
+ {
+ case E_BLOCK_STONE:
+ case E_BLOCK_GRASS:
+ case E_BLOCK_DIRT:
+ case E_BLOCK_COBBLESTONE:
+ case E_BLOCK_PLANKS:
+ case E_BLOCK_BEDROCK:
+ case E_BLOCK_SAND:
+ case E_BLOCK_GRAVEL:
+ case E_BLOCK_GOLD_ORE:
+ case E_BLOCK_IRON_ORE:
+ case E_BLOCK_COAL_ORE:
+ case E_BLOCK_LOG:
+ case E_BLOCK_SPONGE:
+ case E_BLOCK_LAPIS_ORE:
+ case E_BLOCK_LAPIS_BLOCK:
+ case E_BLOCK_SANDSTONE:
+ case E_BLOCK_WOOL:
+ case E_BLOCK_GOLD_BLOCK:
+ case E_BLOCK_IRON_BLOCK:
+ case E_BLOCK_DOUBLE_STONE_SLAB:
+ case E_BLOCK_BRICK:
+ case E_BLOCK_BOOKCASE:
+ case E_BLOCK_MOSSY_COBBLESTONE:
+ case E_BLOCK_OBSIDIAN:
+ case E_BLOCK_MOB_SPAWNER:
+ case E_BLOCK_DIAMOND_ORE:
+ case E_BLOCK_DIAMOND_BLOCK:
+ case E_BLOCK_CRAFTING_TABLE:
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ case E_BLOCK_SNOW_BLOCK:
+ case E_BLOCK_CLAY:
+ case E_BLOCK_JUKEBOX:
+ case E_BLOCK_PUMPKIN:
+ case E_BLOCK_NETHERRACK:
+ case E_BLOCK_SOULSAND:
+ case E_BLOCK_JACK_O_LANTERN:
+ case E_BLOCK_LOCKED_CHEST:
+ case E_BLOCK_STONE_BRICKS:
+ case E_BLOCK_MELON:
+ case E_BLOCK_MYCELIUM:
+ case E_BLOCK_NETHER_BRICK:
+ case E_BLOCK_END_STONE:
+ case E_BLOCK_REDSTONE_LAMP_OFF:
+ case E_BLOCK_REDSTONE_LAMP_ON:
+ case E_BLOCK_DOUBLE_WOODEN_SLAB:
+ case E_BLOCK_EMERALD_ORE:
+ case E_BLOCK_ENDER_CHEST:
+ case E_BLOCK_EMERALD_BLOCK:
+ {
+ return true;
+ }
+
+ case E_BLOCK_GLASS:
+ case E_BLOCK_FENCE:
+ case E_BLOCK_NETHER_BRICK_FENCE:
+ {
+ return (a_Direction == 0x1); // allow only direction "standing on floor"
+ }
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+
+ static bool TorchCanBePlacedAt(cWorld * a_World, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ // TODO: If placing a torch from below, check all 4 XZ neighbors, place it on that neighbor instead
+ // How to propagate that change up?
+ // Simon: The easiest way is to calculate the position two times, shouldn´t cost much cpu power :)
+
+ if(a_Dir == BLOCK_FACE_BOTTOM)
+ return false;
+
+ AddDirection( a_X, a_Y, a_Z, a_Dir, true );
+
+ return CanBePlacedOn(a_World->GetBlock( a_X, a_Y, a_Z ), a_Dir);
+ }
+
+ // Finds a suitable Direction for the Torch. Returns BLOCK_FACE_BOTTOM on failure
+ static char FindSuitableDirection(cWorld * a_World, int a_X, int a_Y, int a_Z)
+ {
+ for(int i = 1; i <= 5; i++)
+ {
+ if(TorchCanBePlacedAt(a_World, a_X, a_Y, a_Z, i))
+ return i;
+ }
+ return BLOCK_FACE_BOTTOM;
+ }
+
+ virtual bool CanBePlacedAt(cWorld * a_World, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ if(TorchCanBePlacedAt(a_World, a_X, a_Y, a_Z, a_Dir))
+ return true;
+
+ return FindSuitableDirection(a_World, a_X, a_Y, a_Z) != BLOCK_FACE_BOTTOM;
+ }
+
+
+ virtual bool CanBeAt(cWorld * a_World, int a_X, int a_Y, int a_Z) override
+ {
+ char Dir = cTorch::MetaDataToDirection(a_World->GetBlockMeta( a_X, a_Y, a_Z));
+ return TorchCanBePlacedAt(a_World, a_X, a_Y, a_Z, Dir);
+ }
+
+ virtual NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return 0;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+};
+
+
+
+
diff --git a/source/Blocks/BlockVine.h b/source/Blocks/BlockVine.h
new file mode 100644
index 000000000..56317219a
--- /dev/null
+++ b/source/Blocks/BlockVine.h
@@ -0,0 +1,35 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../Vine.h"
+
+class cBlockVineHandler : public cBlockHandler
+{
+public:
+ cBlockVineHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual bool IgnoreBuildCollision() override
+ {
+ return true;
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ 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);
+ }
+
+
+ virtual bool AllowBlockOnTop() override
+ {
+ return false;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.grass";
+ }
+
+};
diff --git a/source/Blocks/BlockWood.h b/source/Blocks/BlockWood.h
new file mode 100644
index 000000000..d71d5d71c
--- /dev/null
+++ b/source/Blocks/BlockWood.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "BlockHandler.h"
+
+
+class cBlockWoodHandler : public cBlockHandler
+{
+public:
+ cBlockWoodHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+ NIBBLETYPE GetDropMeta(NIBBLETYPE a_BlockMeta) override
+ {
+ return a_BlockMeta;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+
+};
diff --git a/source/Blocks/BlockWorkbench.h b/source/Blocks/BlockWorkbench.h
new file mode 100644
index 000000000..c1c004dc5
--- /dev/null
+++ b/source/Blocks/BlockWorkbench.h
@@ -0,0 +1,36 @@
+#pragma once
+#include "BlockHandler.h"
+#include "../UI/Window.h"
+#include "../Player.h"
+
+
+
+
+
+class cBlockWorkbenchHandler:
+ public cBlockHandler
+{
+public:
+ cBlockWorkbenchHandler(BLOCKTYPE a_BlockID)
+ : cBlockHandler(a_BlockID)
+ {
+ }
+
+ virtual void OnUse(cWorld * a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ cWindow * Window = new cCraftingWindow(a_BlockX, a_BlockY, a_BlockZ);
+ a_Player->OpenWindow(Window);
+ }
+
+ virtual bool IsUseable() override
+ {
+ return true;
+ }
+
+ virtual AString GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+
+
+}; \ No newline at end of file