From c68aa68c699a618d0172bceacf553ab96fc32cdd Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Thu, 18 Oct 2012 19:41:29 +0000 Subject: 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 --- source/Items/ItemBucket.h | 208 +++++++++++++++++++++++++++++++--------------- 1 file changed, 139 insertions(+), 69 deletions(-) (limited to 'source/Items/ItemBucket.h') diff --git a/source/Items/ItemBucket.h b/source/Items/ItemBucket.h index 21c9da2a9..3490300ae 100644 --- a/source/Items/ItemBucket.h +++ b/source/Items/ItemBucket.h @@ -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_ItemType) + { + 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: + { + 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) { - switch(m_ItemID) + if (a_Dir < 0) { - case E_ITEM_BUCKET: + 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: { - 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; - } + NewItem = E_ITEM_WATER_BUCKET; break; } - - case E_ITEM_WATER_BUCKET: - case E_ITEM_LAVA_BUCKET: + case E_BLOCK_LAVA: + case E_BLOCK_STATIONARY_LAVA: { - 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); + NewItem = E_ITEM_LAVA_BUCKET; + break; + } + + 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); + + // Remove water / lava block + a_Player->GetWorld()->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); + return true; + } - 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; - } - } - } + + 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; } }; \ No newline at end of file -- cgit v1.2.3