summaryrefslogtreecommitdiffstats
path: root/source/items
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/items/Item.cpp224
-rw-r--r--source/items/Item.h45
-rw-r--r--source/items/ItemBucket.h75
-rw-r--r--source/items/ItemCloth.h18
-rw-r--r--source/items/ItemDoor.h25
-rw-r--r--source/items/ItemDye.h32
-rw-r--r--source/items/ItemHoe.h29
-rw-r--r--source/items/ItemLeaves.h17
-rw-r--r--source/items/ItemLighter.h27
-rw-r--r--source/items/ItemPickaxe.h72
-rw-r--r--source/items/ItemRedstoneDust.h27
-rw-r--r--source/items/ItemSapling.h20
-rw-r--r--source/items/ItemSeeds.h58
-rw-r--r--source/items/ItemShears.h41
-rw-r--r--source/items/ItemShovel.h35
-rw-r--r--source/items/ItemSlab.h39
-rw-r--r--source/items/ItemSugarcane.h34
-rw-r--r--source/items/ItemSword.h19
-rw-r--r--source/items/ItemWood.h17
19 files changed, 854 insertions, 0 deletions
diff --git a/source/items/Item.cpp b/source/items/Item.cpp
new file mode 100644
index 000000000..b3a525c6b
--- /dev/null
+++ b/source/items/Item.cpp
@@ -0,0 +1,224 @@
+#include "Globals.h"
+#include "Item.h"
+#include "../cItem.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+//Handler
+#include "ItemCloth.h"
+#include "ItemHoe.h"
+#include "ItemSlab.h"
+#include "ItemWood.h"
+#include "ItemShears.h"
+#include "ItemLeaves.h"
+#include "ItemSapling.h"
+#include "ItemBucket.h"
+#include "ItemLighter.h"
+#include "ItemRedstoneDust.h"
+#include "ItemSeeds.h"
+#include "ItemDye.h"
+#include "ItemSugarcane.h"
+#include "ItemPickaxe.h"
+#include "ItemShovel.h"
+#include "ItemSword.h"
+#include "ItemDoor.h"
+
+#include "../blocks/Block.h"
+
+bool cItemHandler::m_HandlerInitialized = false;
+cItemHandler *cItemHandler::m_ItemHandler[2266];
+
+cItemHandler *cItemHandler::GetItemHandler(int a_ItemID)
+{
+ if(a_ItemID < 0) a_ItemID = 0;
+
+ if(!m_HandlerInitialized)
+ { //We have to initialize
+ memset(m_ItemHandler, 0, sizeof(m_ItemHandler));
+ m_HandlerInitialized = true;
+ }
+ if(m_ItemHandler[a_ItemID])
+ return m_ItemHandler[a_ItemID];
+ m_ItemHandler[a_ItemID] = CreateItemHandler(a_ItemID);
+ return m_ItemHandler[a_ItemID];
+}
+
+cItemHandler *cItemHandler::CreateItemHandler(int a_ItemID)
+{
+ switch(a_ItemID)
+ {
+ case E_ITEM_WOODEN_HOE:
+ case E_ITEM_STONE_HOE:
+ case E_ITEM_IRON_HOE:
+ case E_ITEM_GOLD_HOE:
+ case E_ITEM_DIAMOND_HOE:
+ return new cItemHoeHandler(a_ItemID);
+ case E_ITEM_WHITE_CLOTH:
+ return new cItemClothHandler(a_ItemID);
+ case E_ITEM_STONE_SLAB:
+ case E_ITEM_WOODEN_SLAB:
+ return new cItemSlabHandler(a_ItemID);
+ case E_ITEM_LOG:
+ case E_ITEM_WOOD:
+ return new cItemWoodHandler(a_ItemID);
+ case E_ITEM_SHEARS:
+ return new cItemShearsHandler(a_ItemID);
+ case E_ITEM_LEAVES:
+ return new cItemLeavesHandler(a_ItemID);
+ case E_ITEM_SAPLING:
+ return new cItemSaplingHandler(a_ItemID);
+ case E_ITEM_REDSTONE_DUST:
+ return new cItemRedstoneDustHandler(a_ItemID);
+ case E_ITEM_BUCKET:
+ case E_ITEM_WATER_BUCKET:
+ case E_ITEM_LAVA_BUCKET:
+ return new cItemBucketHandler(a_ItemID);
+ case E_ITEM_FLINT_AND_STEEL:
+ return new cItemLighterHandler(a_ItemID);
+ case E_ITEM_PUMPKIN_SEEDS:
+ case E_ITEM_MELON_SEEDS:
+ case E_ITEM_SEEDS:
+ return new cItemSeedsHandler(a_ItemID);
+ case E_ITEM_DYE:
+ return new cItemDyeHandler(a_ItemID);
+ case E_ITEM_SUGARCANE:
+ return new cItemSugarcaneHandler(a_ItemID);
+ case E_ITEM_WOODEN_PICKAXE:
+ case E_ITEM_STONE_PICKAXE:
+ case E_ITEM_IRON_PICKAXE:
+ case E_ITEM_GOLD_PICKAXE:
+ case E_ITEM_DIAMOND_PICKAXE:
+ return new cItemPickaxeHandler(a_ItemID);
+ case E_ITEM_WOODEN_SHOVEL:
+ case E_ITEM_STONE_SHOVEL:
+ case E_ITEM_IRON_SHOVEL:
+ case E_ITEM_GOLD_SHOVEL:
+ case E_ITEM_DIAMOND_SHOVEL:
+ return new cItemShovelHandler(a_ItemID);
+ case E_ITEM_WOODEN_SWORD:
+ case E_ITEM_STONE_SWORD:
+ case E_ITEM_IRON_SWORD:
+ case E_ITEM_GOLD_SWORD:
+ case E_ITEM_DIAMOND_SWORD:
+ return new cItemSwordHandler(a_ItemID);
+
+ case E_ITEM_IRON_DOOR:
+ case E_ITEM_WOODEN_DOOR:
+ return new cItemDoorHandler(a_ItemID);
+
+ default:
+ return new cItemHandler(a_ItemID);
+ break;
+ }
+}
+
+void cItemHandler::Deinit()
+{
+ for(int i = 0; i < 2266; i++)
+ {
+ delete m_ItemHandler[i];
+ }
+}
+
+cItemHandler::cItemHandler(int a_ItemID)
+{
+ m_ItemID = a_ItemID;
+}
+
+bool cItemHandler::OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ return false;
+}
+
+bool cItemHandler::OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ return false;
+}
+
+void cItemHandler::OnBlockDestroyed(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z)
+{
+ char Block = a_World->GetBlock(a_X, a_Y, a_Z);
+ cBlockHandler *Handler = cBlockHandler::GetBlockHandler(Block);
+
+ if(a_Player->GetGameMode() == eGameMode_Survival)
+ {
+ if(!BlockRequiresSpecialTool(Block) || CanHarvestBlock(Block))
+ {
+ Handler->DropBlock(a_World, a_X, a_Y, a_Z);
+ }
+ }
+
+ a_Player->UseEquippedItem();
+}
+
+void cItemHandler::OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item)
+{
+
+}
+
+int cItemHandler::GetMaxStackSize()
+{
+ return 64;
+}
+
+int cItemHandler::GetMaxDamage()
+{
+ return 0;
+}
+
+bool cItemHandler::IsTool()
+{
+ return
+ (m_ItemID >= 256 && m_ItemID <= 259)
+ || (m_ItemID == 261)
+ || (m_ItemID >= 267 && m_ItemID <= 279)
+ || (m_ItemID >= 283 && m_ItemID <= 286)
+ || (m_ItemID >= 290 && m_ItemID <= 294)
+ || (m_ItemID >= 256 && m_ItemID <= 259)
+ || (m_ItemID == 325)
+ || (m_ItemID == 346);
+}
+
+bool cItemHandler::IsFood()
+{
+ return
+ (m_ItemID == 260)
+ || (m_ItemID == 282)
+ || (m_ItemID == 297)
+ || (m_ItemID >= 319 && m_ItemID <= 320)
+ || (m_ItemID == 335)
+ || (m_ItemID >= 349 && m_ItemID <= 350)
+ || (m_ItemID == 357)
+ || (m_ItemID == 360)
+ || (m_ItemID >= 363 && m_ItemID <= 366);
+}
+
+bool cItemHandler::IsPlaceable()
+{
+ return m_ItemID >= 1 && m_ItemID <= 136;
+}
+
+
+bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockID)
+{
+ return false;
+}
+
+BLOCKTYPE cItemHandler::GetBlockType()
+{
+ return m_ItemID;
+}
+
+char cItemHandler::GetBlockMeta(char a_ItemMeta)
+{
+ return a_ItemMeta; //This keeps most textures. The few other items have to override this
+}
+
+void cItemHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+{
+ BLOCKTYPE Block = GetBlockType();
+ cBlockHandler *Handler = cBlockHandler::GetBlockHandler(Block);
+ Handler->PlaceBlock(a_World, a_Player, GetBlockMeta(a_Item->m_ItemHealth), a_X, a_Y, a_Z, a_Dir);
+ if(a_Player->GetGameMode() == eGameMode_Survival)
+ a_Player->GetInventory().RemoveItem(cItem(a_Item->m_ItemID, 1));
+} \ No newline at end of file
diff --git a/source/items/Item.h b/source/items/Item.h
new file mode 100644
index 000000000..e63ec2fc4
--- /dev/null
+++ b/source/items/Item.h
@@ -0,0 +1,45 @@
+#pragma once
+#include "../Defines.h"
+
+class cWorld;
+class cPlayer;
+
+
+class cItemHandler
+{
+public:
+ cItemHandler(int a_ItemID);
+ virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir); //eg for fishing or hoes
+ virtual bool OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir);
+ virtual void OnBlockDestroyed(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z);
+ virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item);
+ virtual int GetMaxStackSize();
+ virtual int GetMaxDamage();
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir);
+
+ virtual bool IsTool();
+ virtual bool IsFood();
+ //Blocks simply get placed
+ virtual bool IsPlaceable();
+
+ virtual BLOCKTYPE GetBlockType();
+ virtual char GetBlockMeta(char a_ItemMeta);
+
+ virtual bool CanHarvestBlock(BLOCKTYPE a_BlockID);
+
+ static cItemHandler *GetItemHandler(int a_ItemID);
+
+ static void Deinit();
+
+
+protected:
+ int m_ItemID;
+ static cItemHandler *CreateItemHandler(int m_ItemID);
+
+ static cItemHandler *m_ItemHandler[2266];
+ static bool m_HandlerInitialized; //used to detect if the itemhandlers are initialized
+};
+
+//Short function
+inline cItemHandler *ItemHandler(int a_ItemID) { return cItemHandler::GetItemHandler(a_ItemID); } \ No newline at end of file
diff --git a/source/items/ItemBucket.h b/source/items/ItemBucket.h
new file mode 100644
index 000000000..e223d47f1
--- /dev/null
+++ b/source/items/ItemBucket.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "Item.h"
+#include "../cWorld.h"
+
+class cItemBucketHandler : public cItemHandler
+{
+public:
+ cItemBucketHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ switch(m_ItemID)
+ {
+ case E_ITEM_BUCKET:
+ {
+ AddDirection(a_X, a_Y, a_Z, a_Dir);
+ BLOCKTYPE ClickedBlock = a_World->GetBlock(a_X, a_Y, a_Z);
+ LOG("Bucket Clicked BlockID: %d", ClickedBlock);
+ ENUM_ITEM_ID NewItem = E_ITEM_EMPTY;
+ switch (ClickedBlock)
+ {
+ case E_BLOCK_WATER:
+ case E_BLOCK_STATIONARY_WATER:
+ NewItem = E_ITEM_WATER_BUCKET;
+ break;
+ case E_BLOCK_LAVA:
+ case E_BLOCK_STATIONARY_LAVA:
+ NewItem = E_ITEM_LAVA_BUCKET;
+ break;
+ }
+ if (NewItem != E_ITEM_EMPTY
+ && (a_Player->GetGameMode() == 1 || (a_Player->GetInventory().RemoveItem(cItem(a_Item->m_ItemID, 1)))))
+ {
+ //Give New Bucket
+ a_Player->GetInventory().AddItem(cItem(NewItem, 1));
+ //remove water block
+ a_Player->GetWorld()->SetBlock(a_X, a_Y, a_Z, E_BLOCK_AIR, 0);
+ return true;
+ }
+ }
+ break;
+ case E_ITEM_WATER_BUCKET:
+ case E_ITEM_LAVA_BUCKET:
+ {
+ BLOCKTYPE NewBlock = (m_ItemID == E_ITEM_LAVA_BUCKET) ? E_BLOCK_LAVA : E_BLOCK_WATER;
+
+ AddDirection(a_X, a_Y, a_Z, a_Dir);
+ if(a_World->GetBlock(a_X, a_Y, a_Z) == E_BLOCK_AIR)
+ {
+ if ((a_Player->GetGameMode() == 1) || (a_Player->GetInventory().RemoveItem(cItem(a_Item->m_ItemID, 1))))
+ {
+ a_World->SetBlock(a_X, a_Y, a_Z, NewBlock, 0);
+
+ if (a_Player->GetGameMode() == 1)
+ {
+ break; //No new Bucket for creative players
+ }
+
+ a_Player->GetInventory().AddItem(cItem(E_ITEM_BUCKET, 1));
+ return true;
+ }
+ }
+ }
+ break;
+ }
+
+ return false;
+ }
+
+}; \ No newline at end of file
diff --git a/source/items/ItemCloth.h b/source/items/ItemCloth.h
new file mode 100644
index 000000000..805e90cb4
--- /dev/null
+++ b/source/items/ItemCloth.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "Item.h"
+
+
+class cItemClothHandler : public cItemHandler
+{
+public:
+ cItemClothHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ return a_ItemMeta;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemDoor.h b/source/items/ItemDoor.h
new file mode 100644
index 000000000..5b656ce17
--- /dev/null
+++ b/source/items/ItemDoor.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Item.h"
+#include "../cWorld.h"
+
+class cItemDoorHandler : public cItemHandler
+{
+public:
+ cItemDoorHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool IsPlaceable()
+ {
+ return true;
+ }
+
+ virtual BLOCKTYPE GetBlockType()
+ {
+ return (m_ItemID == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR;
+ }
+
+}; \ No newline at end of file
diff --git a/source/items/ItemDye.h b/source/items/ItemDye.h
new file mode 100644
index 000000000..60a1ed289
--- /dev/null
+++ b/source/items/ItemDye.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "Item.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+class cItemDyeHandler : public cItemHandler
+{
+public:
+ cItemDyeHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ // TODO: Handle coloring the sheep, too (OnItemUseOnEntity maybe)
+ // Handle growing the plants:
+ if (a_Item->m_ItemHealth == E_META_DYE_WHITE)
+ {
+ if(a_World->GrowPlant(a_X, a_Y, a_Z, true))
+ {
+ if (a_Player->GetGameMode() == eGameMode_Survival)
+ {
+ a_Player->GetInventory().RemoveItem(cItem(a_Item->m_ItemID, 1, a_Item->m_ItemHealth));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemHoe.h b/source/items/ItemHoe.h
new file mode 100644
index 000000000..dd73f4ac9
--- /dev/null
+++ b/source/items/ItemHoe.h
@@ -0,0 +1,29 @@
+#pragma once
+#include "Item.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+class cItemHoeHandler : public cItemHandler
+{
+public:
+ cItemHoeHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ BLOCKTYPE Block = a_World->GetBlock(a_X, a_Y, a_Z);
+
+ if(Block == E_BLOCK_DIRT || Block == E_BLOCK_GRASS)
+ {
+ a_World->FastSetBlock(a_X, a_Y, a_Z, E_BLOCK_FARMLAND, 0);
+
+ a_Player->UseEquippedItem();
+ return true;
+
+ }
+ return false;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemLeaves.h b/source/items/ItemLeaves.h
new file mode 100644
index 000000000..d328858fd
--- /dev/null
+++ b/source/items/ItemLeaves.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "Item.h"
+
+
+class cItemLeavesHandler : public cItemHandler
+{
+public:
+ cItemLeavesHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+ }
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ return a_ItemMeta | 0x4; //0x4 bit set means this is a player places leave
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemLighter.h b/source/items/ItemLighter.h
new file mode 100644
index 000000000..287a7742f
--- /dev/null
+++ b/source/items/ItemLighter.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "Item.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+class cItemLighterHandler : public cItemHandler
+{
+public:
+ cItemLighterHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ a_Player->UseEquippedItem();
+
+ AddDirection(a_X, a_Y, a_Z, a_Dir);
+
+ a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_FIRE, 0); //0 -> new fire TODO: Make Firesimulator use this
+
+ return false;
+ }
+
+}; \ No newline at end of file
diff --git a/source/items/ItemPickaxe.h b/source/items/ItemPickaxe.h
new file mode 100644
index 000000000..1be3745de
--- /dev/null
+++ b/source/items/ItemPickaxe.h
@@ -0,0 +1,72 @@
+#pragma once
+#include "Item.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+class cItemPickaxeHandler : public cItemHandler
+{
+public:
+ cItemPickaxeHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ char PickaxeLevel()
+ {
+ switch(m_ItemID)
+ {
+ case E_ITEM_WOODEN_PICKAXE:
+ case E_ITEM_GOLD_PICKAXE:
+ return 1;
+ case E_ITEM_STONE_PICKAXE:
+ return 2;
+ case E_ITEM_IRON_PICKAXE:
+ return 3;
+ case E_ITEM_DIAMOND_PICKAXE:
+ return 4;
+ default:
+ return 0;
+ }
+ }
+
+ virtual bool CanHarvestBlock(BLOCKTYPE a_BlockID)
+ {
+ switch(a_BlockID)
+ {
+ case E_BLOCK_OBSIDIAN:
+ return PickaxeLevel() >= 4;
+ case E_BLOCK_DIAMOND_BLOCK:
+ case E_BLOCK_DIAMOND_ORE:
+ case E_BLOCK_GOLD_BLOCK:
+ case E_BLOCK_GOLD_ORE:
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ case E_BLOCK_EMERALD_ORE:
+ return PickaxeLevel() >= 3;
+ case E_BLOCK_IRON_BLOCK:
+ case E_BLOCK_IRON_ORE:
+ case E_BLOCK_LAPIS_ORE:
+ case E_BLOCK_LAPIS_BLOCK:
+ return PickaxeLevel() >= 2;
+ case E_BLOCK_COAL_ORE:
+ case E_BLOCK_STONE:
+ case E_BLOCK_COBBLESTONE:
+ case E_BLOCK_END_STONE:
+ case E_BLOCK_MOSSY_COBBLESTONE:
+ case E_BLOCK_SANDSTONE_STAIRS:
+ case E_BLOCK_SANDSTONE:
+ case E_BLOCK_STONE_BRICKS:
+ case E_BLOCK_NETHER_BRICK:
+ case E_BLOCK_NETHERRACK:
+ case E_BLOCK_STONE_SLAB:
+ case E_BLOCK_DOUBLE_STONE_SLAB:
+ case E_BLOCK_STONE_PRESSURE_PLATE:
+ case E_BLOCK_BRICK:
+ case E_BLOCK_COBBLESTONE_STAIRS:
+ case E_BLOCK_STONE_BRICK_STAIRS:
+ case E_BLOCK_NETHER_BRICK_STAIRS:
+ return PickaxeLevel() >= 1;
+ }
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemRedstoneDust.h b/source/items/ItemRedstoneDust.h
new file mode 100644
index 000000000..99529a4e8
--- /dev/null
+++ b/source/items/ItemRedstoneDust.h
@@ -0,0 +1,27 @@
+#pragma once
+#include "Item.h"
+
+
+class cItemRedstoneDustHandler : public cItemHandler
+{
+public:
+ cItemRedstoneDustHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+ }
+
+ virtual bool IsPlaceable()
+ {
+ return true;
+ }
+
+ virtual BLOCKTYPE GetBlockType()
+ {
+ return E_BLOCK_REDSTONE_WIRE;
+ }
+
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ return 0;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemSapling.h b/source/items/ItemSapling.h
new file mode 100644
index 000000000..29c14abee
--- /dev/null
+++ b/source/items/ItemSapling.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "Item.h"
+
+
+class cItemSaplingHandler : public cItemHandler
+{
+public:
+ cItemSaplingHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ //Only the first 2 bits are important
+ return a_ItemMeta & 3;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemSeeds.h b/source/items/ItemSeeds.h
new file mode 100644
index 000000000..d5f9244b2
--- /dev/null
+++ b/source/items/ItemSeeds.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include "Item.h"
+#include "../cWorld.h"
+
+class cItemSeedsHandler : public cItemHandler
+{
+public:
+ cItemSeedsHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool IsPlaceable()
+ {
+ return true;
+ }
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+ virtual BLOCKTYPE GetBlockType()
+ {
+ switch(m_ItemID)
+ {
+ case E_ITEM_SEEDS:
+ return E_BLOCK_CROPS;
+ case E_ITEM_MELON_SEEDS:
+ E_BLOCK_MELON_STEM;
+ case E_ITEM_PUMPKIN_SEEDS:
+ E_BLOCK_PUMPKIN_STEM;
+ default:
+ return E_BLOCK_AIR;
+ }
+ }
+
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ return 0; //Not grown yet
+ }
+
+ virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ int X = a_X,
+ Y = a_Y,
+ Z = a_Z;
+
+ AddDirection(X, Y, Z, a_Dir, true);
+
+ if(a_World->GetBlock(X, Y, Z) != E_BLOCK_FARMLAND)
+ return;
+
+ return cItemHandler::PlaceBlock(a_World, a_Player, a_Item, a_X, a_Y, a_Z, a_Dir);
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemShears.h b/source/items/ItemShears.h
new file mode 100644
index 000000000..786ea5f5e
--- /dev/null
+++ b/source/items/ItemShears.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "Item.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+class cItemShearsHandler : public cItemHandler
+{
+public:
+ cItemShearsHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+ virtual bool IsTool()
+ {
+ return true;
+ }
+ virtual bool OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ BLOCKTYPE Block = a_World->GetBlock(a_X, a_Y, a_Z);
+ if(Block == E_BLOCK_LEAVES)
+ {
+ cItems Drops;
+ Drops.push_back(cItem(E_ITEM_LEAVES, 1, a_World->GetBlockMeta(a_X, a_Y, a_Z)));
+ a_World->SpawnItemPickups(Drops, a_X, a_Y, a_Z);
+
+ a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_AIR, 0);
+ a_Player->UseEquippedItem();
+ return true;
+ }
+ return false;
+ }
+
+
+ virtual bool CanHarvestBlock(BLOCKTYPE a_BlockID)
+ {
+ return a_BlockID == E_BLOCK_COBWEB
+ || a_BlockID == E_BLOCK_VINES;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemShovel.h b/source/items/ItemShovel.h
new file mode 100644
index 000000000..5fd21cc26
--- /dev/null
+++ b/source/items/ItemShovel.h
@@ -0,0 +1,35 @@
+#pragma once
+#include "Item.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+#include "../blocks/Block.h"
+
+class cItemShovelHandler : public cItemHandler
+{
+public:
+ cItemShovelHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
+ {
+ BLOCKTYPE Block = a_World->GetBlock(a_X, a_Y, a_Z);
+ if(Block == E_BLOCK_SNOW)
+ {
+ BlockHandler(Block)->DropBlock(a_World, a_X, a_Y, a_Z);
+
+ a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_AIR, 0);
+ a_Player->UseEquippedItem();
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool CanHarvestBlock(BLOCKTYPE a_BlockID)
+ {
+ return a_BlockID == E_BLOCK_SNOW;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemSlab.h b/source/items/ItemSlab.h
new file mode 100644
index 000000000..3cb4afeb0
--- /dev/null
+++ b/source/items/ItemSlab.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "Item.h"
+#include "../cWorld.h"
+
+class cItemSlabHandler : public cItemHandler
+{
+public:
+ cItemSlabHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
+ {
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ a_World->GetBlockTypeMeta(a_X, a_Y, a_Z, Block, Meta);
+
+ if( (a_Dir == 0 || a_Dir == 1) //Only when clicking on top or on bottom of the block
+ && (Block == E_BLOCK_WOODEN_SLAB || Block == E_BLOCK_STONE_SLAB) //It is a slab
+ && (Block == a_Item->m_ItemID) //Same slab
+ && ((Meta & 0x7) == (a_Item->m_ItemHealth & 0x7))) //Same Texture
+ {
+ if(a_Player->GetInventory().RemoveItem(cItem(a_Item->m_ItemID, 1)))
+ {
+ a_World->SetBlock(a_X, a_Y, a_Z, Block - 1, Meta); //Block - 1 simple hack to save one if statement
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ return a_ItemMeta;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemSugarcane.h b/source/items/ItemSugarcane.h
new file mode 100644
index 000000000..515f94014
--- /dev/null
+++ b/source/items/ItemSugarcane.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "Item.h"
+#include "../cWorld.h"
+
+class cItemSugarcaneHandler : public cItemHandler
+{
+public:
+ cItemSugarcaneHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool IsPlaceable()
+ {
+ return true;
+ }
+
+ virtual bool AllowBlockOnTop()
+ {
+ return false;
+ }
+
+ virtual BLOCKTYPE GetBlockType()
+ {
+ return E_BLOCK_SUGARCANE;
+ }
+
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ return 0; //Not grown yet
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemSword.h b/source/items/ItemSword.h
new file mode 100644
index 000000000..f49436d51
--- /dev/null
+++ b/source/items/ItemSword.h
@@ -0,0 +1,19 @@
+#pragma once
+#include "Item.h"
+#include "../cWorld.h"
+#include "../cPlayer.h"
+
+class cItemSwordHandler : public cItemHandler
+{
+public:
+ cItemSwordHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+
+ }
+
+ virtual bool CanHarvestBlock(BLOCKTYPE a_BlockID)
+ {
+ return a_BlockID == E_BLOCK_COBWEB;
+ }
+}; \ No newline at end of file
diff --git a/source/items/ItemWood.h b/source/items/ItemWood.h
new file mode 100644
index 000000000..91eaa7675
--- /dev/null
+++ b/source/items/ItemWood.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "Item.h"
+
+
+class cItemWoodHandler : public cItemHandler
+{
+public:
+ cItemWoodHandler(int a_ItemID)
+ : cItemHandler(a_ItemID)
+ {
+ }
+ virtual char GetBlockMeta(char a_ItemMeta)
+ {
+ return a_ItemMeta;
+ }
+}; \ No newline at end of file