diff options
Diffstat (limited to '')
-rw-r--r-- | src/ClientHandle.cpp | 158 |
1 files changed, 10 insertions, 148 deletions
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index cb9d34c84..6fe6e99fa 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1346,12 +1346,19 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e if (ItemHandler->IsPlaceable() && (a_BlockFace != BLOCK_FACE_NONE)) { - HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler); + if (!ItemHandler->OnPlayerPlace(*World, *m_Player, Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ)) + { + // Placement failed, bail out + return; + } } else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable(EquippedDamage))) { - if ((m_Player->IsSatiated() || m_Player->IsGameModeCreative()) && - ItemHandler->IsFood() && (Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE)) + if ( + (m_Player->IsSatiated() || m_Player->IsGameModeCreative()) && // Only creative or hungry players can eat + ItemHandler->IsFood() && + (Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE) // Golden apple is a special case, it is used instead of eaten + ) { // The player is satiated or in creative, and trying to eat return; @@ -1379,151 +1386,6 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e -void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler) -{ - BLOCKTYPE EquippedBlock = (BLOCKTYPE)(m_Player->GetEquippedItem().m_ItemType); - if (a_BlockFace < 0) - { - // Clicked in air - return; - } - - cWorld * World = m_Player->GetWorld(); - - BLOCKTYPE ClickedBlock; - NIBBLETYPE ClickedBlockMeta; - NIBBLETYPE EquippedBlockDamage = (NIBBLETYPE)(m_Player->GetEquippedItem().m_ItemDamage); - - if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) - { - // The block is being placed outside the world, ignore this packet altogether (#128) - return; - } - - World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta); - - // Special slab handling - placing a slab onto another slab produces a dblslab instead: - if ( - cBlockSlabHandler::IsAnySlabType(ClickedBlock) && // Is there a slab already? - cBlockSlabHandler::IsAnySlabType(EquippedBlock) && // Is the player placing another slab? - ((ClickedBlockMeta & 0x07) == EquippedBlockDamage) && // Is it the same slab type? - ( - (a_BlockFace == BLOCK_FACE_TOP) || // Clicking the top of a bottom slab - (a_BlockFace == BLOCK_FACE_BOTTOM) // Clicking the bottom of a top slab - ) - ) - { - // Coordinates at clicked block, which was an eligible slab, and either top or bottom faces were clicked - // If clicked top face and slab occupies the top voxel, we want a slab to be placed above it (therefore increment Y) - // Else if clicked bottom face and slab occupies the bottom voxel, decrement Y for the same reason - // Don't touch coordinates if anything else because a dblslab opportunity is present - if ((ClickedBlockMeta & 0x08) && (a_BlockFace == BLOCK_FACE_TOP)) - { - ++a_BlockY; - } - else if (!(ClickedBlockMeta & 0x08) && (a_BlockFace == BLOCK_FACE_BOTTOM)) - { - --a_BlockY; - } - World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta); - } - else - { - // Check if the block ignores build collision (water, grass etc.): - if ( - BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision() || - BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(m_Player, ClickedBlockMeta) - ) - { - cChunkInterface ChunkInterface(World->GetChunkMap()); - BlockHandler(ClickedBlock)->OnDestroyedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ); - } - else - { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - - if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) - { - // The block is being placed outside the world, ignore this packet altogether (#128) - return; - } - - NIBBLETYPE PlaceMeta; - BLOCKTYPE PlaceBlock; - World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, PlaceBlock, PlaceMeta); - - // Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed. - // No need to do combinability (dblslab) checks, client will do that here. - if (cBlockSlabHandler::IsAnySlabType(PlaceBlock)) - { - // It's a slab, don't do checks and proceed to double-slabbing - } - else - { - if ( - !BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision() && - !BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(m_Player, PlaceMeta) - ) - { - // Tried to place a block *into* another? - // Happens when you place a block aiming at side of block with a torch on it or stem beside it - return; - } - } - } - } - - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if (!a_ItemHandler.GetPlacementBlockTypeMeta(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) - { - // Handler refused the placement, send that information back to the client: - World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - m_Player->GetInventory().SendEquippedSlot(); - return; - } - - cBlockHandler * NewBlock = BlockHandler(BlockType); - - if (cRoot::Get()->GetPluginManager()->CallHookPlayerPlacingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) - { - // A plugin doesn't agree with placing the block, revert the block on the client: - World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - m_Player->GetInventory().SendEquippedSlot(); - return; - } - - // The actual block placement: - World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta); - if (!m_Player->IsGameModeCreative()) - { - m_Player->GetInventory().RemoveOneEquippedItem(); - } - - cChunkInterface ChunkInterface(World->GetChunkMap()); - NewBlock->OnPlacedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta); - - AString PlaceSound = cBlockInfo::GetPlaceSound(BlockType); - float Volume = 1.0f, Pitch = 0.8f; - if (PlaceSound == "dig.metal") - { - Pitch = 1.2f; - PlaceSound = "dig.stone"; - } - else if (PlaceSound == "random.anvil_land") - { - Volume = 0.65f; - } - - World->BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch); - - cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta); -} - - - - - void cClientHandle::HandleChat(const AString & a_Message) { // We no longer need to postpone message processing, because the messages already arrive in the Tick thread |