#include "Globals.h" #include "ItemHandler.h" #include "../Item.h" #include "../World.h" #include "../Player.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 "ItemRedstoneRepeater.h" #include "ItemSeeds.h" #include "ItemDye.h" #include "ItemSugarcane.h" #include "ItemPickaxe.h" #include "ItemShovel.h" #include "ItemSword.h" #include "ItemDoor.h" #include "ItemFood.h" #include "ItemSign.h" #include "ItemBed.h" #include "../blocks/BlockHandler.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) { default: return new cItemHandler(a_ItemID); // Single item per handler: 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_DYE: return new cItemDyeHandler(a_ItemID); case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemID); case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemID); case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemID); case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemID); case E_ITEM_WOOL: return new cItemClothHandler(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_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_STONE_SLAB: case E_ITEM_WOODEN_SLAB: { return new cItemSlabHandler(a_ItemID); } case E_ITEM_LOG: case E_ITEM_PLANKS: { return new cItemWoodHandler(a_ItemID); } case E_ITEM_BUCKET: case E_ITEM_WATER_BUCKET: case E_ITEM_LAVA_BUCKET: { return new cItemBucketHandler(a_ItemID); } case E_ITEM_PUMPKIN_SEEDS: case E_ITEM_MELON_SEEDS: case E_ITEM_SEEDS: { return new cItemSeedsHandler(a_ItemID); } case E_ITEM_IRON_DOOR: case E_ITEM_WOODEN_DOOR: { return new cItemDoorHandler(a_ItemID); } // Food: case E_ITEM_BREAD: case E_ITEM_COOKIE: case E_ITEM_MELON_SLICE: case E_ITEM_RAW_CHICKEN: case E_ITEM_COOKED_CHICKEN: case E_ITEM_RAW_BEEF: case E_ITEM_RAW_MEAT: case E_ITEM_STEAK: case E_ITEM_COOKED_MEAT: case E_ITEM_RAW_FISH: case E_ITEM_COOKED_FISH: case E_ITEM_RED_APPLE: case E_ITEM_GOLDEN_APPLE: case E_ITEM_ROTTEN_FLESH: case E_ITEM_SPIDER_EYE: { return new cItemFoodHandler(a_ItemID); } case E_ITEM_SIGN: return new cItemSignHandler(a_ItemID); case E_ITEM_BED: return new cItemBedHandler(a_ItemID); } } void cItemHandler::Deinit() { for(int i = 0; i < 2266; i++) { delete m_ItemHandler[i]; } m_HandlerInitialized = false; } 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) { } char cItemHandler::GetMaxStackSize(void) { if (m_ItemID < 256) { // All blocks can stack up to 64 return 64; } switch (m_ItemID) { case E_ITEM_APPLE: return 64; case E_ITEM_ARROW: return 64; case E_ITEM_BLAZE_POWDER: return 64; case E_ITEM_BLAZE_ROD: return 64; case E_ITEM_BONE: return 64; case E_ITEM_BOOK: return 64; case E_ITEM_BOWL: return 64; case E_ITEM_BREAD: return 64; case E_ITEM_BROWN_MUSHROOM: return 64; case E_ITEM_BUCKET: return 1; // TODO: change this to 16 when turning compatibility to 1.3 case E_ITEM_COAL: return 64; case E_ITEM_COOKED_CHICKEN: return 64; case E_ITEM_COOKED_FISH: return 64; case E_ITEM_COOKED_PORKCHOP: return 64; case E_ITEM_DIAMOND: return 64; case E_ITEM_FEATHER: return 64; case E_ITEM_FLINT: return 64; case E_ITEM_GOLD: return 64; case E_ITEM_GUNPOWDER: return 64; case E_ITEM_IRON: return 64; case E_ITEM_RAW_PORKCHOP: return 64; case E_ITEM_SEEDS: return 64; case E_ITEM_STICK: return 64; case E_ITEM_STRING: return 64; case E_ITEM_WHEAT: return 64; } // By default items don't stack: return 1; } 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() { ASSERT(m_ItemID < 256); // Items with IDs above 255 should all be handled by specific handlers #ifdef _DEBUG if (m_ItemID > 256) { LOGERROR("Item %d has no valid block!", m_ItemID); } #endif // _DEBUG return (BLOCKTYPE) m_ItemID; } NIBBLETYPE cItemHandler::GetBlockMeta(short a_ItemDamage) { return (NIBBLETYPE)a_ItemDamage & 0x0f; // 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) { cItem Item(a_Item->m_ItemID, 1); a_Player->GetInventory().RemoveItem(Item); } } bool cItemHandler::EatItem(cPlayer *a_Player, cItem *a_Item) { FoodInfo Info = GetFoodInfo(); if(Info.FoodLevel > 0 || Info.Saturation > 0.f) { bool Success = a_Player->Feed(Info.FoodLevel, Info.Saturation); if(Success && Info.PoisionChance > 0) { MTRand r1; if((r1.randInt(100) - Info.PoisionChance) <= 0) { //Unlucky guy :D //TODO: Make player ill } } return Success; } return false; } cItemHandler::FoodInfo cItemHandler::GetFoodInfo() { return FoodInfo(0, 0.f); }