1
0

Fixed a few bugs in fluid placement - fluid into other fluid, fluid into washable blocks.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@977 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2012-10-18 19:41:29 +00:00
parent d2fc9cd9ee
commit c68aa68c69
25 changed files with 344 additions and 235 deletions

View File

@ -7,8 +7,8 @@
class cItemBedHandler : public cItemHandler
{
public:
cItemBedHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemBedHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -3,92 +3,162 @@
#include "ItemHandler.h"
#include "../World.h"
#include "../Simulator/FluidSimulator.h"
#include "../Blocks/BlockHandler.h"
class cItemBucketHandler : public cItemHandler
class cItemBucketHandler :
public cItemHandler
{
public:
cItemBucketHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemBucketHandler(int a_ItemType) :
cItemHandler(a_ItemType)
{
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
switch(m_ItemID)
switch (m_ItemType)
{
case E_ITEM_BUCKET:
case E_ITEM_BUCKET: return ScoopUpFluid(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
case E_ITEM_LAVA_BUCKET: return PlaceFluid (a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir, E_BLOCK_LAVA);
case E_ITEM_WATER_BUCKET: return PlaceFluid (a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir, E_BLOCK_WATER);
default:
{
if (a_Dir >= 0)
{
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;
}
}
cItem Item(a_Item->m_ItemID, 1);
if (
(NewItem != E_ITEM_EMPTY) &&
(
((a_Player->GetGameMode() == 1) ||
a_Player->GetInventory().RemoveItem(Item))
)
)
{
// Give New Bucket
cItem Item(NewItem, 1);
a_Player->GetInventory().AddItem(Item);
// Remove water / lava block
a_Player->GetWorld()->SetBlock(a_X, a_Y, a_Z, E_BLOCK_AIR, 0);
return true;
}
ASSERT(!"Unhandled ItemType");
return false;
}
}
}
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
if (a_Dir < 0)
{
return false;
}
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir);
BLOCKTYPE ClickedBlock;
NIBBLETYPE ClickedMeta;
a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedMeta);
LOGD("Bucket Clicked BlockType %d, meta %d", ClickedBlock, ClickedMeta);
if (ClickedMeta != 0)
{
// Not a source block
return false;
}
if (a_Player->GetGameMode() == eGameMode_Creative)
{
// In creative mode don't modify the inventory, just remove the fluid:
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
return true;
}
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;
}
case E_ITEM_WATER_BUCKET:
case E_ITEM_LAVA_BUCKET:
{
BLOCKTYPE NewBlock = (m_ItemID == E_ITEM_LAVA_BUCKET) ? E_BLOCK_LAVA : E_BLOCK_WATER;
if (a_Dir >= 0)
{
AddDirection(a_X, a_Y, a_Z, a_Dir);
if (a_World->GetBlock(a_X, a_Y, a_Z) == E_BLOCK_AIR)
{
cItem Item(a_Item->m_ItemID, 1);
if ((a_Player->GetGameMode() == 1) || (a_Player->GetInventory().RemoveItem(Item)))
{
a_World->SetBlock(a_X, a_Y, a_Z, NewBlock, 0);
default: return false;
}
// Remove the bucket from the inventory
cItem Item(a_Item->m_ItemType, 1);
if (!a_Player->GetInventory().RemoveItem(Item))
{
LOG("Clicked with an empty bucket, but cannot remove one from the inventory? WTF?");
ASSERT(!"Inventory bucket mismatch");
return true;
}
// Give new bucket, filled with fluid:
Item.m_ItemType = NewItem;
Item.m_ItemCount = 1;
a_Player->GetInventory().AddItem(Item);
if (a_Player->GetGameMode() == 1)
{
break; //No new Bucket for creative players
}
cItem Item(E_ITEM_BUCKET, 1);
a_Player->GetInventory().AddItem(Item);
return true;
}
}
}
// Remove water / lava block
a_Player->GetWorld()->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
return true;
}
bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir, BLOCKTYPE a_FluidBlock)
{
if (a_Dir < 0)
{
return false;
}
BLOCKTYPE CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
bool CanWashAway = cFluidSimulator::CanWashAway(CurrentBlock);
if (!CanWashAway)
{
// The block pointed at cannot be washed away, so put fluid on top of it / on its sides
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir);
CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
}
if (
!CanWashAway &&
(CurrentBlock != E_BLOCK_AIR) &&
(CurrentBlock != E_BLOCK_WATER) &&
(CurrentBlock != E_BLOCK_STATIONARY_WATER) &&
(CurrentBlock != E_BLOCK_LAVA) &&
(CurrentBlock != E_BLOCK_STATIONARY_LAVA)
)
{
// Cannot place water here
return false;
}
if (a_Player->GetGameMode() != eGameMode_Creative)
{
// Remove fluid bucket, add empty bucket:
cItem Item(a_Item->m_ItemType, 1);
if (!a_Player->GetInventory().RemoveItem(Item))
{
LOG("Clicked with a full bucket, but cannot remove one from the inventory? WTF?");
ASSERT(!"Inventory bucket mismatch");
return false;
}
Item.m_ItemType = E_ITEM_BUCKET;
Item.m_ItemCount = 1;
if (!a_Player->GetInventory().AddItem(Item))
{
return false;
}
}
// Wash away anything that was there prior to placing:
if (CanWashAway)
{
cBlockHandler * Handler = BlockHandler(CurrentBlock);
if (Handler->DoesDropOnUnsuitable())
{
Handler->DropBlock(a_World, a_BlockX, a_BlockY, a_BlockZ);
}
break;
}
return false;
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FluidBlock, 0);
return true;
}
};

View File

@ -11,8 +11,8 @@ class cItemClothHandler :
public cItemHandler
{
public:
cItemClothHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemClothHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -7,8 +7,8 @@
class cItemDoorHandler : public cItemHandler
{
public:
cItemDoorHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemDoorHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
@ -20,7 +20,7 @@ public:
virtual BLOCKTYPE GetBlockType() override
{
return (m_ItemID == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR;
return (m_ItemType == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR;
}
};

View File

@ -13,23 +13,23 @@ class cItemDyeHandler :
public cItemHandler
{
public:
cItemDyeHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemDyeHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
// TODO: Handle coloring the sheep, too (OnItemUseOnEntity maybe)
// Handle growing the plants:
if (a_Item->m_ItemHealth == E_META_DYE_WHITE)
{
if (a_World->GrowRipePlant(a_X, a_Y, a_Z, true))
if (a_World->GrowRipePlant(a_BlockX, a_BlockY, a_BlockZ, true))
{
if (a_Player->GetGameMode() == eGameMode_Survival)
if (a_Player->GetGameMode() != eGameMode_Creative)
{
cItem Item(a_Item->m_ItemID, 1, a_Item->m_ItemHealth);
cItem Item(a_Item->m_ItemType, 1, a_Item->m_ItemHealth);
a_Player->GetInventory().RemoveItem(Item);
return true;
}

View File

@ -7,8 +7,8 @@
class cItemFoodHandler : public cItemHandler
{
public:
cItemFoodHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemFoodHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
@ -19,7 +19,7 @@ public:
virtual FoodInfo GetFoodInfo() override
{
switch(m_ItemID)
switch(m_ItemType)
{
case E_ITEM_BREAD:
return FoodInfo(5, 6.f);

View File

@ -42,44 +42,44 @@ cItemHandler * cItemHandler::m_ItemHandler[2266];
cItemHandler *cItemHandler::GetItemHandler(int a_ItemID)
cItemHandler *cItemHandler::GetItemHandler(int a_ItemType)
{
if(a_ItemID < 0) a_ItemID = 0;
if(a_ItemType < 0) a_ItemType = 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];
if(m_ItemHandler[a_ItemType])
return m_ItemHandler[a_ItemType];
m_ItemHandler[a_ItemType] = CreateItemHandler(a_ItemType);
return m_ItemHandler[a_ItemType];
}
cItemHandler *cItemHandler::CreateItemHandler(int a_ItemID)
cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
{
switch(a_ItemID)
switch(a_ItemType)
{
default: return new cItemHandler(a_ItemID);
default: return new cItemHandler(a_ItemType);
// Single item per handler, alphabetically sorted:
case E_ITEM_BED: return new cItemBedHandler(a_ItemID);
case E_ITEM_DYE: return new cItemDyeHandler(a_ItemID);
case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemID);
case E_ITEM_LEAVES: return new cItemLeavesHandler(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_SAPLING: return new cItemSaplingHandler(a_ItemID);
case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemID);
case E_ITEM_SIGN: return new cItemSignHandler(a_ItemID);
case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemID);
case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemID);
case E_ITEM_WOOL: return new cItemClothHandler(a_ItemID);
case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType);
case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType);
case E_ITEM_LEAVES: return new cItemLeavesHandler(a_ItemType);
case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType);
case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType);
case E_ITEM_SAPLING: return new cItemSaplingHandler(a_ItemType);
case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType);
case E_ITEM_SIGN: return new cItemSignHandler(a_ItemType);
case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType);
case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType);
case E_ITEM_WOOL: return new cItemClothHandler(a_ItemType);
case E_ITEM_WOODEN_HOE:
case E_ITEM_STONE_HOE:
@ -87,7 +87,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemID)
case E_ITEM_GOLD_HOE:
case E_ITEM_DIAMOND_HOE:
{
return new cItemHoeHandler(a_ItemID);
return new cItemHoeHandler(a_ItemType);
}
case E_ITEM_WOODEN_PICKAXE:
@ -96,7 +96,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemID)
case E_ITEM_GOLD_PICKAXE:
case E_ITEM_DIAMOND_PICKAXE:
{
return new cItemPickaxeHandler(a_ItemID);
return new cItemPickaxeHandler(a_ItemType);
}
case E_ITEM_WOODEN_SHOVEL:
@ -105,7 +105,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemID)
case E_ITEM_GOLD_SHOVEL:
case E_ITEM_DIAMOND_SHOVEL:
{
return new cItemShovelHandler(a_ItemID);
return new cItemShovelHandler(a_ItemType);
}
case E_ITEM_WOODEN_SWORD:
@ -114,39 +114,39 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemID)
case E_ITEM_GOLD_SWORD:
case E_ITEM_DIAMOND_SWORD:
{
return new cItemSwordHandler(a_ItemID);
return new cItemSwordHandler(a_ItemType);
}
case E_ITEM_STONE_SLAB:
case E_ITEM_WOODEN_SLAB:
{
return new cItemSlabHandler(a_ItemID);
return new cItemSlabHandler(a_ItemType);
}
case E_ITEM_LOG:
case E_ITEM_PLANKS:
{
return new cItemWoodHandler(a_ItemID);
return new cItemWoodHandler(a_ItemType);
}
case E_ITEM_BUCKET:
case E_ITEM_WATER_BUCKET:
case E_ITEM_LAVA_BUCKET:
{
return new cItemBucketHandler(a_ItemID);
return new cItemBucketHandler(a_ItemType);
}
case E_ITEM_PUMPKIN_SEEDS:
case E_ITEM_MELON_SEEDS:
case E_ITEM_SEEDS:
{
return new cItemSeedsHandler(a_ItemID);
return new cItemSeedsHandler(a_ItemType);
}
case E_ITEM_IRON_DOOR:
case E_ITEM_WOODEN_DOOR:
{
return new cItemDoorHandler(a_ItemID);
return new cItemDoorHandler(a_ItemType);
}
// Food:
@ -166,7 +166,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemID)
case E_ITEM_ROTTEN_FLESH:
case E_ITEM_SPIDER_EYE:
{
return new cItemFoodHandler(a_ItemID);
return new cItemFoodHandler(a_ItemType);
}
}
}
@ -188,16 +188,16 @@ void cItemHandler::Deinit()
cItemHandler::cItemHandler(int a_ItemID)
cItemHandler::cItemHandler(int a_ItemType)
{
m_ItemID = a_ItemID;
m_ItemType = a_ItemType;
}
bool cItemHandler::OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
bool cItemHandler::OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
return false;
}
@ -206,7 +206,7 @@ bool cItemHandler::OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item,
bool cItemHandler::OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
bool cItemHandler::OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
return false;
}
@ -246,13 +246,13 @@ void cItemHandler::OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item
char cItemHandler::GetMaxStackSize(void)
{
if (m_ItemID < 256)
if (m_ItemType < 256)
{
// All blocks can stack up to 64
return 64;
}
switch (m_ItemID)
switch (m_ItemType)
{
case E_ITEM_APPLE: return 64;
case E_ITEM_ARROW: return 64;
@ -291,14 +291,14 @@ char cItemHandler::GetMaxStackSize(void)
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);
(m_ItemType >= 256 && m_ItemType <= 259)
|| (m_ItemType == 261)
|| (m_ItemType >= 267 && m_ItemType <= 279)
|| (m_ItemType >= 283 && m_ItemType <= 286)
|| (m_ItemType >= 290 && m_ItemType <= 294)
|| (m_ItemType >= 256 && m_ItemType <= 259)
|| (m_ItemType == 325)
|| (m_ItemType == 346);
}
@ -308,15 +308,15 @@ bool cItemHandler::IsTool()
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);
(m_ItemType == 260)
|| (m_ItemType == 282)
|| (m_ItemType == 297)
|| (m_ItemType >= 319 && m_ItemType <= 320)
|| (m_ItemType == 335)
|| (m_ItemType >= 349 && m_ItemType <= 350)
|| (m_ItemType == 357)
|| (m_ItemType == 360)
|| (m_ItemType >= 363 && m_ItemType <= 366);
}
@ -325,7 +325,7 @@ bool cItemHandler::IsFood()
bool cItemHandler::IsPlaceable()
{
return m_ItemID >= 1 && m_ItemID <= 136;
return m_ItemType >= 1 && m_ItemType <= 136;
}
@ -343,16 +343,16 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
BLOCKTYPE cItemHandler::GetBlockType()
{
ASSERT(m_ItemID < 256); // Items with IDs above 255 should all be handled by specific handlers
ASSERT(m_ItemType < 256); // Items with IDs above 255 should all be handled by specific handlers
#ifdef _DEBUG
if (m_ItemID > 256)
if (m_ItemType > 256)
{
LOGERROR("Item %d has no valid block!", m_ItemID);
LOGERROR("Item %d has no valid block!", m_ItemType);
}
#endif // _DEBUG
return (BLOCKTYPE) m_ItemID;
return (BLOCKTYPE) m_ItemType;
}
@ -368,14 +368,14 @@ NIBBLETYPE cItemHandler::GetBlockMeta(short a_ItemDamage)
void cItemHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir)
void cItemHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, 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);
Handler->PlaceBlock(a_World, a_Player, GetBlockMeta(a_Item->m_ItemHealth), a_BlockX, a_BlockY, a_BlockZ, a_Dir);
if(a_Player->GetGameMode() == eGameMode_Survival)
{
cItem Item(a_Item->m_ItemID, 1);
cItem Item(a_Item->m_ItemType, 1);
a_Player->GetInventory().RemoveItem(Item);
}
}

View File

@ -17,9 +17,9 @@ class cPlayer;
class cItemHandler
{
public:
cItemHandler(int a_ItemID);
cItemHandler(int a_ItemType);
// Called when the player tries to use the item. Return false to make the item unusable. DEFAULT: False
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 OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir); //eg for fishing or hoes
// Called while the player diggs a block using this item
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, cItem * a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
// Called when the player destroys a block using this item. This also calls the drop function for the destroyed block
@ -50,7 +50,7 @@ public:
virtual bool EatItem(cPlayer *a_Player, cItem *a_Item);
// Places the current block and removes the item from the player inventory
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 void PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
// Indicates if this item is a tool
virtual bool IsTool();
@ -66,18 +66,18 @@ public:
// Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can´t) DEFAULT: False
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType);
static cItemHandler *GetItemHandler(int a_ItemID);
static cItemHandler *GetItemHandler(int a_ItemType);
static void Deinit();
protected:
int m_ItemID;
static cItemHandler *CreateItemHandler(int m_ItemID);
int m_ItemType;
static cItemHandler *CreateItemHandler(int m_ItemType);
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); }
inline cItemHandler *ItemHandler(int a_ItemType) { return cItemHandler::GetItemHandler(a_ItemType); }

View File

@ -8,19 +8,19 @@
class cItemHoeHandler : public cItemHandler
{
public:
cItemHoeHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemHoeHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
BLOCKTYPE Block = a_World->GetBlock(a_X, a_Y, a_Z);
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if(Block == E_BLOCK_DIRT || Block == E_BLOCK_GRASS)
if ((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS))
{
a_World->FastSetBlock(a_X, a_Y, a_Z, E_BLOCK_FARMLAND, 0);
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, 0);
a_Player->UseEquippedItem();
return true;

View File

@ -11,8 +11,8 @@ class cItemLeavesHandler :
public cItemHandler
{
public:
cItemLeavesHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemLeavesHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -7,19 +7,24 @@
class cItemLighterHandler : public cItemHandler
{
public:
cItemLighterHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemLighterHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
if (a_Dir < 0)
{
return false;
}
a_Player->UseEquippedItem();
AddDirection(a_X, a_Y, a_Z, a_Dir);
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir);
a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_FIRE, 0); //0 -> new fire TODO: Make Firesimulator use this
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0); //0 -> new fire TODO: Make Firesimulator use this
return false;
}

View File

@ -8,15 +8,15 @@
class cItemPickaxeHandler : public cItemHandler
{
public:
cItemPickaxeHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemPickaxeHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
char PickaxeLevel()
{
switch(m_ItemID)
switch(m_ItemType)
{
case E_ITEM_WOODEN_PICKAXE:
case E_ITEM_GOLD_PICKAXE:

View File

@ -10,8 +10,8 @@
class cItemRedstoneDustHandler : public cItemHandler
{
public:
cItemRedstoneDustHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemRedstoneDustHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -10,8 +10,8 @@
class cItemRedstoneRepeaterHandler : public cItemHandler
{
public:
cItemRedstoneRepeaterHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemRedstoneRepeaterHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -10,8 +10,8 @@
class cItemSaplingHandler : public cItemHandler
{
public:
cItemSaplingHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemSaplingHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -12,8 +12,8 @@ class cItemSeedsHandler :
public cItemHandler
{
public:
cItemSeedsHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemSeedsHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
@ -25,7 +25,7 @@ public:
virtual BLOCKTYPE GetBlockType() override
{
switch(m_ItemID)
switch(m_ItemType)
{
case E_ITEM_SEEDS: return E_BLOCK_CROPS;
case E_ITEM_MELON_SEEDS: return E_BLOCK_MELON_STEM;
@ -39,18 +39,27 @@ public:
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) override
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
int X = a_X,
Y = a_Y,
Z = a_Z;
if (a_Dir != BLOCK_FACE_TOP)
{
// Only allow planting seeds from the top side of the block
return;
}
int X = a_BlockX;
int Y = a_BlockY;
int Z = a_BlockZ;
AddDirection(X, Y, Z, a_Dir, true);
if(a_World->GetBlock(X, Y, Z) != E_BLOCK_FARMLAND)
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);
return cItemHandler::PlaceBlock(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
}
} ;

View File

@ -5,38 +5,59 @@
#include "../World.h"
#include "../Player.h"
class cItemShearsHandler : public cItemHandler
class cItemShearsHandler :
public cItemHandler
{
public:
cItemShearsHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemShearsHandler(int a_ItemType) :
cItemHandler(a_ItemType)
{
}
virtual bool IsTool() override
virtual bool IsTool(void) override
{
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
virtual bool OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
BLOCKTYPE Block = a_World->GetBlock(a_X, a_Y, a_Z);
if(Block == E_BLOCK_LEAVES)
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
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);
Drops.push_back(cItem(E_ITEM_LEAVES, 1, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ)));
a_World->SpawnItemPickups(Drops, a_BlockX, a_BlockY, a_BlockZ);
a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_AIR, 0);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_Player->UseEquippedItem();
return true;
}
// TODO: cobweb, vines
return false;
}
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
return a_BlockType == E_BLOCK_COBWEB
|| a_BlockType == E_BLOCK_VINES;
switch (a_BlockType)
{
case E_BLOCK_COBWEB:
case E_BLOCK_VINES:
case E_BLOCK_LEAVES:
{
return true;
}
} // switch (a_BlockType
return false;
}
};
} ;

View File

@ -14,20 +14,20 @@
class cItemShovelHandler : public cItemHandler
{
public:
cItemShovelHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemShovelHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
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
virtual bool OnDiggingBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
BLOCKTYPE Block = a_World->GetBlock(a_X, a_Y, a_Z);
if(Block == E_BLOCK_SNOW)
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (Block == E_BLOCK_SNOW)
{
BlockHandler(Block)->DropBlock(a_World, a_X, a_Y, a_Z);
BlockHandler(Block)->DropBlock(a_World, a_BlockX, a_BlockY, a_BlockZ);
a_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_AIR, 0);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_Player->UseEquippedItem();
return true;
}
@ -36,6 +36,6 @@ public:
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
return a_BlockType == E_BLOCK_SNOW;
return (a_BlockType == E_BLOCK_SNOW);
}
};

View File

@ -7,8 +7,8 @@
class cItemSignHandler : public cItemHandler
{
public:
cItemSignHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemSignHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -11,28 +11,28 @@
class cItemSlabHandler : public cItemHandler
{
public:
cItemSlabHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemSlabHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
BLOCKTYPE Block;
NIBBLETYPE Meta;
a_World->GetBlockTypeMeta(a_X, a_Y, a_Z, Block, Meta);
a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, 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
((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_ItemType) // Same slab
&& ((Meta & 0x7) == (a_Item->m_ItemHealth & 0x7))) // Same Texture
{
cItem Item(a_Item->m_ItemID, 1);
cItem Item(a_Item->m_ItemType, 1);
if (a_Player->GetInventory().RemoveItem(Item))
{
a_World->SetBlock(a_X, a_Y, a_Z, Block - 1, Meta); //Block - 1 simple hack to save one if statement
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, Block - 1, Meta); // Block - 1 simple hack to save one if statement
return true;
}
}

View File

@ -30,25 +30,25 @@
class cItemSpawnEggHandler : public cItemHandler
{
public:
cItemSpawnEggHandler(int a_ItemID) :
cItemHandler(a_ItemID)
cItemSpawnEggHandler(int a_ItemType) :
cItemHandler(a_ItemType)
{
}
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_X, int a_Y, int a_Z, char a_Dir) override
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
if (a_Dir < 0)
{
return false;
}
AddDirection(a_X, a_Y, a_Z, a_Dir);
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir);
if (a_Dir == BLOCK_FACE_BOTTOM)
{
a_Y--;
a_BlockY--;
}
cMonster * Monster = NULL;
@ -56,7 +56,7 @@ public:
Monster = new cZombie();
Monster->Initialize(a_World);
Monster->TeleportTo(a_X + 0.5, a_Y, a_Z + 0.5);
Monster->TeleportTo(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5);
a_World->BroadcastSpawn(*Monster);
a_Player->UseEquippedItem();

View File

@ -12,8 +12,8 @@ class cItemSugarcaneHandler :
public cItemHandler
{
public:
cItemSugarcaneHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemSugarcaneHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -8,8 +8,8 @@
class cItemSwordHandler : public cItemHandler
{
public:
cItemSwordHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemSwordHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}

View File

@ -11,8 +11,8 @@ class cItemWoodHandler :
public cItemHandler
{
public:
cItemWoodHandler(int a_ItemID)
: cItemHandler(a_ItemID)
cItemWoodHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
}
} ;

View File

@ -32,15 +32,19 @@ bool cFluidSimulator::CanWashAway(BLOCKTYPE a_BlockType)
{
switch (a_BlockType)
{
case E_BLOCK_YELLOW_FLOWER:
case E_BLOCK_RED_ROSE:
case E_BLOCK_RED_MUSHROOM:
case E_BLOCK_BROWN_MUSHROOM:
case E_BLOCK_CACTUS:
case E_BLOCK_TORCH:
case E_BLOCK_DEAD_BUSH:
case E_BLOCK_RAIL:
case E_BLOCK_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON:
case E_BLOCK_RAIL:
case E_BLOCK_REDSTONE_WIRE:
case E_BLOCK_RED_MUSHROOM:
case E_BLOCK_RED_ROSE:
case E_BLOCK_SNOW:
case E_BLOCK_TALL_GRASS:
case E_BLOCK_TORCH:
case E_BLOCK_YELLOW_FLOWER:
{
return true;
}