diff options
Diffstat (limited to 'src/ClientHandle.cpp')
-rw-r--r-- | src/ClientHandle.cpp | 258 |
1 files changed, 107 insertions, 151 deletions
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 94bace43a..a4be87fd1 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -960,22 +960,14 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB /* Check for clickthrough-blocks: When the user breaks a fire block, the client send the wrong block location. We must find the right block with the face direction. */ - int BlockX = a_BlockX; - int BlockY = a_BlockY; - int BlockZ = a_BlockZ; - AddFaceDirection(BlockX, BlockY, BlockZ, a_BlockFace); - if (cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(BlockX, BlockY, BlockZ))->IsClickedThrough()) + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true); + BLOCKTYPE Block = m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY, a_BlockZ); + if (!cBlockInfo::GetHandler(Block)->IsClickedThrough()) { - a_BlockX = BlockX; - a_BlockY = BlockY; - a_BlockZ = BlockZ; + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false); } - if ( - ((Diff(m_Player->GetPosX(), (double)a_BlockX) > 6) || - (Diff(m_Player->GetPosY(), (double)a_BlockY) > 6) || - (Diff(m_Player->GetPosZ(), (double)a_BlockZ) > 6)) - ) + if ((Vector3i(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() > 6) { m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); return; @@ -1012,7 +1004,7 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eB m_Player->AbortEating(); return; } - else + else if (m_Player->GetEquippedItem().m_ItemType == E_ITEM_BOW) { if (PlgMgr->CallHookPlayerShooting(*m_Player)) { @@ -1234,145 +1226,149 @@ void cClientHandle::FinishDigAnimation() void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem) { - // TODO: Rewrite this function - LOGD("HandleRightClick: {%d, %d, %d}, face %d, HeldItem: %s", a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, ItemToFullString(a_HeldItem).c_str() ); - - cWorld * World = m_Player->GetWorld(); - bool AreRealCoords = (Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() <= 5; - if ( - (a_BlockFace != BLOCK_FACE_NONE) && // The client is interacting with a specific block - IsValidBlock(a_HeldItem.m_ItemType) && - !AreRealCoords - ) + // Check equipped item. + const cItem & Equipped = m_Player->GetInventory().GetEquippedItem(); + if ((Equipped.m_ItemType != a_HeldItem.m_ItemType) && (a_HeldItem.m_ItemType != -1)) { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - if ((a_BlockX != -1) && (a_BlockY >= 0) && (a_BlockZ != -1)) - { - World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - if (a_BlockY < cChunkDef::Height - 1) - { - World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things - } - if (a_BlockY > 0) - { - World->SendBlockTo(a_BlockX, a_BlockY - 1, a_BlockZ, m_Player); // 2 block high things - } - } - m_Player->GetInventory().SendEquippedSlot(); + // Only compare ItemType, not meta (torches have different metas) + // The -1 check is there because sometimes the client sends -1 instead of the held item + // Ref.: http://forum.mc-server.org/showthread.php?tid=549&pid=4502#pid4502 + LOGWARN("Player %s tried to place a block that was not equipped (exp %d, got %d)", + m_Username.c_str(), Equipped.m_ItemType, a_HeldItem.m_ItemType + ); + + AbortRightClick(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); return; } - if (!AreRealCoords) + cPluginManager * PlgManager = cRoot::Get()->GetPluginManager(); + + if (PlgManager->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ)) { - a_BlockFace = BLOCK_FACE_NONE; + AbortRightClick(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + return; } - cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager(); - if (PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ)) + // Check block interactions ticks: { - // A plugin doesn't agree with the action, replace the block on the client and quit: - if (AreRealCoords) + m_NumBlockChangeInteractionsThisTick++; + if (!CheckBlockInteractionsRate()) { - cChunkInterface ChunkInterface(World->GetChunkMap()); - BLOCKTYPE BlockType = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); - cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType); - BlockHandler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - - if (a_BlockFace != BLOCK_FACE_NONE) - { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - World->SendBlockTo(a_BlockX, a_BlockY + 1, a_BlockZ, m_Player); // 2 block high things - m_Player->GetInventory().SendEquippedSlot(); - } + Kick("Too many blocks were placed/interacted with per unit time - hacked client?"); + return; } - return; } - m_NumBlockChangeInteractionsThisTick++; - - if (!CheckBlockInteractionsRate()) - { - Kick("Too many blocks were placed/interacted with per unit time - hacked client?"); - return; - } - - const cItem & Equipped = m_Player->GetInventory().GetEquippedItem(); + cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemType); + cWorld * World = m_Player->GetWorld(); + cChunkInterface ChunkInterface(World->GetChunkMap()); - if ((Equipped.m_ItemType != a_HeldItem.m_ItemType) && (a_HeldItem.m_ItemType != -1)) + if (a_BlockFace != BLOCK_FACE_NONE) { - // Only compare ItemType, not meta (torches have different metas) - // The -1 check is there because sometimes the client sends -1 instead of the held item - // Ref.: http://forum.mc-server.org/showthread.php?tid=549&pid=4502#pid4502 - LOGWARN("Player %s tried to place a block that was not equipped (exp %d, got %d)", - m_Username.c_str(), Equipped.m_ItemType, a_HeldItem.m_ItemType - ); - - // Let's send the current world block to the client, so that it can immediately "let the user know" that they haven't placed the block - if (a_BlockFace != BLOCK_FACE_NONE) + // The client is interacting with a block. + + // First test if the interacted block is a clickable block (like buttons) + if (!m_Player->IsCrouched()) { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); - } - return; - } + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta); + cBlockHandler * Handler = cBlockInfo::GetHandler(BlockType); - if (AreRealCoords) - { - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta); - cBlockHandler * BlockHandler = cBlockInfo::GetHandler(BlockType); + if (Handler->IsUseable()) + { + // Test the coordinates: + if ((Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() > 6) + { + Handler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + return; + } - if (BlockHandler->IsUseable() && !m_Player->IsCrouched()) + if (PlgManager->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) + { + // A plugin doesn't agree with using the block, abort. + Handler->OnCancelRightClick(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + return; + } + + Handler->OnUse(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); + PlgManager->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta); + return; + } + } + + // Then test if the block is placeable + if (ItemHandler->IsPlaceable()) { - if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) + // Test the coordinates: + if ((Vector3d(a_BlockX, a_BlockY, a_BlockZ) - m_Player->GetPosition()).Length() > 6) { - // A plugin doesn't agree with using the block, abort + AbortRightClick(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); return; } - cChunkInterface ChunkInterface(World->GetChunkMap()); - BlockHandler->OnUse(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); - PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta); + + HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler); return; } } - - short EquippedDamage = Equipped.m_ItemDamage; - cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemType); - - if (ItemHandler->IsPlaceable() && (a_BlockFace != BLOCK_FACE_NONE)) - { - HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler); - } - else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable(EquippedDamage))) + + if (ItemHandler->IsFood() || ItemHandler->IsDrinkable(Equipped.m_ItemDamage)) { - if ((m_Player->IsSatiated() || m_Player->IsGameModeCreative()) && - ItemHandler->IsFood() && (Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE)) + if ((m_Player->IsSatiated() || m_Player->IsGameModeCreative()) && ItemHandler->IsFood() && (Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE)) { // The player is satiated or in creative, and trying to eat return; } + m_Player->StartEating(); - if (PlgMgr->CallHookPlayerEating(*m_Player)) + if (PlgManager->CallHookPlayerEating(*m_Player)) { // A plugin won't let us eat, abort (send the proper packets to the client, too): m_Player->AbortEating(); } + return; } - else + + // -> No special right click. + if (PlgManager->CallHookPlayerUsingItem(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ)) + { + // A plugin doesn't agree with using the item, abort + return; + } + + ItemHandler->OnItemUse(World, m_Player, Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + PlgManager->CallHookPlayerUsedItem(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); +} + + + + + +void cClientHandle::AbortRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) +{ + m_Player->GetInventory().SendEquippedSlot(); + + if ((a_BlockFace != BLOCK_FACE_NONE) && (a_BlockY >= 0) && (a_BlockY < cChunkDef::Height)) { - if (PlgMgr->CallHookPlayerUsingItem(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ)) + cBlockHandler * Handler = cBlockInfo::GetHandler(m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY, a_BlockZ)); + if (!m_Player->IsCrouched() && Handler->IsUseable()) { - // A plugin doesn't agree with using the item, abort - return; + cChunkInterface ChunkInterface(m_Player->GetWorld()->GetChunkMap()); + Handler->OnCancelRightClick(ChunkInterface, *m_Player->GetWorld(), m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + } + else if (Handler->DoesIgnoreBuildCollision()) + { + m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); + } + else + { + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); } - ItemHandler->OnItemUse(World, m_Player, Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - PlgMgr->CallHookPlayerUsedItem(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ); } } @@ -1516,7 +1512,6 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e } 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); } @@ -1583,45 +1578,6 @@ void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_ -void cClientHandle::HandleAnimation(char a_Animation) -{ - if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_Animation)) - { - // Plugin disagrees, bail out - return; - } - - // Because the animation ID sent to servers by clients are different to those sent back, we need this - switch (a_Animation) - { - case 0: // No animation - wiki.vg doesn't say that client has something specific for it, so I suppose it will just become -1 - case 1: - case 2: - case 3: - { - a_Animation--; // Offset by -1 - break; - } - case 5: - case 6: - case 7: - { - a_Animation -= 2; // Offset by -2 - break; - } - default: // Anything else is the same - { - break; - } - } - - m_Player->GetWorld()->BroadcastEntityAnimation(*m_Player, a_Animation, this); -} - - - - - void cClientHandle::HandleSlotSelected(short a_SlotNum) { m_Player->GetInventory().SetEquippedSlotNum(a_SlotNum); |